or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

chart-registry.mdcoordinate-grid-charts.mdcore-utilities.mddata-display-widgets.mdfilters.mdindex.mdlegends.mdmixins.mdordinal-specialized-charts.md
tile.json

mixins.mddocs/

Mixins and Base Functionality

Composable mixin classes that provide core functionality to chart implementations. Mixins encapsulate common behaviors and can be combined to create sophisticated chart types.

Capabilities

BaseMixin

Core chart functionality providing lifecycle management, event handling, and common methods inherited by all charts.

/**
 * Base mixin providing fundamental chart functionality
 */
class BaseMixin {
  constructor();
  
  /** Set/get chart width */
  width(width?: number): number | BaseMixin;
  
  /** Set/get chart height */
  height(height?: number): number | BaseMixin;
  
  /** Set/get crossfilter dimension */
  dimension(dimension?: any): any | BaseMixin;
  
  /** Set/get crossfilter group */
  group(group?: any): any | BaseMixin;
  
  /** Set/get chart anchor/container */
  anchor(anchor?: string | Element | d3.Selection): any | BaseMixin;
  
  /** Set/get SVG element */
  svg(svg?: d3.Selection): d3.Selection | BaseMixin;
  
  /** Reset all filters */
  filterAll(): BaseMixin;
  
  /** Apply/remove filter */
  filter(filter?: any): any | BaseMixin;
  
  /** Get current filters */
  filters(): any[];
  
  /** Check if filter exists */
  hasFilter(filter?: any): boolean;
  
  /** Remove specific filter */
  removeFilter(filter: any): BaseMixin;
  
  /** Add filter */
  addFilter(filter: any): BaseMixin;
  
  /** Replace all filters with new filter */
  replaceFilter(filter: any): BaseMixin;
  
  /** Render chart (full render) */
  render(): BaseMixin;
  
  /** Redraw chart (incremental update) */
  redraw(): BaseMixin;
  
  /** Set/get key accessor function */
  keyAccessor(accessor?: Function): Function | BaseMixin;
  
  /** Set/get value accessor function */
  valueAccessor(accessor?: Function): Function | BaseMixin;
  
  /** Set/get label function */
  label(labelFunction?: Function): Function | BaseMixin;
  
  /** Set/get whether to render labels */
  renderLabel(render?: boolean): boolean | BaseMixin;
  
  /** Set/get title function */
  title(titleFunction?: Function): Function | BaseMixin;
  
  /** Set/get whether to render title */
  renderTitle(render?: boolean): boolean | BaseMixin;
  
  /** Set/get chart group */
  chartGroup(group?: string): string | BaseMixin;
  
  /** Set/get minimum width */
  minWidth(width?: number): number | BaseMixin;
  
  /** Set/get minimum height */
  minHeight(height?: number): number | BaseMixin;
  
  /** Set/get transition duration */
  transitionDuration(duration?: number): number | BaseMixin;
  
  /** Set/get transition delay */
  transitionDelay(delay?: number): number | BaseMixin;
  
  /** Add event listener */
  on(event: string, listener: Function): BaseMixin;
  
  /** Remove event listener */
  off(event: string, listener?: Function): BaseMixin;
  
  /** Get chart root element */
  root(): d3.Selection;
  
  /** Check if chart is child of composite chart */
  isChild(): boolean;
}

/**
 * Factory function for creating BaseMixin instances
 */
function baseMixin(): BaseMixin;

Usage Example:

import { BaseMixin } from 'dc';

// Custom chart extending BaseMixin
class CustomChart extends BaseMixin {
  constructor(parent, chartGroup) {
    super();
    this.anchor(parent);
    this.chartGroup(chartGroup);
  }
  
  _doRender() {
    // Custom rendering logic
    return this;
  }
  
  _doRedraw() {
    // Custom redraw logic
    return this;
  }
}

CoordinateGridMixin

Grid-based charts with X/Y axes, brushing, zooming, and coordinate-based interactions.

/**
 * Coordinate grid mixin for charts with X/Y axes
 */
class CoordinateGridMixin extends BaseMixin {
  /** Set/get X scale */
  x(scale?: d3.Scale): d3.Scale | CoordinateGridMixin;
  
  /** Set/get Y scale */
  y(scale?: d3.Scale): d3.Scale | CoordinateGridMixin;
  
  /** Set/get X axis units */
  xUnits(units?: Function): Function | CoordinateGridMixin;
  
  /** Set/get X axis units count */
  xUnitsCount(count?: number): number | CoordinateGridMixin;
  
