@tungstenstudio/dartboard-input 1.0.0-rc.5 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -372,12 +372,15 @@ var Dartboard = class {
372
372
  } else {
373
373
  const [radialFrac, tangentialFrac] = DART_OFFSETS[count % DART_OFFSETS.length];
374
374
  const thickness = outerR - innerR;
375
+ const midRadius = (innerR + outerR) / 2;
376
+ const segWidthRad = this.board.segmentWidth * Math.PI / 180;
377
+ const arcHalfWidth = midRadius * Math.sin(segWidthRad / 2);
375
378
  const radX = Math.sin(midAngle);
376
379
  const radY = -Math.cos(midAngle);
377
380
  const tanX = Math.cos(midAngle);
378
381
  const tanY = Math.sin(midAngle);
379
- cx = centroid[0] + radialFrac * thickness * radX + tangentialFrac * thickness * tanX;
380
- cy = centroid[1] + radialFrac * thickness * radY + tangentialFrac * thickness * tanY;
382
+ cx = centroid[0] + radialFrac * thickness * radX + tangentialFrac * arcHalfWidth * tanX;
383
+ cy = centroid[1] + radialFrac * thickness * radY + tangentialFrac * arcHalfWidth * tanY;
381
384
  }
382
385
  group.append("circle").classed("c-Dartboard-dart", true).attr("cx", cx).attr("cy", cy).attr("r", dartRadius).attr("data-bed", key);
