diff --git a/metaflow/cards.py b/metaflow/cards.py index 80538ec7fbb..cfe4f1ff332 100644 --- a/metaflow/cards.py +++ b/metaflow/cards.py @@ -2,6 +2,7 @@ from metaflow.plugins.cards.card_modules.card import MetaflowCardComponent, MetaflowCard from metaflow.plugins.cards.card_modules.components import ( Artifact, + BokehEmbed, Table, Image, Error, diff --git a/metaflow/plugins/cards/card_modules/components.py b/metaflow/plugins/cards/card_modules/components.py index 43c093fda08..fc4c6667a3b 100644 --- a/metaflow/plugins/cards/card_modules/components.py +++ b/metaflow/plugins/cards/card_modules/components.py @@ -1,4 +1,14 @@ -from typing import Any, List, Optional, Union, Callable +from typing import ( + TYPE_CHECKING, + Any, + Callable, + List, + Literal, + NotRequired, + Optional, + TypedDict, + Union, +) from .basic import ( LogComponent, ErrorComponent, @@ -17,6 +27,12 @@ import inspect import textwrap +if TYPE_CHECKING: + from bokeh.document import Document + from bokeh.document.json import DocJson, PatchJson + from bokeh.document.events import DocumentChangedEvent + from bokeh.models import UIElement + def _warning_with_component(component, msg): if component._logger is None: @@ -1062,6 +1078,67 @@ def render(self): return data +class BokehEmbedData(TypedDict): + type: Literal["bokehEmbed"] + id: str | None + doc_json: DocJson + patch_json: NotRequired[PatchJson | None] + + +class BokehEmbed(UserComponent): + type: Literal["bokehEmbed"] = "bokehEmbed" + + _document: Document + _events: list[DocumentChangedEvent] + _has_rendered: bool + + REALTIME_UPDATABLE = True + + def __init__(self, obj: Document | UIElement): + from bokeh.document import Document + if isinstance(obj, Document): + document = obj + else: + document = Document() + document.add_root(obj) + self._document = document + self._events: list[DocumentChangedEvent] = [] + self._document.on_change(lambda event: self._events.append(event)) + self._has_rendered = False + + @with_default_component_id + @render_safely + def render(self): + doc = self._document + doc_json = self._document.to_json(deferred=False) + + # TODO we should want to embed the document once and then only patch it + # if not self._has_rendered: + # self._has_rendered = True + # doc_json = self._document.to_json(deferred=False) + # else: + # doc_json = None + + if len(self._events) != 0: + # patch_doc message's logic + from bokeh.core.serialization import Serializer + from bokeh.document.json import PatchJson + serializer = Serializer(references=doc.models.synced_references) + patch_json = PatchJson(events=serializer.encode(self._events)) + doc.models.flush_synced(lambda model: not serializer.has_ref(model)) + self._events = [] + else: + patch_json = None + + data = BokehEmbedData( + type=self.type, + id=self.component_id, + doc_json=doc_json, + patch_json=patch_json, + ) + return data + + class PythonCode(UserComponent): """ A component to display Python code with syntax highlighting. diff --git a/metaflow/plugins/cards/ui/package-lock.json b/metaflow/plugins/cards/ui/package-lock.json index 4ae2daef0d3..7ad7d40db1b 100644 --- a/metaflow/plugins/cards/ui/package-lock.json +++ b/metaflow/plugins/cards/ui/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "UNLICENSED", "dependencies": { + "@bokeh/bokehjs": "^3.9.0", "@iconify/svelte": "^3.1.4", "svelte-markdown": "^0.4.0", "svelte-vega": "^2.1.0", @@ -50,6 +51,15 @@ "node": ">=6.0.0" } }, + "node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@bahmutov/cy-rollup": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@bahmutov/cy-rollup/-/cy-rollup-2.0.0.tgz", @@ -74,6 +84,88 @@ "ms": "^2.1.1" } }, + "node_modules/@bokeh/bokehjs": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@bokeh/bokehjs/-/bokehjs-3.9.0.tgz", + "integrity": "sha512-nwVuRTRLuWqcPxIbG85N/u29Zh/41OmibbyAaj3AVbY0CvlQqVZH70HsD0RgutNe+tubBYdDOh12KjBg3R9uJg==", + "license": "BSD-3-Clause", + "workspaces": [ + "./make", + "./src/compiler", + "./src/lib", + "./src/server", + "./test" + ], + "dependencies": { + "@bokeh/numbro": "^1.6.2", + "@bokeh/slickgrid": "~2.4.4103", + "@preact/signals": "^2.5.1", + "@types/geojson": "^7946.0.13", + "@types/google.maps": "^3.55.5", + "@types/nearley": "^2.11.5", + "@types/proj4": "^2.5.5", + "@types/semver": "^7.7.1", + "@types/sprintf-js": "^1.1.4", + "choices.js": "^10.2.0", + "dompurify": "^3.3.0", + "fflate": "^0.8.2", + "flatbush": "^4.5.0", + "flatpickr": "^4.6.13", + "marked": "^17.0.1", + "mathjax-full": "^3.2.2", + "nearley": "^2.20.1", + "nouislider": "^15.7.1", + "preact": "^10.28.0", + "proj4": "^2.11.0", + "regl": "^2.1.0", + "sprintf-js": "^1.1.3", + "timezone": "^1.0.23", + "tslib": "^2.8.1", + "underscore.template": "^0.1.7" + }, + "engines": { + "node": ">=16.0", + "npm": ">=8.0" + } + }, + "node_modules/@bokeh/bokehjs/node_modules/marked": { + "version": "17.0.6", + "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.6.tgz", + "integrity": "sha512-gB0gkNafnonOw0obSTEGZTT86IuhILt2Wfx0mWH/1Au83kybTayroZ/V6nS25mN7u8ASy+5fMhgB3XPNrOZdmA==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@bokeh/numbro": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@bokeh/numbro/-/numbro-1.6.2.tgz", + "integrity": "sha512-owIECPc3T3QXHCb2v5Ez+/uE9SIxI7N4nd9iFlWnfBrOelr0/omvFn09VisRn37AAFAY39sJiCVgECwryHWUPA==", + "engines": { + "node": "*" + } + }, + "node_modules/@bokeh/slickgrid": { + "version": "2.4.4103", + "resolved": "https://registry.npmjs.org/@bokeh/slickgrid/-/slickgrid-2.4.4103.tgz", + "integrity": "sha512-wPitQJNUNUHw+86BPemvb1kIuV6UB4CpjEEDIXpU8G6Jges+8nx/iGHW8w9BwvICdeyhAmfX9Hmn5vRJMbe+uw==", + "license": "MIT", + "dependencies": { + "@types/slickgrid": "^2.1.30", + "jquery": ">=3.4.0", + "jquery-ui": ">=1.8.0", + "tslib": "^1.10.0" + } + }, + "node_modules/@bokeh/slickgrid/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, "node_modules/@cypress/request": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@cypress/request/-/request-4.0.0.tgz", @@ -771,6 +863,32 @@ "url": "https://opencollective.com/pkgr" } }, + "node_modules/@preact/signals": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@preact/signals/-/signals-2.9.0.tgz", + "integrity": "sha512-hYrY0KyUqkDgOl1qba/JGn6y81pXnurn21PMaxfcMwdncdZ3M/oVdmpTvEnsGjh48dIwDVc7bjWHqIsngSjYug==", + "license": "MIT", + "dependencies": { + "@preact/signals-core": "^1.14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + }, + "peerDependencies": { + "preact": ">= 10.25.0 || >=11.0.0-0" + } + }, + "node_modules/@preact/signals-core": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.14.1.tgz", + "integrity": "sha512-vxPpfXqrwUe9lpjqfYNjAF/0RF/eFGeLgdJzdmIIZjpOnTmGmAB4BjWone562mJGMRP4frU6iZ6ei3PDsu52Ng==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.46.2", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.2.tgz", @@ -1111,6 +1229,18 @@ "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", "license": "MIT" }, + "node_modules/@types/google.maps": { + "version": "3.64.0", + "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.64.0.tgz", + "integrity": "sha512-dN0H6tB4lgLQLovcbPXFYYOEV41TpyyJghzb5jrzjB96FZmjeOghevVdC+BMGd6YqyCqXaggyEtqRXLRjzCBZA==", + "license": "MIT" + }, + "node_modules/@types/jquery": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-4.0.0.tgz", + "integrity": "sha512-Z+to+A2VkaHq1DfI2oSwsoCdhCHMpTSgjWzNcbNlRGYzksDBpPUgEcAL+RQjOBJRaLoEAOHXxqDGBVP+BblBwg==", + "license": "MIT" + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -1124,6 +1254,12 @@ "integrity": "sha512-OucS4KMHhFzhz27KxmWg7J+kIYqyqoW5kdIEI319hqARQQUTqhao3M/F+uFnDXD0Rg72iDDZxZNxq5gvctmLlg==", "license": "MIT" }, + "node_modules/@types/nearley": { + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@types/nearley/-/nearley-2.11.5.tgz", + "integrity": "sha512-dM7TrN0bVxGGXTYGx4YhGear8ysLO5SOuouAWM9oltjQ3m9oYa13qi8Z1DJp5zxVMPukvQdsrnZmgzpeuTSEQA==", + "license": "MIT" + }, "node_modules/@types/node": { "version": "20.19.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.10.tgz", @@ -1134,6 +1270,12 @@ "undici-types": "~6.21.0" } }, + "node_modules/@types/proj4": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@types/proj4/-/proj4-2.5.6.tgz", + "integrity": "sha512-zfMrPy9fx+8DchqM0kIUGeu2tTVB5ApO1KGAYcSGFS8GoqRIkyL41xq2yCx/iV3sOLzo7v4hEgViSLTiPI1L0w==", + "license": "MIT" + }, "node_modules/@types/pug": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.10.tgz", @@ -1142,10 +1284,9 @@ "license": "MIT" }, "node_modules/@types/semver": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", - "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", - "dev": true, + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", "license": "MIT" }, "node_modules/@types/sinonjs__fake-timers": { @@ -1162,6 +1303,21 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/slickgrid": { + "version": "2.1.40", + "resolved": "https://registry.npmjs.org/@types/slickgrid/-/slickgrid-2.1.40.tgz", + "integrity": "sha512-+HWaipRr4bw0cy4eS8PCWxo+Fi66aL+mh36unRLAWtatAvMnxpldTKfpe9T7zdNtgN+rq+/faux3JzFR1mj/dg==", + "license": "MIT", + "dependencies": { + "@types/jquery": "*" + } + }, + "node_modules/@types/sprintf-js": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/sprintf-js/-/sprintf-js-1.1.4.tgz", + "integrity": "sha512-aWK1reDYWxcjgcIIPmQi3u+OQDuYa9b+lr6eIsGWrekJ9vr1NSjr4Eab8oQ1iKuH1ltFHpXGyerAv1a3FMKxzQ==", + "license": "MIT" + }, "node_modules/@types/tmp": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.6.tgz", @@ -1169,6 +1325,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/yauzl": { "version": "2.10.3", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", @@ -1385,6 +1548,15 @@ "dev": true, "license": "ISC" }, + "node_modules/@xmldom/xmldom": { + "version": "0.9.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.10.tgz", + "integrity": "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==", + "license": "MIT", + "engines": { + "node": ">=14.6" + } + }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", @@ -1801,6 +1973,17 @@ "node": ">=8" } }, + "node_modules/choices.js": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/choices.js/-/choices.js-10.2.0.tgz", + "integrity": "sha512-8PKy6wq7BMjNwDTZwr3+Zry6G2+opJaAJDDA/j3yxvqSCnvkKe7ZIFfIyOhoc7htIWFhsfzF9tJpGUATcpUtPg==", + "license": "MIT", + "dependencies": { + "deepmerge": "^4.2.2", + "fuse.js": "^6.6.2", + "redux": "^4.2.0" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -2533,7 +2716,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -2581,6 +2763,12 @@ "node": ">=8" } }, + "node_modules/discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", + "license": "MIT" + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -2594,6 +2782,15 @@ "node": ">=6.0.0" } }, + "node_modules/dompurify": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.2.tgz", + "integrity": "sha512-lHeS9SA/IKeIFFyYciHBr2n0v1VMPlSj843HdLOwjb2OxNwdq9Xykxqhk+FE42MzAdHvInbAolSE4mhahPpjXA==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -2960,6 +3157,15 @@ "node": "*" } }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -3206,6 +3412,12 @@ "pend": "~1.2.0" } }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -3264,6 +3476,27 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/flatbush": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/flatbush/-/flatbush-4.5.1.tgz", + "integrity": "sha512-5tpuZV/26A5gRYfqyof3/ZTWeARKgZgd9aBrJLGNSGeasdO2PRb/2lIwDHBIuvPhKK2Y4ELuHbRGtegOwH3Lqg==", + "license": "ISC", + "dependencies": { + "flatqueue": "^3.0.0" + } + }, + "node_modules/flatpickr": { + "version": "4.6.13", + "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz", + "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==", + "license": "MIT" + }, + "node_modules/flatqueue": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/flatqueue/-/flatqueue-3.0.0.tgz", + "integrity": "sha512-y1deYaVt+lIc/d2uIcWDNd0CrdQTO5xoCjeFdhX0kSXvm2Acm0o+3bAOiYklTEoRyzwio3sv3/IiBZdusbAe2Q==", + "license": "ISC" + }, "node_modules/flatted": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", @@ -3346,6 +3579,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/fuse.js": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.6.2.tgz", + "integrity": "sha512-cJaJkxCCxC8qIIcPBF9yGxY0W/tVZS3uEISDxhYIdtk8OL93pe+6Zj7LjCqVV4dzbqcriOZ+kQ/NE4RXZHsIGA==", + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -3928,6 +4170,21 @@ "dev": true, "license": "MIT" }, + "node_modules/jquery": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-4.0.0.tgz", + "integrity": "sha512-TXCHVR3Lb6TZdtw1l3RTLf8RBWVGexdxL6AC8/e0xZKEpBflBsjh9/8LXw+dkNFuOyW9B7iB3O1sP7hS0Kiacg==", + "license": "MIT" + }, + "node_modules/jquery-ui": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.14.2.tgz", + "integrity": "sha512-1gSl7PUjyipa2adSr780Ujk16faicrV7PjPPzPtvWk7tTqBnsqp67NNV9jZK2+BIxUPXWSnIUU/LBCgwgGZE+Q==", + "license": "MIT", + "dependencies": { + "jquery": ">=1.12.0 <5.0.0" + } + }, "node_modules/js-yaml": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", @@ -4257,6 +4514,19 @@ "node": ">= 0.4" } }, + "node_modules/mathjax-full": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/mathjax-full/-/mathjax-full-3.2.2.tgz", + "integrity": "sha512-+LfG9Fik+OuI8SLwsiR02IVdjcnRCy5MufYLi0C3TdMT56L/pjB0alMVGgoWJF8pN9Rc7FESycZB9BMNWIid5w==", + "deprecated": "Version 4 replaces this package with the scoped package @mathjax/src", + "license": "Apache-2.0", + "dependencies": { + "esm": "^3.2.25", + "mhchemparser": "^4.1.0", + "mj-context-menu": "^0.6.1", + "speech-rule-engine": "^4.0.6" + } + }, "node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", @@ -4280,6 +4550,18 @@ "node": ">= 8" } }, + "node_modules/mgrs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mgrs/-/mgrs-1.0.0.tgz", + "integrity": "sha512-awNbTOqCxK1DBGjalK3xqWIstBZgN6fxsMSiXLs9/spqWkF2pAhb2rrYCFSsr1/tT7PhcDGjZndG8SWYn0byYA==", + "license": "MIT" + }, + "node_modules/mhchemparser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/mhchemparser/-/mhchemparser-4.2.1.tgz", + "integrity": "sha512-kYmyrCirqJf3zZ9t/0wGgRZ4/ZJw//VwaRVGA75C4nhE60vtnIzhl9J9ndkX/h6hxSN7pjg/cE0VxbnNM+bnDQ==", + "license": "Apache-2.0" + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -4376,6 +4658,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mj-context-menu": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz", + "integrity": "sha512-7NO5s6n10TIV96d4g2uDpG7ZDpIhMh0QNfGdJw/W47JswFcosz457wqz/b5sAKvl12sxINGFCn80NZHKwxQEXA==", + "license": "Apache-2.0" + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -4389,6 +4677,12 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/moo": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.3.tgz", + "integrity": "sha512-m2fmM2dDm7GZQsY7KK2cme8agi+AAljILjQnof7p1ZMDe6dQ4bdnSMx0cPppudoeNv5hEFQirN6u+O4fDE0IWA==", + "license": "BSD-3-Clause" + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -4432,6 +4726,34 @@ "dev": true, "license": "MIT" }, + "node_modules/nearley": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", + "license": "MIT", + "dependencies": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6" + }, + "bin": { + "nearley-railroad": "bin/nearley-railroad.js", + "nearley-test": "bin/nearley-test.js", + "nearley-unparse": "bin/nearley-unparse.js", + "nearleyc": "bin/nearleyc.js" + }, + "funding": { + "type": "individual", + "url": "https://nearley.js.org/#give-to-nearley" + } + }, + "node_modules/nearley/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -4442,6 +4764,12 @@ "node": ">=0.10.0" } }, + "node_modules/nouislider": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/nouislider/-/nouislider-15.8.1.tgz", + "integrity": "sha512-93TweAi8kqntHJSPiSWQ1o/uZ29VWOmal9YKb6KKGGlCkugaNfAupT7o1qTHqdJvNQ7S0su5rO6qRFCjP8fxtw==", + "license": "MIT" + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -4776,6 +5104,16 @@ "node": ">=4" } }, + "node_modules/preact": { + "version": "10.29.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.1.tgz", + "integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4838,6 +5176,19 @@ "node": ">= 0.6.0" } }, + "node_modules/proj4": { + "version": "2.20.8", + "resolved": "https://registry.npmjs.org/proj4/-/proj4-2.20.8.tgz", + "integrity": "sha512-1C8sfT4xY4PAPwk0MroFBTGF4R4bzDXdmPQTGYVLsoNssrZ9odzObxS2dTeGBty8jW8KO7h16C1Hs2JP+ctfFw==", + "license": "MIT", + "dependencies": { + "mgrs": "1.0.0", + "wkt-parser": "^1.5.5" + }, + "funding": { + "url": "https://github.com/sponsors/ahocevar" + } + }, "node_modules/proxy-from-env": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", @@ -4903,6 +5254,25 @@ ], "license": "MIT" }, + "node_modules/railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==", + "license": "CC0-1.0" + }, + "node_modules/randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "license": "MIT", + "dependencies": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + }, + "engines": { + "node": ">=0.12" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -4916,6 +5286,21 @@ "node": ">=8.10.0" } }, + "node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/regl": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/regl/-/regl-2.1.1.tgz", + "integrity": "sha512-+IOGrxl3FZ8ZM9ixCWQZzFRiRn7Rzn9bu3iFHwg/yz4tlOUQgbO4PHLgG+1ZT60zcIV8tief6Qrmyl8qcoJP0g==", + "license": "MIT" + }, "node_modules/request-progress": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", @@ -4982,6 +5367,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "license": "MIT", + "engines": { + "node": ">=0.12" + } + }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -5320,6 +5714,35 @@ "node": ">=0.10.0" } }, + "node_modules/speech-rule-engine": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/speech-rule-engine/-/speech-rule-engine-4.1.4.tgz", + "integrity": "sha512-i/VCLG1fvRc95pMHRqG4aQNscv+9aIsqA2oI7ZQS51sTdUcDHYX6cpT8/tqZ+enjs1tKVwbRBWgxut9SWn+f9g==", + "license": "Apache-2.0", + "dependencies": { + "@xmldom/xmldom": "0.9.10", + "commander": "13.1.0", + "wicked-good-xpath": "1.3.0" + }, + "bin": { + "sre": "bin/sre" + } + }, + "node_modules/speech-rule-engine/node_modules/commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause" + }, "node_modules/sshpk": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", @@ -5671,6 +6094,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/timezone": { + "version": "1.0.23", + "resolved": "https://registry.npmjs.org/timezone/-/timezone-1.0.23.tgz", + "integrity": "sha512-yhQgk6qmSLB+TF8HGmApZAVI5bfzR1CoKUGr+WMZWmx75ED1uDewAZA8QMGCQ70TEv4GmM8pDB9jrHuxdaQ1PA==", + "license": "MIT" + }, "node_modules/tldts": { "version": "6.1.86", "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", @@ -5836,6 +6265,12 @@ "node": ">=14.17" } }, + "node_modules/underscore.template": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/underscore.template/-/underscore.template-0.1.7.tgz", + "integrity": "sha512-wQ25n9/J0Olo3A92QDbSCkD04FKRrjVOn6wooaFDKsrmV9alkc7vZ3MmldbVo4NbJCk9ycWSEcfGn4NzFZIcvA==", + "license": "MIT" + }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", @@ -6501,6 +6936,21 @@ "node": ">= 8" } }, + "node_modules/wicked-good-xpath": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/wicked-good-xpath/-/wicked-good-xpath-1.3.0.tgz", + "integrity": "sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw==", + "license": "MIT" + }, + "node_modules/wkt-parser": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/wkt-parser/-/wkt-parser-1.5.5.tgz", + "integrity": "sha512-/zMYi94/7D7fxcOSlVmWn6vnOMj3Gq5d1xvVjaYOS9n6h0qOJ4I7YYVxBWYcH1vq9+suhqzXkn05Yx47zQNUIA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ahocevar" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", diff --git a/metaflow/plugins/cards/ui/package.json b/metaflow/plugins/cards/ui/package.json index 79e254b8baa..01f6077aa8a 100644 --- a/metaflow/plugins/cards/ui/package.json +++ b/metaflow/plugins/cards/ui/package.json @@ -37,6 +37,7 @@ }, "license": "UNLICENSED", "dependencies": { + "@bokeh/bokehjs": "^3.9.0", "@iconify/svelte": "^3.1.4", "svelte-markdown": "^0.4.0", "svelte-vega": "^2.1.0", diff --git a/metaflow/plugins/cards/ui/src/components/bokeh-embed.svelte b/metaflow/plugins/cards/ui/src/components/bokeh-embed.svelte new file mode 100644 index 00000000000..9d82115bc84 --- /dev/null +++ b/metaflow/plugins/cards/ui/src/components/bokeh-embed.svelte @@ -0,0 +1,59 @@ + + +
diff --git a/metaflow/plugins/cards/ui/src/components/card-component-renderer.svelte b/metaflow/plugins/cards/ui/src/components/card-component-renderer.svelte index 3fc2dd2fe64..1c65c2dd75a 100644 --- a/metaflow/plugins/cards/ui/src/components/card-component-renderer.svelte +++ b/metaflow/plugins/cards/ui/src/components/card-component-renderer.svelte @@ -2,6 +2,7 @@ import type { ComponentType } from "svelte"; import type * as types from "../types"; import Artifacts from "./artifacts.svelte"; + import BokehEmbed from "./bokeh-embed.svelte"; import Dag from "./dag/dag.svelte"; import Heading from "./heading.svelte"; import Image from "./image.svelte"; @@ -25,6 +26,7 @@ const typesMap: Record