@djangocfg/ui-tools
v2.1.118
Published
Heavy React tools with lazy loading - for Electron, Vite, CRA, Next.js apps
Maintainers
Readme
@djangocfg/ui-tools
Heavy React tools with lazy loading (React.lazy + Suspense).
No Next.js dependencies — works with Electron, Vite, CRA, and any React environment.
Part of DjangoCFG — modern Django framework for production-ready SaaS applications.
Install
pnpm add @djangocfg/ui-toolsWhy ui-tools?
This package contains heavy components that are loaded lazily to keep your initial bundle small. Each tool is loaded only when used.
| Package | Use Case |
|---------|----------|
| @djangocfg/ui-core | Lightweight UI components (60+ components) |
| @djangocfg/ui-tools | Heavy tools with lazy loading |
| @djangocfg/ui-nextjs | Next.js apps (extends ui-core) |
Tools (11)
| Tool | Bundle Size | Description |
|------|-------------|-------------|
| Gallery | ~50KB | Image/video gallery with carousel, grid, lightbox |
| Map | ~800KB | MapLibre GL maps with markers, clusters, layers |
| Mermaid | ~800KB | Diagram rendering |
| PrettyCode | ~500KB | Code syntax highlighting |
| OpenapiViewer | ~400KB | OpenAPI schema viewer & playground |
| JsonForm | ~300KB | JSON Schema form generator |
| LottiePlayer | ~200KB | Lottie animation player |
| AudioPlayer | ~200KB | Audio player with WaveSurfer.js |
| VideoPlayer | ~150KB | Professional video player with Vidstack |
| JsonTree | ~100KB | JSON visualization |
| ImageViewer | ~50KB | Image viewer with zoom/pan/rotate |
Tree-Shakeable Imports
For better bundle optimization, use subpath imports:
// Only loads Gallery (~50KB instead of full package)
import { Gallery, GalleryLightbox } from '@djangocfg/ui-tools/gallery';
// Only loads Map (~800KB)
import { MapContainer, MapMarker } from '@djangocfg/ui-tools/map';Gallery
Full-featured image/video gallery with carousel, grid view, and fullscreen lightbox.
import { Gallery } from '@djangocfg/ui-tools/gallery';
const images = [
{ id: '1', src: '/photo1.jpg', alt: 'Photo 1' },
{ id: '2', src: '/photo2.jpg', alt: 'Photo 2' },
{ id: '3', src: '/video.mp4', alt: 'Video', type: 'video' },
];
function PhotoGallery() {
return (
<Gallery
images={images}
previewMode="carousel" // or "grid"
showThumbnails
enableLightbox
aspectRatio={16 / 9}
/>
);
}Gallery Components
| Component | Description |
|-----------|-------------|
| Gallery | Complete gallery with carousel/grid + lightbox |
| GalleryCompact | Minimal carousel for cards |
| GalleryGrid | Grid layout with "show more" badge |
| GalleryLightbox | Fullscreen lightbox viewer |
| GalleryCarousel | Embla-based carousel |
| GalleryThumbnails | Thumbnail strip navigation |
Gallery Hooks
| Hook | Description |
|------|-------------|
| useGallery | Gallery state management |
| useSwipe | Touch swipe gestures |
| usePinchZoom | Pinch-to-zoom for mobile |
| usePreloadImages | Image preloading |
Map
MapLibre GL maps with React components for markers, clusters, popups, and custom layers.
import { MapContainer, MapMarker, MapPopup } from '@djangocfg/ui-tools/map';
const markers = [
{ id: '1', lat: 37.7749, lng: -122.4194, title: 'San Francisco' },
{ id: '2', lat: 34.0522, lng: -118.2437, title: 'Los Angeles' },
];
function LocationMap() {
return (
<MapContainer
initialViewport={{ latitude: 36, longitude: -119, zoom: 5 }}
style="streets"
>
{markers.map((m) => (
<MapMarker key={m.id} latitude={m.lat} longitude={m.lng}>
<MapPopup>{m.title}</MapPopup>
</MapMarker>
))}
</MapContainer>
);
}Map Components
| Component | Description |
|-----------|-------------|
| MapContainer | Main map container with controls |
| MapMarker | Custom marker with React children |
| MapPopup | Popup attached to marker |
| MapCluster | Clustered markers |
| MapSource / MapLayer | Custom GeoJSON layers |
| MapControls | Navigation controls |
| MapLegend | Map legend component |
| LayerSwitcher | Toggle map layers |
| DrawControl | Drawing tools (optional) |
| GeocoderControl | Search/geocoding (optional) |
Map Hooks
| Hook | Description |
|------|-------------|
| useMap | Access map instance |
| useMapControl | Programmatic map control |
| useMarkers | Marker management |
| useMapEvents | Map event handlers |
| useMapViewport | Viewport state |
| useMapLayers | Layer management |
Map Styles
import { MAP_STYLES, getMapStyle } from '@djangocfg/ui-tools/map';
// Available styles: streets, satellite, dark, light, terrain
<MapContainer style="dark" />Layer Utilities
import {
createClusterLayers,
createPointLayer,
createPolygonLayer,
createLineLayer,
} from '@djangocfg/ui-tools/map';Video Player
import { VideoPlayer } from '@djangocfg/ui-tools';
<VideoPlayer
src="https://example.com/video.mp4"
poster="/thumbnail.jpg"
autoplay={false}
/>Audio Player
import { HybridAudioPlayer } from '@djangocfg/ui-tools';
<HybridAudioPlayer
src="https://example.com/audio.mp3"
showWaveform
/>Mermaid Diagrams
import { Mermaid } from '@djangocfg/ui-tools';
<Mermaid chart={`
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[Action]
B -->|No| D[End]
`} />Code Highlighting
import { PrettyCode } from '@djangocfg/ui-tools';
<PrettyCode
code={`const hello = "world";`}
language="typescript"
/>JSON Form
import { JsonSchemaForm } from '@djangocfg/ui-tools';
const schema = {
type: 'object',
properties: {
name: { type: 'string', title: 'Name' },
email: { type: 'string', format: 'email', title: 'Email' },
},
};
<JsonSchemaForm
schema={schema}
onSubmit={(data) => console.log(data)}
/>Components
| Component | Description |
|-----------|-------------|
| Markdown | Markdown renderer with GFM support |
Stores
| Store | Description |
|-------|-------------|
| useMediaCacheStore | Media caching for video/audio players |
Lazy Loading
All heavy tools have unified lazy-loaded versions with built-in Suspense fallbacks:
import {
LazyMapContainer, // ~800KB
LazyMermaid, // ~800KB
LazyPrettyCode, // ~500KB
LazyOpenapiViewer, // ~400KB
LazyJsonSchemaForm, // ~300KB
LazyLottiePlayer, // ~200KB
LazyHybridAudioPlayer, // ~200KB
LazyVideoPlayer, // ~150KB
LazyJsonTree, // ~100KB
LazyImageViewer, // ~50KB
} from '@djangocfg/ui-tools';
// Just use them - no Suspense wrapper needed!
<LazyMermaid chart={diagram} />
<LazyMapContainer initialViewport={viewport} />
<LazyVideoPlayer src="/video.mp4" />Custom Lazy Components
Create your own lazy components with createLazyComponent:
import { createLazyComponent, CardLoadingFallback } from '@djangocfg/ui-tools';
const LazyMyComponent = createLazyComponent(
() => import('./MyHeavyComponent'),
{
displayName: 'LazyMyComponent',
fallback: <CardLoadingFallback title="Loading..." minHeight={200} />,
}
);Loading Fallbacks
Built-in fallback components for different use cases:
| Component | Use Case |
|-----------|----------|
| LoadingFallback | Generic spinner with optional text |
| CardLoadingFallback | Card-styled loading with title |
| MapLoadingFallback | Map-specific with location icon |
| Spinner | Simple spinning loader |
| LazyWrapper | Suspense wrapper with configurable fallback |
Requirements
- React >= 18 or >= 19
- Tailwind CSS >= 4
- Zustand >= 5
- @djangocfg/ui-core (peer dependency)
Optional Dependencies (for Map)
# For drawing tools
pnpm add @mapbox/mapbox-gl-draw
# For geocoding/search
pnpm add @maplibre/maplibre-gl-geocoderLicense
MIT