383
386
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/dartboard.ts","../src/constants.ts","../src/utils.ts"],"sourcesContent":["import './dartboard.css';\nexport { Dartboard } from './dartboard';\nexport type {\n Ring,\n Rings,\n Segment,\n Bed,\n DartboardOptions,\n ThrowDetail,\n HoverDetail,\n BedTarget,\n BedInput,\n HighlightOptions,\n} from './types';\nexport { DEFAULT_OPTIONS, MOBILE_OPTIONS, DEFAULT_RINGS, DEFAULT_SEGMENTS } from './constants';\nexport { buildThrowDetail, asPercent, addRingToSegments, parseBed } from './utils';\n","import { select, type Selection } from 'd3-selection';\nimport { arc, pie, type PieArcDatum } from 'd3-shape';\nimport type {\n DartboardOptions,\n Rings,\n Ring,\n Segment,\n Bed,\n ThrowDetail,\n HoverDetail,\n BedTarget,\n BedInput,\n HighlightOptions,\n} from './types';\nimport { DEFAULT_OPTIONS, DEFAULT_RINGS, DEFAULT_SEGMENTS } from './constants';\nimport { buildThrowDetail, asPercent, addRingToSegments, parseBed } from './utils';\n\ntype RingKey = keyof Rings;\n\n// D3's selection generics are deeply nested and don't compose well across\n// chained calls. Using `any` for internal state avoids 100+ lines of type\n// gymnastics while keeping the public API fully typed.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype D3Sel = Selection<any, any, any, any>;\n\ninterface BoardState {\n container: HTMLElement;\n wrapper: D3Sel;\n width: number;\n height: number;\n radius: number;\n rotation: number;\n segmentWidth: number;\n svg: D3Sel;\n pie: ReturnType<typeof pie<Bed>>;\n}\n\ninterface SizeMap {\n miss: number;\n double: number;\n outerSingle: number;\n triple: number;\n innerSingle: number;\n singleBull: number;\n doubleBull: number;\n}\n\nfunction buildAriaLabel(bed: Bed): string {\n const detail = buildThrowDetail(bed);\n return `${detail.bed}, scores ${detail.score}`;\n}\n\nfunction isBull(ringKey: RingKey): boolean {\n return ringKey === 'DOUBLE_BULL' || ringKey === 'SINGLE_BULL';\n}\n\nfunction bedKey(target: Required<BedTarget>): string {\n return `${target.ring}:${target.segment}`;\n}\n\n// Predefined offsets for multiple darts in the same bed.\n// [radialFraction, tangentialFraction] — scaled to ring thickness, oriented\n// along the bed's radial and arc directions so darts stay within the wedge.\nconst DART_OFFSETS: [number, number][] = [\n [0, 0],\n [-0.25, -0.25],\n [0.25, 0.25],\n [-0.25, 0.25],\n [0.25, -0.25],\n];\n\nexport class Dartboard {\n private board: BoardState | null = null;\n private sizes: SizeMap | null = null;\n private rendered = false;\n private _disabled = false;\n private dartGroup: D3Sel | null = null;\n private dartCounts = new Map<string, number>();\n private readonly options: DartboardOptions;\n readonly segments: Segment[];\n readonly rings: Rings;\n\n constructor(\n container: string | HTMLElement,\n options: Partial<DartboardOptions> = {},\n segments: Segment[] = DEFAULT_SEGMENTS,\n rings: Rings = DEFAULT_RINGS,\n ) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.segments = segments;\n this.rings = rings;\n\n const percentSum =\n this.options.missPercent +\n this.options.doublePercent +\n this.options.outerSinglePercent +\n this.options.triplePercent +\n this.options.innerSinglePercent +\n this.options.singleBullPercent +\n this.options.doubleBullPercent;\n\n if (percentSum !== 100) {\n throw new Error(\n `Dartboard: ring percentages must sum to 100 (got ${percentSum})`,\n );\n }\n\n const boardContainer =\n typeof container === 'string'\n ? document.querySelector<HTMLElement>(container)\n : container;\n\n if (!boardContainer) {\n throw new Error(`Dartboard: container not found`);\n }\n\n const padding = this.options.padding;\n const boardSize =\n this.options.size ||\n Math.min(boardContainer.offsetHeight, boardContainer.offsetWidth);\n const width = boardSize - padding * 2;\n const viewBoxSize = boardSize;\n const segmentWidth = 360 / segments.length;\n const radius = width / 2;\n const rotation = segmentWidth / -2;\n\n const wrapper = select(boardContainer)\n .append('div')\n .classed('c-Dartboard', true);\n\n const svg = wrapper\n .append('svg')\n .attr('viewBox', `0 0 ${viewBoxSize} ${viewBoxSize}`)\n .attr('role', 'group')\n .attr('aria-label', 'Dartboard')\n .append('g')\n .attr(\n 'transform',\n `translate(${viewBoxSize / 2}, ${viewBoxSize / 2}) rotate(${rotation})`,\n );\n\n const pieFn = pie<Bed>()\n .sort((a, b) => (a.position ?? 0) - (b.position ?? 0))\n .value(() => segmentWidth);\n\n this.board = {\n container: boardContainer,\n wrapper,\n width,\n height: width,\n radius,\n rotation,\n segmentWidth,\n svg,\n pie: pieFn,\n };\n\n this.sizes = {\n miss: radius * asPercent(this.options.missPercent),\n double: radius * asPercent(this.options.doublePercent),\n outerSingle: radius * asPercent(this.options.outerSinglePercent),\n triple: radius * asPercent(this.options.triplePercent),\n innerSingle: radius * asPercent(this.options.innerSinglePercent),\n singleBull: radius * asPercent(this.options.singleBullPercent),\n doubleBull: radius * asPercent(this.options.doubleBullPercent),\n };\n }\n\n render(): this {\n if (!this.board || !this.sizes) return this;\n if (this.rendered) return this;\n this.rendered = true;\n\n const { board, sizes } = this;\n\n let innerRadius = 0;\n let outerRadius = innerRadius + sizes.doubleBull;\n this.renderBeds(\n board,\n this.rings.DOUBLE_BULL,\n [{ segment: 25, color: 'Dark' }],\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.singleBull;\n this.renderBeds(\n board,\n this.rings.SINGLE_BULL,\n [{ segment: 25, color: 'Light' }],\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.innerSingle;\n this.renderBeds(\n board,\n this.rings.INNER_SINGLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.triple;\n this.renderBeds(\n board,\n this.rings.TRIPLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.outerSingle;\n this.renderBeds(\n board,\n this.rings.OUTER_SINGLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.double;\n this.renderBeds(\n board,\n this.rings.DOUBLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = board.radius - sizes.miss;\n outerRadius = board.radius;\n this.renderMissRing(\n board,\n this.rings.MISS,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n return this;\n }\n\n destroy(): void {\n if (this.board) {\n // Remove all D3 event listeners before removing from DOM\n this.board.wrapper.selectAll('.c-Dartboard-bed')\n .on('pointerup', null)\n .on('pointerenter', null)\n .on('pointerleave', null)\n .on('keydown', null);\n this.board.wrapper.remove();\n this.board = null;\n this.sizes = null;\n this.rendered = false;\n this.dartGroup = null;\n this.dartCounts.clear();\n }\n }\n\n get disabled(): boolean {\n return this._disabled;\n }\n\n disable(): this {\n this._disabled = true;\n if (this.board) {\n this.board.wrapper.classed('is-disabled', true);\n }\n return this;\n }\n\n enable(): this {\n this._disabled = false;\n if (this.board) {\n this.board.wrapper.classed('is-disabled', false);\n }\n return this;\n }\n\n throwAt(target: BedInput): void {\n if (!this.board || this._disabled) return;\n\n const targets = this.resolveTargets([target]);\n if (targets.length === 0) return;\n const first = targets[0];\n\n if (!this.isValidTarget(first)) {\n throw new Error(`Dartboard: invalid throw target — segment ${first.segment} does not exist`);\n }\n\n const ring = this.rings[first.ring];\n const bed: Bed = { segment: first.segment, color: 'Dark', ring };\n const detail = buildThrowDetail(bed);\n\n this.board.container.dispatchEvent(\n new CustomEvent<ThrowDetail>('throw', { detail }),\n );\n }\n\n highlight(targets: BedInput[], options: HighlightOptions = {}): void {\n if (!this.board) return;\n const className = options.className || 'is-highlighted';\n\n for (const target of this.resolveTargets(targets)) {\n const ring = this.rings[target.ring];\n const selector = `.c-Dartboard-${ring.name} .c-Dartboard-bed--${target.segment}`;\n this.board.wrapper.selectAll(selector).classed(className, true);\n }\n }\n\n unhighlight(targets: BedInput[], options: HighlightOptions = {}): void {\n if (!this.board) return;\n const className = options.className || 'is-highlighted';\n\n for (const target of this.resolveTargets(targets)) {\n const ring = this.rings[target.ring];\n const selector = `.c-Dartboard-${ring.name} .c-Dartboard-bed--${target.segment}`;\n this.board.wrapper.selectAll(selector).classed(className, false);\n }\n }\n\n reset(className = 'is-highlighted'): void {\n if (!this.board) return;\n this.board.wrapper.selectAll(`.${className}`).classed(className, false);\n }\n\n addDart(targets: BedInput[]): this {\n if (!this.board || !this.sizes) return this;\n\n const resolved = this.resolveTargets(targets);\n const group = this.ensureDartGroup();\n const dartRadius = this.sizes.doubleBull * 0.25;\n\n for (const target of resolved) {\n const key = bedKey(target);\n const count = this.dartCounts.get(key) ?? 0;\n this.dartCounts.set(key, count + 1);\n\n const { centroid, midAngle, innerR, outerR } = this.bedGeometry(target);\n let cx: number;\n let cy: number;\n\n if (isBull(target.ring)) {\n // Distribute bull darts evenly around the ring at its midpoint radius.\n const midR = (innerR + outerR) / 2;\n const angle = (count * 2 * Math.PI) / DART_OFFSETS.length;\n cx = midR * Math.sin(angle);\n cy = -midR * Math.cos(angle);\n } else {\n const [radialFrac, tangentialFrac] = DART_OFFSETS[count % DART_OFFSETS.length];\n const thickness = outerR - innerR;\n\n // Radial unit (pointing outward from center)\n const radX = Math.sin(midAngle);\n const radY = -Math.cos(midAngle);\n // Tangential unit (perpendicular, along the arc)\n const tanX = Math.cos(midAngle);\n const tanY = Math.sin(midAngle);\n\n cx = centroid[0] + radialFrac * thickness * radX + tangentialFrac * thickness * tanX;\n cy = centroid[1] + radialFrac * thickness * radY + tangentialFrac * thickness * tanY;\n }\n\n group\n .append('circle')\n .classed('c-Dartboard-dart', true)\n .attr('cx', cx)\n .attr('cy', cy)\n .attr('r', dartRadius)\n .attr('data-bed', key);\n }\n\n return this;\n }\n\n removeDarts(targets?: BedInput[]): this {\n if (!this.dartGroup) return this;\n\n if (!targets) {\n this.dartGroup.selectAll('.c-Dartboard-dart').remove();\n this.dartCounts.clear();\n return this;\n }\n\n const resolved = this.resolveTargets(targets);\n for (const target of resolved) {\n const key = bedKey(target);\n this.dartGroup\n .selectAll(`.c-Dartboard-dart[data-bed=\"${key}\"]`)\n .remove();\n this.dartCounts.delete(key);\n }\n\n return this;\n }\n\n private ensureDartGroup(): D3Sel {\n if (!this.dartGroup) {\n this.dartGroup = this.board!.svg\n .append('g')\n .classed('c-Dartboard-darts', true);\n }\n return this.dartGroup;\n }\n\n private ringRadii(ringKey: RingKey): [number, number] {\n const s = this.sizes!;\n const doubleBullOuter = s.doubleBull;\n const singleBullOuter = doubleBullOuter + s.singleBull;\n const innerSingleOuter = singleBullOuter + s.innerSingle;\n const tripleOuter = innerSingleOuter + s.triple;\n const outerSingleOuter = tripleOuter + s.outerSingle;\n const doubleOuter = outerSingleOuter + s.double;\n\n switch (ringKey) {\n case 'DOUBLE_BULL': return [0, doubleBullOuter];\n case 'SINGLE_BULL': return [doubleBullOuter, singleBullOuter];\n case 'INNER_SINGLE': return [singleBullOuter, innerSingleOuter];\n case 'TRIPLE': return [innerSingleOuter, tripleOuter];\n case 'OUTER_SINGLE': return [tripleOuter, outerSingleOuter];\n case 'DOUBLE': return [outerSingleOuter, doubleOuter];\n case 'MISS': return [this.board!.radius - s.miss, this.board!.radius];\n }\n }\n\n private bedGeometry(target: Required<BedTarget>): {\n centroid: [number, number];\n midAngle: number;\n innerR: number;\n outerR: number;\n } {\n const [innerR, outerR] = this.ringRadii(target.ring);\n\n if (target.segment === 25) {\n return { centroid: [0, 0], midAngle: 0, innerR, outerR };\n }\n\n const seg = this.segments.find((s) => s.segment === target.segment);\n const segWidthRad = (this.board!.segmentWidth * Math.PI) / 180;\n const midAngle = ((seg?.position ?? 1) - 0.5) * segWidthRad;\n const midRadius = (innerR + outerR) / 2;\n\n return {\n centroid: [\n midRadius * Math.sin(midAngle),\n -midRadius * Math.cos(midAngle),\n ],\n midAngle,\n innerR,\n outerR,\n };\n }\n\n private isValidTarget(target: Required<BedTarget>): boolean {\n if (isBull(target.ring)) return target.segment === 25;\n return this.segments.some((s) => s.segment === target.segment);\n }\n\n private resolveTargets(inputs: BedInput[]): Required<BedTarget>[] {\n return inputs.flatMap((input): Required<BedTarget>[] => {\n if (typeof input === 'number') {\n return parseBed(String(input), this.rings, this.segments) as Required<BedTarget>[];\n }\n if (typeof input === 'string') {\n return parseBed(input, this.rings, this.segments) as Required<BedTarget>[];\n }\n if (!input.ring) {\n return parseBed(String(input.segment), this.rings, this.segments) as Required<BedTarget>[];\n }\n return [input as Required<BedTarget>];\n });\n }\n\n private dispatchThrow(bed: Bed): void {\n if (!this.board || this._disabled) return;\n const detail = buildThrowDetail(bed);\n this.board.container.dispatchEvent(\n new CustomEvent<ThrowDetail>('throw', { detail }),\n );\n }\n\n private dispatchHover(bed: Bed, hovering: boolean): void {\n if (!this.board || this._disabled) return;\n const throwDetail = buildThrowDetail(bed);\n const detail: HoverDetail = { ...throwDetail, hovering };\n this.board.container.dispatchEvent(\n new CustomEvent<HoverDetail>('hover', { detail }),\n );\n }\n\n private renderBeds(\n board: BoardState,\n ring: Ring,\n segments: Segment[],\n outerRadius: number,\n innerRadius: number,\n ): void {\n const className = `c-Dartboard-${ring.name}`;\n const arcFn = arc<PieArcDatum<Bed>>()\n .outerRadius(outerRadius)\n .innerRadius(innerRadius);\n\n const beds = board.svg\n .append('g')\n .classed(className, true)\n .selectAll<SVGGElement, PieArcDatum<Bed>>('arc')\n .data(board.pie(addRingToSegments(ring, segments)))\n .enter()\n .append('g')\n .attr(\n 'class',\n (d: PieArcDatum<Bed>) =>\n `c-Dartboard-bed c-Dartboard-bed--${d.data.segment} ${className}--${d.data.segment} is${d.data.color}`,\n )\n .attr('role', 'button')\n .attr('tabindex', '0')\n .attr('aria-label', (d: PieArcDatum<Bed>) =>\n buildAriaLabel(d.data),\n )\n .on(\n 'pointerup',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n this.dispatchThrow(d.data);\n },\n )\n .on(\n 'pointerenter',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n select(_event.currentTarget as Element).classed('is-hovered', true);\n this.dispatchHover(d.data, true);\n },\n )\n .on(\n 'pointerleave',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n select(_event.currentTarget as Element).classed('is-hovered', false);\n this.dispatchHover(d.data, false);\n },\n )\n .on(\n 'keydown',\n (_event: KeyboardEvent, d: PieArcDatum<Bed>) => {\n if (_event.key === 'Enter' || _event.key === ' ') {\n _event.preventDefault();\n this.dispatchThrow(d.data);\n }\n },\n );\n\n beds.append('path').attr('d', arcFn as never);\n }\n\n private renderMissRing(\n board: BoardState,\n ring: Ring,\n segments: Segment[],\n outerRadius: number,\n innerRadius: number,\n ): void {\n const missArc = arc<PieArcDatum<Bed>>()\n .outerRadius(outerRadius)\n .innerRadius(innerRadius);\n\n const missBeds = board.svg\n .append('g')\n .classed('c-Dartboard-miss', true)\n .selectAll<SVGGElement, PieArcDatum<Bed>>('arc')\n .data(board.pie(addRingToSegments(ring, segments)))\n .enter()\n .append('g')\n .attr(\n 'class',\n (d: PieArcDatum<Bed>) =>\n `c-Dartboard-bed c-Dartboard-bed--${d.data.segment} c-Dartboard-miss--${d.data.segment}`,\n )\n .attr('role', 'button')\n .attr('tabindex', '0')\n .attr('aria-label', (d: PieArcDatum<Bed>) =>\n buildAriaLabel(d.data),\n )\n .on(\n 'pointerup',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n this.dispatchThrow(d.data);\n },\n )\n .on(\n 'keydown',\n (_event: KeyboardEvent, d: PieArcDatum<Bed>) => {\n if (_event.key === 'Enter' || _event.key === ' ') {\n _event.preventDefault();\n this.dispatchThrow(d.data);\n }\n },\n );\n\n missBeds.append('path').attr('d', missArc as never);\n\n const determineRotation = (bedData: Bed) =>\n -board.rotation + board.segmentWidth * ((bedData.position ?? 0) - 1);\n\n const determineX = (d: PieArcDatum<Bed>) =>\n missArc.centroid(d)[0];\n\n const determineY = (d: PieArcDatum<Bed>) =>\n missArc.centroid(d)[1];\n\n missBeds\n .append('text')\n .classed('c-Dartboard-missLabel', true)\n .attr('x', (d: PieArcDatum<Bed>) => determineX(d))\n .attr('y', (d: PieArcDatum<Bed>) => determineY(d))\n .attr('dy', '.35em')\n .attr(\n 'transform',\n (d: PieArcDatum<Bed>) =>\n `rotate(${determineRotation(d.data)}, ${determineX(d)}, ${determineY(d)})`,\n )\n .attr('text-anchor', 'middle')\n .text((d: PieArcDatum<Bed>) => d.data.segment);\n }\n}\n","import type { DartboardOptions, Rings, Segment } from './types';\n\nexport const DEFAULT_OPTIONS: DartboardOptions = {\n size: null,\n padding: 2,\n missPercent: 10,\n doublePercent: 10,\n outerSinglePercent: 25,\n triplePercent: 10,\n innerSinglePercent: 30,\n singleBullPercent: 8,\n doubleBullPercent: 7,\n};\n\nexport const DEFAULT_RINGS: Rings = {\n MISS: { name: 'miss', abbr: 'M', multiplier: 0 },\n DOUBLE: { name: 'double', abbr: 'D', multiplier: 2 },\n OUTER_SINGLE: { name: 'outerSingle', abbr: 'S', multiplier: 1 },\n TRIPLE: { name: 'triple', abbr: 'T', multiplier: 3 },\n INNER_SINGLE: { name: 'innerSingle', abbr: 'S', multiplier: 1 },\n SINGLE_BULL: { name: 'singleBull', abbr: 'B', multiplier: 1 },\n DOUBLE_BULL: { name: 'doubleBull', abbr: 'DB', multiplier: 2 },\n};\n\nexport const MOBILE_OPTIONS: Partial<DartboardOptions> = {\n missPercent: 7,\n doublePercent: 14,\n outerSinglePercent: 21,\n triplePercent: 14,\n innerSinglePercent: 26,\n singleBullPercent: 9,\n doubleBullPercent: 9,\n};\n\nexport const DEFAULT_SEGMENTS: Segment[] = [\n { segment: 20, position: 1, color: 'Dark' },\n { segment: 1, position: 2, color: 'Light' },\n { segment: 18, position: 3, color: 'Dark' },\n { segment: 4, position: 4, color: 'Light' },\n { segment: 13, position: 5, color: 'Dark' },\n { segment: 6, position: 6, color: 'Light' },\n { segment: 10, position: 7, color: 'Dark' },\n { segment: 15, position: 8, color: 'Light' },\n { segment: 2, position: 9, color: 'Dark' },\n { segment: 17, position: 10, color: 'Light' },\n { segment: 3, position: 11, color: 'Dark' },\n { segment: 19, position: 12, color: 'Light' },\n { segment: 7, position: 13, color: 'Dark' },\n { segment: 16, position: 14, color: 'Light' },\n { segment: 8, position: 15, color: 'Dark' },\n { segment: 11, position: 16, color: 'Light' },\n { segment: 14, position: 17, color: 'Dark' },\n { segment: 9, position: 18, color: 'Light' },\n { segment: 12, position: 19, color: 'Dark' },\n { segment: 5, position: 20, color: 'Light' },\n];\n","import type { Ring, Rings, Segment, Bed, BedTarget, ThrowDetail } from './types';\n\nconst SCORING_RINGS: (keyof Rings)[] = [\n 'DOUBLE',\n 'TRIPLE',\n 'OUTER_SINGLE',\n 'INNER_SINGLE',\n 'SINGLE_BULL',\n 'DOUBLE_BULL',\n];\n\nexport function buildThrowDetail(bed: Bed): ThrowDetail {\n return {\n bed: bed.ring.abbr + bed.segment,\n segment: bed.segment,\n ring: bed.ring.name,\n score: bed.segment * bed.ring.multiplier,\n };\n}\n\nexport function asPercent(n: number): number {\n return parseFloat((n / 100).toFixed(2));\n}\n\nexport function addRingToSegments(ring: Ring, segments: Segment[]): Bed[] {\n return segments.map((segment) => ({ ...segment, ring }));\n}\n\nexport function parseBed(\n bed: string,\n rings: Rings,\n segments?: Segment[],\n): BedTarget[] {\n // 'miss' keyword — target all segments in the miss ring\n if (bed.toLowerCase() === 'miss') {\n if (!segments) {\n throw new Error(\n 'parseBed: segments are required to resolve the \"miss\" keyword',\n );\n }\n return segments.map((s) => ({ segment: s.segment, ring: 'MISS' as keyof Rings }));\n }\n\n // Number-only string — target all scoring rings on that segment\n const numOnly = bed.match(/^(\\d+)$/);\n if (numOnly) {\n const segment = parseInt(numOnly[1], 10);\n return SCORING_RINGS\n .filter((key) => key in rings)\n .map((ring) => ({ segment, ring }));\n }\n\n const match = bed.match(/^([A-Za-z]+)(\\d+)$/);\n if (!match) {\n throw new Error(`Invalid bed format: \"${bed}\"`);\n }\n\n const [, abbr, numStr] = match.map((s, i) => i === 1 ? s.toUpperCase() : s);\n const segment = parseInt(numStr, 10);\n\n const targets: BedTarget[] = [];\n for (const [key, ring] of Object.entries(rings)) {\n if (ring.abbr === abbr) {\n targets.push({ segment, ring: key as keyof Rings });\n }\n }\n\n if (targets.length === 0) {\n throw new Error(`Unknown bed abbreviation: \"${abbr}\"`);\n }\n\n return targets;\n}\n"],"mappings":"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","names":["segment"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/dartboard.ts","../src/constants.ts","../src/utils.ts"],"sourcesContent":["import './dartboard.css';\nexport { Dartboard } from './dartboard';\nexport type {\n Ring,\n Rings,\n Segment,\n Bed,\n DartboardOptions,\n ThrowDetail,\n HoverDetail,\n BedTarget,\n BedInput,\n HighlightOptions,\n} from './types';\nexport { DEFAULT_OPTIONS, MOBILE_OPTIONS, DEFAULT_RINGS, DEFAULT_SEGMENTS } from './constants';\nexport { buildThrowDetail, asPercent, addRingToSegments, parseBed } from './utils';\n","import { select, type Selection } from 'd3-selection';\nimport { arc, pie, type PieArcDatum } from 'd3-shape';\nimport type {\n DartboardOptions,\n Rings,\n Ring,\n Segment,\n Bed,\n ThrowDetail,\n HoverDetail,\n BedTarget,\n BedInput,\n HighlightOptions,\n} from './types';\nimport { DEFAULT_OPTIONS, DEFAULT_RINGS, DEFAULT_SEGMENTS } from './constants';\nimport { buildThrowDetail, asPercent, addRingToSegments, parseBed } from './utils';\n\ntype RingKey = keyof Rings;\n\n// D3's selection generics are deeply nested and don't compose well across\n// chained calls. Using `any` for internal state avoids 100+ lines of type\n// gymnastics while keeping the public API fully typed.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype D3Sel = Selection<any, any, any, any>;\n\ninterface BoardState {\n container: HTMLElement;\n wrapper: D3Sel;\n width: number;\n height: number;\n radius: number;\n rotation: number;\n segmentWidth: number;\n svg: D3Sel;\n pie: ReturnType<typeof pie<Bed>>;\n}\n\ninterface SizeMap {\n miss: number;\n double: number;\n outerSingle: number;\n triple: number;\n innerSingle: number;\n singleBull: number;\n doubleBull: number;\n}\n\nfunction buildAriaLabel(bed: Bed): string {\n const detail = buildThrowDetail(bed);\n return `${detail.bed}, scores ${detail.score}`;\n}\n\nfunction isBull(ringKey: RingKey): boolean {\n return ringKey === 'DOUBLE_BULL' || ringKey === 'SINGLE_BULL';\n}\n\nfunction bedKey(target: Required<BedTarget>): string {\n return `${target.ring}:${target.segment}`;\n}\n\n// Predefined offsets for multiple darts in the same bed.\n// [radialFraction, tangentialFraction] — scaled to ring thickness, oriented\n// along the bed's radial and arc directions so darts stay within the wedge.\nconst DART_OFFSETS: [number, number][] = [\n [0, 0],\n [-0.25, -0.25],\n [0.25, 0.25],\n [-0.25, 0.25],\n [0.25, -0.25],\n];\n\nexport class Dartboard {\n private board: BoardState | null = null;\n private sizes: SizeMap | null = null;\n private rendered = false;\n private _disabled = false;\n private dartGroup: D3Sel | null = null;\n private dartCounts = new Map<string, number>();\n private readonly options: DartboardOptions;\n readonly segments: Segment[];\n readonly rings: Rings;\n\n constructor(\n container: string | HTMLElement,\n options: Partial<DartboardOptions> = {},\n segments: Segment[] = DEFAULT_SEGMENTS,\n rings: Rings = DEFAULT_RINGS,\n ) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.segments = segments;\n this.rings = rings;\n\n const percentSum =\n this.options.missPercent +\n this.options.doublePercent +\n this.options.outerSinglePercent +\n this.options.triplePercent +\n this.options.innerSinglePercent +\n this.options.singleBullPercent +\n this.options.doubleBullPercent;\n\n if (percentSum !== 100) {\n throw new Error(\n `Dartboard: ring percentages must sum to 100 (got ${percentSum})`,\n );\n }\n\n const boardContainer =\n typeof container === 'string'\n ? document.querySelector<HTMLElement>(container)\n : container;\n\n if (!boardContainer) {\n throw new Error(`Dartboard: container not found`);\n }\n\n const padding = this.options.padding;\n const boardSize =\n this.options.size ||\n Math.min(boardContainer.offsetHeight, boardContainer.offsetWidth);\n const width = boardSize - padding * 2;\n const viewBoxSize = boardSize;\n const segmentWidth = 360 / segments.length;\n const radius = width / 2;\n const rotation = segmentWidth / -2;\n\n const wrapper = select(boardContainer)\n .append('div')\n .classed('c-Dartboard', true);\n\n const svg = wrapper\n .append('svg')\n .attr('viewBox', `0 0 ${viewBoxSize} ${viewBoxSize}`)\n .attr('role', 'group')\n .attr('aria-label', 'Dartboard')\n .append('g')\n .attr(\n 'transform',\n `translate(${viewBoxSize / 2}, ${viewBoxSize / 2}) rotate(${rotation})`,\n );\n\n const pieFn = pie<Bed>()\n .sort((a, b) => (a.position ?? 0) - (b.position ?? 0))\n .value(() => segmentWidth);\n\n this.board = {\n container: boardContainer,\n wrapper,\n width,\n height: width,\n radius,\n rotation,\n segmentWidth,\n svg,\n pie: pieFn,\n };\n\n this.sizes = {\n miss: radius * asPercent(this.options.missPercent),\n double: radius * asPercent(this.options.doublePercent),\n outerSingle: radius * asPercent(this.options.outerSinglePercent),\n triple: radius * asPercent(this.options.triplePercent),\n innerSingle: radius * asPercent(this.options.innerSinglePercent),\n singleBull: radius * asPercent(this.options.singleBullPercent),\n doubleBull: radius * asPercent(this.options.doubleBullPercent),\n };\n }\n\n render(): this {\n if (!this.board || !this.sizes) return this;\n if (this.rendered) return this;\n this.rendered = true;\n\n const { board, sizes } = this;\n\n let innerRadius = 0;\n let outerRadius = innerRadius + sizes.doubleBull;\n this.renderBeds(\n board,\n this.rings.DOUBLE_BULL,\n [{ segment: 25, color: 'Dark' }],\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.singleBull;\n this.renderBeds(\n board,\n this.rings.SINGLE_BULL,\n [{ segment: 25, color: 'Light' }],\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.innerSingle;\n this.renderBeds(\n board,\n this.rings.INNER_SINGLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.triple;\n this.renderBeds(\n board,\n this.rings.TRIPLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.outerSingle;\n this.renderBeds(\n board,\n this.rings.OUTER_SINGLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.double;\n this.renderBeds(\n board,\n this.rings.DOUBLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = board.radius - sizes.miss;\n outerRadius = board.radius;\n this.renderMissRing(\n board,\n this.rings.MISS,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n return this;\n }\n\n destroy(): void {\n if (this.board) {\n // Remove all D3 event listeners before removing from DOM\n this.board.wrapper.selectAll('.c-Dartboard-bed')\n .on('pointerup', null)\n .on('pointerenter', null)\n .on('pointerleave', null)\n .on('keydown', null);\n this.board.wrapper.remove();\n this.board = null;\n this.sizes = null;\n this.rendered = false;\n this.dartGroup = null;\n this.dartCounts.clear();\n }\n }\n\n get disabled(): boolean {\n return this._disabled;\n }\n\n disable(): this {\n this._disabled = true;\n if (this.board) {\n this.board.wrapper.classed('is-disabled', true);\n }\n return this;\n }\n\n enable(): this {\n this._disabled = false;\n if (this.board) {\n this.board.wrapper.classed('is-disabled', false);\n }\n return this;\n }\n\n throwAt(target: BedInput): void {\n if (!this.board || this._disabled) return;\n\n const targets = this.resolveTargets([target]);\n if (targets.length === 0) return;\n const first = targets[0];\n\n if (!this.isValidTarget(first)) {\n throw new Error(`Dartboard: invalid throw target — segment ${first.segment} does not exist`);\n }\n\n const ring = this.rings[first.ring];\n const bed: Bed = { segment: first.segment, color: 'Dark', ring };\n const detail = buildThrowDetail(bed);\n\n this.board.container.dispatchEvent(\n new CustomEvent<ThrowDetail>('throw', { detail }),\n );\n }\n\n highlight(targets: BedInput[], options: HighlightOptions = {}): void {\n if (!this.board) return;\n const className = options.className || 'is-highlighted';\n\n for (const target of this.resolveTargets(targets)) {\n const ring = this.rings[target.ring];\n const selector = `.c-Dartboard-${ring.name} .c-Dartboard-bed--${target.segment}`;\n this.board.wrapper.selectAll(selector).classed(className, true);\n }\n }\n\n unhighlight(targets: BedInput[], options: HighlightOptions = {}): void {\n if (!this.board) return;\n const className = options.className || 'is-highlighted';\n\n for (const target of this.resolveTargets(targets)) {\n const ring = this.rings[target.ring];\n const selector = `.c-Dartboard-${ring.name} .c-Dartboard-bed--${target.segment}`;\n this.board.wrapper.selectAll(selector).classed(className, false);\n }\n }\n\n reset(className = 'is-highlighted'): void {\n if (!this.board) return;\n this.board.wrapper.selectAll(`.${className}`).classed(className, false);\n }\n\n addDart(targets: BedInput[]): this {\n if (!this.board || !this.sizes) return this;\n\n const resolved = this.resolveTargets(targets);\n const group = this.ensureDartGroup();\n const dartRadius = this.sizes.doubleBull * 0.25;\n\n for (const target of resolved) {\n const key = bedKey(target);\n const count = this.dartCounts.get(key) ?? 0;\n this.dartCounts.set(key, count + 1);\n\n const { centroid, midAngle, innerR, outerR } = this.bedGeometry(target);\n let cx: number;\n let cy: number;\n\n if (isBull(target.ring)) {\n // Distribute bull darts evenly around the ring at its midpoint radius.\n const midR = (innerR + outerR) / 2;\n const angle = (count * 2 * Math.PI) / DART_OFFSETS.length;\n cx = midR * Math.sin(angle);\n cy = -midR * Math.cos(angle);\n } else {\n const [radialFrac, tangentialFrac] = DART_OFFSETS[count % DART_OFFSETS.length];\n const thickness = outerR - innerR;\n const midRadius = (innerR + outerR) / 2;\n const segWidthRad = (this.board.segmentWidth * Math.PI) / 180;\n // Arc half-width at the midpoint radius — limits tangential offsets\n // so darts stay within the segment's angular bounds.\n const arcHalfWidth = midRadius * Math.sin(segWidthRad / 2);\n\n // Radial unit (pointing outward from center)\n const radX = Math.sin(midAngle);\n const radY = -Math.cos(midAngle);\n // Tangential unit (perpendicular, along the arc)\n const tanX = Math.cos(midAngle);\n const tanY = Math.sin(midAngle);\n\n cx = centroid[0] + radialFrac * thickness * radX + tangentialFrac * arcHalfWidth * tanX;\n cy = centroid[1] + radialFrac * thickness * radY + tangentialFrac * arcHalfWidth * tanY;\n }\n\n group\n .append('circle')\n .classed('c-Dartboard-dart', true)\n .attr('cx', cx)\n .attr('cy', cy)\n .attr('r', dartRadius)\n .attr('data-bed', key);\n }\n\n return this;\n }\n\n removeDarts(targets?: BedInput[]): this {\n if (!this.dartGroup) return this;\n\n if (!targets) {\n this.dartGroup.selectAll('.c-Dartboard-dart').remove();\n this.dartCounts.clear();\n return this;\n }\n\n const resolved = this.resolveTargets(targets);\n for (const target of resolved) {\n const key = bedKey(target);\n this.dartGroup\n .selectAll(`.c-Dartboard-dart[data-bed=\"${key}\"]`)\n .remove();\n this.dartCounts.delete(key);\n }\n\n return this;\n }\n\n private ensureDartGroup(): D3Sel {\n if (!this.dartGroup) {\n this.dartGroup = this.board!.svg\n .append('g')\n .classed('c-Dartboard-darts', true);\n }\n return this.dartGroup;\n }\n\n private ringRadii(ringKey: RingKey): [number, number] {\n const s = this.sizes!;\n const doubleBullOuter = s.doubleBull;\n const singleBullOuter = doubleBullOuter + s.singleBull;\n const innerSingleOuter = singleBullOuter + s.innerSingle;\n const tripleOuter = innerSingleOuter + s.triple;\n const outerSingleOuter = tripleOuter + s.outerSingle;\n const doubleOuter = outerSingleOuter + s.double;\n\n switch (ringKey) {\n case 'DOUBLE_BULL': return [0, doubleBullOuter];\n case 'SINGLE_BULL': return [doubleBullOuter, singleBullOuter];\n case 'INNER_SINGLE': return [singleBullOuter, innerSingleOuter];\n case 'TRIPLE': return [innerSingleOuter, tripleOuter];\n case 'OUTER_SINGLE': return [tripleOuter, outerSingleOuter];\n case 'DOUBLE': return [outerSingleOuter, doubleOuter];\n case 'MISS': return [this.board!.radius - s.miss, this.board!.radius];\n }\n }\n\n private bedGeometry(target: Required<BedTarget>): {\n centroid: [number, number];\n midAngle: number;\n innerR: number;\n outerR: number;\n } {\n const [innerR, outerR] = this.ringRadii(target.ring);\n\n if (target.segment === 25) {\n return { centroid: [0, 0], midAngle: 0, innerR, outerR };\n }\n\n const seg = this.segments.find((s) => s.segment === target.segment);\n const segWidthRad = (this.board!.segmentWidth * Math.PI) / 180;\n const midAngle = ((seg?.position ?? 1) - 0.5) * segWidthRad;\n const midRadius = (innerR + outerR) / 2;\n\n return {\n centroid: [\n midRadius * Math.sin(midAngle),\n -midRadius * Math.cos(midAngle),\n ],\n midAngle,\n innerR,\n outerR,\n };\n }\n\n private isValidTarget(target: Required<BedTarget>): boolean {\n if (isBull(target.ring)) return target.segment === 25;\n return this.segments.some((s) => s.segment === target.segment);\n }\n\n private resolveTargets(inputs: BedInput[]): Required<BedTarget>[] {\n return inputs.flatMap((input): Required<BedTarget>[] => {\n if (typeof input === 'number') {\n return parseBed(String(input), this.rings, this.segments) as Required<BedTarget>[];\n }\n if (typeof input === 'string') {\n return parseBed(input, this.rings, this.segments) as Required<BedTarget>[];\n }\n if (!input.ring) {\n return parseBed(String(input.segment), this.rings, this.segments) as Required<BedTarget>[];\n }\n return [input as Required<BedTarget>];\n });\n }\n\n private dispatchThrow(bed: Bed): void {\n if (!this.board || this._disabled) return;\n const detail = buildThrowDetail(bed);\n this.board.container.dispatchEvent(\n new CustomEvent<ThrowDetail>('throw', { detail }),\n );\n }\n\n private dispatchHover(bed: Bed, hovering: boolean): void {\n if (!this.board || this._disabled) return;\n const throwDetail = buildThrowDetail(bed);\n const detail: HoverDetail = { ...throwDetail, hovering };\n this.board.container.dispatchEvent(\n new CustomEvent<HoverDetail>('hover', { detail }),\n );\n }\n\n private renderBeds(\n board: BoardState,\n ring: Ring,\n segments: Segment[],\n outerRadius: number,\n innerRadius: number,\n ): void {\n const className = `c-Dartboard-${ring.name}`;\n const arcFn = arc<PieArcDatum<Bed>>()\n .outerRadius(outerRadius)\n .innerRadius(innerRadius);\n\n const beds = board.svg\n .append('g')\n .classed(className, true)\n .selectAll<SVGGElement, PieArcDatum<Bed>>('arc')\n .data(board.pie(addRingToSegments(ring, segments)))\n .enter()\n .append('g')\n .attr(\n 'class',\n (d: PieArcDatum<Bed>) =>\n `c-Dartboard-bed c-Dartboard-bed--${d.data.segment} ${className}--${d.data.segment} is${d.data.color}`,\n )\n .attr('role', 'button')\n .attr('tabindex', '0')\n .attr('aria-label', (d: PieArcDatum<Bed>) =>\n buildAriaLabel(d.data),\n )\n .on(\n 'pointerup',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n this.dispatchThrow(d.data);\n },\n )\n .on(\n 'pointerenter',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n select(_event.currentTarget as Element).classed('is-hovered', true);\n this.dispatchHover(d.data, true);\n },\n )\n .on(\n 'pointerleave',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n select(_event.currentTarget as Element).classed('is-hovered', false);\n this.dispatchHover(d.data, false);\n },\n )\n .on(\n 'keydown',\n (_event: KeyboardEvent, d: PieArcDatum<Bed>) => {\n if (_event.key === 'Enter' || _event.key === ' ') {\n _event.preventDefault();\n this.dispatchThrow(d.data);\n }\n },\n );\n\n beds.append('path').attr('d', arcFn as never);\n }\n\n private renderMissRing(\n board: BoardState,\n ring: Ring,\n segments: Segment[],\n outerRadius: number,\n innerRadius: number,\n ): void {\n const missArc = arc<PieArcDatum<Bed>>()\n .outerRadius(outerRadius)\n .innerRadius(innerRadius);\n\n const missBeds = board.svg\n .append('g')\n .classed('c-Dartboard-miss', true)\n .selectAll<SVGGElement, PieArcDatum<Bed>>('arc')\n .data(board.pie(addRingToSegments(ring, segments)))\n .enter()\n .append('g')\n .attr(\n 'class',\n (d: PieArcDatum<Bed>) =>\n `c-Dartboard-bed c-Dartboard-bed--${d.data.segment} c-Dartboard-miss--${d.data.segment}`,\n )\n .attr('role', 'button')\n .attr('tabindex', '0')\n .attr('aria-label', (d: PieArcDatum<Bed>) =>\n buildAriaLabel(d.data),\n )\n .on(\n 'pointerup',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n this.dispatchThrow(d.data);\n },\n )\n .on(\n 'keydown',\n (_event: KeyboardEvent, d: PieArcDatum<Bed>) => {\n if (_event.key === 'Enter' || _event.key === ' ') {\n _event.preventDefault();\n this.dispatchThrow(d.data);\n }\n },\n );\n\n missBeds.append('path').attr('d', missArc as never);\n\n const determineRotation = (bedData: Bed) =>\n -board.rotation + board.segmentWidth * ((bedData.position ?? 0) - 1);\n\n const determineX = (d: PieArcDatum<Bed>) =>\n missArc.centroid(d)[0];\n\n const determineY = (d: PieArcDatum<Bed>) =>\n missArc.centroid(d)[1];\n\n missBeds\n .append('text')\n .classed('c-Dartboard-missLabel', true)\n .attr('x', (d: PieArcDatum<Bed>) => determineX(d))\n .attr('y', (d: PieArcDatum<Bed>) => determineY(d))\n .attr('dy', '.35em')\n .attr(\n 'transform',\n (d: PieArcDatum<Bed>) =>\n `rotate(${determineRotation(d.data)}, ${determineX(d)}, ${determineY(d)})`,\n )\n .attr('text-anchor', 'middle')\n .text((d: PieArcDatum<Bed>) => d.data.segment);\n }\n}\n","import type { DartboardOptions, Rings, Segment } from './types';\n\nexport const DEFAULT_OPTIONS: DartboardOptions = {\n size: null,\n padding: 2,\n missPercent: 10,\n doublePercent: 10,\n outerSinglePercent: 25,\n triplePercent: 10,\n innerSinglePercent: 30,\n singleBullPercent: 8,\n doubleBullPercent: 7,\n};\n\nexport const DEFAULT_RINGS: Rings = {\n MISS: { name: 'miss', abbr: 'M', multiplier: 0 },\n DOUBLE: { name: 'double', abbr: 'D', multiplier: 2 },\n OUTER_SINGLE: { name: 'outerSingle', abbr: 'S', multiplier: 1 },\n TRIPLE: { name: 'triple', abbr: 'T', multiplier: 3 },\n INNER_SINGLE: { name: 'innerSingle', abbr: 'S', multiplier: 1 },\n SINGLE_BULL: { name: 'singleBull', abbr: 'B', multiplier: 1 },\n DOUBLE_BULL: { name: 'doubleBull', abbr: 'DB', multiplier: 2 },\n};\n\nexport const MOBILE_OPTIONS: Partial<DartboardOptions> = {\n missPercent: 7,\n doublePercent: 14,\n outerSinglePercent: 21,\n triplePercent: 14,\n innerSinglePercent: 26,\n singleBullPercent: 9,\n doubleBullPercent: 9,\n};\n\nexport const DEFAULT_SEGMENTS: Segment[] = [\n { segment: 20, position: 1, color: 'Dark' },\n { segment: 1, position: 2, color: 'Light' },\n { segment: 18, position: 3, color: 'Dark' },\n { segment: 4, position: 4, color: 'Light' },\n { segment: 13, position: 5, color: 'Dark' },\n { segment: 6, position: 6, color: 'Light' },\n { segment: 10, position: 7, color: 'Dark' },\n { segment: 15, position: 8, color: 'Light' },\n { segment: 2, position: 9, color: 'Dark' },\n { segment: 17, position: 10, color: 'Light' },\n { segment: 3, position: 11, color: 'Dark' },\n { segment: 19, position: 12, color: 'Light' },\n { segment: 7, position: 13, color: 'Dark' },\n { segment: 16, position: 14, color: 'Light' },\n { segment: 8, position: 15, color: 'Dark' },\n { segment: 11, position: 16, color: 'Light' },\n { segment: 14, position: 17, color: 'Dark' },\n { segment: 9, position: 18, color: 'Light' },\n { segment: 12, position: 19, color: 'Dark' },\n { segment: 5, position: 20, color: 'Light' },\n];\n","import type { Ring, Rings, Segment, Bed, BedTarget, ThrowDetail } from './types';\n\nconst SCORING_RINGS: (keyof Rings)[] = [\n 'DOUBLE',\n 'TRIPLE',\n 'OUTER_SINGLE',\n 'INNER_SINGLE',\n 'SINGLE_BULL',\n 'DOUBLE_BULL',\n];\n\nexport function buildThrowDetail(bed: Bed): ThrowDetail {\n return {\n bed: bed.ring.abbr + bed.segment,\n segment: bed.segment,\n ring: bed.ring.name,\n score: bed.segment * bed.ring.multiplier,\n };\n}\n\nexport function asPercent(n: number): number {\n return parseFloat((n / 100).toFixed(2));\n}\n\nexport function addRingToSegments(ring: Ring, segments: Segment[]): Bed[] {\n return segments.map((segment) => ({ ...segment, ring }));\n}\n\nexport function parseBed(\n bed: string,\n rings: Rings,\n segments?: Segment[],\n): BedTarget[] {\n // 'miss' keyword — target all segments in the miss ring\n if (bed.toLowerCase() === 'miss') {\n if (!segments) {\n throw new Error(\n 'parseBed: segments are required to resolve the \"miss\" keyword',\n );\n }\n return segments.map((s) => ({ segment: s.segment, ring: 'MISS' as keyof Rings }));\n }\n\n // Number-only string — target all scoring rings on that segment\n const numOnly = bed.match(/^(\\d+)$/);\n if (numOnly) {\n const segment = parseInt(numOnly[1], 10);\n return SCORING_RINGS\n .filter((key) => key in rings)\n .map((ring) => ({ segment, ring }));\n }\n\n const match = bed.match(/^([A-Za-z]+)(\\d+)$/);\n if (!match) {\n throw new Error(`Invalid bed format: \"${bed}\"`);\n }\n\n const [, abbr, numStr] = match.map((s, i) => i === 1 ? s.toUpperCase() : s);\n const segment = parseInt(numStr, 10);\n\n const targets: BedTarget[] = [];\n for (const [key, ring] of Object.entries(rings)) {\n if (ring.abbr === abbr) {\n targets.push({ segment, ring: key as keyof Rings });\n }\n }\n\n if (targets.length === 0) {\n throw new Error(`Unknown bed abbreviation: \"${abbr}\"`);\n }\n\n return targets;\n}\n"],"mappings":"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","names":["segment"]}
package/dist/index.js CHANGED
@@ -338,12 +338,15 @@ var Dartboard = class {
338
338
  } else {
339
339
  const [radialFrac, tangentialFrac] = DART_OFFSETS[count % DART_OFFSETS.length];
340
340
  const thickness = outerR - innerR;
341
+ const midRadius = (innerR + outerR) / 2;
342
+ const segWidthRad = this.board.segmentWidth * Math.PI / 180;
343
+ const arcHalfWidth = midRadius * Math.sin(segWidthRad / 2);
341
344
  const radX = Math.sin(midAngle);
342
345
  const radY = -Math.cos(midAngle);
343
346
  const tanX = Math.cos(midAngle);
344
347
  const tanY = Math.sin(midAngle);
345
- cx = centroid[0] + radialFrac * thickness * radX + tangentialFrac * thickness * tanX;
346
- cy = centroid[1] + radialFrac * thickness * radY + tangentialFrac * thickness * tanY;
348
+ cx = centroid[0] + radialFrac * thickness * radX + tangentialFrac * arcHalfWidth * tanX;
349
+ cy = centroid[1] + radialFrac * thickness * radY + tangentialFrac * arcHalfWidth * tanY;
347
350
  }
