Additional web components that provide specialized cropping interface elements including handles, grid overlays, crosshairs, shading, and viewer functionality.
Base class for all cropper web components, providing common functionality and styling capabilities.
/**
* Base class for all cropper web components
* Provides shadow DOM, styling, and common functionality for all cropper elements
*/
class CropperElement extends HTMLElement {
/**
* Element tag name (static property)
*/
static $name: string;
/**
* Version string (static property)
*/
static $version: string;
/**
* Shadow root mode ('open' or 'closed')
* @default 'open'
*/
shadowRootMode: ShadowRootMode;
/**
* Whether element supports slot content
* @default true
*/
slottable: boolean;
/**
* Theme color for the element
* @default '#39f'
*/
themeColor?: string;
/**
* Define the custom element
* @param name - Custom element name (optional)
* @param options - Element definition options (optional)
*/
static $define(name?: string, options?: ElementDefinitionOptions): void;
/**
* Get the shadow root for this element
* @returns The shadow root instance
*/
$getShadowRoot(): ShadowRoot;
/**
* Add styles to the element
* @param styles - CSS styles string
* @returns Style sheet or style element
*/
$addStyles(styles: string): CSSStyleSheet | HTMLStyleElement;
/**
* Emit a custom event
* @param type - Event type
* @param detail - Event detail data (optional)
* @param options - Event options (optional)
* @returns Whether the event was not cancelled
*/
$emit(type: string, detail?: unknown, options?: EventInit): boolean;
/**
* Defer execution to next DOM update cycle
* @param callback - Optional callback function
* @returns Promise that resolves after next DOM update
*/
$nextTick(callback?: Function): Promise<void>;
}Usage Examples:
// All cropper components extend CropperElement
const canvas = cropper.getCropperCanvas();
const image = cropper.getCropperImage();
const selection = cropper.getCropperSelection();
// Access base class functionality
console.log('Canvas version:', canvas.constructor.$version);
console.log('Image tag name:', image.constructor.$name);
// Use shadow root
const shadowRoot = canvas.$getShadowRoot();
console.log('Shadow root:', shadowRoot);
// Apply custom theming
canvas.themeColor = '#ff4444';
image.themeColor = '#00ff00';
selection.themeColor = '#0044ff';
// Emit custom events
canvas.$emit('custom-action', { action: 'crop', area: selection });
// Defer operations
await selection.$nextTick();
console.log('DOM updated');
// Add custom styles
const customStyles = `
:host {
border: 2px solid var(--theme-color);
border-radius: 4px;
}
`;
selection.$addStyles(customStyles);Interactive handle element for resize and manipulation controls.
/**
* Interactive handle element for resize and manipulation controls
* Provides visual handles for resizing selections and controlling image transformations
*/
class CropperHandle extends CropperElement {
/**
* Action type for this handle (move, n-resize, se-resize, etc.)
* @default ''
*/
action: string;
/**
* Whether to use plain styling without decorations
* @default false
*/
plain: boolean;
/**
* Theme color for the handle
* @default '#39f'
*/
themeColor: string;
}Usage Examples:
// Access handles from a selection
const selection = cropper.getCropperSelection();
const handles = selection.querySelectorAll('cropper-handle');
// Configure handle appearance
handles.forEach(handle => {
handle.themeColor = '#ff4444';
if (handle.action === 'move') {
handle.plain = true; // Simplify move handle appearance
}
});
// Create custom handle
const customHandle = document.createElement('cropper-handle');
customHandle.action = 'custom-action';
customHandle.themeColor = 'rgba(0, 255, 0, 0.8)';
selection.appendChild(customHandle);Grid overlay element that displays alignment guides within the selection area.
/**
* Grid overlay element for displaying alignment guides
* Shows a rule-of-thirds grid or custom grid layout within selections
*/
class CropperGrid extends CropperElement {
/**
* Whether to show borders around the grid
* @default false
*/
bordered: boolean;
/**
* Number of grid columns
* @default 3
*/
columns: number;
/**
* Whether the grid covers the entire selection area
* @default false
*/
covered: boolean;
/**
* Number of grid rows
* @default 3
*/
rows: number;
/**
* Theme color for the grid lines
* @default '#39f'
*/
themeColor: string;
}Usage Examples:
const selection = cropper.getCropperSelection();
const grid = selection.querySelector('cropper-grid');
// Configure grid appearance
grid.bordered = true; // Show borders
grid.covered = true; // Fill selection area
grid.themeColor = '#ffffff'; // White grid lines
// Custom grid layout
grid.columns = 4; // 4x4 grid instead of 3x3
grid.rows = 4;
// Create golden ratio grid
const goldenGrid = document.createElement('cropper-grid');
goldenGrid.columns = 2;
goldenGrid.rows = 2;
goldenGrid.bordered = true;
selection.appendChild(goldenGrid);Crosshair overlay element that displays center guides or cursor guides.
/**
* Crosshair overlay element for displaying center or cursor guides
* Shows horizontal and vertical lines to aid in precise positioning
*/
class CropperCrosshair extends CropperElement {
/**
* Whether to center the crosshair in the container
* @default false
*/
centered: boolean;
/**
* Theme color for the crosshair lines
* @default '#39f'
*/
themeColor: string;
}Usage Examples:
const selection = cropper.getCropperSelection();
const crosshair = selection.querySelector('cropper-crosshair');
// Configure crosshair
crosshair.centered = true; // Center in selection
crosshair.themeColor = '#ff0000'; // Red crosshair
// Create custom crosshair for image center
const imageCrosshair = document.createElement('cropper-crosshair');
imageCrosshair.centered = true;
imageCrosshair.themeColor = 'rgba(255, 255, 255, 0.7)';
const canvas = cropper.getCropperCanvas();
canvas.appendChild(imageCrosshair);Shade overlay element that darkens areas outside the selection.
/**
* Shade overlay element for darkening unselected areas
* Creates a semi-transparent overlay to highlight the selected region
*/
class CropperShade extends CropperElement {
/**
* X position of the shade area in pixels
* @default 0
*/
x: number;
/**
* Y position of the shade area in pixels
* @default 0
*/
y: number;
/**
* Width of the shade area in pixels
* @default 0
*/
width: number;
/**
* Height of the shade area in pixels
* @default 0
*/
height: number;
/**
* Theme color for the shade overlay
* @default '#39f'
*/
themeColor: string;
/**
* Change the shade area dimensions and position
* @param x - X position in pixels
* @param y - Y position in pixels
* @param width - Width in pixels (optional)
* @param height - Height in pixels (optional)
* @returns This instance for method chaining
*/
$change(x: number, y: number, width?: number, height?: number): this;
/**
* Reset the shade to initial state
* @returns This instance for method chaining
*/
$reset(): this;
/**
* Render/update the shade display
* @returns This instance for method chaining
*/
$render(): this;
}Usage Examples:
const canvas = cropper.getCropperCanvas();
const shade = canvas.querySelector('cropper-shade');
// Configure shade appearance
shade.themeColor = 'rgba(0, 0, 0, 0.6)'; // Semi-transparent black
// Manually control shade area
shade.$change(50, 30, 200, 150); // Set specific area
shade.$render(); // Update display
// Reset shade
shade.$reset();
// Create custom shade
const customShade = document.createElement('cropper-shade');
customShade.themeColor = 'rgba(128, 0, 0, 0.3)'; // Red tint
customShade.$change(0, 0, 300, 200);
canvas.appendChild(customShade);
// Sync shade with selection
const selection = cropper.getCropperSelection();
selection.addEventListener('change', () => {
shade.$change(selection.x, selection.y, selection.width, selection.height);
});Viewer element for displaying and controlling selection previews.
/**
* Viewer element for displaying selection previews
* Shows a live preview of the selected area with optional resize controls
*/
class CropperViewer extends CropperElement {
/**
* Resize behavior for the viewer
* @default 'none'
*/
resize: string;
/**
* CSS selector for the associated selection element
* @default ''
*/
selection: string;
}
// Resize mode constants
const RESIZE_BOTH: string; // 'both'
const RESIZE_HORIZONTAL: string; // 'horizontal'
const RESIZE_VERTICAL: string; // 'vertical'
const RESIZE_NONE: string; // 'none'Usage Examples:
// Create a viewer for a selection
const viewer = document.createElement('cropper-viewer');
viewer.selection = 'cropper-selection'; // Target first selection
viewer.resize = 'both'; // Allow resizing in both directions
document.body.appendChild(viewer);
// Configure resize behavior
viewer.resize = 'horizontal'; // Only horizontal resize
viewer.resize = 'vertical'; // Only vertical resize
viewer.resize = 'none'; // No resize controls
// Multiple viewers for multiple selections
const selections = cropper.getCropperSelections();
if (selections) {
Array.from(selections).forEach((selection, index) => {
const viewer = document.createElement('cropper-viewer');
viewer.selection = `cropper-selection:nth-child(${index + 1})`;
viewer.resize = 'both';
// Add to a viewer container
document.querySelector('#viewers').appendChild(viewer);
});
}
// Viewer with specific selection reference
const specificViewer = document.createElement('cropper-viewer');
specificViewer.selection = '#my-selection'; // Target by ID
specificViewer.resize = RESIZE_BOTH; // Use constantThese components work together to create a complete cropping interface:
// Complete cropper setup with all components
const template = `
<cropper-canvas background>
<cropper-image rotatable scalable translatable></cropper-image>
<cropper-shade></cropper-shade>
<cropper-selection movable resizable>
<cropper-grid bordered covered rows="3" columns="3"></cropper-grid>
<cropper-crosshair centered></cropper-crosshair>
<cropper-handle action="move" plain></cropper-handle>
<cropper-handle action="n-resize"></cropper-handle>
<cropper-handle action="e-resize"></cropper-handle>
<cropper-handle action="s-resize"></cropper-handle>
<cropper-handle action="w-resize"></cropper-handle>
<cropper-handle action="ne-resize"></cropper-handle>
<cropper-handle action="nw-resize"></cropper-handle>
<cropper-handle action="se-resize"></cropper-handle>
<cropper-handle action="sw-resize"></cropper-handle>
</cropper-selection>
</cropper-canvas>
`;
const cropper = new Cropper('#image', {
template: template
});
// Configure components after creation
const canvas = cropper.getCropperCanvas();
const grid = canvas.querySelector('cropper-grid');
const crosshair = canvas.querySelector('cropper-crosshair');
const shade = canvas.querySelector('cropper-shade');
// Apply consistent theming
const themeColor = '#00ff88';
grid.themeColor = themeColor;
crosshair.themeColor = themeColor;
shade.themeColor = 'rgba(0, 0, 0, 0.4)';
// Create external viewer
const viewer = document.createElement('cropper-viewer');
viewer.selection = 'cropper-selection';
viewer.resize = 'both';
document.querySelector('#preview').appendChild(viewer);// Handle action constants
const ACTION_SELECT: string; // 'select'
const ACTION_MOVE: string; // 'move'
const ACTION_RESIZE_NORTH: string; // 'n-resize'
const ACTION_RESIZE_EAST: string; // 'e-resize'
const ACTION_RESIZE_SOUTH: string; // 's-resize'
const ACTION_RESIZE_WEST: string; // 'w-resize'
const ACTION_RESIZE_NORTHEAST: string; // 'ne-resize'
const ACTION_RESIZE_NORTHWEST: string; // 'nw-resize'
const ACTION_RESIZE_SOUTHEAST: string; // 'se-resize'
const ACTION_RESIZE_SOUTHWEST: string; // 'sw-resize'
// Viewer resize modes
const RESIZE_BOTH: string; // 'both'
const RESIZE_HORIZONTAL: string; // 'horizontal'
const RESIZE_VERTICAL: string; // 'vertical'
const RESIZE_NONE: string; // 'none'
// Element tag names
const CROPPER_HANDLE: string; // 'cropper-handle'
const CROPPER_GIRD: string; // 'cropper-grid'
const CROPPER_CROSSHAIR: string; // 'cropper-crosshair'
const CROPPER_SHADE: string; // 'cropper-shade'
const CROPPER_VIEWER: string; // 'cropper-viewer'