{"_id":"@data-navigator/bokeh-wrapper","_rev":"2-4478660f1c3d5896681832013d254b39","name":"@data-navigator/bokeh-wrapper","dist-tags":{"latest":"2.0.0"},"versions":{"0.2.0":{"name":"@data-navigator/bokeh-wrapper","version":"0.2.0","keywords":["visualization","accessibility","bokeh","data-navigator","a11y"],"author":{"name":"Frank Elavsky"},"license":"MIT","_id":"@data-navigator/bokeh-wrapper@0.2.0","maintainers":[{"name":"frank-elavsky","email":"frankelavsky@gmail.com"}],"dist":{"shasum":"01fde4995ece216fc0ec07161d2c21aeb58e96e9","tarball":"https://registry.npmjs.org/@data-navigator/bokeh-wrapper/-/bokeh-wrapper-0.2.0.tgz","fileCount":7,"integrity":"sha512-JRLYw+sO+O4GVlhOpvIjzyYWurJErAXvKORl3wFhJUkI71Zubwj5M6q/uYp4y91TKd2ujCPAiKb6pP2RUBucuw==","signatures":[{"sig":"MEYCIQCz2v3UzXe4Gr533rM7a7VVLrkerVD4TZShwlOHLbAVrwIhAOoiUWa1uxmRWWbqEjm7FrPTtnT6j+ip8OwoVRhuDaFL","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":74402},"main":"./dist/index.cjs","type":"module","types":"./dist/src/index.d.ts","module":"./dist/index.js","exports":{".":{"import":{"types":"./dist/src/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/src/index.d.ts","default":"./dist/index.cjs"}}},"gitHead":"bf14370594c46a70d0c666786b942cf16243cb6d","scripts":{"dev":"vitepress dev docs","build":"tsup src/index.ts --format cjs,esm --dts","clean":"rm -rf ./dist","preview":"vitepress preview docs","build:docs":"vitepress build docs","prepublishOnly":"yarn build && cp ../../README.md ../../LICENSE . 2>/dev/null || true"},"_npmUser":{"name":"frank-elavsky","email":"frankelavsky@gmail.com"},"_npmVersion":"10.9.2","description":"A data-navigator wrapper for Bokeh charts with smart defaults and a text-chat navigation interface.","directories":{},"_nodeVersion":"23.11.0","_hasShrinkwrap":false,"devDependencies":{"vue":"^3.5.0","tsup":"^7.2.0","@swc/core":"^1.3.75","vitepress":"^1.4.0","typescript":"^5.1.6","data-navigator":"*"},"peerDependencies":{"data-navigator":">=2.3.0"},"_npmOperationalInternal":{"tmp":"tmp/bokeh-wrapper_0.2.0_1772150400453_0.26010340075737615","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@data-navigator/bokeh-wrapper","version":"2.0.0","type":"module","author":{"name":"Frank Elavsky"},"license":"MIT","description":"A data-navigator wrapper for Bokeh charts with smart defaults and a text-chat navigation interface.","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","sideEffects":false,"repository":{"type":"git","url":"git+https://github.com/cmudig/data-navigator.git","directory":"packages/bokeh-wrapper"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"keywords":["visualization","accessibility","bokeh","data-navigator","a11y"],"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","clean":"rm -rf ./dist","dev":"vitepress dev docs","build:docs":"vitepress build docs","preview":"vitepress preview docs","prepublishOnly":"yarn build && cp ../../LICENSE . 2>/dev/null || true"},"peerDependencies":{"data-navigator":">=2.4.0"},"devDependencies":{"@swc/core":"^1.3.75","data-navigator":"*","tsup":"^7.2.0","typescript":"^5.1.6","vitepress":"^1.4.0","vue":"^3.5.0"},"_id":"@data-navigator/bokeh-wrapper@2.0.0","gitHead":"5a5ed832296493a552bc7e47111cebebc91ab6f1","bugs":{"url":"https://github.com/cmudig/data-navigator/issues"},"homepage":"https://github.com/cmudig/data-navigator#readme","_nodeVersion":"23.11.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-29C3kmQj9rZ64wsqXVHWVU7nyEOT/lKHbQLgxEOFAo2eAM3pMTAPzlUtUMrJRANV4hh4Evm1X+C+U3/7duAmhg==","shasum":"f76690c1a2cc6dfb6154096332abc2f78cb3f719","tarball":"https://registry.npmjs.org/@data-navigator/bokeh-wrapper/-/bokeh-wrapper-2.0.0.tgz","fileCount":7,"unpackedSize":78666,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCRoWJjOBfDh7R34iWWPxu2pm0D8vyXlPG7hS5cki20kAIgfqWO4ooFaDyHzpxgz16TJpD8WgjyfZBbMFdYD3p7fho="}]},"_npmUser":{"name":"frank-elavsky","email":"frankelavsky@gmail.com"},"directories":{},"maintainers":[{"name":"frank-elavsky","email":"frankelavsky@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/bokeh-wrapper_2.0.0_1772727341803_0.8393591287561584"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-27T00:00:00.287Z","modified":"2026-03-05T16:15:42.118Z","0.2.0":"2026-02-27T00:00:00.618Z","2.0.0":"2026-03-05T16:15:41.958Z"},"author":{"name":"Frank Elavsky"},"license":"MIT","keywords":["visualization","accessibility","bokeh","data-navigator","a11y"],"description":"A data-navigator wrapper for Bokeh charts with smart defaults and a text-chat navigation interface.","maintainers":[{"name":"frank-elavsky","email":"frankelavsky@gmail.com"}],"readme":"# @data-navigator/bokeh-wrapper\n\nAccessible data navigation for [Bokeh](https://bokeh.org/) charts. One function call adds a keyboard, screen reader, and text-chat navigation interface to any Bokeh chart.\n\nPart of the [Data Navigator](https://dig.cmu.edu/data-navigator/) project.\n\n**[Documentation](https://dig.cmu.edu/data-navigator/bokeh-wrapper/)** · **[Getting Started](https://dig.cmu.edu/data-navigator/bokeh-wrapper/getting-started)** · **[npm](https://www.npmjs.com/package/@data-navigator/bokeh-wrapper)**\n\n## Install\n\n```bash\nnpm install data-navigator @data-navigator/bokeh-wrapper\n```\n\nAlso import the text-chat stylesheet:\n\n```js\nimport 'data-navigator/text-chat.css';\n```\n\n## Quick start\n\nRender your Bokeh chart first, then call `addDataNavigator`:\n\n```js\nimport { addDataNavigator } from '@data-navigator/bokeh-wrapper';\nimport 'data-navigator/text-chat.css';\n\nconst wrapper = addDataNavigator({\n    plotContainer: '#my-plot',\n    data: myData\n});\n```\n\nThe wrapper automatically:\n\n1. Sets the Bokeh plot to `inert` so screen readers skip the inaccessible canvas output\n2. Infers the chart type from your data shape (you can also specify it)\n3. Builds a navigable graph structure (the hard part!)\n4. Appends a text-chat interface after the plot (this can be styled further using css)\n\n## Options\n\n```ts\naddDataNavigator({\n    // Required\n    plotContainer: '#my-plot', // CSS selector or HTMLElement\n    data: myData, // Array of plain objects (same data passed to Bokeh)\n\n    // Chart type — auto-detected if omitted\n    type: 'bar',\n    // 'bar' | 'hbar' | 'cartesian' | 'line' | 'multiline' | 'stacked_bar' | 'auto'\n\n    // Field mappings — inferred from data if omitted\n    xField: 'fruit', // Categorical or x-axis field\n    yField: 'count', // Numerical or y-axis field\n    groupField: 'year', // Series/stack layer field (multiline, stacked_bar)\n\n    // Interface mode (default: 'text')\n    mode: 'text', // 'text' | 'keyboard' | 'both'\n\n    // Place the chat UI in a specific container (optional)\n    chatContainer: '#my-chat-area',\n\n    // Sync with the Bokeh chart\n    onNavigate(node) {\n        // Called on every navigation move — use to redraw focus indicators\n        highlightBar(node.data);\n    },\n    onExit() {\n        clearHighlight();\n    },\n\n    // Interaction callbacks (text mode)\n    onClick(node) {\n        // Triggered when user types \"click\" or \"select\"\n        triggerBokehClick(node.data);\n    },\n    onHover(node) {\n        // Triggered when user types \"hover\" or \"inspect\"\n        triggerBokehHover(node.data);\n    },\n\n    // LLM integration (optional)\n    llm: async messages => {\n        const res = await fetch('/api/llm', { method: 'POST', body: JSON.stringify({ messages }) });\n        return (await res.json()).content;\n    },\n\n    // Override auto-generated navigation command labels\n    commandLabels: {\n        left: 'Previous fruit',\n        right: 'Next fruit'\n    },\n\n    // Advanced: pass extra options to the underlying data-navigator structure builder\n    structureOptions: {}\n});\n```\n\n## Returned instance\n\n```ts\nconst wrapper = addDataNavigator({ ... });\n\nwrapper.getCurrentNode();  // Currently focused node, or null\nwrapper.structure;         // Underlying data-navigator Structure (pass to Inspector, etc.)\nwrapper.destroy();         // Remove all DOM additions and restore the plot\n```\n\n## Connecting to Bokeh\n\nBecause Bokeh renders to a `<canvas>`, the cleanest way to show focus is to redraw the chart with an extra highlight layer on each navigation event. Bokeh also, unfortunately, makes it hard for Data Navigator to know where elements are rendered. This means that focus during navigation takes place on the whole visualization, while an indicator is added using bokeh to the specific location. This isn't ideal, but is the best approach we can take unless Bokeh adds some way to query element `x`, `y`, `width`, and `height` programmatically. We also [discuss the focus indication challenge further](https://dig.cmu.edu/data-navigator/getting-started/first-chart.html#trouble-with-focus-indication) in our core docs for Data Navigator.\n\n```js\nconst drawChart = highlight => {\n    /* re-render with highlight layer */\n};\n\nconst wrapper = addDataNavigator({\n    plotContainer: '#my-plot',\n    data,\n    onNavigate(node) {\n        drawChart(node.derivedNode ? null : { x: node.data.fruit });\n    },\n    onExit() {\n        drawChart(null);\n    }\n});\n```\n\nSee the [Getting Started guide](https://dig.cmu.edu/data-navigator/bokeh-wrapper/getting-started) for the full walkthrough and [examples](https://dig.cmu.edu/data-navigator/bokeh-wrapper/examples/bar-chart) for complete runnable code.\n\n## Using with the Inspector\n\nPass `wrapper.structure` to [`@data-navigator/inspector`](https://www.npmjs.com/package/@data-navigator/inspector) to visualize the navigation graph:\n\n```js\nimport { Inspector } from '@data-navigator/inspector';\n\nconst wrapper = addDataNavigator({ plotContainer: '#plot', data });\nconst inspector = Inspector({ structure: wrapper.structure, container: 'inspector-container' });\n```\n\n## Background\n\nBokeh charts are visually rich but historically inaccessible — assistive technologies cannot meaningfully interact with the canvas or SVG output. This wrapper builds a parallel accessible interface using a bokeh visualization's underlying data. Our work is informed by the ongoing [Bokeh Accessibility Audit](https://bokeh-a11y-audit.readthedocs.io/), which documents accessibility issues in Bokeh. The audit and this package was supported by a [CZI Essential Open Source Software](https://chanzuckerberg.com/eoss/) (EOSS) Cycle 6 grant.\n\n## Credit\n\nDeveloped at CMU's [Data Interaction Group](https://dig.cmu.edu/) by [Frank Elavsky](https://frank.computer), in collaboration with Quansight, Anaconda, and Bokeh.\n\n## Citing Data Navigator\n\n```bib\n@article{2023-data-navigator,\n  title = {{Data Navigator}: An Accessibility-Centered Data Navigation Toolkit},\n  publisher = {{IEEE}},\n  author = {Frank Elavsky and Lucas Nadolskis and Dominik Moritz},\n  journal = {{IEEE} Transactions on Visualization and Computer Graphics},\n  year = {2023},\n  url = {http://dig.cmu.edu/data-navigator/}\n}\n```\n","readmeFilename":"README.md","homepage":"https://github.com/cmudig/data-navigator#readme","repository":{"type":"git","url":"git+https://github.com/cmudig/data-navigator.git","directory":"packages/bokeh-wrapper"},"bugs":{"url":"https://github.com/cmudig/data-navigator/issues"}}