348
351
  group.append("circle").classed("c-Dartboard-dart", true).attr("cx", cx).attr("cy", cy).attr("r", dartRadius).attr("data-bed", key);
349
352
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dartboard.ts","../src/constants.ts","../src/utils.ts"],"sourcesContent":["import { select, type Selection } from 'd3-selection';\nimport { arc, pie, type PieArcDatum } from 'd3-shape';\nimport type {\n DartboardOptions,\n Rings,\n Ring,\n Segment,\n Bed,\n ThrowDetail,\n HoverDetail,\n BedTarget,\n BedInput,\n HighlightOptions,\n} from './types';\nimport { DEFAULT_OPTIONS, DEFAULT_RINGS, DEFAULT_SEGMENTS } from './constants';\nimport { buildThrowDetail, asPercent, addRingToSegments, parseBed } from './utils';\n\ntype RingKey = keyof Rings;\n\n// D3's selection generics are deeply nested and don't compose well across\n// chained calls. Using `any` for internal state avoids 100+ lines of type\n// gymnastics while keeping the public API fully typed.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype D3Sel = Selection<any, any, any, any>;\n\ninterface BoardState {\n container: HTMLElement;\n wrapper: D3Sel;\n width: number;\n height: number;\n radius: number;\n rotation: number;\n segmentWidth: number;\n svg: D3Sel;\n pie: ReturnType<typeof pie<Bed>>;\n}\n\ninterface SizeMap {\n miss: number;\n double: number;\n outerSingle: number;\n triple: number;\n innerSingle: number;\n singleBull: number;\n doubleBull: number;\n}\n\nfunction buildAriaLabel(bed: Bed): string {\n const detail = buildThrowDetail(bed);\n return `${detail.bed}, scores ${detail.score}`;\n}\n\nfunction isBull(ringKey: RingKey): boolean {\n return ringKey === 'DOUBLE_BULL' || ringKey === 'SINGLE_BULL';\n}\n\nfunction bedKey(target: Required<BedTarget>): string {\n return `${target.ring}:${target.segment}`;\n}\n\n// Predefined offsets for multiple darts in the same bed.\n// [radialFraction, tangentialFraction] — scaled to ring thickness, oriented\n// along the bed's radial and arc directions so darts stay within the wedge.\nconst DART_OFFSETS: [number, number][] = [\n [0, 0],\n [-0.25, -0.25],\n [0.25, 0.25],\n [-0.25, 0.25],\n [0.25, -0.25],\n];\n\nexport class Dartboard {\n private board: BoardState | null = null;\n private sizes: SizeMap | null = null;\n private rendered = false;\n private _disabled = false;\n private dartGroup: D3Sel | null = null;\n private dartCounts = new Map<string, number>();\n private readonly options: DartboardOptions;\n readonly segments: Segment[];\n readonly rings: Rings;\n\n constructor(\n container: string | HTMLElement,\n options: Partial<DartboardOptions> = {},\n segments: Segment[] = DEFAULT_SEGMENTS,\n rings: Rings = DEFAULT_RINGS,\n ) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.segments = segments;\n this.rings = rings;\n\n const percentSum =\n this.options.missPercent +\n this.options.doublePercent +\n this.options.outerSinglePercent +\n this.options.triplePercent +\n this.options.innerSinglePercent +\n this.options.singleBullPercent +\n this.options.doubleBullPercent;\n\n if (percentSum !== 100) {\n throw new Error(\n `Dartboard: ring percentages must sum to 100 (got ${percentSum})`,\n );\n }\n\n const boardContainer =\n typeof container === 'string'\n ? document.querySelector<HTMLElement>(container)\n : container;\n\n if (!boardContainer) {\n throw new Error(`Dartboard: container not found`);\n }\n\n const padding = this.options.padding;\n const boardSize =\n this.options.size ||\n Math.min(boardContainer.offsetHeight, boardContainer.offsetWidth);\n const width = boardSize - padding * 2;\n const viewBoxSize = boardSize;\n const segmentWidth = 360 / segments.length;\n const radius = width / 2;\n const rotation = segmentWidth / -2;\n\n const wrapper = select(boardContainer)\n .append('div')\n .classed('c-Dartboard', true);\n\n const svg = wrapper\n .append('svg')\n .attr('viewBox', `0 0 ${viewBoxSize} ${viewBoxSize}`)\n .attr('role', 'group')\n .attr('aria-label', 'Dartboard')\n .append('g')\n .attr(\n 'transform',\n `translate(${viewBoxSize / 2}, ${viewBoxSize / 2}) rotate(${rotation})`,\n );\n\n const pieFn = pie<Bed>()\n .sort((a, b) => (a.position ?? 0) - (b.position ?? 0))\n .value(() => segmentWidth);\n\n this.board = {\n container: boardContainer,\n wrapper,\n width,\n height: width,\n radius,\n rotation,\n segmentWidth,\n svg,\n pie: pieFn,\n };\n\n this.sizes = {\n miss: radius * asPercent(this.options.missPercent),\n double: radius * asPercent(this.options.doublePercent),\n outerSingle: radius * asPercent(this.options.outerSinglePercent),\n triple: radius * asPercent(this.options.triplePercent),\n innerSingle: radius * asPercent(this.options.innerSinglePercent),\n singleBull: radius * asPercent(this.options.singleBullPercent),\n doubleBull: radius * asPercent(this.options.doubleBullPercent),\n };\n }\n\n render(): this {\n if (!this.board || !this.sizes) return this;\n if (this.rendered) return this;\n this.rendered = true;\n\n const { board, sizes } = this;\n\n let innerRadius = 0;\n let outerRadius = innerRadius + sizes.doubleBull;\n this.renderBeds(\n board,\n this.rings.DOUBLE_BULL,\n [{ segment: 25, color: 'Dark' }],\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.singleBull;\n this.renderBeds(\n board,\n this.rings.SINGLE_BULL,\n [{ segment: 25, color: 'Light' }],\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.innerSingle;\n this.renderBeds(\n board,\n this.rings.INNER_SINGLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.triple;\n this.renderBeds(\n board,\n this.rings.TRIPLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.outerSingle;\n this.renderBeds(\n board,\n this.rings.OUTER_SINGLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.double;\n this.renderBeds(\n board,\n this.rings.DOUBLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = board.radius - sizes.miss;\n outerRadius = board.radius;\n this.renderMissRing(\n board,\n this.rings.MISS,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n return this;\n }\n\n destroy(): void {\n if (this.board) {\n // Remove all D3 event listeners before removing from DOM\n this.board.wrapper.selectAll('.c-Dartboard-bed')\n .on('pointerup', null)\n .on('pointerenter', null)\n .on('pointerleave', null)\n .on('keydown', null);\n this.board.wrapper.remove();\n this.board = null;\n this.sizes = null;\n this.rendered = false;\n this.dartGroup = null;\n this.dartCounts.clear();\n }\n }\n\n get disabled(): boolean {\n return this._disabled;\n }\n\n disable(): this {\n this._disabled = true;\n if (this.board) {\n this.board.wrapper.classed('is-disabled', true);\n }\n return this;\n }\n\n enable(): this {\n this._disabled = false;\n if (this.board) {\n this.board.wrapper.classed('is-disabled', false);\n }\n return this;\n }\n\n throwAt(target: BedInput): void {\n if (!this.board || this._disabled) return;\n\n const targets = this.resolveTargets([target]);\n if (targets.length === 0) return;\n const first = targets[0];\n\n if (!this.isValidTarget(first)) {\n throw new Error(`Dartboard: invalid throw target — segment ${first.segment} does not exist`);\n }\n\n const ring = this.rings[first.ring];\n const bed: Bed = { segment: first.segment, color: 'Dark', ring };\n const detail = buildThrowDetail(bed);\n\n this.board.container.dispatchEvent(\n new CustomEvent<ThrowDetail>('throw', { detail }),\n );\n }\n\n highlight(targets: BedInput[], options: HighlightOptions = {}): void {\n if (!this.board) return;\n const className = options.className || 'is-highlighted';\n\n for (const target of this.resolveTargets(targets)) {\n const ring = this.rings[target.ring];\n const selector = `.c-Dartboard-${ring.name} .c-Dartboard-bed--${target.segment}`;\n this.board.wrapper.selectAll(selector).classed(className, true);\n }\n }\n\n unhighlight(targets: BedInput[], options: HighlightOptions = {}): void {\n if (!this.board) return;\n const className = options.className || 'is-highlighted';\n\n for (const target of this.resolveTargets(targets)) {\n const ring = this.rings[target.ring];\n const selector = `.c-Dartboard-${ring.name} .c-Dartboard-bed--${target.segment}`;\n this.board.wrapper.selectAll(selector).classed(className, false);\n }\n }\n\n reset(className = 'is-highlighted'): void {\n if (!this.board) return;\n this.board.wrapper.selectAll(`.${className}`).classed(className, false);\n }\n\n addDart(targets: BedInput[]): this {\n if (!this.board || !this.sizes) return this;\n\n const resolved = this.resolveTargets(targets);\n const group = this.ensureDartGroup();\n const dartRadius = this.sizes.doubleBull * 0.25;\n\n for (const target of resolved) {\n const key = bedKey(target);\n const count = this.dartCounts.get(key) ?? 0;\n this.dartCounts.set(key, count + 1);\n\n const { centroid, midAngle, innerR, outerR } = this.bedGeometry(target);\n let cx: number;\n let cy: number;\n\n if (isBull(target.ring)) {\n // Distribute bull darts evenly around the ring at its midpoint radius.\n const midR = (innerR + outerR) / 2;\n const angle = (count * 2 * Math.PI) / DART_OFFSETS.length;\n cx = midR * Math.sin(angle);\n cy = -midR * Math.cos(angle);\n } else {\n const [radialFrac, tangentialFrac] = DART_OFFSETS[count % DART_OFFSETS.length];\n const thickness = outerR - innerR;\n\n // Radial unit (pointing outward from center)\n const radX = Math.sin(midAngle);\n const radY = -Math.cos(midAngle);\n // Tangential unit (perpendicular, along the arc)\n const tanX = Math.cos(midAngle);\n const tanY = Math.sin(midAngle);\n\n cx = centroid[0] + radialFrac * thickness * radX + tangentialFrac * thickness * tanX;\n cy = centroid[1] + radialFrac * thickness * radY + tangentialFrac * thickness * tanY;\n }\n\n group\n .append('circle')\n .classed('c-Dartboard-dart', true)\n .attr('cx', cx)\n .attr('cy', cy)\n .attr('r', dartRadius)\n .attr('data-bed', key);\n }\n\n return this;\n }\n\n removeDarts(targets?: BedInput[]): this {\n if (!this.dartGroup) return this;\n\n if (!targets) {\n this.dartGroup.selectAll('.c-Dartboard-dart').remove();\n this.dartCounts.clear();\n return this;\n }\n\n const resolved = this.resolveTargets(targets);\n for (const target of resolved) {\n const key = bedKey(target);\n this.dartGroup\n .selectAll(`.c-Dartboard-dart[data-bed=\"${key}\"]`)\n .remove();\n this.dartCounts.delete(key);\n }\n\n return this;\n }\n\n private ensureDartGroup(): D3Sel {\n if (!this.dartGroup) {\n this.dartGroup = this.board!.svg\n .append('g')\n .classed('c-Dartboard-darts', true);\n }\n return this.dartGroup;\n }\n\n private ringRadii(ringKey: RingKey): [number, number] {\n const s = this.sizes!;\n const doubleBullOuter = s.doubleBull;\n const singleBullOuter = doubleBullOuter + s.singleBull;\n const innerSingleOuter = singleBullOuter + s.innerSingle;\n const tripleOuter = innerSingleOuter + s.triple;\n const outerSingleOuter = tripleOuter + s.outerSingle;\n const doubleOuter = outerSingleOuter + s.double;\n\n switch (ringKey) {\n case 'DOUBLE_BULL': return [0, doubleBullOuter];\n case 'SINGLE_BULL': return [doubleBullOuter, singleBullOuter];\n case 'INNER_SINGLE': return [singleBullOuter, innerSingleOuter];\n case 'TRIPLE': return [innerSingleOuter, tripleOuter];\n case 'OUTER_SINGLE': return [tripleOuter, outerSingleOuter];\n case 'DOUBLE': return [outerSingleOuter, doubleOuter];\n case 'MISS': return [this.board!.radius - s.miss, this.board!.radius];\n }\n }\n\n private bedGeometry(target: Required<BedTarget>): {\n centroid: [number, number];\n midAngle: number;\n innerR: number;\n outerR: number;\n } {\n const [innerR, outerR] = this.ringRadii(target.ring);\n\n if (target.segment === 25) {\n return { centroid: [0, 0], midAngle: 0, innerR, outerR };\n }\n\n const seg = this.segments.find((s) => s.segment === target.segment);\n const segWidthRad = (this.board!.segmentWidth * Math.PI) / 180;\n const midAngle = ((seg?.position ?? 1) - 0.5) * segWidthRad;\n const midRadius = (innerR + outerR) / 2;\n\n return {\n centroid: [\n midRadius * Math.sin(midAngle),\n -midRadius * Math.cos(midAngle),\n ],\n midAngle,\n innerR,\n outerR,\n };\n }\n\n private isValidTarget(target: Required<BedTarget>): boolean {\n if (isBull(target.ring)) return target.segment === 25;\n return this.segments.some((s) => s.segment === target.segment);\n }\n\n private resolveTargets(inputs: BedInput[]): Required<BedTarget>[] {\n return inputs.flatMap((input): Required<BedTarget>[] => {\n if (typeof input === 'number') {\n return parseBed(String(input), this.rings, this.segments) as Required<BedTarget>[];\n }\n if (typeof input === 'string') {\n return parseBed(input, this.rings, this.segments) as Required<BedTarget>[];\n }\n if (!input.ring) {\n return parseBed(String(input.segment), this.rings, this.segments) as Required<BedTarget>[];\n }\n return [input as Required<BedTarget>];\n });\n }\n\n private dispatchThrow(bed: Bed): void {\n if (!this.board || this._disabled) return;\n const detail = buildThrowDetail(bed);\n this.board.container.dispatchEvent(\n new CustomEvent<ThrowDetail>('throw', { detail }),\n );\n }\n\n private dispatchHover(bed: Bed, hovering: boolean): void {\n if (!this.board || this._disabled) return;\n const throwDetail = buildThrowDetail(bed);\n const detail: HoverDetail = { ...throwDetail, hovering };\n this.board.container.dispatchEvent(\n new CustomEvent<HoverDetail>('hover', { detail }),\n );\n }\n\n private renderBeds(\n board: BoardState,\n ring: Ring,\n segments: Segment[],\n outerRadius: number,\n innerRadius: number,\n ): void {\n const className = `c-Dartboard-${ring.name}`;\n const arcFn = arc<PieArcDatum<Bed>>()\n .outerRadius(outerRadius)\n .innerRadius(innerRadius);\n\n const beds = board.svg\n .append('g')\n .classed(className, true)\n .selectAll<SVGGElement, PieArcDatum<Bed>>('arc')\n .data(board.pie(addRingToSegments(ring, segments)))\n .enter()\n .append('g')\n .attr(\n 'class',\n (d: PieArcDatum<Bed>) =>\n `c-Dartboard-bed c-Dartboard-bed--${d.data.segment} ${className}--${d.data.segment} is${d.data.color}`,\n )\n .attr('role', 'button')\n .attr('tabindex', '0')\n .attr('aria-label', (d: PieArcDatum<Bed>) =>\n buildAriaLabel(d.data),\n )\n .on(\n 'pointerup',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n this.dispatchThrow(d.data);\n },\n )\n .on(\n 'pointerenter',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n select(_event.currentTarget as Element).classed('is-hovered', true);\n this.dispatchHover(d.data, true);\n },\n )\n .on(\n 'pointerleave',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n select(_event.currentTarget as Element).classed('is-hovered', false);\n this.dispatchHover(d.data, false);\n },\n )\n .on(\n 'keydown',\n (_event: KeyboardEvent, d: PieArcDatum<Bed>) => {\n if (_event.key === 'Enter' || _event.key === ' ') {\n _event.preventDefault();\n this.dispatchThrow(d.data);\n }\n },\n );\n\n beds.append('path').attr('d', arcFn as never);\n }\n\n private renderMissRing(\n board: BoardState,\n ring: Ring,\n segments: Segment[],\n outerRadius: number,\n innerRadius: number,\n ): void {\n const missArc = arc<PieArcDatum<Bed>>()\n .outerRadius(outerRadius)\n .innerRadius(innerRadius);\n\n const missBeds = board.svg\n .append('g')\n .classed('c-Dartboard-miss', true)\n .selectAll<SVGGElement, PieArcDatum<Bed>>('arc')\n .data(board.pie(addRingToSegments(ring, segments)))\n .enter()\n .append('g')\n .attr(\n 'class',\n (d: PieArcDatum<Bed>) =>\n `c-Dartboard-bed c-Dartboard-bed--${d.data.segment} c-Dartboard-miss--${d.data.segment}`,\n )\n .attr('role', 'button')\n .attr('tabindex', '0')\n .attr('aria-label', (d: PieArcDatum<Bed>) =>\n buildAriaLabel(d.data),\n )\n .on(\n 'pointerup',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n this.dispatchThrow(d.data);\n },\n )\n .on(\n 'keydown',\n (_event: KeyboardEvent, d: PieArcDatum<Bed>) => {\n if (_event.key === 'Enter' || _event.key === ' ') {\n _event.preventDefault();\n this.dispatchThrow(d.data);\n }\n },\n );\n\n missBeds.append('path').attr('d', missArc as never);\n\n const determineRotation = (bedData: Bed) =>\n -board.rotation + board.segmentWidth * ((bedData.position ?? 0) - 1);\n\n const determineX = (d: PieArcDatum<Bed>) =>\n missArc.centroid(d)[0];\n\n const determineY = (d: PieArcDatum<Bed>) =>\n missArc.centroid(d)[1];\n\n missBeds\n .append('text')\n .classed('c-Dartboard-missLabel', true)\n .attr('x', (d: PieArcDatum<Bed>) => determineX(d))\n .attr('y', (d: PieArcDatum<Bed>) => determineY(d))\n .attr('dy', '.35em')\n .attr(\n 'transform',\n (d: PieArcDatum<Bed>) =>\n `rotate(${determineRotation(d.data)}, ${determineX(d)}, ${determineY(d)})`,\n )\n .attr('text-anchor', 'middle')\n .text((d: PieArcDatum<Bed>) => d.data.segment);\n }\n}\n","import type { DartboardOptions, Rings, Segment } from './types';\n\nexport const DEFAULT_OPTIONS: DartboardOptions = {\n size: null,\n padding: 2,\n missPercent: 10,\n doublePercent: 10,\n outerSinglePercent: 25,\n triplePercent: 10,\n innerSinglePercent: 30,\n singleBullPercent: 8,\n doubleBullPercent: 7,\n};\n\nexport const DEFAULT_RINGS: Rings = {\n MISS: { name: 'miss', abbr: 'M', multiplier: 0 },\n DOUBLE: { name: 'double', abbr: 'D', multiplier: 2 },\n OUTER_SINGLE: { name: 'outerSingle', abbr: 'S', multiplier: 1 },\n TRIPLE: { name: 'triple', abbr: 'T', multiplier: 3 },\n INNER_SINGLE: { name: 'innerSingle', abbr: 'S', multiplier: 1 },\n SINGLE_BULL: { name: 'singleBull', abbr: 'B', multiplier: 1 },\n DOUBLE_BULL: { name: 'doubleBull', abbr: 'DB', multiplier: 2 },\n};\n\nexport const MOBILE_OPTIONS: Partial<DartboardOptions> = {\n missPercent: 7,\n doublePercent: 14,\n outerSinglePercent: 21,\n triplePercent: 14,\n innerSinglePercent: 26,\n singleBullPercent: 9,\n doubleBullPercent: 9,\n};\n\nexport const DEFAULT_SEGMENTS: Segment[] = [\n { segment: 20, position: 1, color: 'Dark' },\n { segment: 1, position: 2, color: 'Light' },\n { segment: 18, position: 3, color: 'Dark' },\n { segment: 4, position: 4, color: 'Light' },\n { segment: 13, position: 5, color: 'Dark' },\n { segment: 6, position: 6, color: 'Light' },\n { segment: 10, position: 7, color: 'Dark' },\n { segment: 15, position: 8, color: 'Light' },\n { segment: 2, position: 9, color: 'Dark' },\n { segment: 17, position: 10, color: 'Light' },\n { segment: 3, position: 11, color: 'Dark' },\n { segment: 19, position: 12, color: 'Light' },\n { segment: 7, position: 13, color: 'Dark' },\n { segment: 16, position: 14, color: 'Light' },\n { segment: 8, position: 15, color: 'Dark' },\n { segment: 11, position: 16, color: 'Light' },\n { segment: 14, position: 17, color: 'Dark' },\n { segment: 9, position: 18, color: 'Light' },\n { segment: 12, position: 19, color: 'Dark' },\n { segment: 5, position: 20, color: 'Light' },\n];\n","import type { Ring, Rings, Segment, Bed, BedTarget, ThrowDetail } from './types';\n\nconst SCORING_RINGS: (keyof Rings)[] = [\n 'DOUBLE',\n 'TRIPLE',\n 'OUTER_SINGLE',\n 'INNER_SINGLE',\n 'SINGLE_BULL',\n 'DOUBLE_BULL',\n];\n\nexport function buildThrowDetail(bed: Bed): ThrowDetail {\n return {\n bed: bed.ring.abbr + bed.segment,\n segment: bed.segment,\n ring: bed.ring.name,\n score: bed.segment * bed.ring.multiplier,\n };\n}\n\nexport function asPercent(n: number): number {\n return parseFloat((n / 100).toFixed(2));\n}\n\nexport function addRingToSegments(ring: Ring, segments: Segment[]): Bed[] {\n return segments.map((segment) => ({ ...segment, ring }));\n}\n\nexport function parseBed(\n bed: string,\n rings: Rings,\n segments?: Segment[],\n): BedTarget[] {\n // 'miss' keyword — target all segments in the miss ring\n if (bed.toLowerCase() === 'miss') {\n if (!segments) {\n throw new Error(\n 'parseBed: segments are required to resolve the \"miss\" keyword',\n );\n }\n return segments.map((s) => ({ segment: s.segment, ring: 'MISS' as keyof Rings }));\n }\n\n // Number-only string — target all scoring rings on that segment\n const numOnly = bed.match(/^(\\d+)$/);\n if (numOnly) {\n const segment = parseInt(numOnly[1], 10);\n return SCORING_RINGS\n .filter((key) => key in rings)\n .map((ring) => ({ segment, ring }));\n }\n\n const match = bed.match(/^([A-Za-z]+)(\\d+)$/);\n if (!match) {\n throw new Error(`Invalid bed format: \"${bed}\"`);\n }\n\n const [, abbr, numStr] = match.map((s, i) => i === 1 ? s.toUpperCase() : s);\n const segment = parseInt(numStr, 10);\n\n const targets: BedTarget[] = [];\n for (const [key, ring] of Object.entries(rings)) {\n if (ring.abbr === abbr) {\n targets.push({ segment, ring: key as keyof Rings });\n }\n }\n\n if (targets.length === 0) {\n throw new Error(`Unknown bed abbreviation: \"${abbr}\"`);\n }\n\n return targets;\n}\n"],"mappings":"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","names":["segment"]}
1
+ {"version":3,"sources":["../src/dartboard.ts","../src/constants.ts","../src/utils.ts"],"sourcesContent":["import { select, type Selection } from 'd3-selection';\nimport { arc, pie, type PieArcDatum } from 'd3-shape';\nimport type {\n DartboardOptions,\n Rings,\n Ring,\n Segment,\n Bed,\n ThrowDetail,\n HoverDetail,\n BedTarget,\n BedInput,\n HighlightOptions,\n} from './types';\nimport { DEFAULT_OPTIONS, DEFAULT_RINGS, DEFAULT_SEGMENTS } from './constants';\nimport { buildThrowDetail, asPercent, addRingToSegments, parseBed } from './utils';\n\ntype RingKey = keyof Rings;\n\n// D3's selection generics are deeply nested and don't compose well across\n// chained calls. Using `any` for internal state avoids 100+ lines of type\n// gymnastics while keeping the public API fully typed.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype D3Sel = Selection<any, any, any, any>;\n\ninterface BoardState {\n container: HTMLElement;\n wrapper: D3Sel;\n width: number;\n height: number;\n radius: number;\n rotation: number;\n segmentWidth: number;\n svg: D3Sel;\n pie: ReturnType<typeof pie<Bed>>;\n}\n\ninterface SizeMap {\n miss: number;\n double: number;\n outerSingle: number;\n triple: number;\n innerSingle: number;\n singleBull: number;\n doubleBull: number;\n}\n\nfunction buildAriaLabel(bed: Bed): string {\n const detail = buildThrowDetail(bed);\n return `${detail.bed}, scores ${detail.score}`;\n}\n\nfunction isBull(ringKey: RingKey): boolean {\n return ringKey === 'DOUBLE_BULL' || ringKey === 'SINGLE_BULL';\n}\n\nfunction bedKey(target: Required<BedTarget>): string {\n return `${target.ring}:${target.segment}`;\n}\n\n// Predefined offsets for multiple darts in the same bed.\n// [radialFraction, tangentialFraction] — scaled to ring thickness, oriented\n// along the bed's radial and arc directions so darts stay within the wedge.\nconst DART_OFFSETS: [number, number][] = [\n [0, 0],\n [-0.25, -0.25],\n [0.25, 0.25],\n [-0.25, 0.25],\n [0.25, -0.25],\n];\n\nexport class Dartboard {\n private board: BoardState | null = null;\n private sizes: SizeMap | null = null;\n private rendered = false;\n private _disabled = false;\n private dartGroup: D3Sel | null = null;\n private dartCounts = new Map<string, number>();\n private readonly options: DartboardOptions;\n readonly segments: Segment[];\n readonly rings: Rings;\n\n constructor(\n container: string | HTMLElement,\n options: Partial<DartboardOptions> = {},\n segments: Segment[] = DEFAULT_SEGMENTS,\n rings: Rings = DEFAULT_RINGS,\n ) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.segments = segments;\n this.rings = rings;\n\n const percentSum =\n this.options.missPercent +\n this.options.doublePercent +\n this.options.outerSinglePercent +\n this.options.triplePercent +\n this.options.innerSinglePercent +\n this.options.singleBullPercent +\n this.options.doubleBullPercent;\n\n if (percentSum !== 100) {\n throw new Error(\n `Dartboard: ring percentages must sum to 100 (got ${percentSum})`,\n );\n }\n\n const boardContainer =\n typeof container === 'string'\n ? document.querySelector<HTMLElement>(container)\n : container;\n\n if (!boardContainer) {\n throw new Error(`Dartboard: container not found`);\n }\n\n const padding = this.options.padding;\n const boardSize =\n this.options.size ||\n Math.min(boardContainer.offsetHeight, boardContainer.offsetWidth);\n const width = boardSize - padding * 2;\n const viewBoxSize = boardSize;\n const segmentWidth = 360 / segments.length;\n const radius = width / 2;\n const rotation = segmentWidth / -2;\n\n const wrapper = select(boardContainer)\n .append('div')\n .classed('c-Dartboard', true);\n\n const svg = wrapper\n .append('svg')\n .attr('viewBox', `0 0 ${viewBoxSize} ${viewBoxSize}`)\n .attr('role', 'group')\n .attr('aria-label', 'Dartboard')\n .append('g')\n .attr(\n 'transform',\n `translate(${viewBoxSize / 2}, ${viewBoxSize / 2}) rotate(${rotation})`,\n );\n\n const pieFn = pie<Bed>()\n .sort((a, b) => (a.position ?? 0) - (b.position ?? 0))\n .value(() => segmentWidth);\n\n this.board = {\n container: boardContainer,\n wrapper,\n width,\n height: width,\n radius,\n rotation,\n segmentWidth,\n svg,\n pie: pieFn,\n };\n\n this.sizes = {\n miss: radius * asPercent(this.options.missPercent),\n double: radius * asPercent(this.options.doublePercent),\n outerSingle: radius * asPercent(this.options.outerSinglePercent),\n triple: radius * asPercent(this.options.triplePercent),\n innerSingle: radius * asPercent(this.options.innerSinglePercent),\n singleBull: radius * asPercent(this.options.singleBullPercent),\n doubleBull: radius * asPercent(this.options.doubleBullPercent),\n };\n }\n\n render(): this {\n if (!this.board || !this.sizes) return this;\n if (this.rendered) return this;\n this.rendered = true;\n\n const { board, sizes } = this;\n\n let innerRadius = 0;\n let outerRadius = innerRadius + sizes.doubleBull;\n this.renderBeds(\n board,\n this.rings.DOUBLE_BULL,\n [{ segment: 25, color: 'Dark' }],\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.singleBull;\n this.renderBeds(\n board,\n this.rings.SINGLE_BULL,\n [{ segment: 25, color: 'Light' }],\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.innerSingle;\n this.renderBeds(\n board,\n this.rings.INNER_SINGLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.triple;\n this.renderBeds(\n board,\n this.rings.TRIPLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.outerSingle;\n this.renderBeds(\n board,\n this.rings.OUTER_SINGLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = outerRadius;\n outerRadius = innerRadius + sizes.double;\n this.renderBeds(\n board,\n this.rings.DOUBLE,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n innerRadius = board.radius - sizes.miss;\n outerRadius = board.radius;\n this.renderMissRing(\n board,\n this.rings.MISS,\n this.segments,\n outerRadius,\n innerRadius,\n );\n\n return this;\n }\n\n destroy(): void {\n if (this.board) {\n // Remove all D3 event listeners before removing from DOM\n this.board.wrapper.selectAll('.c-Dartboard-bed')\n .on('pointerup', null)\n .on('pointerenter', null)\n .on('pointerleave', null)\n .on('keydown', null);\n this.board.wrapper.remove();\n this.board = null;\n this.sizes = null;\n this.rendered = false;\n this.dartGroup = null;\n this.dartCounts.clear();\n }\n }\n\n get disabled(): boolean {\n return this._disabled;\n }\n\n disable(): this {\n this._disabled = true;\n if (this.board) {\n this.board.wrapper.classed('is-disabled', true);\n }\n return this;\n }\n\n enable(): this {\n this._disabled = false;\n if (this.board) {\n this.board.wrapper.classed('is-disabled', false);\n }\n return this;\n }\n\n throwAt(target: BedInput): void {\n if (!this.board || this._disabled) return;\n\n const targets = this.resolveTargets([target]);\n if (targets.length === 0) return;\n const first = targets[0];\n\n if (!this.isValidTarget(first)) {\n throw new Error(`Dartboard: invalid throw target — segment ${first.segment} does not exist`);\n }\n\n const ring = this.rings[first.ring];\n const bed: Bed = { segment: first.segment, color: 'Dark', ring };\n const detail = buildThrowDetail(bed);\n\n this.board.container.dispatchEvent(\n new CustomEvent<ThrowDetail>('throw', { detail }),\n );\n }\n\n highlight(targets: BedInput[], options: HighlightOptions = {}): void {\n if (!this.board) return;\n const className = options.className || 'is-highlighted';\n\n for (const target of this.resolveTargets(targets)) {\n const ring = this.rings[target.ring];\n const selector = `.c-Dartboard-${ring.name} .c-Dartboard-bed--${target.segment}`;\n this.board.wrapper.selectAll(selector).classed(className, true);\n }\n }\n\n unhighlight(targets: BedInput[], options: HighlightOptions = {}): void {\n if (!this.board) return;\n const className = options.className || 'is-highlighted';\n\n for (const target of this.resolveTargets(targets)) {\n const ring = this.rings[target.ring];\n const selector = `.c-Dartboard-${ring.name} .c-Dartboard-bed--${target.segment}`;\n this.board.wrapper.selectAll(selector).classed(className, false);\n }\n }\n\n reset(className = 'is-highlighted'): void {\n if (!this.board) return;\n this.board.wrapper.selectAll(`.${className}`).classed(className, false);\n }\n\n addDart(targets: BedInput[]): this {\n if (!this.board || !this.sizes) return this;\n\n const resolved = this.resolveTargets(targets);\n const group = this.ensureDartGroup();\n const dartRadius = this.sizes.doubleBull * 0.25;\n\n for (const target of resolved) {\n const key = bedKey(target);\n const count = this.dartCounts.get(key) ?? 0;\n this.dartCounts.set(key, count + 1);\n\n const { centroid, midAngle, innerR, outerR } = this.bedGeometry(target);\n let cx: number;\n let cy: number;\n\n if (isBull(target.ring)) {\n // Distribute bull darts evenly around the ring at its midpoint radius.\n const midR = (innerR + outerR) / 2;\n const angle = (count * 2 * Math.PI) / DART_OFFSETS.length;\n cx = midR * Math.sin(angle);\n cy = -midR * Math.cos(angle);\n } else {\n const [radialFrac, tangentialFrac] = DART_OFFSETS[count % DART_OFFSETS.length];\n const thickness = outerR - innerR;\n const midRadius = (innerR + outerR) / 2;\n const segWidthRad = (this.board.segmentWidth * Math.PI) / 180;\n // Arc half-width at the midpoint radius — limits tangential offsets\n // so darts stay within the segment's angular bounds.\n const arcHalfWidth = midRadius * Math.sin(segWidthRad / 2);\n\n // Radial unit (pointing outward from center)\n const radX = Math.sin(midAngle);\n const radY = -Math.cos(midAngle);\n // Tangential unit (perpendicular, along the arc)\n const tanX = Math.cos(midAngle);\n const tanY = Math.sin(midAngle);\n\n cx = centroid[0] + radialFrac * thickness * radX + tangentialFrac * arcHalfWidth * tanX;\n cy = centroid[1] + radialFrac * thickness * radY + tangentialFrac * arcHalfWidth * tanY;\n }\n\n group\n .append('circle')\n .classed('c-Dartboard-dart', true)\n .attr('cx', cx)\n .attr('cy', cy)\n .attr('r', dartRadius)\n .attr('data-bed', key);\n }\n\n return this;\n }\n\n removeDarts(targets?: BedInput[]): this {\n if (!this.dartGroup) return this;\n\n if (!targets) {\n this.dartGroup.selectAll('.c-Dartboard-dart').remove();\n this.dartCounts.clear();\n return this;\n }\n\n const resolved = this.resolveTargets(targets);\n for (const target of resolved) {\n const key = bedKey(target);\n this.dartGroup\n .selectAll(`.c-Dartboard-dart[data-bed=\"${key}\"]`)\n .remove();\n this.dartCounts.delete(key);\n }\n\n return this;\n }\n\n private ensureDartGroup(): D3Sel {\n if (!this.dartGroup) {\n this.dartGroup = this.board!.svg\n .append('g')\n .classed('c-Dartboard-darts', true);\n }\n return this.dartGroup;\n }\n\n private ringRadii(ringKey: RingKey): [number, number] {\n const s = this.sizes!;\n const doubleBullOuter = s.doubleBull;\n const singleBullOuter = doubleBullOuter + s.singleBull;\n const innerSingleOuter = singleBullOuter + s.innerSingle;\n const tripleOuter = innerSingleOuter + s.triple;\n const outerSingleOuter = tripleOuter + s.outerSingle;\n const doubleOuter = outerSingleOuter + s.double;\n\n switch (ringKey) {\n case 'DOUBLE_BULL': return [0, doubleBullOuter];\n case 'SINGLE_BULL': return [doubleBullOuter, singleBullOuter];\n case 'INNER_SINGLE': return [singleBullOuter, innerSingleOuter];\n case 'TRIPLE': return [innerSingleOuter, tripleOuter];\n case 'OUTER_SINGLE': return [tripleOuter, outerSingleOuter];\n case 'DOUBLE': return [outerSingleOuter, doubleOuter];\n case 'MISS': return [this.board!.radius - s.miss, this.board!.radius];\n }\n }\n\n private bedGeometry(target: Required<BedTarget>): {\n centroid: [number, number];\n midAngle: number;\n innerR: number;\n outerR: number;\n } {\n const [innerR, outerR] = this.ringRadii(target.ring);\n\n if (target.segment === 25) {\n return { centroid: [0, 0], midAngle: 0, innerR, outerR };\n }\n\n const seg = this.segments.find((s) => s.segment === target.segment);\n const segWidthRad = (this.board!.segmentWidth * Math.PI) / 180;\n const midAngle = ((seg?.position ?? 1) - 0.5) * segWidthRad;\n const midRadius = (innerR + outerR) / 2;\n\n return {\n centroid: [\n midRadius * Math.sin(midAngle),\n -midRadius * Math.cos(midAngle),\n ],\n midAngle,\n innerR,\n outerR,\n };\n }\n\n private isValidTarget(target: Required<BedTarget>): boolean {\n if (isBull(target.ring)) return target.segment === 25;\n return this.segments.some((s) => s.segment === target.segment);\n }\n\n private resolveTargets(inputs: BedInput[]): Required<BedTarget>[] {\n return inputs.flatMap((input): Required<BedTarget>[] => {\n if (typeof input === 'number') {\n return parseBed(String(input), this.rings, this.segments) as Required<BedTarget>[];\n }\n if (typeof input === 'string') {\n return parseBed(input, this.rings, this.segments) as Required<BedTarget>[];\n }\n if (!input.ring) {\n return parseBed(String(input.segment), this.rings, this.segments) as Required<BedTarget>[];\n }\n return [input as Required<BedTarget>];\n });\n }\n\n private dispatchThrow(bed: Bed): void {\n if (!this.board || this._disabled) return;\n const detail = buildThrowDetail(bed);\n this.board.container.dispatchEvent(\n new CustomEvent<ThrowDetail>('throw', { detail }),\n );\n }\n\n private dispatchHover(bed: Bed, hovering: boolean): void {\n if (!this.board || this._disabled) return;\n const throwDetail = buildThrowDetail(bed);\n const detail: HoverDetail = { ...throwDetail, hovering };\n this.board.container.dispatchEvent(\n new CustomEvent<HoverDetail>('hover', { detail }),\n );\n }\n\n private renderBeds(\n board: BoardState,\n ring: Ring,\n segments: Segment[],\n outerRadius: number,\n innerRadius: number,\n ): void {\n const className = `c-Dartboard-${ring.name}`;\n const arcFn = arc<PieArcDatum<Bed>>()\n .outerRadius(outerRadius)\n .innerRadius(innerRadius);\n\n const beds = board.svg\n .append('g')\n .classed(className, true)\n .selectAll<SVGGElement, PieArcDatum<Bed>>('arc')\n .data(board.pie(addRingToSegments(ring, segments)))\n .enter()\n .append('g')\n .attr(\n 'class',\n (d: PieArcDatum<Bed>) =>\n `c-Dartboard-bed c-Dartboard-bed--${d.data.segment} ${className}--${d.data.segment} is${d.data.color}`,\n )\n .attr('role', 'button')\n .attr('tabindex', '0')\n .attr('aria-label', (d: PieArcDatum<Bed>) =>\n buildAriaLabel(d.data),\n )\n .on(\n 'pointerup',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n this.dispatchThrow(d.data);\n },\n )\n .on(\n 'pointerenter',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n select(_event.currentTarget as Element).classed('is-hovered', true);\n this.dispatchHover(d.data, true);\n },\n )\n .on(\n 'pointerleave',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n select(_event.currentTarget as Element).classed('is-hovered', false);\n this.dispatchHover(d.data, false);\n },\n )\n .on(\n 'keydown',\n (_event: KeyboardEvent, d: PieArcDatum<Bed>) => {\n if (_event.key === 'Enter' || _event.key === ' ') {\n _event.preventDefault();\n this.dispatchThrow(d.data);\n }\n },\n );\n\n beds.append('path').attr('d', arcFn as never);\n }\n\n private renderMissRing(\n board: BoardState,\n ring: Ring,\n segments: Segment[],\n outerRadius: number,\n innerRadius: number,\n ): void {\n const missArc = arc<PieArcDatum<Bed>>()\n .outerRadius(outerRadius)\n .innerRadius(innerRadius);\n\n const missBeds = board.svg\n .append('g')\n .classed('c-Dartboard-miss', true)\n .selectAll<SVGGElement, PieArcDatum<Bed>>('arc')\n .data(board.pie(addRingToSegments(ring, segments)))\n .enter()\n .append('g')\n .attr(\n 'class',\n (d: PieArcDatum<Bed>) =>\n `c-Dartboard-bed c-Dartboard-bed--${d.data.segment} c-Dartboard-miss--${d.data.segment}`,\n )\n .attr('role', 'button')\n .attr('tabindex', '0')\n .attr('aria-label', (d: PieArcDatum<Bed>) =>\n buildAriaLabel(d.data),\n )\n .on(\n 'pointerup',\n (_event: PointerEvent, d: PieArcDatum<Bed>) => {\n this.dispatchThrow(d.data);\n },\n )\n .on(\n 'keydown',\n (_event: KeyboardEvent, d: PieArcDatum<Bed>) => {\n if (_event.key === 'Enter' || _event.key === ' ') {\n _event.preventDefault();\n this.dispatchThrow(d.data);\n }\n },\n );\n\n missBeds.append('path').attr('d', missArc as never);\n\n const determineRotation = (bedData: Bed) =>\n -board.rotation + board.segmentWidth * ((bedData.position ?? 0) - 1);\n\n const determineX = (d: PieArcDatum<Bed>) =>\n missArc.centroid(d)[0];\n\n const determineY = (d: PieArcDatum<Bed>) =>\n missArc.centroid(d)[1];\n\n missBeds\n .append('text')\n .classed('c-Dartboard-missLabel', true)\n .attr('x', (d: PieArcDatum<Bed>) => determineX(d))\n .attr('y', (d: PieArcDatum<Bed>) => determineY(d))\n .attr('dy', '.35em')\n .attr(\n 'transform',\n (d: PieArcDatum<Bed>) =>\n `rotate(${determineRotation(d.data)}, ${determineX(d)}, ${determineY(d)})`,\n )\n .attr('text-anchor', 'middle')\n .text((d: PieArcDatum<Bed>) => d.data.segment);\n }\n}\n","import type { DartboardOptions, Rings, Segment } from './types';\n\nexport const DEFAULT_OPTIONS: DartboardOptions = {\n size: null,\n padding: 2,\n missPercent: 10,\n doublePercent: 10,\n outerSinglePercent: 25,\n triplePercent: 10,\n innerSinglePercent: 30,\n singleBullPercent: 8,\n doubleBullPercent: 7,\n};\n\nexport const DEFAULT_RINGS: Rings = {\n MISS: { name: 'miss', abbr: 'M', multiplier: 0 },\n DOUBLE: { name: 'double', abbr: 'D', multiplier: 2 },\n OUTER_SINGLE: { name: 'outerSingle', abbr: 'S', multiplier: 1 },\n TRIPLE: { name: 'triple', abbr: 'T', multiplier: 3 },\n INNER_SINGLE: { name: 'innerSingle', abbr: 'S', multiplier: 1 },\n SINGLE_BULL: { name: 'singleBull', abbr: 'B', multiplier: 1 },\n DOUBLE_BULL: { name: 'doubleBull', abbr: 'DB', multiplier: 2 },\n};\n\nexport const MOBILE_OPTIONS: Partial<DartboardOptions> = {\n missPercent: 7,\n doublePercent: 14,\n outerSinglePercent: 21,\n triplePercent: 14,\n innerSinglePercent: 26,\n singleBullPercent: 9,\n doubleBullPercent: 9,\n};\n\nexport const DEFAULT_SEGMENTS: Segment[] = [\n { segment: 20, position: 1, color: 'Dark' },\n { segment: 1, position: 2, color: 'Light' },\n { segment: 18, position: 3, color: 'Dark' },\n { segment: 4, position: 4, color: 'Light' },\n { segment: 13, position: 5, color: 'Dark' },\n { segment: 6, position: 6, color: 'Light' },\n { segment: 10, position: 7, color: 'Dark' },\n { segment: 15, position: 8, color: 'Light' },\n { segment: 2, position: 9, color: 'Dark' },\n { segment: 17, position: 10, color: 'Light' },\n { segment: 3, position: 11, color: 'Dark' },\n { segment: 19, position: 12, color: 'Light' },\n { segment: 7, position: 13, color: 'Dark' },\n { segment: 16, position: 14, color: 'Light' },\n { segment: 8, position: 15, color: 'Dark' },\n { segment: 11, position: 16, color: 'Light' },\n { segment: 14, position: 17, color: 'Dark' },\n { segment: 9, position: 18, color: 'Light' },\n { segment: 12, position: 19, color: 'Dark' },\n { segment: 5, position: 20, color: 'Light' },\n];\n","import type { Ring, Rings, Segment, Bed, BedTarget, ThrowDetail } from './types';\n\nconst SCORING_RINGS: (keyof Rings)[] = [\n 'DOUBLE',\n 'TRIPLE',\n 'OUTER_SINGLE',\n 'INNER_SINGLE',\n 'SINGLE_BULL',\n 'DOUBLE_BULL',\n];\n\nexport function buildThrowDetail(bed: Bed): ThrowDetail {\n return {\n bed: bed.ring.abbr + bed.segment,\n segment: bed.segment,\n ring: bed.ring.name,\n score: bed.segment * bed.ring.multiplier,\n };\n}\n\nexport function asPercent(n: number): number {\n return parseFloat((n / 100).toFixed(2));\n}\n\nexport function addRingToSegments(ring: Ring, segments: Segment[]): Bed[] {\n return segments.map((segment) => ({ ...segment, ring }));\n}\n\nexport function parseBed(\n bed: string,\n rings: Rings,\n segments?: Segment[],\n): BedTarget[] {\n // 'miss' keyword — target all segments in the miss ring\n if (bed.toLowerCase() === 'miss') {\n if (!segments) {\n throw new Error(\n 'parseBed: segments are required to resolve the \"miss\" keyword',\n );\n }\n return segments.map((s) => ({ segment: s.segment, ring: 'MISS' as keyof Rings }));\n }\n\n // Number-only string — target all scoring rings on that segment\n const numOnly = bed.match(/^(\\d+)$/);\n if (numOnly) {\n const segment = parseInt(numOnly[1], 10);\n return SCORING_RINGS\n .filter((key) => key in rings)\n .map((ring) => ({ segment, ring }));\n }\n\n const match = bed.match(/^([A-Za-z]+)(\\d+)$/);\n if (!match) {\n throw new Error(`Invalid bed format: \"${bed}\"`);\n }\n\n const [, abbr, numStr] = match.map((s, i) => i === 1 ? s.toUpperCase() : s);\n const segment = parseInt(numStr, 10);\n\n const targets: BedTarget[] = [];\n for (const [key, ring] of Object.entries(rings)) {\n if (ring.abbr === abbr) {\n targets.push({ segment, ring: key as keyof Rings });\n }\n }\n\n if (targets.length === 0) {\n throw new Error(`Unknown bed abbreviation: \"${abbr}\"`);\n }\n\n return targets;\n}\n"],"mappings":";AAAA,SAAS,cAA8B;AACvC,SAAS,KAAK,WAA6B;;;ACCpC,IAAM,kBAAoC;AAAA,EAC/C,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aAAa;AAAA,EACb,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,mBAAmB;AACrB;AAEO,IAAM,gBAAuB;AAAA,EAClC,MAAM,EAAE,MAAM,QAAQ,MAAM,KAAK,YAAY,EAAE;AAAA,EAC/C,QAAQ,EAAE,MAAM,UAAU,MAAM,KAAK,YAAY,EAAE;AAAA,EACnD,cAAc,EAAE,MAAM,eAAe,MAAM,KAAK,YAAY,EAAE;AAAA,EAC9D,QAAQ,EAAE,MAAM,UAAU,MAAM,KAAK,YAAY,EAAE;AAAA,EACnD,cAAc,EAAE,MAAM,eAAe,MAAM,KAAK,YAAY,EAAE;AAAA,EAC9D,aAAa,EAAE,MAAM,cAAc,MAAM,KAAK,YAAY,EAAE;AAAA,EAC5D,aAAa,EAAE,MAAM,cAAc,MAAM,MAAM,YAAY,EAAE;AAC/D;AAEO,IAAM,iBAA4C;AAAA,EACvD,aAAa;AAAA,EACb,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,mBAAmB;AACrB;AAEO,IAAM,mBAA8B;AAAA,EACzC,EAAE,SAAS,IAAI,UAAU,GAAG,OAAO,OAAO;AAAA,EAC1C,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,QAAQ;AAAA,EAC1C,EAAE,SAAS,IAAI,UAAU,GAAG,OAAO,OAAO;AAAA,EAC1C,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,QAAQ;AAAA,EAC1C,EAAE,SAAS,IAAI,UAAU,GAAG,OAAO,OAAO;AAAA,EAC1C,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,QAAQ;AAAA,EAC1C,EAAE,SAAS,IAAI,UAAU,GAAG,OAAO,OAAO;AAAA,EAC1C,EAAE,SAAS,IAAI,UAAU,GAAG,OAAO,QAAQ;AAAA,EAC3C,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,OAAO;AAAA,EACzC,EAAE,SAAS,IAAI,UAAU,IAAI,OAAO,QAAQ;AAAA,EAC5C,EAAE,SAAS,GAAG,UAAU,IAAI,OAAO,OAAO;AAAA,EAC1C,EAAE,SAAS,IAAI,UAAU,IAAI,OAAO,QAAQ;AAAA,EAC5C,EAAE,SAAS,GAAG,UAAU,IAAI,OAAO,OAAO;AAAA,EAC1C,EAAE,SAAS,IAAI,UAAU,IAAI,OAAO,QAAQ;AAAA,EAC5C,EAAE,SAAS,GAAG,UAAU,IAAI,OAAO,OAAO;AAAA,EAC1C,EAAE,SAAS,IAAI,UAAU,IAAI,OAAO,QAAQ;AAAA,EAC5C,EAAE,SAAS,IAAI,UAAU,IAAI,OAAO,OAAO;AAAA,EAC3C,EAAE,SAAS,GAAG,UAAU,IAAI,OAAO,QAAQ;AAAA,EAC3C,EAAE,SAAS,IAAI,UAAU,IAAI,OAAO,OAAO;AAAA,EAC3C,EAAE,SAAS,GAAG,UAAU,IAAI,OAAO,QAAQ;AAC7C;;;ACrDA,IAAM,gBAAiC;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,iBAAiB,KAAuB;AACtD,SAAO;AAAA,IACL,KAAK,IAAI,KAAK,OAAO,IAAI;AAAA,IACzB,SAAS,IAAI;AAAA,IACb,MAAM,IAAI,KAAK;AAAA,IACf,OAAO,IAAI,UAAU,IAAI,KAAK;AAAA,EAChC;AACF;AAEO,SAAS,UAAU,GAAmB;AAC3C,SAAO,YAAY,IAAI,KAAK,QAAQ,CAAC,CAAC;AACxC;AAEO,SAAS,kBAAkB,MAAY,UAA4B;AACxE,SAAO,SAAS,IAAI,CAAC,aAAa,EAAE,GAAG,SAAS,KAAK,EAAE;AACzD;AAEO,SAAS,SACd,KACA,OACA,UACa;AAEb,MAAI,IAAI,YAAY,MAAM,QAAQ;AAChC,QAAI,CAAC,UAAU;AACb,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO,SAAS,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,MAAM,OAAsB,EAAE;AAAA,EAClF;AAGA,QAAM,UAAU,IAAI,MAAM,SAAS;AACnC,MAAI,SAAS;AACX,UAAMA,WAAU,SAAS,QAAQ,CAAC,GAAG,EAAE;AACvC,WAAO,cACJ,OAAO,CAAC,QAAQ,OAAO,KAAK,EAC5B,IAAI,CAAC,UAAU,EAAE,SAAAA,UAAS,KAAK,EAAE;AAAA,EACtC;AAEA,QAAM,QAAQ,IAAI,MAAM,oBAAoB;AAC5C,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,wBAAwB,GAAG,GAAG;AAAA,EAChD;AAEA,QAAM,CAAC,EAAE,MAAM,MAAM,IAAI,MAAM,IAAI,CAAC,GAAG,MAAM,MAAM,IAAI,EAAE,YAAY,IAAI,CAAC;AAC1E,QAAM,UAAU,SAAS,QAAQ,EAAE;AAEnC,QAAM,UAAuB,CAAC;AAC9B,aAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC/C,QAAI,KAAK,SAAS,MAAM;AACtB,cAAQ,KAAK,EAAE,SAAS,MAAM,IAAmB,CAAC;AAAA,IACpD;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,GAAG;AACxB,UAAM,IAAI,MAAM,8BAA8B,IAAI,GAAG;AAAA,EACvD;AAEA,SAAO;AACT;;;AFzBA,SAAS,eAAe,KAAkB;AACxC,QAAM,SAAS,iBAAiB,GAAG;AACnC,SAAO,GAAG,OAAO,GAAG,YAAY,OAAO,KAAK;AAC9C;AAEA,SAAS,OAAO,SAA2B;AACzC,SAAO,YAAY,iBAAiB,YAAY;AAClD;AAEA,SAAS,OAAO,QAAqC;AACnD,SAAO,GAAG,OAAO,IAAI,IAAI,OAAO,OAAO;AACzC;AAKA,IAAM,eAAmC;AAAA,EACvC,CAAC,GAAG,CAAC;AAAA,EACL,CAAC,OAAO,KAAK;AAAA,EACb,CAAC,MAAM,IAAI;AAAA,EACX,CAAC,OAAO,IAAI;AAAA,EACZ,CAAC,MAAM,KAAK;AACd;AAEO,IAAM,YAAN,MAAgB;AAAA,EAWrB,YACE,WACA,UAAqC,CAAC,GACtC,WAAsB,kBACtB,QAAe,eACf;AAfF,SAAQ,QAA2B;AACnC,SAAQ,QAAwB;AAChC,SAAQ,WAAW;AACnB,SAAQ,YAAY;AACpB,SAAQ,YAA0B;AAClC,SAAQ,aAAa,oBAAI,IAAoB;AAW3C,SAAK,UAAU,EAAE,GAAG,iBAAiB,GAAG,QAAQ;AAChD,SAAK,WAAW;AAChB,SAAK,QAAQ;AAEb,UAAM,aACJ,KAAK,QAAQ,cACb,KAAK,QAAQ,gBACb,KAAK,QAAQ,qBACb,KAAK,QAAQ,gBACb,KAAK,QAAQ,qBACb,KAAK,QAAQ,oBACb,KAAK,QAAQ;AAEf,QAAI,eAAe,KAAK;AACtB,YAAM,IAAI;AAAA,QACR,oDAAoD,UAAU;AAAA,MAChE;AAAA,IACF;AAEA,UAAM,iBACJ,OAAO,cAAc,WACjB,SAAS,cAA2B,SAAS,IAC7C;AAEN,QAAI,CAAC,gBAAgB;AACnB,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AAEA,UAAM,UAAU,KAAK,QAAQ;AAC7B,UAAM,YACJ,KAAK,QAAQ,QACb,KAAK,IAAI,eAAe,cAAc,eAAe,WAAW;AAClE,UAAM,QAAQ,YAAY,UAAU;AACpC,UAAM,cAAc;AACpB,UAAM,eAAe,MAAM,SAAS;AACpC,UAAM,SAAS,QAAQ;AACvB,UAAM,WAAW,eAAe;AAEhC,UAAM,UAAU,OAAO,cAAc,EAClC,OAAO,KAAK,EACZ,QAAQ,eAAe,IAAI;AAE9B,UAAM,MAAM,QACT,OAAO,KAAK,EACZ,KAAK,WAAW,OAAO,WAAW,IAAI,WAAW,EAAE,EACnD,KAAK,QAAQ,OAAO,EACpB,KAAK,cAAc,WAAW,EAC9B,OAAO,GAAG,EACV;AAAA,MACC;AAAA,MACA,aAAa,cAAc,CAAC,KAAK,cAAc,CAAC,YAAY,QAAQ;AAAA,IACtE;AAEF,UAAM,QAAQ,IAAS,EACpB,KAAK,CAAC,GAAG,OAAO,EAAE,YAAY,MAAM,EAAE,YAAY,EAAE,EACpD,MAAM,MAAM,YAAY;AAE3B,SAAK,QAAQ;AAAA,MACX,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK;AAAA,IACP;AAEA,SAAK,QAAQ;AAAA,MACX,MAAM,SAAS,UAAU,KAAK,QAAQ,WAAW;AAAA,MACjD,QAAQ,SAAS,UAAU,KAAK,QAAQ,aAAa;AAAA,MACrD,aAAa,SAAS,UAAU,KAAK,QAAQ,kBAAkB;AAAA,MAC/D,QAAQ,SAAS,UAAU,KAAK,QAAQ,aAAa;AAAA,MACrD,aAAa,SAAS,UAAU,KAAK,QAAQ,kBAAkB;AAAA,MAC/D,YAAY,SAAS,UAAU,KAAK,QAAQ,iBAAiB;AAAA,MAC7D,YAAY,SAAS,UAAU,KAAK,QAAQ,iBAAiB;AAAA,IAC/D;AAAA,EACF;AAAA,EAEA,SAAe;AACb,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,MAAO,QAAO;AACvC,QAAI,KAAK,SAAU,QAAO;AAC1B,SAAK,WAAW;AAEhB,UAAM,EAAE,OAAO,MAAM,IAAI;AAEzB,QAAI,cAAc;AAClB,QAAI,cAAc,cAAc,MAAM;AACtC,SAAK;AAAA,MACH;AAAA,MACA,KAAK,MAAM;AAAA,MACX,CAAC,EAAE,SAAS,IAAI,OAAO,OAAO,CAAC;AAAA,MAC/B;AAAA,MACA;AAAA,IACF;AAEA,kBAAc;AACd,kBAAc,cAAc,MAAM;AAClC,SAAK;AAAA,MACH;AAAA,MACA,KAAK,MAAM;AAAA,MACX,CAAC,EAAE,SAAS,IAAI,OAAO,QAAQ,CAAC;AAAA,MAChC;AAAA,MACA;AAAA,IACF;AAEA,kBAAc;AACd,kBAAc,cAAc,MAAM;AAClC,SAAK;AAAA,MACH;AAAA,MACA,KAAK,MAAM;AAAA,MACX,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAEA,kBAAc;AACd,kBAAc,cAAc,MAAM;AAClC,SAAK;AAAA,MACH;AAAA,MACA,KAAK,MAAM;AAAA,MACX,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAEA,kBAAc;AACd,kBAAc,cAAc,MAAM;AAClC,SAAK;AAAA,MACH;AAAA,MACA,KAAK,MAAM;AAAA,MACX,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAEA,kBAAc;AACd,kBAAc,cAAc,MAAM;AAClC,SAAK;AAAA,MACH;AAAA,MACA,KAAK,MAAM;AAAA,MACX,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAEA,kBAAc,MAAM,SAAS,MAAM;AACnC,kBAAc,MAAM;AACpB,SAAK;AAAA,MACH;AAAA,MACA,KAAK,MAAM;AAAA,MACX,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,OAAO;AAEd,WAAK,MAAM,QAAQ,UAAU,kBAAkB,EAC5C,GAAG,aAAa,IAAI,EACpB,GAAG,gBAAgB,IAAI,EACvB,GAAG,gBAAgB,IAAI,EACvB,GAAG,WAAW,IAAI;AACrB,WAAK,MAAM,QAAQ,OAAO;AAC1B,WAAK,QAAQ;AACb,WAAK,QAAQ;AACb,WAAK,WAAW;AAChB,WAAK,YAAY;AACjB,WAAK,WAAW,MAAM;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,IAAI,WAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,UAAgB;AACd,SAAK,YAAY;AACjB,QAAI,KAAK,OAAO;AACd,WAAK,MAAM,QAAQ,QAAQ,eAAe,IAAI;AAAA,IAChD;AACA,WAAO;AAAA,EACT;AAAA,EAEA,SAAe;AACb,SAAK,YAAY;AACjB,QAAI,KAAK,OAAO;AACd,WAAK,MAAM,QAAQ,QAAQ,eAAe,KAAK;AAAA,IACjD;AACA,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,QAAwB;AAC9B,QAAI,CAAC,KAAK,SAAS,KAAK,UAAW;AAEnC,UAAM,UAAU,KAAK,eAAe,CAAC,MAAM,CAAC;AAC5C,QAAI,QAAQ,WAAW,EAAG;AAC1B,UAAM,QAAQ,QAAQ,CAAC;AAEvB,QAAI,CAAC,KAAK,cAAc,KAAK,GAAG;AAC9B,YAAM,IAAI,MAAM,kDAA6C,MAAM,OAAO,iBAAiB;AAAA,IAC7F;AAEA,UAAM,OAAO,KAAK,MAAM,MAAM,IAAI;AAClC,UAAM,MAAW,EAAE,SAAS,MAAM,SAAS,OAAO,QAAQ,KAAK;AAC/D,UAAM,SAAS,iBAAiB,GAAG;AAEnC,SAAK,MAAM,UAAU;AAAA,MACnB,IAAI,YAAyB,SAAS,EAAE,OAAO,CAAC;AAAA,IAClD;AAAA,EACF;AAAA,EAEA,UAAU,SAAqB,UAA4B,CAAC,GAAS;AACnE,QAAI,CAAC,KAAK,MAAO;AACjB,UAAM,YAAY,QAAQ,aAAa;AAEvC,eAAW,UAAU,KAAK,eAAe,OAAO,GAAG;AACjD,YAAM,OAAO,KAAK,MAAM,OAAO,IAAI;AACnC,YAAM,WAAW,gBAAgB,KAAK,IAAI,sBAAsB,OAAO,OAAO;AAC9E,WAAK,MAAM,QAAQ,UAAU,QAAQ,EAAE,QAAQ,WAAW,IAAI;AAAA,IAChE;AAAA,EACF;AAAA,EAEA,YAAY,SAAqB,UAA4B,CAAC,GAAS;AACrE,QAAI,CAAC,KAAK,MAAO;AACjB,UAAM,YAAY,QAAQ,aAAa;AAEvC,eAAW,UAAU,KAAK,eAAe,OAAO,GAAG;AACjD,YAAM,OAAO,KAAK,MAAM,OAAO,IAAI;AACnC,YAAM,WAAW,gBAAgB,KAAK,IAAI,sBAAsB,OAAO,OAAO;AAC9E,WAAK,MAAM,QAAQ,UAAU,QAAQ,EAAE,QAAQ,WAAW,KAAK;AAAA,IACjE;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,kBAAwB;AACxC,QAAI,CAAC,KAAK,MAAO;AACjB,SAAK,MAAM,QAAQ,UAAU,IAAI,SAAS,EAAE,EAAE,QAAQ,WAAW,KAAK;AAAA,EACxE;AAAA,EAEA,QAAQ,SAA2B;AACjC,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,MAAO,QAAO;AAEvC,UAAM,WAAW,KAAK,eAAe,OAAO;AAC5C,UAAM,QAAQ,KAAK,gBAAgB;AACnC,UAAM,aAAa,KAAK,MAAM,aAAa;AAE3C,eAAW,UAAU,UAAU;AAC7B,YAAM,MAAM,OAAO,MAAM;AACzB,YAAM,QAAQ,KAAK,WAAW,IAAI,GAAG,KAAK;AAC1C,WAAK,WAAW,IAAI,KAAK,QAAQ,CAAC;AAElC,YAAM,EAAE,UAAU,UAAU,QAAQ,OAAO,IAAI,KAAK,YAAY,MAAM;AACtE,UAAI;AACJ,UAAI;AAEJ,UAAI,OAAO,OAAO,IAAI,GAAG;AAEvB,cAAM,QAAQ,SAAS,UAAU;AACjC,cAAM,QAAS,QAAQ,IAAI,KAAK,KAAM,aAAa;AACnD,aAAK,OAAO,KAAK,IAAI,KAAK;AAC1B,aAAK,CAAC,OAAO,KAAK,IAAI,KAAK;AAAA,MAC7B,OAAO;AACL,cAAM,CAAC,YAAY,cAAc,IAAI,aAAa,QAAQ,aAAa,MAAM;AAC7E,cAAM,YAAY,SAAS;AAC3B,cAAM,aAAa,SAAS,UAAU;AACtC,cAAM,cAAe,KAAK,MAAM,eAAe,KAAK,KAAM;AAG1D,cAAM,eAAe,YAAY,KAAK,IAAI,cAAc,CAAC;AAGzD,cAAM,OAAO,KAAK,IAAI,QAAQ;AAC9B,cAAM,OAAO,CAAC,KAAK,IAAI,QAAQ;AAE/B,cAAM,OAAO,KAAK,IAAI,QAAQ;AAC9B,cAAM,OAAO,KAAK,IAAI,QAAQ;AAE9B,aAAK,SAAS,CAAC,IAAI,aAAa,YAAY,OAAO,iBAAiB,eAAe;AACnF,aAAK,SAAS,CAAC,IAAI,aAAa,YAAY,OAAO,iBAAiB,eAAe;AAAA,MACrF;AAEA,YACG,OAAO,QAAQ,EACf,QAAQ,oBAAoB,IAAI,EAChC,KAAK,MAAM,EAAE,EACb,KAAK,MAAM,EAAE,EACb,KAAK,KAAK,UAAU,EACpB,KAAK,YAAY,GAAG;AAAA,IACzB;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,SAA4B;AACtC,QAAI,CAAC,KAAK,UAAW,QAAO;AAE5B,QAAI,CAAC,SAAS;AACZ,WAAK,UAAU,UAAU,mBAAmB,EAAE,OAAO;AACrD,WAAK,WAAW,MAAM;AACtB,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,KAAK,eAAe,OAAO;AAC5C,eAAW,UAAU,UAAU;AAC7B,YAAM,MAAM,OAAO,MAAM;AACzB,WAAK,UACF,UAAU,+BAA+B,GAAG,IAAI,EAChD,OAAO;AACV,WAAK,WAAW,OAAO,GAAG;AAAA,IAC5B;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,kBAAyB;AAC/B,QAAI,CAAC,KAAK,WAAW;AACnB,WAAK,YAAY,KAAK,MAAO,IAC1B,OAAO,GAAG,EACV,QAAQ,qBAAqB,IAAI;AAAA,IACtC;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,UAAU,SAAoC;AACpD,UAAM,IAAI,KAAK;AACf,UAAM,kBAAkB,EAAE;AAC1B,UAAM,kBAAkB,kBAAkB,EAAE;AAC5C,UAAM,mBAAmB,kBAAkB,EAAE;AAC7C,UAAM,cAAc,mBAAmB,EAAE;AACzC,UAAM,mBAAmB,cAAc,EAAE;AACzC,UAAM,cAAc,mBAAmB,EAAE;AAEzC,YAAQ,SAAS;AAAA,MACf,KAAK;AAAe,eAAO,CAAC,GAAG,eAAe;AAAA,MAC9C,KAAK;AAAe,eAAO,CAAC,iBAAiB,eAAe;AAAA,MAC5D,KAAK;AAAgB,eAAO,CAAC,iBAAiB,gBAAgB;AAAA,MAC9D,KAAK;AAAU,eAAO,CAAC,kBAAkB,WAAW;AAAA,MACpD,KAAK;AAAgB,eAAO,CAAC,aAAa,gBAAgB;AAAA,MAC1D,KAAK;AAAU,eAAO,CAAC,kBAAkB,WAAW;AAAA,MACpD,KAAK;AAAQ,eAAO,CAAC,KAAK,MAAO,SAAS,EAAE,MAAM,KAAK,MAAO,MAAM;AAAA,IACtE;AAAA,EACF;AAAA,EAEQ,YAAY,QAKlB;AACA,UAAM,CAAC,QAAQ,MAAM,IAAI,KAAK,UAAU,OAAO,IAAI;AAEnD,QAAI,OAAO,YAAY,IAAI;AACzB,aAAO,EAAE,UAAU,CAAC,GAAG,CAAC,GAAG,UAAU,GAAG,QAAQ,OAAO;AAAA,IACzD;AAEA,UAAM,MAAM,KAAK,SAAS,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO,OAAO;AAClE,UAAM,cAAe,KAAK,MAAO,eAAe,KAAK,KAAM;AAC3D,UAAM,aAAa,KAAK,YAAY,KAAK,OAAO;AAChD,UAAM,aAAa,SAAS,UAAU;AAEtC,WAAO;AAAA,MACL,UAAU;AAAA,QACR,YAAY,KAAK,IAAI,QAAQ;AAAA,QAC7B,CAAC,YAAY,KAAK,IAAI,QAAQ;AAAA,MAChC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,cAAc,QAAsC;AAC1D,QAAI,OAAO,OAAO,IAAI,EAAG,QAAO,OAAO,YAAY;AACnD,WAAO,KAAK,SAAS,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO,OAAO;AAAA,EAC/D;AAAA,EAEQ,eAAe,QAA2C;AAChE,WAAO,OAAO,QAAQ,CAAC,UAAiC;AACtD,UAAI,OAAO,UAAU,UAAU;AAC7B,eAAO,SAAS,OAAO,KAAK,GAAG,KAAK,OAAO,KAAK,QAAQ;AAAA,MAC1D;AACA,UAAI,OAAO,UAAU,UAAU;AAC7B,eAAO,SAAS,OAAO,KAAK,OAAO,KAAK,QAAQ;AAAA,MAClD;AACA,UAAI,CAAC,MAAM,MAAM;AACf,eAAO,SAAS,OAAO,MAAM,OAAO,GAAG,KAAK,OAAO,KAAK,QAAQ;AAAA,MAClE;AACA,aAAO,CAAC,KAA4B;AAAA,IACtC,CAAC;AAAA,EACH;AAAA,EAEQ,cAAc,KAAgB;AACpC,QAAI,CAAC,KAAK,SAAS,KAAK,UAAW;AACnC,UAAM,SAAS,iBAAiB,GAAG;AACnC,SAAK,MAAM,UAAU;AAAA,MACnB,IAAI,YAAyB,SAAS,EAAE,OAAO,CAAC;AAAA,IAClD;AAAA,EACF;AAAA,EAEQ,cAAc,KAAU,UAAyB;AACvD,QAAI,CAAC,KAAK,SAAS,KAAK,UAAW;AACnC,UAAM,cAAc,iBAAiB,GAAG;AACxC,UAAM,SAAsB,EAAE,GAAG,aAAa,SAAS;AACvD,SAAK,MAAM,UAAU;AAAA,MACnB,IAAI,YAAyB,SAAS,EAAE,OAAO,CAAC;AAAA,IAClD;AAAA,EACF;AAAA,EAEQ,WACN,OACA,MACA,UACA,aACA,aACM;AACN,UAAM,YAAY,eAAe,KAAK,IAAI;AAC1C,UAAM,QAAQ,IAAsB,EACjC,YAAY,WAAW,EACvB,YAAY,WAAW;AAE1B,UAAM,OAAO,MAAM,IAChB,OAAO,GAAG,EACV,QAAQ,WAAW,IAAI,EACvB,UAAyC,KAAK,EAC9C,KAAK,MAAM,IAAI,kBAAkB,MAAM,QAAQ,CAAC,CAAC,EACjD,MAAM,EACN,OAAO,GAAG,EACV;AAAA,MACC;AAAA,MACA,CAAC,MACC,oCAAoC,EAAE,KAAK,OAAO,IAAI,SAAS,KAAK,EAAE,KAAK,OAAO,MAAM,EAAE,KAAK,KAAK;AAAA,IACxG,EACC,KAAK,QAAQ,QAAQ,EACrB,KAAK,YAAY,GAAG,EACpB;AAAA,MAAK;AAAA,MAAc,CAAC,MACnB,eAAe,EAAE,IAAI;AAAA,IACvB,EACC;AAAA,MACC;AAAA,MACA,CAAC,QAAsB,MAAwB;AAC7C,aAAK,cAAc,EAAE,IAAI;AAAA,MAC3B;AAAA,IACF,EACC;AAAA,MACC;AAAA,MACA,CAAC,QAAsB,MAAwB;AAC7C,eAAO,OAAO,aAAwB,EAAE,QAAQ,cAAc,IAAI;AAClE,aAAK,cAAc,EAAE,MAAM,IAAI;AAAA,MACjC;AAAA,IACF,EACC;AAAA,MACC;AAAA,MACA,CAAC,QAAsB,MAAwB;AAC7C,eAAO,OAAO,aAAwB,EAAE,QAAQ,cAAc,KAAK;AACnE,aAAK,cAAc,EAAE,MAAM,KAAK;AAAA,MAClC;AAAA,IACF,EACC;AAAA,MACC;AAAA,MACA,CAAC,QAAuB,MAAwB;AAC9C,YAAI,OAAO,QAAQ,WAAW,OAAO,QAAQ,KAAK;AAChD,iBAAO,eAAe;AACtB,eAAK,cAAc,EAAE,IAAI;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAEF,SAAK,OAAO,MAAM,EAAE,KAAK,KAAK,KAAc;AAAA,EAC9C;AAAA,EAEQ,eACN,OACA,MACA,UACA,aACA,aACM;AACN,UAAM,UAAU,IAAsB,EACnC,YAAY,WAAW,EACvB,YAAY,WAAW;AAE1B,UAAM,WAAW,MAAM,IACpB,OAAO,GAAG,EACV,QAAQ,oBAAoB,IAAI,EAChC,UAAyC,KAAK,EAC9C,KAAK,MAAM,IAAI,kBAAkB,MAAM,QAAQ,CAAC,CAAC,EACjD,MAAM,EACN,OAAO,GAAG,EACV;AAAA,MACC;AAAA,MACA,CAAC,MACC,oCAAoC,EAAE,KAAK,OAAO,sBAAsB,EAAE,KAAK,OAAO;AAAA,IAC1F,EACC,KAAK,QAAQ,QAAQ,EACrB,KAAK,YAAY,GAAG,EACpB;AAAA,MAAK;AAAA,MAAc,CAAC,MACnB,eAAe,EAAE,IAAI;AAAA,IACvB,EACC;AAAA,MACC;AAAA,MACA,CAAC,QAAsB,MAAwB;AAC7C,aAAK,cAAc,EAAE,IAAI;AAAA,MAC3B;AAAA,IACF,EACC;AAAA,MACC;AAAA,MACA,CAAC,QAAuB,MAAwB;AAC9C,YAAI,OAAO,QAAQ,WAAW,OAAO,QAAQ,KAAK;AAChD,iBAAO,eAAe;AACtB,eAAK,cAAc,EAAE,IAAI;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAEF,aAAS,OAAO,MAAM,EAAE,KAAK,KAAK,OAAgB;AAElD,UAAM,oBAAoB,CAAC,YACzB,CAAC,MAAM,WAAW,MAAM,iBAAiB,QAAQ,YAAY,KAAK;AAEpE,UAAM,aAAa,CAAC,MAClB,QAAQ,SAAS,CAAC,EAAE,CAAC;AAEvB,UAAM,aAAa,CAAC,MAClB,QAAQ,SAAS,CAAC,EAAE,CAAC;AAEvB,aACG,OAAO,MAAM,EACb,QAAQ,yBAAyB,IAAI,EACrC,KAAK,KAAK,CAAC,MAAwB,WAAW,CAAC,CAAC,EAChD,KAAK,KAAK,CAAC,MAAwB,WAAW,CAAC,CAAC,EAChD,KAAK,MAAM,OAAO,EAClB;AAAA,MACC;AAAA,MACA,CAAC,MACC,UAAU,kBAAkB,EAAE,IAAI,CAAC,KAAK,WAAW,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC;AAAA,IAC3E,EACC,KAAK,eAAe,QAAQ,EAC5B,KAAK,CAAC,MAAwB,EAAE,KAAK,OAAO;AAAA,EACjD;AACF;","names":["segment"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tungstenstudio/dartboard-input",
3
- "version": "1.0.0-rc.5",
3
+ "version": "1.0.0",
4
4
  "description": "Interactive SVG dartboard input component built with D3",
5
5
  "type": "module",
6
6
  "sideEffects": [