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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@tradly/asset

v1.0.5

Published

A reusable media gallery component for uploading and selecting images, videos, and files with Tradly authentication

Readme

@tradly/asset

A reusable React component package for uploading and selecting media (images, videos, files) with Tradly authentication support.

Features

  • 📸 Upload and browse images
  • 🎥 Upload and browse videos
  • 📁 Upload and browse files
  • 🔐 Tradly authentication support
  • 🎨 Customizable UI
  • 📱 Responsive design
  • 🔄 Pagination support
  • ⚡ Lightweight and performant

Installation

npm install @tradly/asset
# or
yarn add @tradly/asset

Peer Dependencies

This package requires the following peer dependencies:

  • react (>=16.8.0)
  • react-dom (>=16.8.0)
  • @headlessui/react (^1.7.0) - for Tab components
  • axios (^0.24.0) - for API calls

Note:

  • All pagination logic is built-in, no external pagination library needed!
  • No Tradly SDK dependency - uses direct API calls

Basic Usage

import React, { useState } from "react";
import { MediaPopup, MediaApiService } from "@tradly/asset";

function MyComponent() {
	const [isOpen, setIsOpen] = useState(false);
	const [selectedMedia, setSelectedMedia] = useState(null);

	// Initialize API service with your auth key
	// API base URL is automatically detected from ENVIRONMENT:
	// - Dev: https://api.dev.tradly.app
	// - Prod: https://api.tradly.app
	const apiService = new MediaApiService({
		authKey: "your-tradly-auth-key", // Required: X-Auth-Key header
		bearerToken: "your-bearer-token", // Required: Bearer token for Authorization header
		// environment is auto-detected from process.env.ENVIRONMENT
		// apiBaseUrl is auto-set based on environment (can be overridden)
	});

	const handleSelect = (mediaUrl) => {
		setSelectedMedia(mediaUrl);
		setIsOpen(false);
	};

	return (
		<>
			<button onClick={() => setIsOpen(true)}>
				Open Media Gallery
			</button>

			<MediaPopup
				isOpen={isOpen}
				onClose={() => setIsOpen(false)}
				onSelect={handleSelect}
				options={["image", "video"]} // Options: 'image', 'video', 'file'
				apiService={apiService}
			/>
		</>
	);
}

Advanced Usage

Upload Functionality

The package includes complete upload functionality using direct API calls. All upload logic is handled internally:

  1. Get S3 signed URLs via API call to /v1/utils/S3signedUploadURL
  2. Upload files to S3 using the signed URLs
  3. Save media metadata to your API

Configuration:

import { MediaApiService } from "@tradly/asset";

const apiService = new MediaApiService({
	authKey: "your-auth-key", // Required: X-Auth-Key header
	bearerToken: "your-bearer-token", // Required: Bearer token for Authorization header
	environment: "dev", // Optional: 'dev' or 'production' (auto-detected from process.env.ENVIRONMENT)
	apiBaseUrl: "https://api.tradly.app", // Optional: Override auto-detected base URL
});

API Base URL Auto-Detection:

  • If environment includes 'dev' → https://api.dev.tradly.app
  • Otherwise → https://api.tradly.app
  • You can override by providing apiBaseUrl explicitly

Using Individual Components

You can also use the components individually:

import { ImagesGallery, MediaApiService } from "@tradly/asset";

function CustomGallery() {
	const apiService = new MediaApiService({
		authKey: "your-auth-key",
		baseUrl: "/api",
	});

	return (
		<ImagesGallery
			update_data={(url) => console.log("Selected:", url)}
			closePopup={() => console.log("Closed")}
			apiService={apiService}
		/>
	);
}

Error Handling

<MediaPopup
	isOpen={isOpen}
	onClose={() => setIsOpen(false)}
	onSelect={handleSelect}
	apiService={apiService}
	onError={(error) => {
		console.error("Media gallery error:", error);
		// Handle error (show toast, etc.)
	}}
/>

API Service Configuration

MediaApiService Options

const apiService = new MediaApiService({
	authKey: "string", // Required: Authentication key for X-Auth-Key header
	bearerToken: "string", // Required: Bearer token for Authorization header
	environment: "string", // Optional: 'dev' or 'production' (auto-detected from process.env.ENVIRONMENT)
	apiBaseUrl: "string", // Optional: Override auto-detected base URL (defaults: https://api.dev.tradly.app for dev, https://api.tradly.app for prod)
	onError: (error) => {}, // Optional: Global error handler
});

Methods

// Update auth key
apiService.setAuthKey("new-auth-key");

// Update API base URL (used for all API calls)
apiService.setApiBaseUrl("https://api.tradly.app");

// Set Bearer token
apiService.setBearerToken("new-bearer-token");

Props

MediaPopup Props

| Prop | Type | Default | Description | | ------------- | ----------------- | ----------------- | --------------------------------------------------- | | isOpen | boolean | false | Controls popup visibility | | onClose | function | - | Callback when popup closes | | onSelect | function | - | Callback when media is selected | | currentData | any | - | Currently selected media data | | options | array | ['image'] | Media types to show: 'image', 'video', 'file' | | apiService | MediaApiService | - | Required: API service instance | | onError | function | - | Error handler callback | | title | string | 'Media Gallery' | Popup title |

Styling

This package uses Tailwind CSS classes and supports full customization at every component level. All components accept className props that allow you to override default styles.

Quick Customization Example

<MediaPopup
	isOpen={isOpen}
	onClose={() => setIsOpen(false)}
	onSelect={handleSelect}
	apiService={apiService}
	// Customize popup
	overlayClassName="bg-black/60 backdrop-blur-sm"
	containerClassName="max-w-4xl bg-gray-900 rounded-xl"
	titleClassName="text-2xl font-bold text-white"
	// Customize tabs
	tabButtonActiveClassName="text-blue-400 border-b-2 border-blue-400"
	// Customize gallery
	gridClassName="grid grid-cols-4 gap-4"
	imageItemClassName="rounded-lg border-2 hover:border-blue-500"
/>

Available Styling Props

MediaPopup:

  • overlayClassName - Overlay/backdrop
  • containerClassName - Main popup container
  • headerClassName - Header container
  • titleClassName - Title text
  • closeButtonClassName - Close button
  • tabListClassName - Tab list (passed to MediaTab)
  • tabButtonClassName - Base tab button
  • tabButtonActiveClassName - Active tab button
  • tabButtonInactiveClassName - Inactive tab button
  • gridClassName - Media grid layout
  • imageItemClassName - Image item styles
  • videoItemClassName - Video item styles
  • paginationContainerClassName - Pagination container

Individual Components: You can also style individual components when using them separately. See STYLING_GUIDE.md for complete documentation.

Full Styling Guide

For detailed styling documentation with examples, see STYLING_GUIDE.md.

Examples

Image Only Gallery

<MediaPopup
	isOpen={isOpen}
	onClose={() => setIsOpen(false)}
	onSelect={handleSelect}
	options={["image"]}
	apiService={apiService}
/>

Video Only Gallery

<MediaPopup
	isOpen={isOpen}
	onClose={() => setIsOpen(false)}
	onSelect={handleSelect}
	options={["video"]}
	apiService={apiService}
/>

All Media Types

<MediaPopup
	isOpen={isOpen}
	onClose={() => setIsOpen(false)}
	onSelect={handleSelect}
	options={["image", "video", "file"]}
	apiService={apiService}
/>

Development

To develop or modify this package:

cd packages/asset
npm install
npm run dev

License

MIT

Support

For issues and questions, please open an issue on the repository.