  /** Set/get whether X axis is elastic */
  elasticX(elastic?: boolean): boolean | CoordinateGridMixin;
  
  /** Set/get whether Y axis is elastic */
  elasticY(elastic?: boolean): boolean | CoordinateGridMixin;
  
  /** Set/get whether brushing is enabled */
  brushOn(brushOn?: boolean): boolean | CoordinateGridMixin;
  
  /** Set/get brush event handler */
  brushHandler(handler?: Function): Function | CoordinateGridMixin;
  
  /** Set/get parent brush coordination */
  parentBrushOn(brushOn?: boolean): boolean | CoordinateGridMixin;
  
  /** Set/get zoom scale */
  zoomScale(scale?: d3.Scale): d3.Scale | CoordinateGridMixin;
  
  /** Set/get zoom out restriction */
  zoomOutRestrict(restrict?: boolean): boolean | CoordinateGridMixin;
  
  /** Focus on specific domain */
  focus(range?: [any, any]): CoordinateGridMixin;
  
  /** Remove focus/zoom */
  refocus(): CoordinateGridMixin;
  
  /** Set/get X axis */
  xAxis(axis?: d3.Axis): d3.Axis | CoordinateGridMixin;
  
  /** Set/get Y axis */
  yAxis(axis?: d3.Axis): d3.Axis | CoordinateGridMixin;
  
  /** Set/get X axis label */
  xAxisLabel(label?: string, padding?: number): string | CoordinateGridMixin;
  
  /** Set/get Y axis label */
  yAxisLabel(label?: string, padding?: number): string | CoordinateGridMixin;
  
  /** Set/get clip padding */
  clipPadding(padding?: number): number | CoordinateGridMixin;
  
  /** Set/get mouse zoom capability */
  mouseZoomable(zoomable?: boolean): boolean | CoordinateGridMixin;
  
  /** Set/get X axis padding */
  xAxisPadding(padding?: number): number | CoordinateGridMixin;
  
  /** Set/get Y axis padding */
  yAxisPadding(padding?: number): number | CoordinateGridMixin;
  
  /** Set/get X axis padding unit */
  xAxisPaddingUnit(unit?: string): string | CoordinateGridMixin;
  
  /** Set/get Y axis padding unit */
  yAxisPaddingUnit(unit?: string): string | CoordinateGridMixin;
  
  /** Set/get round function */
  round(round?: Function): Function | CoordinateGridMixin;
}

Usage Example:

import { CoordinateGridMixin } from 'dc';

class CustomGridChart extends CoordinateGridMixin {
  constructor(parent, chartGroup) {
    super();
    this.anchor(parent)
        .chartGroup(chartGroup)
        .x(d3.scaleLinear())
        .y(d3.scaleLinear())
        .brushOn(true)
        .elasticY(true);
  }
}

StackMixin

Stackable chart support using d3.stack layout for layered visualizations.

/**
 * Stack mixin for creating layered/stacked charts
 */
class StackMixin extends CoordinateGridMixin {
  /** Add stack layer */
  stack(group: any, name?: string, accessor?: Function): StackMixin;
  
  /** Set/get stack layout */
  stackLayout(layout?: d3.Stack): d3.Stack | StackMixin;
  
  /** Set/get whether stacks are hidable */
  hidableStacks(hidable?: boolean): boolean | StackMixin;
  
  /** Hide specific stack */
  hideStack(name: string): StackMixin;
  
  /** Show specific stack */
  showStack(name: string): StackMixin;
  
  /** Get all stack names */
  stackNames(): string[];
  
  /** Check if stack is hidden */
  stackHidden(name: string): boolean;
  
  /** Set/get custom value for hidden stacks */
  hiddenStackValue(value?: any): any | StackMixin;
}

Usage Example:

import { StackMixin } from 'dc';

const stackChart = new StackMixin('#stacked-chart')
  .x(d3.scaleLinear())
  .y(d3.scaleLinear())
  .dimension(dateDimension)
  .group(salesGroup)
  .stack(profitGroup, 'Profit')
  .stack(expenseGroup, 'Expenses')
  .hidableStacks(true);

// Hide a stack
stackChart.hideStack('Expenses');

ColorMixin

Color management and ordinal color schemes for charts.

/**
 * Color mixin for managing chart colors
 * @param {any} Base - Base class to extend
 * @returns {Function} Color mixin constructor
 */
function ColorMixin(Base: any): ColorMixinClass;

interface ColorMixinClass {
  /** Set/get color scale */
  colors(scale?: d3.Scale | string[]): d3.Scale | string[] | ColorMixinClass;
  
