@dooboostore/simple-web-component-library

NPM versionBuild and TestLicense: MIT

A canvas-based chart and control component library built on@dooboostore/simple-web-component(SWC). Every component here is a native Custom Element defined with SWC's@elementDefine, configureddeclaratively through light-DOM child markup(e.g.<candle>,<vector>,<marker>,<thumb>) rather than a JS-side configuration object, and rendered onto an internal<canvas>inside its shadow root.

Components watch their own children with@mutationObserverLightand re-collect + redraw automatically whenever that markup changes — you build charts by writing/mutating HTML, not by calling imperative draw APIs (though asetData(...)escape hatch exists on most of them for when you'd rather push data from JS).


Public API

@dooboostore/simple-web-component-libraryroot currently exposescomponentFactories: ComponentFactory[]— six factory functions ((w: Window) => CustomElementCtor), one per component below. Each factory registers its tag onw.customElementsthe first time it's called (idempotent — returns the existing constructor on subsequent calls) and is meant to be handed to SWC's app bootstrap (onStartedLazyDefineComponent: [...componentFactories]) alongside your own page/component factories (seesimple-web-component/examples/stock).

import{ componentFactories }from'@dooboostore/simple-web-component-library';// componentFactories: [StockChart, RadarChart, BubbleChart, RangeSlider, CartesianChart, CartesianChart3D]

The packageexportsmap only exposes the root (.), which exportscomponentFactoriesand theComponentFactorytype. Per-component types (CartesianChartData,StockChartPoint,CandleInfo,BubbleChartPoint,RangeThumbValues, ...) live in each component's source file (src/*.ts) and are not re-exported from the root.

Installation

# pnpmpnpm add @dooboostore/simple-web-component-library# npmnpm install @dooboostore/simple-web-component-library# yarnyarn add @dooboostore/simple-web-component-library

Register the components once at app startup:

import'reflect-metadata';import{ defineSwcAppBody }from'@dooboostore/simple-web-component';import{ componentFactories }from'@dooboostore/simple-web-component-library';awaitdefineSwcAppBody(window);document.querySelector('#app')!.connect({onStartedLazyDefineComponent: [...componentFactories],// ...});

Components

<cartesian-chart>(CartesianChart)

A general-purpose 2D coordinate-plane chart: draws series (polylines), polygons, vectors (arrows), markers (dots), circles/ellipses and arcs on a canvas with an auto-scaling grid, axis labels, wheel zoom, drag-to-pan, and pinch-zoom. Redraws whenever its children change (@mutationObserverLight) or the element resizes (@resizeObserverLight).

Host attributes:

AttributeEffect
x-min,x-max,y-min,y-maxExplicit axis bounds. Omitted / empty /"auto"→ that bound is computed from the data (with ~18% padding).
x-label,y-labelAxis titles.
center-x,center-yForce the view to be symmetric around this value on that axis (the auto-computed half-range is kept, but centered here) unless the corresponding-min/-maxis explicit.
disabled-aspectBy default the chart forces equal pixel-scale on both axes (so vectors/circles aren't visually distorted); set this to plot each axis independently, stretched to fill the box.
disabled-zoomDisable wheel/drag/pinch interaction.
hide-gridHide the background grid lines (axis labels/ticks still show).

Public methods:setData(data: CartesianChartData)(push series/polygons/vectors/markers/circles/arcs from JS instead of child markup) andreset()(reset pan/zoom).

Child elements (read once on connect and on every mutation):

TagAttributesDraws
<series>points="x,y x,y ..."(space/;/|-separated pairs),color,width(default2),dash(e.g."5,4"),label,label-colorPolyline
<polygon>samepointsformat (≥3 points),color,width(default1.5),dash,fill,label,label-colorClosed filled/stroked polygon, label at centroid
<vector>x1,y1,x2,y2,color,width(default2),dash,label,label-colorArrow from(x1,y1)to(x2,y2)
<marker>x,y,color(default#10b981),size(default4),label,label-colorFilled dot
<circle>x,y,r,ry(optional — omit for a visually round circle even on non-1:1 axes),color,width(default2),dash,fill,label,label-colorCircle/ellipse
<arc>x,y,r(px),start-angle,end-angle(radians, math convention, y-up),color(default#10b981),width(default1.6)Arc segment
<cartesian-chartx-min="-2"x-max="2"y-min="-2"y-max="2"x-label="x"y-label="y"style="height:280px"><vectorx1="0"y1="0"x2="1"y2="0.5"color="#0f766e"width="4"label="v"></vector><markerx="1"y="0.5"color="#ef4444"size="6"label="tip"></marker><circlex="0"y="0"r="1.5"color="#e2e8f0"dash="4,4"></circle></cartesian-chart>

<cartesian-chart-3d>(CartesianChart3D)

A 3D scene rendered with a hand-rolled orthographic-style projection (own 3×3 rotation-matrix math, no external 3D library) — draws a bounding grid box, X/Y/Z axes, 3D vectors/points/polygons, with mouse-drag / touch-drag orbit, two-finger pinch-zoom + twist-to-roll, wheel zoom, and optional on-screen jog rails for yaw/pitch/roll/zoom.

Host attributes:yaw,pitch,roll(initial camera angles in degrees, read once on connect and byreset()),range(fixes the axis extent; omitted → auto-fit to the largest child coordinate × 1.25),hide-grid,hide-controls(hides the jog rails),show-rail-controller,disabled-drag.

Public method:reset()— recomputeviewMatfromyaw/pitch/rolland zoom back to 1.

Child elements:

TagAttributesDraws
<vector3d>x1,y1,z1,x2,y2,z2,color,width(default2),label,label-color3D arrow
<point3d>x,y,z,color(default#10b981),size(default4),label,label-color3D point
<polygon3d>points="x,y,z x,y,z ..."(≥3),color,width(default1.5),fill,label,label-color3D filled face

Vectors and points are depth-sorted (painter's algorithm) before drawing so nearer shapes correctly occlude farther ones.

<stock-chart>(StockChart)

A candlestick chart with volume/MACD/RSI/OBV sub-panels, moving averages, arbitrary line-series overlays, and rectangle/arc shape overlays — plus drag-to-pan, wheel/pinch zoom, and a tap/click readout mode. Indicator math (SMA/EMA/MACD/RSI/OBV) is computed bycomputeSmaSeries/computeEmaSeries/computeMacdSeries/computeRsiSeries/computeObvSeriesfrom@dooboostore/algorithm(src/stock/trend.ts) — this component is the library's concrete UI consumer of that package.

Host attributes:show-close-line,show-min-max,show-last-line(booleans),enabled-control(drag-pan/wheel/pinch-zoom),enabled-readout(tap a candle to show itsCandleInfo),hidden-x-label,hidden-y-label,disabled-event(ignore all pointer/touch/wheel input).

Child elements:

TagAttributesMeaning
<candle>date,open,high,low,close,volume;name; nested<line width color target>/<tooltip position label color|fill-color line-color label-color line-width>(position:top|bottom|candle-top|candle-bottom)One OHLCV bar, with optional per-candle overlay line(s)/tooltip(s) — e.g. marking a buy/sell signal
<ma>period(orsize),color,type(sma|exponential, defaultsma)A moving-average overlay line
<series>values="n n n",color,dash,width,label,anchor(after-lastdefault, orat:INDEX),extendA domain-agnostic overlay polyline (predictions, targets, comparison lines) drawn over/after the candles, display-only (excluded from indicator math)
<volume>(no attributes — presence alone enables the volume sub-panel)Volume bars panel
<macd>nested<fast period color><slow period><signal period color>(defaults 12/26/9)MACD sub-panel
<rsi>period(default 14); nested<line color><overbought level color><oversold level color>(defaults 70/30)RSI sub-panel
<obv>nested<line color>On-Balance-Volume sub-panel
<rect>x/y/width/heightorstart-x/start-y/end-x/end-y, ordate-start+date-end(auto y-range);fill,stroke,stroke-width,dash(aliases:fill-style/stroke-style/stroke-dasharray),target(candle|volume|all),margin-top,margin-bottom,label,colorPixel- or date-anchored rectangle overlay
<arc>x,y,r(aliasesradius),start/start-angle,end/end-angle,fill,stroke,stroke-widthPixel-space arc overlay

Public API:

setData(points:StockChartPoint[]):void;// push data from JS instead of <candle> childrensetView(start:number,end:number):void;// programmatic zoom/focus (candle indices, inclusive)resetView():void;// show full rangegetCandleInfo(key:string|number):CandleInfo|null;// by date string or index — OHLCV + all active indicator values at that candlegetCandleInfos(keys?: (string|number)[]):CandleInfo[];getCandleInfoByName(name:string):CandleInfo|null;// by <candle name="..."> (falls back to date)getCandleInfoByNames(names?:string[]):CandleInfo[];

Each child<candle>also gets a.valueproperty (CandleInfo, including indicator values) injected after every redraw.

Also dispatches aview-edgeCustomEvent(detail: { edge: 'start' | 'end' }) the first time the visible window reaches either end of the data — useful for triggering lazy-loading of more history.

<stock-chartenabled-controlenabled-readoutshow-min-maxstyle="height:360px"><candledate="2024-01-01"open="100"high="105"low="98"close="103"volume="12345"></candle><candledate="2024-01-02"open="103"high="108"low="101"close="106"volume="15230"></candle><maperiod="20"color="#6366f1"></ma><volume></volume><rsiperiod="14"></rsi></stock-chart>

<stock-radar>(RadarChart)

A radar/spider chart: N axes around a circle (0–100% grid rings), with one or more overlaid score polygons.

Child elements:

TagAttributes
<axis>id(oraxis; falls back toax0,ax1, ...),label(supports\nfor multi-line),color
<score-set>fill-style,stroke-style,stroke-width(default1); nested<score axis="AXIS_ID" value="0-100">per axis (missing axes default to50)
<stock-radarstyle="height:320px"><axisid="speed"label="Speed"color="#6366f1"></axis><axisid="power"label="Power"color="#ef4444"></axis><axisid="control"label="Control"color="#10b981"></axis><score-setfill-style="rgba(99,102,241,0.25)"stroke-style="#6366f1"stroke-width="2"><scoreaxis="speed"value="80"></score><scoreaxis="power"value="55"></score><scoreaxis="control"value="70"></score></score-set></stock-radar>

<bubble-chart>(BubbleChart)

An x/y scatter chart where each point is a circle whoseradius encodes a 0–100 value(independent of zoom level), with click/tap selection (opens a description tooltip), optional straight-line overlays, wheel zoom, and drag-pan/pinch-zoom (opt-in viaenabled-zoom).

Host attributes:x-label,y-label,show-center-cross(draw a small crosshair through every bubble's center),enabled-zoom(enables wheel/drag/pinch — without it the chart is static/click-only).

Public method:setData(points: BubbleChartPoint[]); alsoreset()(pan/zoom + selection reset).

Child elements:

TagAttributes
<bubble>label,x,y,value(orr; 0–100, clamped),description(\n-separated lines shown in the selection tooltip),show-center-cross,fill-style(orfillStyle),stroke-style/stroke/strokeStyle,line-width/lineWidth,label-color/labelColor
<line>start-x,start-y,end-x,end-y(all required);line-dash/line-style,line-width/stroke-width/strokeWidth(default1.5),strokeStyle/stroke/color(default#94a3b8)

Clicking/tapping a bubble dispatches abubble-selectCustomEventwithdetailset to the selectedBubbleChartPoint(ornullon deselect).

<bubble-chartx-label="Market cap"y-label="Change %"enabled-zoomstyle="height:340px"><bubblelabel="AAA"x="1200"y="0.032"value="80"description="Sector: Tech"></bubble><bubblelabel="BBB"x="800"y="-0.015"value="45"></bubble></bubble-chart>

<range-slider>(RangeSlider)

A form-associated (formAssociated = true) slider supporting three shapes:

  1. Legacy single/range(no<thumb>children) — one or two draggable handles, like a native<input type="range">(single) or a min/max range slider.
  2. Declarative multi-thumb— one or more<thumb name="...">children, each independently draggable, withcross-referencing bounds: a thumb'smin/maxcan be either a number or another thumb'sname, so thumbs can be constrained relative to each other (resolved and clamped in document order, converging over repeated passes so reference cycles are also handled safely).
  3. Grouped multi-thumb— wrap<thumb>elements in a<thumb-group label="..." color="...">; the group renders an extra draggable "bracket" bar spanning its members' min↔max, dragging the bracket rigidly translates the whole group (staying within its own combined bounds).

Host attributes:min,max,step,mode(single|range, defaultrange),orientation(horizontal|vertical),min-value,max-value,value(single mode: absolute value; range mode:max - mindifference, matching this element's own.valuegetter).

Thumb child attributes (multi mode):name(required),value,min,max(number or another thumb'sname),step,color,size(10–48px),fill.

Public API / properties:min/max/step/mode/orientation(get/set, reflected to attributes),minValue/maxValue/avgValue(get),value(legacy: numeric string; multi-thumb:{[thumbName]: number}object),setValues(values)(bulk-set thumb values without firing events).

Emitsinput(while dragging) andchange(on release/commit)CustomEvents;detailis{ values, minValue, maxValue, avgValue, changed, mode: 'multi' }in thumb mode, or{ minValue, maxValue, value, mode }in legacy mode.

<!-- legacy range --><range-slidermin="0"max="100"min-value="20"max-value="80"></range-slider><!-- declarative multi-thumb with cross-referenced bounds --><range-slidermin="0"max="10"step="0.1"><thumbname="p1"value="2"min="0"max="p2"color="#ef4444"></thumb><thumbname="p2"value="6"min="p1"max="10"color="#3b82f6"></thumb></range-slider>

Related Packages

License

This package is licensed under theMIT License.