Skip to content

Controller Guide

When to use

Use this page when you are implementing serious product behavior around color state, history, presets, plugins, and event orchestration.

Quick example

ts
import { createBerryPickrController } from '@appberry/berrypickr';

const controller = createBerryPickrController({
  defaultValue: '#486dff',
  formats: ['hex', 'rgba', 'hsla'],
  history: { limit: 120 },
  recentColors: { limit: 24 },
  pluginErrorPolicy: 'emit'
});

controller.on('change', ({ source, transactionId, value }) => {
  console.log('change', source, transactionId, value?.to('rgba'));
});

controller.on('commit', ({ transactionId, value }) => {
  console.log('commit', transactionId, value?.to('hexa'));
});

Options/Methods

createBerryPickrController(options)

BerryPickrControllerOptions

OptionTypeDefaultBehavior
valuestring | nullundefinedInitial controlled value; if provided, takes precedence over defaultValue
defaultValuestring | nullnullInitial fallback color when value is not provided
formatBerryPickrFormatFirst available formatActive format if included in formats
formatsBerryPickrFormat[]['hex','hexa','rgb','rgba','hsl','hsla','hsv','hsva','cmyk']Allowed output formats; deduped
disabledbooleanfalseDisables edits and blocks opening when UI is mounted
lockAlphabooleanfalseRemoves alpha-inclusive formats and forces alpha to 1
precisionnumber2Decimal precision for formatted output
swatchesstring[][]Invalid colors are ignored during parse
history.limitnumber100Max undo entries, clamped to at least 1
contextsPartial<Record<Context, string | null>>all nullSeed context-specific values
contextBerryPickrContext'default'Active context pointer
presetsRecord<string, string[]>{}Preset groups; invalid colors are filtered out
recentColors.limitnumber24Max recent entries, clamped to at least 1
recentColors.storage{ load; save }undefinedOptional persistence adapter
recentColors.storageKeystring'berrypickr:recent'Key used for persistence adapter
pluginsBerryPickrPlugin[][]Plugin callbacks on setup/change/commit/teardown
pluginErrorPolicy'emit' | 'throw''emit'Plugin failure handling strategy

State and write methods

MethodReturnsNotes
getState()BerryPickrStateSnapshotSafe snapshot copy with colors, history, contexts, and flags
subscribe(listener)() => voidFires on every state update
setValue(input, opts?)booleanfalse for invalid non-null input; can auto-commit with opts.commit
commit(opts?)string | nullEmits commit; returns transaction ID unless destroyed
cancel()booleanRestores active context value to saved value
undo()booleanPops history and applies previous entry
redo()booleanReapplies next entry from future stack
destroy()voidEmits destroy, runs plugin teardowns, clears listeners

Context methods

MethodReturnsNotes
selectContext(context)booleanChanges active context; emits optionsChange and change (source: 'context')
setContextValue(context, input, opts?)booleanShortcut for writing a specific context
getContextValue(context)BerryPickrColor | nullSnapshot-safe clone

UI coordination methods

MethodReturnsNotes
setOpen(open)booleanNo-op if disabled and opening requested
isOpen()booleanCurrent open flag
setDisabled(disabled)voidCloses open UI when set to true
setFormat(format)booleanFails if format is unavailable
getFormat()BerryPickrFormatActive format
getFormats()BerryPickrFormat[]Current allowed formats

Swatches and presets

MethodReturnsNotes
addSwatch(color)booleanInvalid colors are rejected
removeSwatch(index)booleanFails for out-of-range indices
setSwatches(colors)voidReplaces and filters invalid values
setPresets(presets)voidReplaces grouped preset palette
getPresets()Record<string, BerryPickrColor[]>Includes runtime recent group
applyPreset(category, index, opts?)booleanSupports 'recent' as a category
getRecentColors()BerryPickrColor[]Most-recent-first committed colors

Events

Event names

  • change
  • commit
  • historyChange
  • optionsChange
  • openChange
  • pluginError
  • destroy

All payloads include instanceId, transactionId, and timestamp.

Event examples

ts
controller.on('change', ({ source, context, previousValue, value, transactionId }) => {
  console.log(source, context, transactionId, previousValue?.to('hexa'), value?.to('hexa'));
});

controller.on('historyChange', ({ action, history }) => {
  console.log(action, history.index, history.length, history.canUndo, history.canRedo);
});

controller.on('pluginError', ({ plugin, phase, error }) => {
  console.error(`[${plugin}] ${phase}`, error);
});

Behavior notes

  • setValue('invalid') returns false, emits nothing.
  • setValue with same resolved color is a no-op; with { commit: true }, it still commits.
  • commit() only changes saved state and recents, not history stacks.
  • undo()/redo() switch active context to the history entry context.
  • Updating disabled: true closes the picker if currently open.

Gotchas

  • updateOptions({ value }) emits change with source: 'options' when value differs.
  • Updating recentColors.storage triggers a reload from storage key.
  • pluginErrorPolicy: 'throw' can interrupt calling flows if plugin callbacks throw.