  /** Set/get ordinal colors */
  ordinalColors(colors?: string[]): string[] | ColorMixinClass;
  
  /** Set/get linear colors */
  linearColors(colors?: string[]): string[] | ColorMixinClass;
  
  /** Set/get color accessor function */
  colorAccessor(accessor?: Function): Function | ColorMixinClass;
  
  /** Set/get color domain */
  colorDomain(domain?: any[]): any[] | ColorMixinClass;
  
  /** Calculate color domain from data */
  calculateColorDomain(): ColorMixinClass;
  
  /** Get color for specific value */
  getColor(value: any, index?: number): string;
}

Usage Example:

import { ColorMixin, BaseMixin } from 'dc';

class ColoredChart extends ColorMixin(BaseMixin) {
  constructor(parent) {
    super();
    this.anchor(parent)
        .colors(d3.scaleOrdinal(d3.schemeCategory10))
        .colorAccessor(d => d.key);
  }
}

CapMixin

"Others" group management for capping the number of displayed items.

/**
 * Cap mixin for managing "others" groups
 * @param {any} Base - Base class to extend
 * @returns {Function} Cap mixin constructor
 */
function CapMixin(Base: any): CapMixinClass;

interface CapMixinClass {
  /** Set/get cap (maximum number of items) */
  cap(cap?: number): number | CapMixinClass;
  
  /** Set/get others grouper function */
  othersGrouper(grouper?: Function): Function | CapMixinClass;
  
  /** Set/get others label */
  othersLabel(label?: string): string | CapMixinClass;
  
  /** Set/get data ordering function */
  ordering(orderFunction?: Function): Function | CapMixinClass;
  
  /** Set/get whether chart takes focus on click */
  takeFocus(takeFocus?: boolean): boolean | CapMixinClass;
  
  /** Get data with cap applied */
  _computeOrderedGroups(data: any[]): any[];
}

Usage Example:

import { CapMixin, BaseMixin } from 'dc';

class CappedChart extends CapMixin(BaseMixin) {
  constructor(parent) {
    super();
    this.anchor(parent)
        .cap(10)
        .othersLabel('Others')
        .ordering(d => -d.value); // Descending by value
  }
}

BubbleMixin

Bubble sizing and positioning calculations for bubble charts.

/**
 * Bubble mixin for size-encoded charts
 * @param {any} Base - Base class to extend
 * @returns {Function} Bubble mixin constructor
 */
function BubbleMixin(Base: any): BubbleMixinClass;

interface BubbleMixinClass {
  /** Set/get radius scale */
  r(scale?: d3.Scale): d3.Scale | BubbleMixinClass;
  
  /** Set/get radius value accessor */
  radiusValueAccessor(accessor?: Function): Function | BubbleMixinClass;
  
  /** Set/get minimum radius */
  minRadius(radius?: number): number | BubbleMixinClass;
  
  /** Set/get maximum radius */
  maxRadius(radius?: number): number | BubbleMixinClass;
  
  /** Set/get minimum radius with data */
  minRadiusWithData(radius?: number): number | BubbleMixinClass;
  
  /** Calculate bubble radius for value */
  bubbleR(d: any): number;
  
  /** Get radius domain */
  rDomain(): [number, number];
}

Usage Example:

import { BubbleMixin, CoordinateGridMixin } from 'dc';

class BubbleChart extends BubbleMixin(CoordinateGridMixin) {
  constructor(parent) {
    super();
    this.anchor(parent)
        .r(d3.scaleSqrt().range([3, 20]))
        .radiusValueAccessor(d => d.value)
        .minRadius(3)
        .maxRadius(20);
  }
}

MarginMixin

Margin management for chart layout and positioning.

/**
 * Margin mixin for chart layout management
 */
class MarginMixin {
  /** Set/get chart margins */
  margins(margins?: {top: number, right: number, bottom: number, left: number}): any | MarginMixin;
  
  /** Get effective width (width - margins) */
  effectiveWidth(): number;
  
  /** Get effective height (height - margins) */
  effectiveHeight(): number;
}

Usage Example:

import { MarginMixin, BaseMixin } from 'dc';

class MarginalChart extends MarginMixin {
  constructor(parent) {
    super();
    this.margins({top: 20, right: 50, bottom: 30, left: 40});
  }
}

Mixin Composition Patterns

Multiple Inheritance

Mixins can be combined to create sophisticated chart types:

