@unpunnyfuns/d3-blockmap 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +118 -2
- package/dist/chunk-WIDC3EN2.js +987 -0
- package/dist/chunk-WIDC3EN2.js.map +1 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/react/index.d.ts +23 -0
- package/dist/react/index.js +88 -0
- package/dist/react/index.js.map +1 -0
- package/package.json +80 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/axis.ts","../src/constants.ts","../src/dom.ts","../src/view.ts","../src/colors.ts","../src/interaction.ts","../src/renderer.ts","../src/bitset.ts","../src/bins.ts","../src/ranges.ts","../src/state.ts","../src/tooltip.ts","../src/blockMap.ts"],"sourcesContent":["import { tickStep } from \"d3-array\";\nimport {\n CSS_VAR_AXIS_COLOR,\n DECIMAL_BASE,\n EDGE_ANCHOR_RATIO,\n MIN_TICKS,\n TICK_SPACING_PX,\n} from \"./constants\";\nimport { ensureRelative } from \"./dom\";\nimport { viewLength } from \"./view\";\nimport type { BlockView } from \"./view\";\n\nexport type AxisOptions = {\n format?: (block: number, step: number) => string;\n tickCount?: number;\n};\n\nexport type Tick = { block: number; x: number; step: number };\n\nexport type BlockScale = {\n domain: readonly [number, number];\n range: readonly [number, number];\n x(block: number): number;\n block(x: number): number;\n};\n\nexport type Axis = {\n update(view: BlockView, cssWidth: number): void;\n destroy(): void;\n};\n\nconst AXIS_ATTRIBUTE = \"data-blockmap-axis\";\nconst TICK_ATTRIBUTE = \"data-blockmap-tick\";\nconst FULL = \"100%\";\nconst CENTER = \"translateX(-50%)\";\nconst LEFT_EDGE = \"translateX(0)\";\nconst RIGHT_EDGE = \"translateX(-100%)\";\nconst COMPACT_THRESHOLD = 1000;\nconst MAGNITUDE_STEP = 3;\nconst MAX_COMPACT_FRACTION_DIGITS = 3;\n\nconst groupedFormat = new Intl.NumberFormat(\"en-US\");\nconst compactFormatters = new Map<number, Intl.NumberFormat>();\n\nconst compactFormatterFor = (digits: number): Intl.NumberFormat => {\n const cached = compactFormatters.get(digits);\n if (cached) return cached;\n const formatter = new Intl.NumberFormat(\"en-US\", {\n notation: \"compact\",\n maximumFractionDigits: digits,\n });\n compactFormatters.set(digits, formatter);\n return formatter;\n};\n\nexport const defaultFormat = (block: number, step = 1): string => {\n if (block < COMPACT_THRESHOLD) return groupedFormat.format(block);\n const magnitude =\n Math.floor(Math.log10(Math.max(Math.abs(block), 1)) / MAGNITUDE_STEP) * MAGNITUDE_STEP;\n const unit = DECIMAL_BASE ** magnitude;\n const digits = Math.max(0, Math.ceil(Math.log10(unit / step)));\n if (digits > MAX_COMPACT_FRACTION_DIGITS) return groupedFormat.format(block);\n return compactFormatterFor(digits).format(block);\n};\n\nexport const createScale = (view: BlockView, cssWidth: number): BlockScale => {\n const length = viewLength(view);\n return {\n domain: [view.start, view.end],\n range: [0, cssWidth],\n x: (block) => (cssWidth === 0 ? 0 : ((block - view.start) / length) * cssWidth),\n block: (x) => (cssWidth === 0 ? view.start : view.start + (x / cssWidth) * length),\n };\n};\n\nexport const computeTicks = (view: BlockView, cssWidth: number, tickCount?: number): Tick[] => {\n if (cssWidth <= 0) return [];\n const count = tickCount ?? Math.max(MIN_TICKS, Math.floor(cssWidth / TICK_SPACING_PX));\n const scale = createScale(view, cssWidth);\n const rawStep = tickStep(view.start, view.end, count);\n const step = Math.max(1, rawStep);\n const first = Math.ceil(view.start / step) * step;\n const result: Tick[] = [];\n for (let value = first; value <= view.end; value += step) {\n result.push({ block: value, x: scale.x(value), step });\n }\n return result;\n};\n\nexport const anchorFor = (x: number, cssWidth: number): string => {\n const edge = TICK_SPACING_PX * EDGE_ANCHOR_RATIO;\n const nearLeft = x < edge;\n const nearRight = cssWidth - x < edge;\n if (nearLeft && nearRight) return x < cssWidth - x ? LEFT_EDGE : RIGHT_EDGE;\n if (nearLeft) return LEFT_EDGE;\n if (nearRight) return RIGHT_EDGE;\n return CENTER;\n};\n\nexport const createAxis = (container: HTMLElement, options: AxisOptions): Axis => {\n const format = options.format ?? defaultFormat;\n ensureRelative(container);\n const root = document.createElement(\"div\");\n root.setAttribute(AXIS_ATTRIBUTE, \"\");\n root.setAttribute(\"aria-hidden\", \"true\");\n Object.assign(root.style, {\n position: \"absolute\",\n left: \"0\",\n right: \"0\",\n top: FULL,\n pointerEvents: \"none\",\n userSelect: \"none\",\n color: `var(${CSS_VAR_AXIS_COLOR}, currentColor)`,\n });\n container.append(root);\n\n return {\n update: (view, cssWidth) => {\n const spans = computeTicks(view, cssWidth, options.tickCount).map((tick) => {\n const span = document.createElement(\"span\");\n span.setAttribute(TICK_ATTRIBUTE, \"\");\n span.dataset.block = String(tick.block);\n span.textContent = format(tick.block, tick.step);\n Object.assign(span.style, {\n display: \"block\",\n position: \"absolute\",\n top: \"0\",\n left: `${tick.x}px`,\n transform: anchorFor(tick.x, cssWidth),\n whiteSpace: \"nowrap\",\n });\n return span;\n });\n root.replaceChildren(...spans);\n },\n destroy: () => {\n root.remove();\n },\n };\n};\n","export const BITS_PER_BYTE = 8;\nexport const BYTE_SHIFT = 3;\nexport const BYTE_MASK = 0b111;\nexport const BYTES_PER_PIXEL = 4;\nexport const OPAQUE_ALPHA = 255;\nexport const COLOR_TABLE_SIZE = 256;\nexport const PERCENT = 100;\nexport const PERCENT_FRACTION_DIGITS = 1;\nexport const TOOLTIP_OFFSET_PX = 8;\nexport const CANVAS_ROWS = 1;\n\nexport const CSS_VAR_MISSING = \"--blockmap-missing\";\nexport const CSS_VAR_PARTIAL_LOW = \"--blockmap-partial-low\";\nexport const CSS_VAR_PARTIAL_HIGH = \"--blockmap-partial-high\";\nexport const CSS_VAR_PARTIAL = \"--blockmap-partial\";\nexport const CSS_VAR_COMPLETE = \"--blockmap-complete\";\nexport const CSS_VAR_HIGHLIGHT = \"--blockmap-highlight\";\nexport const REDUCED_MOTION_QUERY = \"(prefers-reduced-motion: reduce)\";\nexport const ZOOM_STEP = 1.25;\nexport const DRAG_THRESHOLD_PX = 3;\nexport const BLINK_INTERVAL_MS = 500;\nexport const MIN_VIEW_LENGTH = 1;\n\nexport const DEFAULT_THEME = {\n missing: \"#2b2b2b\",\n partialLow: \"#5b3a00\",\n partialHigh: \"#e0a500\",\n partial: \"#e0a500\",\n complete: \"#2ecc71\",\n highlight: \"#ff4d4f\",\n} as const;\n\nexport const THEME_ATTRIBUTES = [\"class\", \"style\", \"data-theme\"] as const;\nexport const DARK_SCHEME_QUERY = \"(prefers-color-scheme: dark)\";\n\nexport const RANGE_PAIR = 2;\nexport const FULL_BYTE = 0xff;\nexport const MAX_BLOCKS = 0xffffffff;\n\nexport const CSS_VAR_AXIS_COLOR = \"--blockmap-axis-color\";\nexport const TICK_SPACING_PX = 80;\nexport const MIN_TICKS = 2;\nexport const EDGE_ANCHOR_RATIO = 0.5;\nexport const DECIMAL_BASE = 10;\n","export const ensureRelative = (container: HTMLElement): void => {\n const position = getComputedStyle(container).position;\n if (position === \"static\" || !position) container.style.position = \"relative\";\n};\n","import { MIN_VIEW_LENGTH } from \"./constants\";\n\nexport type BlockView = { start: number; end: number };\n\nexport const fullView = (totalBlocks: number): BlockView => ({ start: 0, end: totalBlocks });\n\nexport const viewLength = (view: BlockView): number => view.end - view.start;\n\nexport const sameView = (a: BlockView, b: BlockView): boolean =>\n a.start === b.start && a.end === b.end;\n\nexport const clampView = (view: BlockView, totalBlocks: number): BlockView => {\n let start = Math.round(Math.min(view.start, view.end));\n let end = Math.round(Math.max(view.start, view.end));\n if (end - start < MIN_VIEW_LENGTH) end = start + MIN_VIEW_LENGTH;\n const length = Math.min(end - start, totalBlocks);\n start = Math.max(0, Math.min(start, totalBlocks - length));\n return { start, end: start + length };\n};\n\nexport const zoomView = (\n view: BlockView,\n anchor: number,\n factor: number,\n totalBlocks: number,\n): BlockView => {\n const length = viewLength(view);\n const scaled = length * factor;\n const nextLength = Math.max(\n MIN_VIEW_LENGTH,\n Math.min(totalBlocks, factor < 1 ? Math.floor(scaled) : Math.ceil(scaled)),\n );\n const ratio = (anchor - view.start) / length;\n const start = Math.round(anchor - ratio * nextLength);\n return clampView({ start, end: start + nextLength }, totalBlocks);\n};\n\nexport const panView = (view: BlockView, deltaBlocks: number, totalBlocks: number): BlockView => {\n const length = viewLength(view);\n const start = Math.round(view.start + deltaBlocks);\n return clampView({ start, end: start + length }, totalBlocks);\n};\n","import { rgb } from \"d3-color\";\nimport { interpolateRgb, piecewise } from \"d3-interpolate\";\nimport {\n BYTES_PER_PIXEL,\n COLOR_TABLE_SIZE,\n CSS_VAR_COMPLETE,\n CSS_VAR_HIGHLIGHT,\n CSS_VAR_MISSING,\n CSS_VAR_PARTIAL,\n CSS_VAR_PARTIAL_HIGH,\n CSS_VAR_PARTIAL_LOW,\n DARK_SCHEME_QUERY,\n DEFAULT_THEME,\n OPAQUE_ALPHA,\n THEME_ATTRIBUTES,\n} from \"./constants\";\n\nexport type Theme = {\n missing: string;\n partialLow: string;\n partialHigh: string;\n partial: string;\n complete: string;\n highlight: string;\n};\n\nexport type ColorScale = (fraction: number) => Uint8ClampedArray;\n\nexport type PartialStyle = \"gradient\" | \"coverage\";\n\nconst THEME_VARS: Record<keyof Theme, string> = {\n missing: CSS_VAR_MISSING,\n partialLow: CSS_VAR_PARTIAL_LOW,\n partialHigh: CSS_VAR_PARTIAL_HIGH,\n partial: CSS_VAR_PARTIAL,\n complete: CSS_VAR_COMPLETE,\n highlight: CSS_VAR_HIGHLIGHT,\n};\n\nconst LAST_INDEX = COLOR_TABLE_SIZE - 1;\nconst FIRST_PARTIAL_INDEX = 1;\nconst LAST_PARTIAL_INDEX = LAST_INDEX - 1;\n\nconst parseOr = (value: string, fallback: string): string => {\n try {\n return rgb(value).displayable() ? value : fallback;\n } catch {\n return fallback;\n }\n};\n\nconst writeColor = (table: Uint8ClampedArray, index: number, css: string): void => {\n const color = rgb(css);\n const offset = index * BYTES_PER_PIXEL;\n table.set([color.r, color.g, color.b, OPAQUE_ALPHA], offset);\n};\n\nexport const readTheme = (el: HTMLElement): Theme => {\n const style = getComputedStyle(el);\n const read = (key: keyof Theme): string =>\n style.getPropertyValue(THEME_VARS[key]).trim() || DEFAULT_THEME[key];\n return {\n missing: read(\"missing\"),\n partialLow: read(\"partialLow\"),\n partialHigh: read(\"partialHigh\"),\n partial: read(\"partial\"),\n complete: read(\"complete\"),\n highlight: read(\"highlight\"),\n };\n};\n\nexport const createColorScale = (theme: Theme, partial: PartialStyle = \"coverage\"): ColorScale => {\n const table = new Uint8ClampedArray(COLOR_TABLE_SIZE * BYTES_PER_PIXEL);\n const missing = parseOr(theme.missing, DEFAULT_THEME.missing);\n const complete = parseOr(theme.complete, DEFAULT_THEME.complete);\n const partialScale =\n partial === \"coverage\"\n ? piecewise(interpolateRgb, [\n missing,\n parseOr(theme.partial, DEFAULT_THEME.partial),\n complete,\n ])\n : interpolateRgb(\n parseOr(theme.partialLow, DEFAULT_THEME.partialLow),\n parseOr(theme.partialHigh, DEFAULT_THEME.partialHigh),\n );\n\n writeColor(table, 0, missing);\n writeColor(table, LAST_INDEX, complete);\n for (let i = FIRST_PARTIAL_INDEX; i <= LAST_PARTIAL_INDEX; i += 1) {\n writeColor(table, i, partialScale(i / LAST_INDEX));\n }\n\n return (fraction) => {\n let index = Math.round(fraction * LAST_INDEX);\n if (fraction > 0 && index < FIRST_PARTIAL_INDEX) index = FIRST_PARTIAL_INDEX;\n if (fraction < 1 && index > LAST_PARTIAL_INDEX) index = LAST_PARTIAL_INDEX;\n const offset = index * BYTES_PER_PIXEL;\n return table.subarray(offset, offset + BYTES_PER_PIXEL);\n };\n};\n\nexport const highlightColor = (theme: Theme): Uint8ClampedArray => {\n const color = rgb(parseOr(theme.highlight, DEFAULT_THEME.highlight));\n return Uint8ClampedArray.of(color.r, color.g, color.b, OPAQUE_ALPHA);\n};\n\nexport const watchTheme = (onChange: () => void): (() => void) => {\n const observer = new MutationObserver(onChange);\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [...THEME_ATTRIBUTES],\n });\n const media = matchMedia(DARK_SCHEME_QUERY);\n media.addEventListener(\"change\", onChange);\n return () => {\n observer.disconnect();\n media.removeEventListener(\"change\", onChange);\n };\n};\n","import { DRAG_THRESHOLD_PX, ZOOM_STEP } from \"./constants\";\nimport { panView, viewLength, zoomView } from \"./view\";\nimport type { BlockView } from \"./view\";\n\nexport type InteractionDeps = {\n getView(): BlockView;\n setView(view: BlockView): void;\n resetView(): void;\n getBinCount(): number;\n getDpr(): number;\n getTotalBlocks(): number;\n onDragStart(): void;\n onDragEnd(): void;\n};\n\nconst PRIMARY_BUTTON = 0;\nconst GRABBING = \"grabbing\";\nconst NO_POINTER = -1;\n\ntype DragState = { downX: number; view: BlockView; pointerId: number; active: boolean };\n\nexport const attachInteraction = (\n canvas: HTMLCanvasElement,\n deps: InteractionDeps,\n): (() => void) => {\n let drag: DragState | undefined;\n\n const columnsToBlocks = (px: number, view: BlockView): number =>\n ((px * deps.getDpr()) / deps.getBinCount()) * viewLength(view);\n\n const onWheel = (event: WheelEvent): void => {\n if (!(event.ctrlKey || event.metaKey)) return;\n if (drag?.active) return;\n if (deps.getBinCount() === 0) return;\n event.preventDefault();\n const view = deps.getView();\n const anchor = view.start + columnsToBlocks(event.offsetX, view);\n const factor = event.deltaY > 0 ? ZOOM_STEP : 1 / ZOOM_STEP;\n deps.setView(zoomView(view, anchor, factor, deps.getTotalBlocks()));\n };\n\n const onPointerDown = (event: PointerEvent): void => {\n if (event.button !== PRIMARY_BUTTON) return;\n drag = {\n downX: event.offsetX,\n view: deps.getView(),\n pointerId: event.pointerId ?? NO_POINTER,\n active: false,\n };\n };\n\n const onPointerMove = (event: PointerEvent): void => {\n if (!drag) return;\n const dx = event.offsetX - drag.downX;\n if (!drag.active) {\n if (Math.abs(dx) < DRAG_THRESHOLD_PX) return;\n drag.active = true;\n if (typeof canvas.setPointerCapture === \"function\" && drag.pointerId !== NO_POINTER) {\n canvas.setPointerCapture(drag.pointerId);\n }\n canvas.style.cursor = GRABBING;\n deps.onDragStart();\n }\n if (deps.getBinCount() === 0) return;\n deps.setView(panView(drag.view, -columnsToBlocks(dx, drag.view), deps.getTotalBlocks()));\n };\n\n const endDrag = (): void => {\n if (!drag) return;\n if (drag.active) {\n const hasCapture =\n drag.pointerId !== NO_POINTER && (canvas.hasPointerCapture?.(drag.pointerId) ?? true);\n if (typeof canvas.releasePointerCapture === \"function\" && hasCapture) {\n canvas.releasePointerCapture(drag.pointerId);\n }\n canvas.style.cursor = \"\";\n deps.onDragEnd();\n }\n drag = undefined;\n };\n\n const onDblClick = (): void => deps.resetView();\n\n canvas.addEventListener(\"wheel\", onWheel, { passive: false });\n canvas.addEventListener(\"pointerdown\", onPointerDown);\n canvas.addEventListener(\"pointermove\", onPointerMove);\n canvas.addEventListener(\"pointerup\", endDrag);\n canvas.addEventListener(\"pointercancel\", endDrag);\n canvas.addEventListener(\"dblclick\", onDblClick);\n\n return () => {\n endDrag();\n canvas.removeEventListener(\"wheel\", onWheel);\n canvas.removeEventListener(\"pointerdown\", onPointerDown);\n canvas.removeEventListener(\"pointermove\", onPointerMove);\n canvas.removeEventListener(\"pointerup\", endDrag);\n canvas.removeEventListener(\"pointercancel\", endDrag);\n canvas.removeEventListener(\"dblclick\", onDblClick);\n };\n};\n","import type { ColorScale } from \"./colors\";\nimport { BLINK_INTERVAL_MS, BYTES_PER_PIXEL, CANVAS_ROWS } from \"./constants\";\nimport { viewLength } from \"./view\";\nimport type { BlockView } from \"./view\";\n\nexport type ImageDataLike = {\n readonly data: Uint8ClampedArray;\n readonly width: number;\n readonly height: number;\n};\n\nexport type Canvas2dLike = {\n createImageData(width: number, height: number): ImageDataLike;\n putImageData(image: ImageDataLike, dx: number, dy: number): void;\n};\n\nexport type RenderSource = {\n readonly binCount: number;\n readonly view: BlockView;\n fraction(bin: number): number;\n has(index: number): boolean;\n};\n\nexport type Scheduler = {\n request(callback: () => void): number;\n cancel(handle: number): void;\n};\n\nexport type IntervalTimer = {\n set(callback: () => void, ms: number): number;\n clear(id: number): void;\n};\n\nexport type Renderer = {\n setColors(scale: ColorScale): void;\n setHighlight(on: boolean, color: Uint8ClampedArray, blink: boolean): void;\n setHighlightColor(color: Uint8ClampedArray): void;\n markDirty(bins: ArrayLike<number>): void;\n markAllDirty(): void;\n destroy(): void;\n};\n\nconst NO_FRAME = 0;\nconst NO_TIMER = 0;\nconst COMPLETE = 1;\n\nexport const RAF_SCHEDULER: Scheduler = {\n request: (callback) => requestAnimationFrame(callback),\n cancel: (handle) => cancelAnimationFrame(handle),\n};\n\nexport const WINDOW_TIMER: IntervalTimer = {\n set: (callback, ms) => window.setInterval(callback, ms),\n clear: (id) => window.clearInterval(id),\n};\n\nexport const createRenderer = (\n ctx: Canvas2dLike,\n source: RenderSource,\n scheduler: Scheduler = RAF_SCHEDULER,\n timer: IntervalTimer = WINDOW_TIMER,\n): Renderer => {\n let image: ImageDataLike | undefined;\n let scale: ColorScale | undefined;\n let frame = NO_FRAME;\n let scheduled = false;\n let allDirty = false;\n let highlight: Uint8ClampedArray | undefined;\n let phase = false;\n let blinkId = NO_TIMER;\n const dirty = new Set<number>();\n\n const ensureImage = (): ImageDataLike | undefined => {\n const { binCount } = source;\n if (binCount === 0) return undefined;\n if (!image || image.width !== binCount) {\n image = ctx.createImageData(binCount, CANVAS_ROWS);\n allDirty = true;\n }\n return image;\n };\n\n const colorFor = (colors: ColorScale, fraction: number): Uint8ClampedArray =>\n highlight && phase && fraction < COMPLETE ? highlight : colors(fraction);\n\n const writeColumn = (target: ImageDataLike, column: number, color: Uint8ClampedArray): void => {\n target.data.set(color, column * BYTES_PER_PIXEL);\n };\n\n const paintDiscrete = (target: ImageDataLike, colors: ColorScale): void => {\n const { view, binCount } = source;\n const length = viewLength(view);\n for (let block = 0; block < length; block += 1) {\n const color = colorFor(colors, source.has(view.start + block) ? COMPLETE : 0);\n const start = Math.floor((block * binCount) / length);\n const end = Math.floor(((block + 1) * binCount) / length);\n for (let column = start; column < end; column += 1) writeColumn(target, column, color);\n }\n };\n\n const paintBins = (target: ImageDataLike, colors: ColorScale): void => {\n if (allDirty) {\n for (let bin = 0; bin < source.binCount; bin += 1)\n writeColumn(target, bin, colorFor(colors, source.fraction(bin)));\n return;\n }\n for (const bin of dirty) {\n if (bin >= target.width) continue;\n writeColumn(target, bin, colorFor(colors, source.fraction(bin)));\n }\n };\n\n const paint = (): void => {\n scheduled = false;\n frame = NO_FRAME;\n const target = ensureImage();\n if (!target || !scale) {\n dirty.clear();\n allDirty = false;\n return;\n }\n if (viewLength(source.view) < source.binCount) paintDiscrete(target, scale);\n else paintBins(target, scale);\n ctx.putImageData(target, 0, 0);\n dirty.clear();\n allDirty = false;\n };\n\n const schedule = (): void => {\n if (scheduled) return;\n scheduled = true;\n frame = scheduler.request(paint);\n };\n\n const markAllDirty = (): void => {\n allDirty = true;\n schedule();\n };\n\n const stopBlink = (): void => {\n if (blinkId !== NO_TIMER) timer.clear(blinkId);\n blinkId = NO_TIMER;\n };\n\n return {\n setColors: (next) => {\n scale = next;\n markAllDirty();\n },\n setHighlight: (on, color, blink) => {\n if (!on && highlight === undefined) return;\n stopBlink();\n highlight = on ? color : undefined;\n phase = on;\n if (on && blink) {\n blinkId = timer.set(() => {\n phase = !phase;\n markAllDirty();\n }, BLINK_INTERVAL_MS);\n }\n markAllDirty();\n },\n setHighlightColor: (color) => {\n if (highlight === undefined) return;\n highlight = color;\n markAllDirty();\n },\n markDirty: (bins) => {\n for (let i = 0; i < bins.length; i += 1) dirty.add(bins[i]);\n if (bins.length > 0) schedule();\n },\n markAllDirty,\n destroy: () => {\n stopBlink();\n if (scheduled) scheduler.cancel(frame);\n scheduled = false;\n frame = NO_FRAME;\n dirty.clear();\n },\n };\n};\n","import { BITS_PER_BYTE, BYTE_MASK, BYTE_SHIFT, FULL_BYTE } from \"./constants\";\n\nexport type Bitset = {\n has(index: number): boolean;\n set(index: number): boolean;\n fill(start: number, end: number): void;\n clearRange(start: number, end: number): void;\n countRange(start: number, end: number): number;\n clear(): void;\n setCount(next: number): void;\n readonly count: number;\n};\n\nconst maskRange = (from: number, to: number): number => ((1 << to) - 1) & ~((1 << from) - 1);\n\nconst POPCOUNT = new Uint8Array(1 << BITS_PER_BYTE);\nfor (let i = 1; i < POPCOUNT.length; i += 1) {\n POPCOUNT[i] = POPCOUNT[i >> 1] + (i & 1);\n}\n\nexport const createBitset = (size: number): Bitset => {\n const bytes = new Uint8Array(Math.ceil(size / BITS_PER_BYTE));\n let count = 0;\n\n return {\n has: (index) => (bytes[index >>> BYTE_SHIFT] & (1 << (index & BYTE_MASK))) !== 0,\n set: (index) => {\n const byte = index >>> BYTE_SHIFT;\n const mask = 1 << (index & BYTE_MASK);\n if ((bytes[byte] & mask) !== 0) return false;\n bytes[byte] |= mask;\n count += 1;\n return true;\n },\n fill: (start, end) => {\n if (end <= start) return;\n const firstByte = start >>> BYTE_SHIFT;\n const lastByte = (end - 1) >>> BYTE_SHIFT;\n const fromBit = start & BYTE_MASK;\n const toBit = ((end - 1) & BYTE_MASK) + 1;\n if (firstByte === lastByte) {\n bytes[firstByte] |= maskRange(fromBit, toBit);\n return;\n }\n bytes[firstByte] |= maskRange(fromBit, BITS_PER_BYTE);\n bytes.fill(FULL_BYTE, firstByte + 1, lastByte);\n bytes[lastByte] |= maskRange(0, toBit);\n },\n clearRange: (start, end) => {\n if (end <= start) return;\n const firstByte = start >>> BYTE_SHIFT;\n const lastByte = (end - 1) >>> BYTE_SHIFT;\n const fromBit = start & BYTE_MASK;\n const toBit = ((end - 1) & BYTE_MASK) + 1;\n if (firstByte === lastByte) {\n bytes[firstByte] &= ~maskRange(fromBit, toBit);\n return;\n }\n bytes[firstByte] &= ~maskRange(fromBit, BITS_PER_BYTE);\n bytes.fill(0, firstByte + 1, lastByte);\n bytes[lastByte] &= ~maskRange(0, toBit);\n },\n countRange: (start, end) => {\n if (end <= start) return 0;\n const firstByte = start >>> BYTE_SHIFT;\n const lastByte = (end - 1) >>> BYTE_SHIFT;\n const fromBit = start & BYTE_MASK;\n const toBit = ((end - 1) & BYTE_MASK) + 1;\n if (firstByte === lastByte) {\n return POPCOUNT[bytes[firstByte] & maskRange(fromBit, toBit)];\n }\n let total = POPCOUNT[bytes[firstByte] & maskRange(fromBit, BITS_PER_BYTE)];\n for (let b = firstByte + 1; b < lastByte; b += 1) total += POPCOUNT[bytes[b]];\n total += POPCOUNT[bytes[lastByte] & maskRange(0, toBit)];\n return total;\n },\n clear: () => {\n bytes.fill(0);\n count = 0;\n },\n setCount: (next) => {\n count = next;\n },\n get count() {\n return count;\n },\n };\n};\n","import type { BlockView } from \"./view\";\n\nexport type BlockRange = { start: number; end: number };\n\nexport type Bins = {\n readonly view: BlockView;\n readonly binCount: number;\n readonly counts: Uint32Array;\n binOf(index: number): number;\n rangeOf(bin: number): BlockRange;\n sizeOf(bin: number): number;\n rebuild(countInRange: (start: number, end: number) => number): void;\n addRange(start: number, end: number): void;\n binsTouching(start: number, end: number): number[];\n recountBins(bins: Iterable<number>, countInRange: (start: number, end: number) => number): void;\n};\n\nconst clipToView = (\n rawStart: number,\n rawEnd: number,\n viewStart: number,\n viewEnd: number,\n): BlockRange => ({\n start: Math.max(rawStart, viewStart),\n end: Math.min(rawEnd, viewEnd),\n});\n\nexport const createBins = (view: BlockView, binCount: number): Bins => {\n const { start: viewStart, end: viewEnd } = view;\n const length = viewEnd - viewStart;\n const counts = new Uint32Array(binCount);\n const binOf = (index: number): number => Math.floor(((index - viewStart) * binCount) / length);\n const rangeOf = (bin: number): BlockRange => ({\n start: viewStart + Math.ceil((bin * length) / binCount),\n end: viewStart + Math.ceil(((bin + 1) * length) / binCount),\n });\n const sizeOf = (bin: number): number => {\n const { start, end } = rangeOf(bin);\n return end - start;\n };\n\n return {\n view,\n binCount,\n counts,\n binOf,\n rangeOf,\n sizeOf,\n rebuild: (countInRange) => {\n counts.fill(0);\n if (binCount === 0) return;\n for (let bin = 0; bin < binCount; bin += 1) {\n const { start, end } = rangeOf(bin);\n counts[bin] = countInRange(start, end);\n }\n },\n addRange: (rawStart, rawEnd) => {\n const { start, end } = clipToView(rawStart, rawEnd, viewStart, viewEnd);\n if (binCount === 0 || end <= start) return;\n const first = binOf(start);\n const last = binOf(end - 1);\n if (first === last) {\n counts[first] += end - start;\n return;\n }\n counts[first] += rangeOf(first).end - start;\n for (let bin = first + 1; bin < last; bin += 1) counts[bin] += sizeOf(bin);\n counts[last] += end - rangeOf(last).start;\n },\n binsTouching: (rawStart, rawEnd) => {\n const { start, end } = clipToView(rawStart, rawEnd, viewStart, viewEnd);\n if (binCount === 0 || end <= start) return [];\n const first = binOf(start);\n const last = binOf(end - 1);\n const touched: number[] = [];\n for (let bin = first; bin <= last; bin += 1) touched.push(bin);\n return touched;\n },\n recountBins: (bins, countInRange) => {\n for (const bin of bins) {\n const range = rangeOf(bin);\n counts[bin] = countInRange(range.start, range.end);\n }\n },\n };\n};\n","import { RANGE_PAIR } from \"./constants\";\n\nexport type BlockRangeTuple = readonly [start: number, end: number];\nexport type RangeInput = ArrayLike<BlockRangeTuple> | ArrayLike<number>;\n\ntype Pair = [number, number];\n\nconst isFlatPairs = (input: RangeInput): input is ArrayLike<number> =>\n ArrayBuffer.isView(input) || typeof input[0] === \"number\";\n\nconst readPairs = (input: RangeInput): Pair[] => {\n const pairs: Pair[] = [];\n if (isFlatPairs(input)) {\n const pairCount = Math.floor(input.length / RANGE_PAIR);\n for (let i = 0; i < pairCount; i += 1) {\n pairs.push([input[i * RANGE_PAIR], input[i * RANGE_PAIR + 1]]);\n }\n return pairs;\n }\n for (let i = 0; i < input.length; i += 1) {\n const tuple = input[i];\n pairs.push([tuple[0], tuple[1]]);\n }\n return pairs;\n};\n\nexport const normalizeRanges = (input: RangeInput, totalBlocks: number): Uint32Array => {\n const clamped: Pair[] = [];\n for (const [rawStart, rawEnd] of readPairs(input)) {\n if (!Number.isInteger(rawStart) || !Number.isInteger(rawEnd)) continue;\n const start = Math.max(0, rawStart);\n const end = Math.min(totalBlocks, rawEnd);\n if (end > start) clamped.push([start, end]);\n }\n clamped.sort((a, b) => a[0] - b[0]);\n\n const merged: number[] = [];\n for (const [start, end] of clamped) {\n const lastIndex = merged.length - 1;\n if (merged.length > 0 && start <= merged[lastIndex]) {\n merged[lastIndex] = Math.max(merged[lastIndex], end);\n } else {\n merged.push(start, end);\n }\n }\n return Uint32Array.from(merged);\n};\n\nexport const rangesLength = (flat: Uint32Array): number => {\n let total = 0;\n for (let i = 0; i < flat.length; i += RANGE_PAIR) total += flat[i + 1] - flat[i];\n return total;\n};\n","import { createBitset } from \"./bitset\";\nimport { createBins } from \"./bins\";\nimport type { Bins, BlockRange } from \"./bins\";\nimport { MAX_BLOCKS, RANGE_PAIR } from \"./constants\";\nimport { normalizeRanges, rangesLength } from \"./ranges\";\nimport type { RangeInput } from \"./ranges\";\nimport { clampView, fullView, sameView } from \"./view\";\nimport type { BlockView } from \"./view\";\n\nexport type Progress = { completed: number; total: number };\n\n/**\n * Dirty arrays are ascending and deduplicated.\n */\nexport type BlockState = {\n readonly totalBlocks: number;\n readonly binCount: number;\n readonly view: BlockView;\n resize(binCount: number): void;\n setView(view: BlockView): boolean;\n getView(): BlockView;\n add(indices: ArrayLike<number>): Uint32Array;\n replace(indices: ArrayLike<number>): void;\n replaceRanges(input: RangeInput): void;\n addRanges(input: RangeInput): Uint32Array;\n removeRanges(input: RangeInput): Uint32Array;\n has(index: number): boolean;\n fraction(bin: number): number;\n countOf(bin: number): number;\n sizeOf(bin: number): number;\n rangeOf(bin: number): BlockRange;\n progress(): Progress;\n};\n\nconst EMPTY_DIRTY = new Uint32Array(0);\n\nconst isValidIndex = (index: number, totalBlocks: number): boolean =>\n Number.isInteger(index) && index >= 0 && index < totalBlocks;\n\nexport const createBlockState = (totalBlocks: number): BlockState => {\n if (!Number.isInteger(totalBlocks) || totalBlocks < 1) {\n throw new RangeError(`totalBlocks must be a positive integer, got ${totalBlocks}`);\n }\n if (totalBlocks > MAX_BLOCKS) {\n throw new RangeError(\n `totalBlocks must fit in an unsigned 32-bit integer (<= ${MAX_BLOCKS}), got ${totalBlocks}`,\n );\n }\n\n const bitset = createBitset(totalBlocks);\n let view: BlockView = fullView(totalBlocks);\n let bins: Bins = createBins(view, 0);\n\n const inView = (index: number): boolean => index >= view.start && index < view.end;\n\n const add = (indices: ArrayLike<number>): Uint32Array => {\n const hasBins = bins.binCount > 0;\n const dirty = new Set<number>();\n for (let i = 0; i < indices.length; i += 1) {\n const index = indices[i];\n if (!isValidIndex(index, totalBlocks) || !bitset.set(index)) continue;\n if (!hasBins || !inView(index)) continue;\n const bin = bins.binOf(index);\n bins.counts[bin] += 1;\n dirty.add(bin);\n }\n return dirty.size === 0 ? EMPTY_DIRTY : Uint32Array.from(dirty).sort();\n };\n\n const applyRanges = (input: RangeInput, complete: boolean): Uint32Array => {\n const flat = normalizeRanges(input, totalBlocks);\n const dirty = new Set<number>();\n let delta = 0;\n for (let i = 0; i < flat.length; i += RANGE_PAIR) {\n const start = flat[i];\n const end = flat[i + 1];\n const present = bitset.countRange(start, end);\n if (complete) {\n bitset.fill(start, end);\n delta += end - start - present;\n } else {\n bitset.clearRange(start, end);\n delta -= present;\n }\n for (const bin of bins.binsTouching(start, end)) dirty.add(bin);\n }\n bins.recountBins(dirty, bitset.countRange);\n bitset.setCount(bitset.count + delta);\n return dirty.size === 0 ? EMPTY_DIRTY : Uint32Array.from(dirty).sort();\n };\n\n return {\n totalBlocks,\n get binCount() {\n return bins.binCount;\n },\n get view() {\n return view;\n },\n resize: (binCount) => {\n bins = createBins(view, binCount);\n bins.rebuild(bitset.countRange);\n },\n setView: (next) => {\n if (!Number.isFinite(next.start) || !Number.isFinite(next.end)) return false;\n const clamped = clampView(next, totalBlocks);\n if (sameView(clamped, view)) return false;\n view = clamped;\n bins = createBins(view, bins.binCount);\n bins.rebuild(bitset.countRange);\n return true;\n },\n getView: () => ({ ...view }),\n add,\n replace: (indices) => {\n bitset.clear();\n bins.counts.fill(0);\n add(indices);\n },\n replaceRanges: (input) => {\n const flat = normalizeRanges(input, totalBlocks);\n bitset.clear();\n bins.counts.fill(0);\n for (let i = 0; i < flat.length; i += RANGE_PAIR) {\n bitset.fill(flat[i], flat[i + 1]);\n bins.addRange(flat[i], flat[i + 1]);\n }\n bitset.setCount(rangesLength(flat));\n },\n addRanges: (input) => applyRanges(input, true),\n removeRanges: (input) => applyRanges(input, false),\n has: bitset.has,\n fraction: (bin) => {\n const size = bins.sizeOf(bin);\n return size === 0 ? 0 : bins.counts[bin] / size;\n },\n countOf: (bin) => bins.counts[bin],\n sizeOf: (bin) => bins.sizeOf(bin),\n rangeOf: (bin) => bins.rangeOf(bin),\n progress: () => ({ completed: bitset.count, total: totalBlocks }),\n };\n};\n","import type { BlockRange } from \"./bins\";\nimport { DECIMAL_BASE, PERCENT, PERCENT_FRACTION_DIGITS, TOOLTIP_OFFSET_PX } from \"./constants\";\nimport { ensureRelative } from \"./dom\";\n\nexport type Tooltip = {\n show(x: number, text: string): void;\n hide(): void;\n destroy(): void;\n};\n\nconst LOCALE = \"en-US\";\nconst TOOLTIP_ATTRIBUTE = \"data-blockmap-tooltip\";\nconst SEPARATOR = \" · \";\nconst EN_DASH = \"–\";\n\nconst countFormat = new Intl.NumberFormat(LOCALE);\n\nconst MIN_PARTIAL_STEP = 1 / DECIMAL_BASE ** PERCENT_FRACTION_DIGITS;\nconst MAX_PARTIAL = (PERCENT - MIN_PARTIAL_STEP).toFixed(PERCENT_FRACTION_DIGITS);\nconst MIN_PARTIAL = MIN_PARTIAL_STEP.toFixed(PERCENT_FRACTION_DIGITS);\nconst MAX_FIXED = PERCENT.toFixed(PERCENT_FRACTION_DIGITS);\nconst MIN_FIXED = (0).toFixed(PERCENT_FRACTION_DIGITS);\n\nconst formatPercent = (count: number, size: number): string => {\n if (count === 0) return \"0%\";\n if (count === size) return \"100%\";\n const value = (count / size) * PERCENT;\n const text = value.toFixed(PERCENT_FRACTION_DIGITS);\n if (text === MAX_FIXED) {\n return `>${MAX_PARTIAL}%`;\n }\n if (text === MIN_FIXED) {\n return `<${MIN_PARTIAL}%`;\n }\n return `${text}%`;\n};\n\nexport const formatBinTooltip = (range: BlockRange, count: number): string => {\n const size = range.end - range.start;\n const label =\n size === 1\n ? `Block ${countFormat.format(range.start)}`\n : `Blocks ${countFormat.format(range.start)}${EN_DASH}${countFormat.format(range.end - 1)}`;\n return `${label}${SEPARATOR}${countFormat.format(count)} / ${countFormat.format(size)} (${formatPercent(count, size)})`;\n};\n\nexport const formatBlockTooltip = (index: number, complete: boolean): string =>\n `Block ${countFormat.format(index)}${SEPARATOR}${complete ? \"complete\" : \"missing\"}`;\n\nexport const createTooltip = (container: HTMLElement): Tooltip => {\n const el = document.createElement(\"div\");\n el.setAttribute(TOOLTIP_ATTRIBUTE, \"\");\n Object.assign(el.style, {\n position: \"absolute\",\n top: \"0\",\n left: \"0\",\n display: \"none\",\n pointerEvents: \"none\",\n whiteSpace: \"nowrap\",\n transform: \"translateY(-100%)\",\n });\n ensureRelative(container);\n container.append(el);\n\n return {\n show: (x, text) => {\n el.textContent = text;\n el.style.left = `${x + TOOLTIP_OFFSET_PX}px`;\n el.style.display = \"block\";\n },\n hide: () => {\n el.style.display = \"none\";\n },\n destroy: () => {\n el.remove();\n },\n };\n};\n","import { createAxis, createScale } from \"./axis\";\nimport type { Axis, AxisOptions, BlockScale } from \"./axis\";\nimport { createColorScale, highlightColor, readTheme, watchTheme } from \"./colors\";\nimport type { PartialStyle, Theme } from \"./colors\";\nimport { CANVAS_ROWS, REDUCED_MOTION_QUERY } from \"./constants\";\nimport { attachInteraction } from \"./interaction\";\nimport { createRenderer } from \"./renderer\";\nimport type { Renderer } from \"./renderer\";\nimport type { RangeInput } from \"./ranges\";\nimport { createBlockState } from \"./state\";\nimport type { Progress } from \"./state\";\nimport { createTooltip, formatBinTooltip, formatBlockTooltip } from \"./tooltip\";\nimport { clampView, fullView, sameView, viewLength } from \"./view\";\nimport type { BlockView } from \"./view\";\n\nexport type BlockMapOptions = {\n totalBlocks: number;\n initialBlocks?: ArrayLike<number>;\n initialRanges?: RangeInput;\n partial?: PartialStyle;\n view?: BlockView;\n interactive?: boolean;\n axis?: boolean | AxisOptions;\n onViewChange?: (view: BlockView) => void;\n};\n\nexport type BlockMap = {\n setBlocks(indices: ArrayLike<number>): void;\n setRanges(ranges: RangeInput): void;\n addBlocks(indices: ArrayLike<number>): void;\n addRanges(ranges: RangeInput): void;\n removeRanges(ranges: RangeInput): void;\n setView(view: BlockView): void;\n resetView(): void;\n getView(): BlockView;\n getScale(): BlockScale;\n setHighlight(on: boolean): void;\n getProgress(): Progress;\n destroy(): void;\n};\n\nconst FULL = \"100%\";\nconst CONTEXT_ID = \"2d\";\nconst NO_FRAME = 0;\n\nconst dprQuery = (dpr: number): string => `(resolution: ${dpr}dppx)`;\n\nconst discreteBlock = (column: number, length: number, binCount: number, start: number): number =>\n start + Math.ceil(((column + 1) * length) / binCount) - 1;\n\nexport const createBlockMap = (container: HTMLElement, options: BlockMapOptions): BlockMap => {\n const state = createBlockState(options.totalBlocks);\n if (options.view) state.setView(options.view);\n\n const canvas = document.createElement(\"canvas\");\n Object.assign(canvas.style, {\n display: \"block\",\n width: FULL,\n height: FULL,\n touchAction: \"none\",\n });\n canvas.height = CANVAS_ROWS;\n container.append(canvas);\n\n const ctx = canvas.getContext(CONTEXT_ID);\n if (!ctx) {\n canvas.remove();\n throw new Error(`Could not acquire a ${CONTEXT_ID} canvas context`);\n }\n\n const renderer: Renderer = createRenderer(ctx, state);\n const tooltip = createTooltip(container);\n const axisOptions: AxisOptions | undefined =\n options.axis === true\n ? {}\n : options.axis === false || options.axis === undefined\n ? undefined\n : options.axis;\n const axis: Axis | undefined = axisOptions ? createAxis(container, axisOptions) : undefined;\n let destroyed = false;\n let cssWidth = 0;\n let dpr = devicePixelRatio;\n let dprMedia: MediaQueryList | undefined;\n let theme: Theme = readTheme(container);\n let highlightOn = false;\n let dragging = false;\n\n const blinkAllowed = (): boolean => !matchMedia(REDUCED_MOTION_QUERY).matches;\n\n const applyHighlight = (): void => {\n renderer.setHighlight(highlightOn, highlightColor(theme), blinkAllowed());\n };\n\n const applyTheme = (): void => {\n theme = readTheme(container);\n renderer.setColors(createColorScale(theme, options.partial));\n if (highlightOn) renderer.setHighlightColor(highlightColor(theme));\n };\n\n let pendingView: BlockView | undefined;\n let viewFrame = NO_FRAME;\n\n const getView = (): BlockView => ({ ...(pendingView ?? state.view) });\n\n const commitView = (): void => {\n viewFrame = NO_FRAME;\n const next = pendingView;\n pendingView = undefined;\n if (!next || !state.setView(next)) return;\n renderer.markAllDirty();\n axis?.update(state.view, cssWidth);\n options.onViewChange?.(state.getView());\n };\n\n const setView = (view: BlockView): void => {\n if (!Number.isFinite(view.start) || !Number.isFinite(view.end)) return;\n const clamped = clampView(view, state.totalBlocks);\n if (sameView(clamped, pendingView ?? state.view)) return;\n const hasPendingFrame = pendingView !== undefined;\n pendingView = clamped;\n if (!hasPendingFrame) viewFrame = requestAnimationFrame(commitView);\n };\n const resetView = (): void => setView(fullView(state.totalBlocks));\n\n const layout = (): void => {\n const binCount = Math.round(cssWidth * dpr);\n if (binCount === state.binCount) return;\n canvas.width = binCount;\n state.resize(binCount);\n renderer.markAllDirty();\n axis?.update(state.view, cssWidth);\n };\n\n const onDprChange = (): void => {\n dpr = devicePixelRatio;\n layout();\n watchDpr();\n };\n\n const watchDpr = (): void => {\n dprMedia?.removeEventListener(\"change\", onDprChange);\n dprMedia = matchMedia(dprQuery(dpr));\n dprMedia.addEventListener(\"change\", onDprChange, { once: true });\n };\n\n const resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (!entry) return;\n cssWidth = entry.contentRect.width;\n layout();\n });\n resizeObserver.observe(container);\n\n const onPointerMove = (event: PointerEvent): void => {\n if (dragging) return;\n const { binCount, view } = state;\n if (binCount === 0) return;\n const column = Math.min(binCount - 1, Math.max(0, Math.floor(event.offsetX * dpr)));\n const length = viewLength(view);\n let text: string;\n if (length < binCount) {\n const block = discreteBlock(column, length, binCount, view.start);\n text = formatBlockTooltip(block, state.has(block));\n } else {\n text = formatBinTooltip(state.rangeOf(column), state.countOf(column));\n }\n tooltip.show(event.offsetX, text);\n };\n const onPointerLeave = (): void => tooltip.hide();\n\n canvas.addEventListener(\"pointermove\", onPointerMove);\n canvas.addEventListener(\"pointerleave\", onPointerLeave);\n const detachInteraction =\n options.interactive === false\n ? undefined\n : attachInteraction(canvas, {\n getView,\n setView,\n resetView,\n getBinCount: () => state.binCount,\n getDpr: () => dpr,\n getTotalBlocks: () => state.totalBlocks,\n onDragStart: () => {\n dragging = true;\n tooltip.hide();\n },\n onDragEnd: () => {\n dragging = false;\n },\n });\n const unwatchTheme = watchTheme(applyTheme);\n watchDpr();\n applyTheme();\n if (options.initialRanges) state.replaceRanges(options.initialRanges);\n if (options.initialBlocks) renderer.markDirty(state.add(options.initialBlocks));\n\n return {\n setBlocks: (indices) => {\n if (destroyed) return;\n state.replace(indices);\n renderer.markAllDirty();\n },\n setRanges: (ranges) => {\n if (destroyed) return;\n state.replaceRanges(ranges);\n renderer.markAllDirty();\n },\n addBlocks: (indices) => {\n if (destroyed) return;\n renderer.markDirty(state.add(indices));\n },\n addRanges: (ranges) => {\n if (destroyed) return;\n renderer.markDirty(state.addRanges(ranges));\n },\n removeRanges: (ranges) => {\n if (destroyed) return;\n renderer.markDirty(state.removeRanges(ranges));\n },\n setView: (view) => {\n if (destroyed) return;\n setView(view);\n },\n resetView: () => {\n if (destroyed) return;\n resetView();\n },\n getView,\n getScale: () => createScale(state.getView(), cssWidth),\n setHighlight: (on) => {\n if (destroyed) return;\n highlightOn = on;\n applyHighlight();\n },\n getProgress: () => (destroyed ? { completed: 0, total: state.totalBlocks } : state.progress()),\n destroy: () => {\n if (destroyed) return;\n destroyed = true;\n if (viewFrame !== NO_FRAME) cancelAnimationFrame(viewFrame);\n viewFrame = NO_FRAME;\n pendingView = undefined;\n resizeObserver.disconnect();\n unwatchTheme();\n dprMedia?.removeEventListener(\"change\", onDprChange);\n canvas.removeEventListener(\"pointermove\", onPointerMove);\n canvas.removeEventListener(\"pointerleave\", onPointerLeave);\n detachInteraction?.();\n renderer.destroy();\n tooltip.destroy();\n axis?.destroy();\n canvas.remove();\n },\n };\n};\n"],"mappings":"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","names":["FULL","NO_FRAME"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
type BlockView = {
|
|
2
|
+
start: number;
|
|
3
|
+
end: number;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
type AxisOptions = {
|
|
7
|
+
format?: (block: number, step: number) => string;
|
|
8
|
+
tickCount?: number;
|
|
9
|
+
};
|
|
10
|
+
type BlockScale = {
|
|
11
|
+
domain: readonly [number, number];
|
|
12
|
+
range: readonly [number, number];
|
|
13
|
+
x(block: number): number;
|
|
14
|
+
block(x: number): number;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
type Theme = {
|
|
18
|
+
missing: string;
|
|
19
|
+
partialLow: string;
|
|
20
|
+
partialHigh: string;
|
|
21
|
+
partial: string;
|
|
22
|
+
complete: string;
|
|
23
|
+
highlight: string;
|
|
24
|
+
};
|
|
25
|
+
type PartialStyle = "gradient" | "coverage";
|
|
26
|
+
|
|
27
|
+
type BlockRangeTuple = readonly [start: number, end: number];
|
|
28
|
+
type RangeInput = ArrayLike<BlockRangeTuple> | ArrayLike<number>;
|
|
29
|
+
|
|
30
|
+
type Progress = {
|
|
31
|
+
completed: number;
|
|
32
|
+
total: number;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
type BlockMapOptions = {
|
|
36
|
+
totalBlocks: number;
|
|
37
|
+
initialBlocks?: ArrayLike<number>;
|
|
38
|
+
initialRanges?: RangeInput;
|
|
39
|
+
partial?: PartialStyle;
|
|
40
|
+
view?: BlockView;
|
|
41
|
+
interactive?: boolean;
|
|
42
|
+
axis?: boolean | AxisOptions;
|
|
43
|
+
onViewChange?: (view: BlockView) => void;
|
|
44
|
+
};
|
|
45
|
+
type BlockMap = {
|
|
46
|
+
setBlocks(indices: ArrayLike<number>): void;
|
|
47
|
+
setRanges(ranges: RangeInput): void;
|
|
48
|
+
addBlocks(indices: ArrayLike<number>): void;
|
|
49
|
+
addRanges(ranges: RangeInput): void;
|
|
50
|
+
removeRanges(ranges: RangeInput): void;
|
|
51
|
+
setView(view: BlockView): void;
|
|
52
|
+
resetView(): void;
|
|
53
|
+
getView(): BlockView;
|
|
54
|
+
getScale(): BlockScale;
|
|
55
|
+
setHighlight(on: boolean): void;
|
|
56
|
+
getProgress(): Progress;
|
|
57
|
+
destroy(): void;
|
|
58
|
+
};
|
|
59
|
+
declare const createBlockMap: (container: HTMLElement, options: BlockMapOptions) => BlockMap;
|
|
60
|
+
|
|
61
|
+
export { createBlockMap };
|
|
62
|
+
export type { AxisOptions, BlockMap, BlockMapOptions, BlockRangeTuple, BlockScale, BlockView, PartialStyle, Progress, RangeInput, Theme };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { CSSProperties, Ref } from 'react';
|
|
3
|
+
import { RangeInput, PartialStyle, BlockView, AxisOptions, BlockMap as BlockMap$1 } from '../index.js';
|
|
4
|
+
|
|
5
|
+
type BlockMapProps = {
|
|
6
|
+
totalBlocks: number;
|
|
7
|
+
blocks?: ArrayLike<number>;
|
|
8
|
+
ranges?: RangeInput;
|
|
9
|
+
partial?: PartialStyle;
|
|
10
|
+
view?: BlockView;
|
|
11
|
+
interactive?: boolean;
|
|
12
|
+
axis?: boolean | AxisOptions;
|
|
13
|
+
onViewChange?: (view: BlockView) => void;
|
|
14
|
+
highlight?: boolean;
|
|
15
|
+
className?: string;
|
|
16
|
+
style?: CSSProperties;
|
|
17
|
+
ref?: Ref<BlockMapHandle>;
|
|
18
|
+
};
|
|
19
|
+
type BlockMapHandle = Pick<BlockMap$1, "addBlocks" | "setRanges" | "addRanges" | "removeRanges" | "setView" | "resetView" | "getView" | "getScale" | "setHighlight" | "getProgress">;
|
|
20
|
+
declare const BlockMap: ({ totalBlocks, blocks, ranges, partial, view, interactive, axis, onViewChange, highlight, className, style, ref, }: BlockMapProps) => react.JSX.Element;
|
|
21
|
+
|
|
22
|
+
export { BlockMap };
|
|
23
|
+
export type { BlockMapHandle, BlockMapProps };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createBlockMap
|
|
3
|
+
} from "../chunk-WIDC3EN2.js";
|
|
4
|
+
|
|
5
|
+
// src/react/BlockMap.tsx
|
|
6
|
+
import { useEffect, useImperativeHandle, useRef } from "react";
|
|
7
|
+
import { jsx } from "react/jsx-runtime";
|
|
8
|
+
var EMPTY_BLOCKS = [];
|
|
9
|
+
var EMPTY_PROGRESS = { completed: 0, total: 0 };
|
|
10
|
+
var BlockMap = ({
|
|
11
|
+
totalBlocks,
|
|
12
|
+
blocks,
|
|
13
|
+
ranges,
|
|
14
|
+
partial,
|
|
15
|
+
view,
|
|
16
|
+
interactive,
|
|
17
|
+
axis,
|
|
18
|
+
onViewChange,
|
|
19
|
+
highlight,
|
|
20
|
+
className,
|
|
21
|
+
style,
|
|
22
|
+
ref
|
|
23
|
+
}) => {
|
|
24
|
+
const containerRef = useRef(null);
|
|
25
|
+
const instanceRef = useRef(null);
|
|
26
|
+
const onViewChangeRef = useRef(onViewChange);
|
|
27
|
+
onViewChangeRef.current = onViewChange;
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
const container = containerRef.current;
|
|
30
|
+
if (!container) return void 0;
|
|
31
|
+
const options = {
|
|
32
|
+
totalBlocks,
|
|
33
|
+
onViewChange: (next) => onViewChangeRef.current?.(next)
|
|
34
|
+
};
|
|
35
|
+
if (partial) options.partial = partial;
|
|
36
|
+
if (interactive !== void 0) options.interactive = interactive;
|
|
37
|
+
if (view) options.view = view;
|
|
38
|
+
if (axis !== void 0) options.axis = axis;
|
|
39
|
+
const instance = createBlockMap(container, options);
|
|
40
|
+
instanceRef.current = instance;
|
|
41
|
+
return () => {
|
|
42
|
+
instance.destroy();
|
|
43
|
+
instanceRef.current = null;
|
|
44
|
+
};
|
|
45
|
+
}, [totalBlocks, partial, interactive, axis]);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
const instance = instanceRef.current;
|
|
48
|
+
if (!instance) return;
|
|
49
|
+
if (ranges !== void 0) {
|
|
50
|
+
instance.setRanges(ranges);
|
|
51
|
+
if (blocks !== void 0) instance.addBlocks(blocks);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
instance.setBlocks(blocks ?? EMPTY_BLOCKS);
|
|
55
|
+
}, [totalBlocks, partial, interactive, axis, ranges, blocks]);
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (view !== void 0) instanceRef.current?.setView(view);
|
|
58
|
+
}, [totalBlocks, partial, interactive, axis, view]);
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
instanceRef.current?.setHighlight(highlight ?? false);
|
|
61
|
+
}, [totalBlocks, partial, interactive, axis, highlight]);
|
|
62
|
+
useImperativeHandle(
|
|
63
|
+
ref,
|
|
64
|
+
() => ({
|
|
65
|
+
addBlocks: (indices) => instanceRef.current?.addBlocks(indices),
|
|
66
|
+
setRanges: (next) => instanceRef.current?.setRanges(next),
|
|
67
|
+
addRanges: (next) => instanceRef.current?.addRanges(next),
|
|
68
|
+
removeRanges: (next) => instanceRef.current?.removeRanges(next),
|
|
69
|
+
setView: (next) => instanceRef.current?.setView(next),
|
|
70
|
+
resetView: () => instanceRef.current?.resetView(),
|
|
71
|
+
getView: () => instanceRef.current?.getView() ?? { start: 0, end: totalBlocks },
|
|
72
|
+
getScale: () => instanceRef.current?.getScale() ?? {
|
|
73
|
+
domain: [0, totalBlocks],
|
|
74
|
+
range: [0, 0],
|
|
75
|
+
x: () => 0,
|
|
76
|
+
block: () => 0
|
|
77
|
+
},
|
|
78
|
+
setHighlight: (on) => instanceRef.current?.setHighlight(on),
|
|
79
|
+
getProgress: () => instanceRef.current?.getProgress() ?? { ...EMPTY_PROGRESS, total: totalBlocks }
|
|
80
|
+
}),
|
|
81
|
+
[totalBlocks]
|
|
82
|
+
);
|
|
83
|
+
return /* @__PURE__ */ jsx("div", { ref: containerRef, className, style });
|
|
84
|
+
};
|
|
85
|
+
export {
|
|
86
|
+
BlockMap
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/BlockMap.tsx"],"sourcesContent":["import { useEffect, useImperativeHandle, useRef } from \"react\";\nimport type { CSSProperties, Ref } from \"react\";\nimport type { AxisOptions } from \"../axis\";\nimport type { PartialStyle } from \"../colors\";\nimport { createBlockMap } from \"../blockMap\";\nimport type { BlockMap as BlockMapInstance, BlockMapOptions } from \"../blockMap\";\nimport type { RangeInput } from \"../ranges\";\nimport type { BlockView } from \"../view\";\n\nexport type BlockMapProps = {\n totalBlocks: number;\n blocks?: ArrayLike<number>;\n ranges?: RangeInput;\n partial?: PartialStyle;\n view?: BlockView;\n interactive?: boolean;\n axis?: boolean | AxisOptions;\n onViewChange?: (view: BlockView) => void;\n highlight?: boolean;\n className?: string;\n style?: CSSProperties;\n ref?: Ref<BlockMapHandle>;\n};\n\nexport type BlockMapHandle = Pick<\n BlockMapInstance,\n | \"addBlocks\"\n | \"setRanges\"\n | \"addRanges\"\n | \"removeRanges\"\n | \"setView\"\n | \"resetView\"\n | \"getView\"\n | \"getScale\"\n | \"setHighlight\"\n | \"getProgress\"\n>;\n\nconst EMPTY_BLOCKS: readonly number[] = [];\nconst EMPTY_PROGRESS = { completed: 0, total: 0 };\n\nexport const BlockMap = ({\n totalBlocks,\n blocks,\n ranges,\n partial,\n view,\n interactive,\n axis,\n onViewChange,\n highlight,\n className,\n style,\n ref,\n}: BlockMapProps) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const instanceRef = useRef<BlockMapInstance>(null);\n const onViewChangeRef = useRef(onViewChange);\n onViewChangeRef.current = onViewChange;\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return undefined;\n const options: BlockMapOptions = {\n totalBlocks,\n onViewChange: (next) => onViewChangeRef.current?.(next),\n };\n if (partial) options.partial = partial;\n if (interactive !== undefined) options.interactive = interactive;\n if (view) options.view = view;\n if (axis !== undefined) options.axis = axis;\n const instance = createBlockMap(container, options);\n instanceRef.current = instance;\n return () => {\n instance.destroy();\n instanceRef.current = null;\n };\n }, [totalBlocks, partial, interactive, axis]);\n\n useEffect(() => {\n const instance = instanceRef.current;\n if (!instance) return;\n if (ranges !== undefined) {\n instance.setRanges(ranges);\n if (blocks !== undefined) instance.addBlocks(blocks);\n return;\n }\n instance.setBlocks(blocks ?? EMPTY_BLOCKS);\n }, [totalBlocks, partial, interactive, axis, ranges, blocks]);\n\n useEffect(() => {\n if (view !== undefined) instanceRef.current?.setView(view);\n }, [totalBlocks, partial, interactive, axis, view]);\n\n useEffect(() => {\n instanceRef.current?.setHighlight(highlight ?? false);\n }, [totalBlocks, partial, interactive, axis, highlight]);\n\n useImperativeHandle(\n ref,\n () => ({\n addBlocks: (indices) => instanceRef.current?.addBlocks(indices),\n setRanges: (next) => instanceRef.current?.setRanges(next),\n addRanges: (next) => instanceRef.current?.addRanges(next),\n removeRanges: (next) => instanceRef.current?.removeRanges(next),\n setView: (next) => instanceRef.current?.setView(next),\n resetView: () => instanceRef.current?.resetView(),\n getView: () => instanceRef.current?.getView() ?? { start: 0, end: totalBlocks },\n getScale: () =>\n instanceRef.current?.getScale() ?? {\n domain: [0, totalBlocks],\n range: [0, 0],\n x: () => 0,\n block: () => 0,\n },\n setHighlight: (on) => instanceRef.current?.setHighlight(on),\n getProgress: () =>\n instanceRef.current?.getProgress() ?? { ...EMPTY_PROGRESS, total: totalBlocks },\n }),\n [totalBlocks],\n );\n\n return <div ref={containerRef} className={className} style={style} />;\n};\n"],"mappings":";;;;;AAAA,SAAS,WAAW,qBAAqB,cAAc;AA0H9C;AApFT,IAAM,eAAkC,CAAC;AACzC,IAAM,iBAAiB,EAAE,WAAW,GAAG,OAAO,EAAE;AAEzC,IAAM,WAAW,CAAC;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAqB;AACnB,QAAM,eAAe,OAAuB,IAAI;AAChD,QAAM,cAAc,OAAyB,IAAI;AACjD,QAAM,kBAAkB,OAAO,YAAY;AAC3C,kBAAgB,UAAU;AAE1B,YAAU,MAAM;AACd,UAAM,YAAY,aAAa;AAC/B,QAAI,CAAC,UAAW,QAAO;AACvB,UAAM,UAA2B;AAAA,MAC/B;AAAA,MACA,cAAc,CAAC,SAAS,gBAAgB,UAAU,IAAI;AAAA,IACxD;AACA,QAAI,QAAS,SAAQ,UAAU;AAC/B,QAAI,gBAAgB,OAAW,SAAQ,cAAc;AACrD,QAAI,KAAM,SAAQ,OAAO;AACzB,QAAI,SAAS,OAAW,SAAQ,OAAO;AACvC,UAAM,WAAW,eAAe,WAAW,OAAO;AAClD,gBAAY,UAAU;AACtB,WAAO,MAAM;AACX,eAAS,QAAQ;AACjB,kBAAY,UAAU;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,aAAa,SAAS,aAAa,IAAI,CAAC;AAE5C,YAAU,MAAM;AACd,UAAM,WAAW,YAAY;AAC7B,QAAI,CAAC,SAAU;AACf,QAAI,WAAW,QAAW;AACxB,eAAS,UAAU,MAAM;AACzB,UAAI,WAAW,OAAW,UAAS,UAAU,MAAM;AACnD;AAAA,IACF;AACA,aAAS,UAAU,UAAU,YAAY;AAAA,EAC3C,GAAG,CAAC,aAAa,SAAS,aAAa,MAAM,QAAQ,MAAM,CAAC;AAE5D,YAAU,MAAM;AACd,QAAI,SAAS,OAAW,aAAY,SAAS,QAAQ,IAAI;AAAA,EAC3D,GAAG,CAAC,aAAa,SAAS,aAAa,MAAM,IAAI,CAAC;AAElD,YAAU,MAAM;AACd,gBAAY,SAAS,aAAa,aAAa,KAAK;AAAA,EACtD,GAAG,CAAC,aAAa,SAAS,aAAa,MAAM,SAAS,CAAC;AAEvD;AAAA,IACE;AAAA,IACA,OAAO;AAAA,MACL,WAAW,CAAC,YAAY,YAAY,SAAS,UAAU,OAAO;AAAA,MAC9D,WAAW,CAAC,SAAS,YAAY,SAAS,UAAU,IAAI;AAAA,MACxD,WAAW,CAAC,SAAS,YAAY,SAAS,UAAU,IAAI;AAAA,MACxD,cAAc,CAAC,SAAS,YAAY,SAAS,aAAa,IAAI;AAAA,MAC9D,SAAS,CAAC,SAAS,YAAY,SAAS,QAAQ,IAAI;AAAA,MACpD,WAAW,MAAM,YAAY,SAAS,UAAU;AAAA,MAChD,SAAS,MAAM,YAAY,SAAS,QAAQ,KAAK,EAAE,OAAO,GAAG,KAAK,YAAY;AAAA,MAC9E,UAAU,MACR,YAAY,SAAS,SAAS,KAAK;AAAA,QACjC,QAAQ,CAAC,GAAG,WAAW;AAAA,QACvB,OAAO,CAAC,GAAG,CAAC;AAAA,QACZ,GAAG,MAAM;AAAA,QACT,OAAO,MAAM;AAAA,MACf;AAAA,MACF,cAAc,CAAC,OAAO,YAAY,SAAS,aAAa,EAAE;AAAA,MAC1D,aAAa,MACX,YAAY,SAAS,YAAY,KAAK,EAAE,GAAG,gBAAgB,OAAO,YAAY;AAAA,IAClF;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,SAAO,oBAAC,SAAI,KAAK,cAAc,WAAsB,OAAc;AACrE;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,82 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unpunnyfuns/d3-blockmap",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Canvas block map for millions of download blocks, D3 scales and colours",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
9
|
+
"type": "module",
|
|
10
|
+
"sideEffects": false,
|
|
11
|
+
"main": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./react": {
|
|
19
|
+
"types": "./dist/react/index.d.ts",
|
|
20
|
+
"import": "./dist/react/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"test": "vitest run",
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"test:watch": "vitest",
|
|
27
|
+
"lint": "oxlint src",
|
|
28
|
+
"format": "oxfmt src",
|
|
29
|
+
"format:check": "oxfmt --check src",
|
|
30
|
+
"typecheck": "tsc --noEmit",
|
|
31
|
+
"demo": "python3 -m http.server 4173",
|
|
32
|
+
"verify": "npm run lint && npm run format:check && npm run typecheck && npm test && npm run build"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"d3-array": "^3.2.5",
|
|
36
|
+
"d3-color": "^3.1.1",
|
|
37
|
+
"d3-interpolate": "^3.0.2"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@testing-library/react": "^16.3.3",
|
|
41
|
+
"@types/d3-array": "^3.2.2",
|
|
42
|
+
"@types/d3-color": "^3.1.3",
|
|
43
|
+
"@types/d3-interpolate": "^3.0.4",
|
|
44
|
+
"@types/react": "^19.3.0",
|
|
45
|
+
"@types/react-dom": "^19.3.0",
|
|
46
|
+
"@vitest/browser-playwright": "^5.1.0",
|
|
47
|
+
"oxfmt": "^0.77.0",
|
|
48
|
+
"oxlint": "^1.92.0",
|
|
49
|
+
"playwright": "^1.65.0",
|
|
50
|
+
"react": "^19.3.1",
|
|
51
|
+
"react-dom": "^19.3.1",
|
|
52
|
+
"tsup": "^9.0.0",
|
|
53
|
+
"typescript": "^5.9.3",
|
|
54
|
+
"vitest": "^5.1.0"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"react": ">=19"
|
|
58
|
+
},
|
|
59
|
+
"peerDependenciesMeta": {
|
|
60
|
+
"react": {
|
|
61
|
+
"optional": true
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"keywords": [
|
|
65
|
+
"d3",
|
|
66
|
+
"canvas",
|
|
67
|
+
"progress",
|
|
68
|
+
"block-map",
|
|
69
|
+
"bittorrent"
|
|
70
|
+
],
|
|
71
|
+
"repository": {
|
|
72
|
+
"type": "git",
|
|
73
|
+
"url": "git+https://github.com/unpunnyfuns/d3-blockmap.git"
|
|
74
|
+
},
|
|
75
|
+
"publishConfig": {
|
|
76
|
+
"access": "public"
|
|
77
|
+
},
|
|
78
|
+
"homepage": "https://github.com/unpunnyfuns/d3-blockmap#readme",
|
|
79
|
+
"bugs": {
|
|
80
|
+
"url": "https://github.com/unpunnyfuns/d3-blockmap/issues"
|
|
81
|
+
}
|
|
82
|
+
}
|