Framework-agnostic Asset Picker Web Component for Scaleflex VXP DAM.
Browse, search, filter, and select assets from your DAM — in any frontend stack.
Live Demo | Documentation | Examples | npm | Scaleflex DAM
- Overview
- Features
- Requirements
- Installation
- Quick Start
- Configuration
- Public Methods
- Events
- React API
- Asset Utilities
- Theming
- Filters Reference
- Types Reference
- Browser Support
- Claude Code Integration
- License
@scaleflex/asset-picker is a drop-in modal component that connects to a Scaleflex VXP DAM project and lets users browse, search, filter, preview, and select digital assets. It ships as a standard Web Component (Custom Element) built with Lit 3, so it works everywhere — vanilla JS, React, Vue, Angular, Svelte, or any other framework.
The npm package contains only pre-built, minified production files (dist/). Source code is maintained in a private Scaleflex GitLab repository.
- Framework-agnostic — standard
<sfx-asset-picker>custom element, works in any stack - First-class React wrapper —
forwardRefcomponent with controlledopenprop and imperative ref - Two auth modes — security templates or direct SASS key
- Grid & list views — switchable with persistent user preference
- Full-text search — real-time search across your DAM
- 14+ filter types — type, date, size, tags, labels, color, approval status, metadata, and more
- Filter pinning — users can pin favourite filters; persisted to
localStorage - Default & forced filters — pre-apply filters on open or lock filters the user cannot remove
- Infinite scroll — automatic pagination as the user scrolls
- Folder navigation — browse the full DAM folder tree with breadcrumb
- Asset preview panel — side panel with metadata, thumbnails, and video/audio playback
- Multi-select & select all — single or bulk selection with configurable max
- Keyboard navigation — arrow keys, Enter, Escape, Shift+click range select
- Marquee selection — click-and-drag to select multiple assets
- Approval workflow — filter by approval status, approver, requester, due date
- Regional variants — metadata variant groups with per-variant filtering
- Customisable theming — brand color config + 20 CSS custom properties
- Tiny footprint — ~70 KB gzipped (main chunk)
- A Scaleflex VXP DAM account with a project token
- Either a security template key or a SASS key for authentication
- Modern browser with Custom Elements v1 support (see Browser Support)
npm install @scaleflex/asset-pickeryarn add @scaleflex/asset-pickerpnpm add @scaleflex/asset-pickerlit is bundled with the package. For React usage, you also need react and react-dom (v18+) as peer dependencies.
No bundler? Add a single script tag:
<script src="https://cdn.scaleflex.com/asset-picker/0.2.17/asset-picker.min.js"></script>This auto-registers <sfx-asset-picker> — no imports needed. See the CDN quick start below.
| Export path | Description |
|---|---|
@scaleflex/asset-picker |
AssetPicker class + all TypeScript types + asset utility functions |
@scaleflex/asset-picker/react |
React wrapper component + AssetPickerProvider + useAssetPicker hook |
@scaleflex/asset-picker/define |
Side-effect import — registers <sfx-asset-picker> custom element |
Both ESM (import) and CJS (require) builds are provided.
<sfx-asset-picker></sfx-asset-picker>
<script type="module">
// 1. Register the custom element (once)
import '@scaleflex/asset-picker/define';
// 2. Grab the element
const picker = document.querySelector('sfx-asset-picker');
// 3. Configure
picker.config = {
auth: {
mode: 'securityTemplate',
securityTemplateKey: 'YOUR_KEY',
projectToken: 'YOUR_TOKEN',
},
};
// 4. Listen for events
picker.addEventListener('ap-select', (e) => {
console.log('Selected assets:', e.detail.assets);
});
picker.addEventListener('ap-cancel', (e) => {
console.log('Cancelled via:', e.detail.reason);
});
// 5. Open
picker.open();
</script>import { useRef } from 'react';
import { AssetPicker, type AssetPickerRef } from '@scaleflex/asset-picker/react';
function App() {
const pickerRef = useRef<AssetPickerRef>(null);
return (
<>
<button onClick={() => pickerRef.current?.open()}>
Pick assets
</button>
<AssetPicker
ref={pickerRef}
config={{
auth: {
mode: 'securityTemplate',
securityTemplateKey: 'YOUR_KEY',
projectToken: 'YOUR_TOKEN',
},
}}
onSelect={(assets) => console.log(assets)}
onCancel={() => console.log('Cancelled')}
/>
</>
);
}<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.scaleflex.com/asset-picker/0.2.17/asset-picker.min.js"></script>
</head>
<body>
<sfx-asset-picker></sfx-asset-picker>
<button onclick="document.querySelector('sfx-asset-picker').open()">Open Picker</button>
<script>
const picker = document.querySelector('sfx-asset-picker');
picker.config = {
auth: {
mode: 'securityTemplate',
securityTemplateKey: 'YOUR_KEY',
projectToken: 'YOUR_TOKEN',
},
};
picker.addEventListener('ap-select', (e) => {
console.log('Selected:', e.detail.assets);
});
</script>
</body>
</html>The picker supports two authentication modes:
Use for client-side integrations. The picker automatically exchanges the security template key for a SASS key on init.
{
auth: {
mode: 'securityTemplate',
securityTemplateKey: string, // Exchanged for a SASS key via API
projectToken: string,
}
}Use when your application already has a SASS key — e.g. inside the Scaleflex Hub where the host app manages SASS key generation and renewal.
{
auth: {
mode: 'sassKey',
sassKey: string, // X-Filerobot-Key
projectToken: string,
}
}| Property | Type | Default | Description |
|---|---|---|---|
auth |
AuthConfig |
required | Authentication credentials (see above) |
apiBase |
string |
auto | Override the API base URL |
locale |
string |
undefined |
Locale for translations |
multiSelect |
boolean |
true |
Enable multi-asset selection |
maxSelections |
number |
undefined |
Maximum number of selectable assets |
defaultViewMode |
'grid' | 'list' |
'grid' |
Initial view mode |
defaultSortBy |
SortBy |
'created_at' |
Initial sort field (see table below) |
defaultSortDirection |
'asc' | 'desc' |
'desc' |
Initial sort direction |
tabs |
TabKey[] |
['assets', 'folders'] |
Tabs to show. If only one, the dropdown is hidden |
defaultTab |
TabKey |
first in tabs |
Which tab to activate when the picker opens |
enabledFilters |
FilterKey[] |
all | Restrict which filters appear in the toolbar |
rootFolderPath |
string |
'/' |
Start browsing from a specific folder path (e.g. '/marketing/banners/') |
showMetadata |
boolean |
true |
Show metadata sections in the preview panel |
brandColor |
string |
from API | Brand accent colour as hex (e.g. '#3b82f6'). Overrides the API-fetched value |
rememberLastFolder |
boolean |
false |
Persist the last browsed folder and restore on next open |
rememberLastView |
boolean |
false |
Persist the last used view mode (grid/list) and restore on next open |
rememberLastTab |
boolean |
false |
Persist the last active tab (assets/folders) and restore on next open |
defaultFilters |
FiltersInput |
undefined |
Filters pre-applied on open. User can modify/remove |
forcedFilters |
FiltersInput |
undefined |
Filters always active. Shown as locked chips the user cannot remove |
displayMode |
'modal' | 'inline' |
'modal' |
'modal' renders as a dialog overlay, 'inline' renders in page flow |
gridSize |
'normal' | 'large' |
'normal' |
Grid card density: 'normal' (4 cols at ~1200px) or 'large' (3 cols) |
stickyFilters |
boolean |
false |
Make the toolbar and filters bar sticky while scrolling content |
folderSelection |
boolean |
true |
Allow selecting folders via checkboxes |
folderSelectionMode |
'folder' | 'assets' |
'folder' |
'folder' returns Folder objects; 'assets' fetches folder contents and returns only Assets |
uploader |
UploaderIntegrationConfig |
undefined |
Enable integrated uploader. Adds an "Upload" button and drop zone. Requires @scaleflex/uploader |
onSelect |
(assets: Asset[], folders?: Folder[]) => void |
undefined |
Callback when assets are selected |
onCancel |
() => void |
undefined |
Callback when the picker is cancelled |
| Value | Available in |
|---|---|
'name' |
Assets, Folders |
'created_at' |
Assets, Folders |
'modified_at' |
Assets, Folders |
'size' |
Assets |
'type' |
Assets |
'relevance' |
Search results only |
'title' |
Assets |
'color' |
Assets |
'uploaded' |
Assets |
'updated_at' |
Assets |
'files_count_recursive' |
Folders only |
'files_size_recursive' |
Folders only |
You can pre-configure filters that are applied when the picker opens, and/or lock filters that the user cannot remove.
picker.config = {
auth: { /* ... */ },
// Pre-applied on open — user can modify or remove
defaultFilters: {
type: { type: 'string', values: ['image'] },
},
// Always active — locked chip with lock icon, cannot be removed
forcedFilters: {
tags: { type: 'string', values: ['approved'] },
},
};// Lock to specific extensions using subtype values (category_extension)
forcedFilters: {
type: { values: ['image_svg', 'image_png'] },
},Behaviour:
defaultFiltersare seeded into the applied filters state whenopen()is called. The user sees them as normal filter chips and can modify or remove them freely.forcedFiltersare merged into every API request but are not stored in the mutable applied state. They render as locked chips (with a lock icon instead of an X button). The user cannot remove them, and "Clear filters" does not affect them. Forced filter keys are also hidden from the "Add filter" dropdown.- If the same key appears in both
defaultFiltersandforcedFilters, the forced filter takes precedence — the default filter for that key is skipped.
| Method | Returns | Description |
|---|---|---|
open() |
Promise<void> |
Opens the picker modal. Initialises the API client and loads initial data if not already done. Fires ap-open on success. |
close() |
void |
Closes the picker modal and clears the selection state. |
// Open the picker
await picker.open();
// Close programmatically
picker.close();All events bubble and cross shadow DOM boundaries (composed: true).
| Event | Detail | Description |
|---|---|---|
ap-select |
{ assets: Asset[] } |
Fired when the user confirms their selection |
ap-cancel |
{ reason: 'backdrop' | 'escape' | 'button' } |
Fired when the picker is closed without selecting |
ap-open |
{ timestamp: number } |
Fired when the picker opens successfully |
ap-error |
{ error: Error, context: string } |
Fired on initialisation or runtime errors |
picker.addEventListener('ap-select', (e) => {
const { assets } = e.detail;
assets.forEach((asset) => {
console.log(asset.name, asset.url?.cdn);
});
});
picker.addEventListener('ap-cancel', (e) => {
console.log('Cancelled via:', e.detail.reason);
});
picker.addEventListener('ap-error', (e) => {
console.error(`[${e.detail.context}]`, e.detail.error);
});import { AssetPicker, type AssetPickerRef, type AssetPickerProps } from '@scaleflex/asset-picker/react';| Prop | Type | Description |
|---|---|---|
config |
AssetPickerConfig |
Configuration object (see Config Options) |
open |
boolean |
Controlled open state |
onSelect |
(assets: Asset[], folders?: Folder[]) => void |
Selection callback (assets + optional folders) |
onSelectWithFolders |
(result: { assets: Asset[]; folders: Folder[] }) => void |
Alternative callback that always includes folders |
onCancel |
() => void |
Cancel callback |
className |
string |
CSS class for the wrapper |
style |
CSSProperties |
Inline styles for the wrapper |
| Method | Description |
|---|---|
open() |
Open the picker imperatively |
close() |
Close the picker imperatively |
const [isOpen, setIsOpen] = useState(false);
<AssetPicker
config={config}
open={isOpen}
onSelect={(assets) => {
console.log(assets);
setIsOpen(false);
}}
onCancel={() => setIsOpen(false)}
/>const ref = useRef<AssetPickerRef>(null);
<button onClick={() => ref.current?.open()}>Open</button>
<AssetPicker ref={ref} config={config} onSelect={handleSelect} />For apps that open the picker from many places, use AssetPickerProvider + useAssetPicker() to avoid managing open/close state yourself. One picker instance is mounted at the root and shared across the tree.
import { AssetPickerProvider } from '@scaleflex/asset-picker/react';
function App() {
return (
<AssetPickerProvider
config={{
auth: {
mode: 'sassKey',
sassKey: 'YOUR_SASS_KEY',
projectToken: 'YOUR_TOKEN',
},
}}
>
<Dashboard />
</AssetPickerProvider>
);
}import { useAssetPicker } from '@scaleflex/asset-picker/react';
function ImageSelector() {
const picker = useAssetPicker();
const handleClick = async () => {
try {
const assets = await picker.open({ multiSelect: true });
console.log('Selected:', assets);
} catch {
console.log('User cancelled');
}
};
return <button onClick={handleClick}>Choose images</button>;
}The promise resolves with the selected Asset[] on confirm, and rejects with 'cancelled' when the user closes without selecting. Note: promise mode returns only assets — use callback mode with onSelect(assets, folders) if you need folder data.
function VideoSelector() {
const picker = useAssetPicker();
return (
<button
onClick={() =>
picker.open({
forcedFilters: { type: { values: ['video'] } },
onSelect: (assets) => console.log(assets),
onCancel: () => console.log('Cancelled'),
})
}
>
Choose video
</button>
);
}Any AssetPickerConfig property passed to open() is merged with (and overrides) the base config from the provider:
// Base config has multiSelect: false
// This call overrides it to true and adds a forced filter
const assets = await picker.open({
multiSelect: true,
forcedFilters: { type: { values: ['image'] } },
});interface UseAssetPickerReturn {
open(overrides?: OpenOptions): Promise<Asset[]>;
close(): void;
isOpen: boolean;
}Pure helper functions for working with Asset objects. Exported from the main entry point — no React required.
import {
getAltText,
getCdnUrl,
getAssetWidth,
getAssetHeight,
getAssetDimensions,
isTranscoded,
getTranscodedUrl,
getBestVideoUrl,
isVideo,
isImage,
isAudio,
} from '@scaleflex/asset-picker';| Function | Returns | Description |
|---|---|---|
isImage(asset) |
boolean |
true if asset.type starts with "image" |
isVideo(asset) |
boolean |
true if asset.type starts with "video" |
isAudio(asset) |
boolean |
true if asset.type starts with "audio" |
| Function | Returns | Description |
|---|---|---|
getCdnUrl(asset) |
string |
CDN URL, falling back to public URL, then "" |
getBestVideoUrl(asset) |
string |
Transcoded HLS URL > CDN URL > public URL |
getTranscodedUrl(asset) |
string | null |
HLS manifest URL, or null if not transcoded |
const alt = getAltText(asset); // uses first available language
const alt = getAltText(asset, 'fr'); // prefers French titleResolution priority: meta.alt > meta.title (string or localized Record<string, string>) > filename without extension.
| Function | Returns | Description |
|---|---|---|
getAssetWidth(asset) |
number |
Width in px (0 if unknown). Works for images and videos. |
getAssetHeight(asset) |
number |
Height in px (0 if unknown). Works for images and videos. |
getAssetDimensions(asset) |
{ width, height } |
Both dimensions as an object. |
| Function | Returns | Description |
|---|---|---|
isTranscoded(asset) |
boolean |
Whether the asset has a transcoded HLS version |
getTranscodedUrl(asset) |
string | null |
The HLS manifest URL, or null |
getBestVideoUrl(asset) |
string |
Best playback URL (transcoded > CDN > public) |
The simplest way to theme the picker is via the brandColor config option. It accepts a hex colour string and applies it as the primary accent across all UI elements.
picker.config = {
auth: { /* ... */ },
brandColor: '#6366f1', // Indigo
};If not set, the picker uses the brand colour configured in your Scaleflex project settings.
For fine-grained control, override these CSS custom properties on the <sfx-asset-picker> element or any ancestor. All variables use the --ap- prefix.
| Property | Default | Description |
|---|---|---|
--ap-primary |
oklch(0.65 0.19 258) |
Primary accent colour |
--ap-primary-foreground |
#fff |
Text on primary backgrounds |
--ap-primary-10 |
primary @ 10% | Subtle primary tint |
--ap-primary-20 |
primary @ 20% | Light primary background |
--ap-background |
#ffffff |
Main background |
--ap-foreground |
#09090b |
Main text colour |
--ap-card |
#ffffff |
Card/panel background |
--ap-border |
#e4e4e7 |
Border colour |
--ap-muted |
#f4f4f5 |
Muted/disabled background |
--ap-muted-foreground |
#71717a |
Muted/disabled text |
--ap-ring |
same as primary | Focus ring colour |
--ap-selection-bg |
primary @ 8% | Selected item background |
| Property | Default | Description |
|---|---|---|
--ap-modal-backdrop |
rgba(0,0,0,0.5) |
Backdrop overlay colour |
--ap-modal-radius |
12px |
Modal corner radius |
--ap-modal-shadow |
large shadow | Modal box shadow |
--ap-modal-max-width |
1200px |
Maximum modal width |
--ap-modal-max-height |
85vh |
Maximum modal height |
| Property | Default | Description |
|---|---|---|
--ap-font-family |
system-ui, -apple-system, sans-serif |
Font stack |
--ap-radius |
8px |
Default border radius |
--ap-radius-sm |
6px |
Small border radius |
--ap-radius-lg |
12px |
Large border radius |
asset-picker {
--ap-primary: #6366f1;
--ap-primary-foreground: #fff;
--ap-radius: 12px;
--ap-modal-max-width: 1400px;
}These are the keys used in enabledFilters, defaultFilters, and forcedFilters.
| Key | Constant | Description |
|---|---|---|
'type' |
FILTER_KEYS.TYPE |
File format (image, video, audio, document, archive, font) |
'mimetype' |
FILTER_KEYS.MIME_TYPE |
MIME type |
'date' |
FILTER_KEYS.DATE |
Upload/modification date |
'size' |
FILTER_KEYS.SIZE |
File size range |
'tags' |
FILTER_KEYS.TAGS |
Asset tags |
'labels' |
FILTER_KEYS.LABELS |
Asset labels |
'color' |
FILTER_KEYS.COLOR |
Dominant colour search |
'image' |
FILTER_KEYS.IMAGE |
Image-specific (resolution, orientation, faces) |
'approval' |
FILTER_KEYS.APPROVAL |
Approval workflow status |
'metadata' |
FILTER_KEYS.METADATA |
Custom metadata fields |
'product_ref' |
FILTER_KEYS.PRODUCT_REF |
Product reference |
'asset_expiration' |
FILTER_KEYS.LICENSE_EXPIRY |
License/asset expiry date |
'folders' |
FILTER_KEYS.FOLDERS |
Folder location |
'resolution' |
FILTER_KEYS.RESOLUTION |
Image resolution |
'orientation' |
FILTER_KEYS.ORIENTATION |
Image orientation |
'faces' |
FILTER_KEYS.FACES |
Detected faces count |
'products' |
FILTER_KEYS.PRODUCTS |
Products |
Filters used in defaultFilters and forcedFilters use these shapes:
{
type: 'string',
values: string[], // Filter values
operator?: string, // Filter operator (default: ':')
logic?: 'OR' | 'AND', // Combine logic (default: 'OR')
}Examples:
// Only images
{ type: 'string', values: ['image'] }
// Only JPEG and PNG
{ type: 'string', values: ['image/jpeg', 'image/png'] }
// Tagged with "hero" or "banner"
{ type: 'string', values: ['hero', 'banner'] }
// Size range: 1 MB to 50 MB (values in bytes as "min..max")
{ type: 'string', values: ['1000000..50000000'] }{
type: 'date',
field: 'created' | 'updated',
kind: 'preset' | 'after' | 'before' | 'between' | 'specific' | null,
preset: string | null, // e.g. 'today', 'last_week', 'last_month'
from: string | null, // ISO date string
to: string | null, // ISO date string
}Examples:
// Uploaded in the last month
{
type: 'date',
field: 'created',
kind: 'preset',
preset: 'last_month',
from: null,
to: null,
}
// Modified after a specific date
{
type: 'date',
field: 'updated',
kind: 'after',
preset: null,
from: '2025-01-01T00:00:00.000Z',
to: null,
}Available date presets: 'today', 'last_week', 'within_week', 'last_month', 'within_month', 'last_year', 'within_year', 'empty', 'non-empty'
| Operator | Symbol | Description |
|---|---|---|
IS |
: |
Exact match (default) |
EQUAL |
= |
Equality |
NOT_EQUAL |
!= |
Inequality |
RANGE |
.. |
Range match |
IS_NOT |
:- |
Negated match |
IS_EXACT |
:= |
Strict exact match |
CONTAINS |
~ |
Contains substring |
CONTAINS_IN_TEXT |
~~~ |
Full text search |
STARTS_WITH |
~^ |
Starts with |
GREATER_THAN |
> |
Greater than |
LESS_THAN |
< |
Less than |
GREATER_THAN_OR_EQUAL |
>= |
Greater than or equal |
LESS_THAN_OR_EQUAL |
<= |
Less than or equal |
SIMILAR_TO |
~~ |
Similarity match |
All types are exported from the main entry point:
import type {
AssetPickerConfig,
AuthConfig,
SecurityTemplateAuth,
SassKeyAuth,
Asset,
Folder,
FilterKey,
AnyFilterKey,
AnyFilter,
StringFilter,
DateFilter,
Filters,
FiltersState,
ViewMode,
SortBy,
SortDirection,
TabKey,
AssetPickerSelectDetail,
AssetPickerCancelDetail,
} from '@scaleflex/asset-picker';The Asset object returned in ap-select events:
interface Asset {
uuid: string;
name: string;
extension: string;
type: string; // 'image', 'video', 'audio', 'document', ...
mime?: string; // MIME type
size: {
bytes: number;
pretty: string;
};
url?: {
public: string; // Public URL
cdn: string; // CDN-optimised URL
path: string; // Relative path
permalink?: string; // Permanent link
};
created_at: string; // ISO timestamp
modified_at: string; // ISO timestamp
tags: Record<string, Array<{ label: string; sid: string }>>
| Record<string, { label: string; sid: string }>
| string[];
labels: string[];
meta: {
title?: string | Record<string, string>; // plain or localized by language code
description?: string;
alt?: string;
[key: string]: unknown;
};
info: {
img_type?: string; // Image format (e.g. "jpeg", "png")
img_w?: number; // Image width (px)
img_h?: number; // Image height (px)
duration?: number; // Audio duration (seconds)
video_duration?: number; // Video duration (seconds)
video_w?: number; // Video width (px)
video_h?: number; // Video height (px)
thumbnail?: string; // Thumbnail URL
preview?: string; // Preview URL
video_thumbnail?: string; // Video poster image URL
video_gif?: string; // Animated GIF preview URL
image_thumbnail?: string; // Image thumbnail URL
main_colors?: string[]; // Dominant colours (names)
main_colors_hex?: string[]; // Dominant colours (hex)
dominant_color?: string; // Most dominant colour (name)
dominant_color_hex?: string; // Most dominant colour (hex)
color_space?: string; // Colour space (e.g. "sRGB")
metadata?: Record<string, unknown>; // Embedded metadata (EXIF, IPTC, etc.)
playlists?: Array<{ playlists: string[]; resolution?: string }>; // HLS transcoded playlists
};
folder?: {
uuid: string;
name: string;
};
owner?: {
uuid: string;
name: string;
email: string;
};
}interface Folder {
uuid: string;
name: string;
path: string;
owner?: string;
created_at: string;
modified_at?: string;
updated_at?: string;
count?: {
files_recursive?: number;
files_direct?: number;
};
size?: {
total_recursive_bytes?: number;
};
visibility?: {
in_cdn?: { actual: string; set: string };
in_dam?: { actual: string; set: string };
};
}| Browser | Minimum version |
|---|---|
| Chrome | 67+ |
| Firefox | 63+ |
| Safari | 13.1+ |
| Edge (Chromium) | 79+ |
Requires native support for Custom Elements v1, Shadow DOM, and ES2020+. Internet Explorer is not supported.
npm run release # patch bump (0.2.8 → 0.2.9)
npm run release -- minor # minor bump (0.2.8 → 0.3.0)
npm run release -- major # major bump (0.2.8 → 1.0.0)This single command handles the full pipeline: version bump, CDN build + upload, library build, npm publish, git commit + tag + push.
If you use Claude Code, this package ships with a ready-made skill that helps Claude add the asset picker to your project — detecting your framework, wiring auth, events, theming, and filters automatically.
Copy the skill into your project so every team member who uses Claude Code gets it:
mkdir -p .claude/skills/integrate-asset-picker
cp node_modules/@scaleflex/asset-picker/.claude/skills/integrate-asset-picker/SKILL.md \
.claude/skills/integrate-asset-picker/SKILL.mdCommit the .claude/skills/ directory to version control. The skill is now available to everyone on the team.
Install it once for all your projects:
mkdir -p ~/.claude/skills/integrate-asset-picker
cp node_modules/@scaleflex/asset-picker/.claude/skills/integrate-asset-picker/SKILL.md \
~/.claude/skills/integrate-asset-picker/SKILL.mdType /integrate-asset-picker in Claude Code and it will walk you through the full integration — install, config, events, and theming — tailored to your stack (React, Vue, vanilla JS, etc.).
PROPRIETARY — All Rights Reserved.
Copyright © 2025 Scaleflex SAS.
This software and associated documentation are the exclusive property of Scaleflex SAS. No part of this software may be copied, modified, distributed, sublicensed, sold, or otherwise made available to any third party without prior written permission from Scaleflex SAS.
This package is distributed via npm solely for the convenience of licensed customers. Installing or using this package does not grant any licence to use the software. Use is permitted only under a separate written licence agreement with Scaleflex SAS.
Unauthorised use, reproduction, or distribution of this software may result in civil and criminal penalties and will be prosecuted to the maximum extent permitted by law.
For licensing enquiries, contact sales@scaleflex.com.
Made with care by Scaleflex