import { BaseMixin, CoordinateGridMixin, StackMixin, ColorMixin } from 'dc';

// Stacked chart automatically inherits from CoordinateGridMixin and BaseMixin
class StackedBarChart extends StackMixin {
  constructor(parent, chartGroup) {
    super();
    this.anchor(parent)
        .chartGroup(chartGroup);
  }
}

// Add color management to any chart
class ColoredPieChart extends ColorMixin(BaseMixin) {
  constructor(parent) {
    super();
    this.colors(d3.scaleOrdinal().range(['#FF6B6B', '#4ECDC4', '#45B7D1']));
  }
}

Mixin Hierarchy

Understanding the inheritance chain:

BaseMixin (root)
├── CoordinateGridMixin extends BaseMixin
│   ├── StackMixin extends CoordinateGridMixin
│   └── Other coordinate-based charts
├── ColorMixin(Base) - functional mixin
├── CapMixin(Base) - functional mixin  
├── BubbleMixin(Base) - functional mixin
└── MarginMixin - standalone utility mixin

Custom Mixin Creation

Create your own mixins following the established patterns:

function TooltipMixin(Base) {
  return class extends Base {
    constructor(...args) {
      super(...args);
      this._tooltip = d3.select('body').append('div')
        .attr('class', 'dc-tooltip')
        .style('opacity', 0);
    }
    
    showTooltip(data, event) {
      this._tooltip.transition()
        .duration(200)
        .style('opacity', 0.9);
      
      this._tooltip.html(this.title()(data))
        .style('left', (event.pageX + 10) + 'px')
        .style('top', (event.pageY - 28) + 'px');
      
      return this;
    }
    
    hideTooltip() {
      this._tooltip.transition()
        .duration(500)
        .style('opacity', 0);
      
      return this;
    }
  };
}

// Use custom mixin
class TooltipChart extends TooltipMixin(BaseMixin) {
  constructor(parent) {
    super();
    this.anchor(parent);
  }
}

Types

interface BaseMixin {
  width(width?: number): number | BaseMixin;
  height(height?: number): number | BaseMixin;
  dimension(dimension?: any): any | BaseMixin;
  group(group?: any): any | BaseMixin;
  anchor(anchor?: string | Element | d3.Selection): any | BaseMixin;
  svg(svg?: d3.Selection): d3.Selection | BaseMixin;
  filterAll(): BaseMixin;
  filter(filter?: any): any | BaseMixin;
  filters(): any[];
  render(): BaseMixin;
  redraw(): BaseMixin;
  on(event: string, listener: Function): BaseMixin;
  root(): d3.Selection;
}

interface CoordinateGridMixin extends BaseMixin {
  x(scale?: d3.Scale): d3.Scale | CoordinateGridMixin;
  y(scale?: d3.Scale): d3.Scale | CoordinateGridMixin;
  elasticX(elastic?: boolean): boolean | CoordinateGridMixin;
  elasticY(elastic?: boolean): boolean | CoordinateGridMixin;
  brushOn(brushOn?: boolean): boolean | CoordinateGridMixin;
  focus(range?: [any, any]): CoordinateGridMixin;
  refocus(): CoordinateGridMixin;
}

interface StackMixin extends CoordinateGridMixin {
  stack(group: any, name?: string, accessor?: Function): StackMixin;
  hideStack(name: string): StackMixin;
  showStack(name: string): StackMixin;
  hidableStacks(hidable?: boolean): boolean | StackMixin;
}

type ColorMixinConstructor = <T>(Base: T) => T & ColorMixinMethods;
type CapMixinConstructor = <T>(Base: T) => T & CapMixinMethods;  
type BubbleMixinConstructor = <T>(Base: T) => T & BubbleMixinMethods;

interface ColorMixinMethods {
  colors(scale?: d3.Scale | string[]): d3.Scale | string[] | this;
  colorAccessor(accessor?: Function): Function | this;
  colorDomain(domain?: any[]): any[] | this;
}

interface CapMixinMethods {
  cap(cap?: number): number | this;
  othersLabel(label?: string): string | this;
  ordering(orderFunction?: Function): Function | this;
}

interface BubbleMixinMethods {
  r(scale?: d3.Scale): d3.Scale | this;
  radiusValueAccessor(accessor?: Function): Function | this;
  minRadius(radius?: number): number | this;
  maxRadius(radius?: number): number | this;
}

interface MarginMixin {
  margins(margins?: {top: number, right: number, bottom: number, left: number}): any | MarginMixin;
  effectiveWidth(): number;
  effectiveHeight(): number;
}