@perspective-dev/react 5.4.0 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +2 -2
- package/package.json +4 -4
- package/src/viewer.tsx +9 -2
package/dist/esm/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import*as i from"react";import*as
|
|
1
|
+
import*as i from"react";import*as c from"react";function s(e,t,r,n=a=>a.detail){c.useEffect(()=>{if(!r||!e)return;let a=new AbortController,l=o=>r(n(o));return e?.addEventListener(t,l,{signal:a.signal}),()=>a.abort()},[e,r])}function d(e){let[t,r]=i.useState(null);return i.useEffect(()=>()=>{t?.delete()},[t]),i.useEffect(()=>{if(!t)return;let n=!1;return(async()=>{if(!e.client){await t.eject();return}await t.load(e.client),!(n||!e.config)&&("panels"in e.config?await t.restoreWorkspace(e.config,{wait_for_table:!0}):await t.restore(e.config,{wait_for_table:!0}))})(),()=>{n=!0}},[t,e.client,JSON.stringify(e.config)]),s(t,"perspective-click",e.onClick),s(t,"perspective-select",e.onSelect),s(t,"perspective-config-update",e.onConfigUpdate,n=>n.detail.getConfig()),i.createElement("perspective-viewer",{ref:r,id:e.id,className:e.className,hidden:e.hidden,slot:e.slot,style:e.style,tabIndex:e.tabIndex,title:e.title})}var u=i.memo(d);export{u as PerspectiveViewer};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/viewer.tsx", "../../src/utils.tsx"],
|
|
4
|
-
"sourcesContent": ["// \u250F\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2513\n// \u2503 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588 \u2588 \u2588 \u2588 \u2588 \u2588\u2584 \u2580\u2588\u2588\u2588 \u2588 \u2503\n// \u2503 \u2584\u2584\u2584\u2584\u2584\u2588 \u2588\u2584\u2584\u2584\u2584\u2584 \u2584\u2584\u2584\u2584\u2584\u2588 \u2580\u2580\u2580\u2580\u2580\u2588\u2580\u2580\u2580\u2580\u2580 \u2588 \u2580\u2580\u2580\u2580\u2580\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258C\u2590\u2588\u2588\u2588 \u2588\u2588\u2588\u2584 \u2580\u2588 \u2588 \u2580\u2580\u2580\u2580\u2580 \u2503\n// \u2503 \u2588\u2580\u2580\u2580\u2580\u2580 \u2588\u2580\u2580\u2580\u2580\u2580 \u2588\u2580\u2588\u2588\u2580\u2580 \u2584\u2584\u2584\u2584\u2584 \u2588 \u2584\u2584\u2584\u2584\u2584\u2588 \u2584\u2584\u2584\u2584\u2584\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258C\u2590\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2584 \u2588 \u2584\u2584\u2584\u2584\u2584 \u2503\n// \u2503 \u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588 \u2580\u2588\u2584 \u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588 \u2588\u2588\u2588\u258C\u2590\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2584 \u2588 \u2503\n// \u2523\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u252B\n// \u2503 Copyright (c) 2017, the Perspective Authors. \u2503\n// \u2503 \u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C \u2503\n// \u2503 This file is part of the Perspective library, distributed under the terms \u2503\n// \u2503 of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). \u2503\n// \u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u251B\n\nimport * as React from \"react\";\nimport type * as psp from \"@perspective-dev/client\";\nimport type * as pspViewer from \"@perspective-dev/viewer\";\nimport { usePspListener } from \"./utils\";\n\nfunction PerspectiveViewerImpl(props: PerspectiveViewerProps) {\n const [viewer, setViewer] =\n React.useState<pspViewer.HTMLPerspectiveViewerElement | null>(null);\n\n React.useEffect(() => {\n return () => {\n viewer?.delete();\n };\n }, [viewer]);\n\n React.useEffect(() => {\n if (!viewer) {\n return;\n }\n\n let cancelled = false;\n (async () => {\n if (!props.client) {\n await viewer.eject();\n return;\n }\n\n await viewer.load(props.client);\n if (cancelled || !props.config) {\n return;\n }\n\n if (\"panels\" in props.config) {\n await viewer.restoreWorkspace(props.config);\n } else {\n await viewer.restore(props.config);\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [viewer, props.client, JSON.stringify(props.config)]);\n\n usePspListener(viewer, \"perspective-click\", props.onClick);\n usePspListener(viewer, \"perspective-select\", props.onSelect);\n usePspListener(\n viewer,\n \"perspective-config-update\",\n props.onConfigUpdate,\n (e) => e.detail.getConfig(),\n );\n\n return (\n <perspective-viewer\n ref={setViewer}\n id={props.id}\n className={props.className}\n hidden={props.hidden}\n slot={props.slot}\n style={props.style}\n tabIndex={props.tabIndex}\n title={props.title}\n />\n );\n}\n\n/**\n * Props for the {@link PerspectiveViewer} component.\n */\nexport interface PerspectiveViewerProps {\n /**\n * The viewer's data source, forwarded to the element's `load()` method\n * whenever it changes.\n *\n * - A `Table` (or `Promise<Table>`) displays that table directly.\n * - A `Client` (e.g. from `perspective.worker()` or a WebSocket\n * connection to a remote server) connects the viewer to every table\n * hosted by that client; the table each panel displays is chosen by\n * {@link PerspectiveViewerProps.config} or interactively by the user.\n * - `undefined` calls `eject()`, returning the viewer to an unloaded\n * state without unmounting it.\n *\n * The component does not take ownership of the `Table` \u2014 delete it\n * yourself when it is no longer needed, e.g.\n * `table.delete({ lazy: true })`.\n */\n client?: psp.Client | Promise<psp.Client> | psp.Table | Promise<psp.Table>;\n\n /**\n * Declarative viewer state \u2014 group-bys, splits, filters, sorts,\n * expressions, plugin and plugin config \u2014 applied with the element's\n * `restore()` method whenever it (or\n * {@link PerspectiveViewerProps.client}) changes. A config with a\n * `panels` property is treated as a multi-panel workspace layout and\n * applied with `restoreWorkspace()` instead.\n *\n * Configs are compared structurally, so passing a fresh-but-equal object\n * literal on each render does not re-apply. Combine with\n * {@link PerspectiveViewerProps.onConfigUpdate} to use the viewer as a\n * controlled component.\n *\n * When {@link PerspectiveViewerProps.client} is a bare `Client` (which\n * creates no panel by itself), the config must include `table` \u2014 a\n * panel-creating `restore()` without one rejects. `Table` clients bind\n * their own panel, so `table` may be omitted there.\n */\n config?: pspViewer.ViewerConfigUpdate | pspViewer.WorkspaceConfigUpdate;\n\n /**\n * Called with the viewer's complete configuration whenever the user\n * reconfigures it through its UI (the element's\n * `\"perspective-config-update\"` Custom Event). Use this to persist the\n * user's view or reflect it back through\n * {@link PerspectiveViewerProps.config}.\n */\n onConfigUpdate?: (config: pspViewer.ViewerConfigUpdate) => void;\n\n /**\n * Called when the user clicks a datapoint (the element's\n * `\"perspective-click\"` Custom Event), with the clicked row's data and a\n * filter config which would select it.\n */\n onClick?: (data: pspViewer.PerspectiveClickEventDetail) => void;\n\n /**\n * Called when the user selects or deselects a datapoint or row (the\n * element's `\"perspective-select\"` Custom Event).\n */\n onSelect?: (data: pspViewer.PerspectiveSelectEventDetail) => void;\n\n // Applicable props from `React.HTMLAttributes`, which we cannot extend\n // directly because Perspective changes the signature of `onClick`.\n\n /** Forwarded to the element's `class` attribute. */\n className?: string | undefined;\n\n /** Forwarded to the element's `hidden` attribute. */\n hidden?: boolean | undefined;\n\n /** Forwarded to the element's `id` attribute. */\n id?: string | undefined;\n\n /** Forwarded to the element's `slot` attribute. */\n slot?: string | undefined;\n\n /** Forwarded to the element's inline `style`. */\n style?: React.CSSProperties | undefined;\n\n /** Forwarded to the element's `tabindex` attribute. */\n tabIndex?: number | undefined;\n\n /** Forwarded to the element's `title` attribute. */\n title?: string | undefined;\n}\n\n/**\n * A declarative React wrapper for the `<perspective-viewer>` Custom Element.\n *\n * `<PerspectiveViewer>` manages the element's imperative lifecycle: it\n * `load()`s the {@link PerspectiveViewerProps.client}, `restore()`s the\n * {@link PerspectiveViewerProps.config} whenever either changes, subscribes\n * the `on*` callback props to the element's Custom Events, and `delete()`s\n * the viewer (freeing its WebAssembly resources) on unmount. Tables and\n * clients are created outside the component and are yours to manage \u2014 a\n * `Table` passed as `client` survives unmount and can be shown again by a\n * later mount.\n *\n * The component is memoized, so re-rendering a parent with unchanged props\n * does not touch the viewer.\n *\n * @example\n * ```tsx\n * const WORKER = await perspective.worker();\n * const TABLE = WORKER.table(\n * fetch(\"superstore.lz4.arrow\").then((resp) => resp.arrayBuffer()),\n * { name: \"superstore\" },\n * );\n *\n * const App: React.FC = () => {\n * const [config, setConfig] = React.useState<pspViewer.ViewerConfigUpdate>({\n * group_by: [\"State\"],\n * plugin: \"Y Bar\",\n * });\n *\n * return (\n * <PerspectiveViewer\n * client={TABLE}\n * config={config}\n * onConfigUpdate={setConfig}\n * />\n * );\n * };\n * ```\n */\nexport const PerspectiveViewer: React.FC<PerspectiveViewerProps> = React.memo(\n PerspectiveViewerImpl,\n);\n", "// \u250F\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2513\n// \u2503 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588 \u2588 \u2588 \u2588 \u2588 \u2588\u2584 \u2580\u2588\u2588\u2588 \u2588 \u2503\n// \u2503 \u2584\u2584\u2584\u2584\u2584\u2588 \u2588\u2584\u2584\u2584\u2584\u2584 \u2584\u2584\u2584\u2584\u2584\u2588 \u2580\u2580\u2580\u2580\u2580\u2588\u2580\u2580\u2580\u2580\u2580 \u2588 \u2580\u2580\u2580\u2580\u2580\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258C\u2590\u2588\u2588\u2588 \u2588\u2588\u2588\u2584 \u2580\u2588 \u2588 \u2580\u2580\u2580\u2580\u2580 \u2503\n// \u2503 \u2588\u2580\u2580\u2580\u2580\u2580 \u2588\u2580\u2580\u2580\u2580\u2580 \u2588\u2580\u2588\u2588\u2580\u2580 \u2584\u2584\u2584\u2584\u2584 \u2588 \u2584\u2584\u2584\u2584\u2584\u2588 \u2584\u2584\u2584\u2584\u2584\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258C\u2590\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2584 \u2588 \u2584\u2584\u2584\u2584\u2584 \u2503\n// \u2503 \u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588 \u2580\u2588\u2584 \u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588 \u2588\u2588\u2588\u258C\u2590\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2584 \u2588 \u2503\n// \u2523\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u252B\n// \u2503 Copyright (c) 2017, the Perspective Authors. \u2503\n// \u2503 \u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C \u2503\n// \u2503 This file is part of the Perspective library, distributed under the terms \u2503\n// \u2503 of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). \u2503\n// \u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u251B\n\nimport * as React from \"react\";\n\n/**\n * Subscribe `cb` to a Custom Event on `el` for the lifetime of the component,\n * projecting the event through `map` (by default, `e.detail`).\n */\nexport function usePspListener<A>(\n el: HTMLElement | undefined | null,\n event: string,\n cb?: (x: A) => void,\n map: (e: CustomEvent) => A = (e) => e.detail,\n) {\n React.useEffect(() => {\n if (!cb || !el) return;\n const ctx = new AbortController();\n const callback = (e: Event) => cb(map(e as CustomEvent));\n el?.addEventListener(event, callback, { signal: ctx.signal });\n return () => ctx.abort();\n }, [el, cb]);\n}\n"],
|
|
5
|
-
"mappings": "AAYA,UAAYA,MAAW,QCAvB,UAAYC,MAAW,QAMhB,SAASC,EACZC,EACAC,EACAC,EACAC,EAA8BC,GAAMA,EAAE,OACxC,CACQ,YAAU,IAAM,CAClB,GAAI,CAACF,GAAM,CAACF,EAAI,OAChB,IAAMK,EAAM,IAAI,gBACVC,EAAYF,GAAaF,EAAGC,EAAIC,CAAgB,CAAC,EACvD,OAAAJ,GAAI,iBAAiBC,EAAOK,EAAU,CAAE,OAAQD,EAAI,MAAO,CAAC,EACrD,IAAMA,EAAI,MAAM,CAC3B,EAAG,CAACL,EAAIE,CAAE,CAAC,CACf,CDdA,SAASK,EAAsBC,EAA+B,CAC1D,GAAM,CAACC,EAAQC,CAAS,EACd,WAAwD,IAAI,EAEtE,OAAM,YAAU,IACL,IAAM,CACTD,GAAQ,OAAO,CACnB,EACD,CAACA,CAAM,CAAC,EAEL,YAAU,IAAM,CAClB,GAAI,CAACA,EACD,OAGJ,IAAIE,EAAY,GAChB,OAAC,SAAY,CACT,GAAI,CAACH,EAAM,OAAQ,CACf,MAAMC,EAAO,MAAM,EACnB,MACJ,CAEA,MAAMA,EAAO,KAAKD,EAAM,MAAM,EAC1B,EAAAG,GAAa,CAACH,EAAM,UAIpB,WAAYA,EAAM,OAClB,MAAMC,EAAO,iBAAiBD,EAAM,
|
|
4
|
+
"sourcesContent": ["// \u250F\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2513\n// \u2503 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588 \u2588 \u2588 \u2588 \u2588 \u2588\u2584 \u2580\u2588\u2588\u2588 \u2588 \u2503\n// \u2503 \u2584\u2584\u2584\u2584\u2584\u2588 \u2588\u2584\u2584\u2584\u2584\u2584 \u2584\u2584\u2584\u2584\u2584\u2588 \u2580\u2580\u2580\u2580\u2580\u2588\u2580\u2580\u2580\u2580\u2580 \u2588 \u2580\u2580\u2580\u2580\u2580\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258C\u2590\u2588\u2588\u2588 \u2588\u2588\u2588\u2584 \u2580\u2588 \u2588 \u2580\u2580\u2580\u2580\u2580 \u2503\n// \u2503 \u2588\u2580\u2580\u2580\u2580\u2580 \u2588\u2580\u2580\u2580\u2580\u2580 \u2588\u2580\u2588\u2588\u2580\u2580 \u2584\u2584\u2584\u2584\u2584 \u2588 \u2584\u2584\u2584\u2584\u2584\u2588 \u2584\u2584\u2584\u2584\u2584\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258C\u2590\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2584 \u2588 \u2584\u2584\u2584\u2584\u2584 \u2503\n// \u2503 \u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588 \u2580\u2588\u2584 \u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588 \u2588\u2588\u2588\u258C\u2590\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2584 \u2588 \u2503\n// \u2523\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u252B\n// \u2503 Copyright (c) 2017, the Perspective Authors. \u2503\n// \u2503 \u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C \u2503\n// \u2503 This file is part of the Perspective library, distributed under the terms \u2503\n// \u2503 of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). \u2503\n// \u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u251B\n\nimport * as React from \"react\";\nimport type * as psp from \"@perspective-dev/client\";\nimport type * as pspViewer from \"@perspective-dev/viewer\";\nimport { usePspListener } from \"./utils\";\n\nfunction PerspectiveViewerImpl(props: PerspectiveViewerProps) {\n const [viewer, setViewer] =\n React.useState<pspViewer.HTMLPerspectiveViewerElement | null>(null);\n\n React.useEffect(() => {\n return () => {\n viewer?.delete();\n };\n }, [viewer]);\n\n React.useEffect(() => {\n if (!viewer) {\n return;\n }\n\n let cancelled = false;\n (async () => {\n if (!props.client) {\n await viewer.eject();\n return;\n }\n\n await viewer.load(props.client);\n if (cancelled || !props.config) {\n return;\n }\n\n if (\"panels\" in props.config) {\n await viewer.restoreWorkspace(props.config, {\n wait_for_table: true,\n });\n } else {\n await viewer.restore(\n props.config as pspViewer.ViewerConfigUpdate,\n {\n wait_for_table: true,\n },\n );\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [viewer, props.client, JSON.stringify(props.config)]);\n\n usePspListener(viewer, \"perspective-click\", props.onClick);\n usePspListener(viewer, \"perspective-select\", props.onSelect);\n usePspListener(\n viewer,\n \"perspective-config-update\",\n props.onConfigUpdate,\n (e) => e.detail.getConfig(),\n );\n\n return (\n <perspective-viewer\n ref={setViewer}\n id={props.id}\n className={props.className}\n hidden={props.hidden}\n slot={props.slot}\n style={props.style}\n tabIndex={props.tabIndex}\n title={props.title}\n />\n );\n}\n\n/**\n * Props for the {@link PerspectiveViewer} component.\n */\nexport interface PerspectiveViewerProps {\n /**\n * The viewer's data source, forwarded to the element's `load()` method\n * whenever it changes.\n *\n * - A `Table` (or `Promise<Table>`) displays that table directly.\n * - A `Client` (e.g. from `perspective.worker()` or a WebSocket\n * connection to a remote server) connects the viewer to every table\n * hosted by that client; the table each panel displays is chosen by\n * {@link PerspectiveViewerProps.config} or interactively by the user.\n * - `undefined` calls `eject()`, returning the viewer to an unloaded\n * state without unmounting it.\n *\n * The component does not take ownership of the `Table` \u2014 delete it\n * yourself when it is no longer needed, e.g.\n * `table.delete({ lazy: true })`.\n */\n client?: psp.Client | Promise<psp.Client> | psp.Table | Promise<psp.Table>;\n\n /**\n * Declarative viewer state \u2014 group-bys, splits, filters, sorts,\n * expressions, plugin and plugin config \u2014 applied with the element's\n * `restore()` method whenever it (or\n * {@link PerspectiveViewerProps.client}) changes. A config with a\n * `panels` property is treated as a multi-panel workspace layout and\n * applied with `restoreWorkspace()` instead.\n *\n * Configs are compared structurally, so passing a fresh-but-equal object\n * literal on each render does not re-apply. Combine with\n * {@link PerspectiveViewerProps.onConfigUpdate} to use the viewer as a\n * controlled component.\n *\n * When {@link PerspectiveViewerProps.client} is a bare `Client` (which\n * creates no panel by itself), the config must include `table` \u2014 a\n * panel-creating `restore()` without one rejects. `Table` clients bind\n * their own panel, so `table` may be omitted there.\n */\n config?: pspViewer.ViewerConfigUpdate | pspViewer.WorkspaceConfigUpdate;\n\n /**\n * Called with the viewer's complete configuration whenever the user\n * reconfigures it through its UI (the element's\n * `\"perspective-config-update\"` Custom Event). Use this to persist the\n * user's view or reflect it back through\n * {@link PerspectiveViewerProps.config}.\n */\n onConfigUpdate?: (config: pspViewer.ViewerConfigUpdate) => void;\n\n /**\n * Called when the user clicks a datapoint (the element's\n * `\"perspective-click\"` Custom Event), with the clicked row's data and a\n * filter config which would select it.\n */\n onClick?: (data: pspViewer.PerspectiveClickEventDetail) => void;\n\n /**\n * Called when the user selects or deselects a datapoint or row (the\n * element's `\"perspective-select\"` Custom Event).\n */\n onSelect?: (data: pspViewer.PerspectiveSelectEventDetail) => void;\n\n // Applicable props from `React.HTMLAttributes`, which we cannot extend\n // directly because Perspective changes the signature of `onClick`.\n\n /** Forwarded to the element's `class` attribute. */\n className?: string | undefined;\n\n /** Forwarded to the element's `hidden` attribute. */\n hidden?: boolean | undefined;\n\n /** Forwarded to the element's `id` attribute. */\n id?: string | undefined;\n\n /** Forwarded to the element's `slot` attribute. */\n slot?: string | undefined;\n\n /** Forwarded to the element's inline `style`. */\n style?: React.CSSProperties | undefined;\n\n /** Forwarded to the element's `tabindex` attribute. */\n tabIndex?: number | undefined;\n\n /** Forwarded to the element's `title` attribute. */\n title?: string | undefined;\n}\n\n/**\n * A declarative React wrapper for the `<perspective-viewer>` Custom Element.\n *\n * `<PerspectiveViewer>` manages the element's imperative lifecycle: it\n * `load()`s the {@link PerspectiveViewerProps.client}, `restore()`s the\n * {@link PerspectiveViewerProps.config} whenever either changes, subscribes\n * the `on*` callback props to the element's Custom Events, and `delete()`s\n * the viewer (freeing its WebAssembly resources) on unmount. Tables and\n * clients are created outside the component and are yours to manage \u2014 a\n * `Table` passed as `client` survives unmount and can be shown again by a\n * later mount.\n *\n * The component is memoized, so re-rendering a parent with unchanged props\n * does not touch the viewer.\n *\n * @example\n * ```tsx\n * const WORKER = await perspective.worker();\n * const TABLE = WORKER.table(\n * fetch(\"superstore.lz4.arrow\").then((resp) => resp.arrayBuffer()),\n * { name: \"superstore\" },\n * );\n *\n * const App: React.FC = () => {\n * const [config, setConfig] = React.useState<pspViewer.ViewerConfigUpdate>({\n * group_by: [\"State\"],\n * plugin: \"Y Bar\",\n * });\n *\n * return (\n * <PerspectiveViewer\n * client={TABLE}\n * config={config}\n * onConfigUpdate={setConfig}\n * />\n * );\n * };\n * ```\n */\nexport const PerspectiveViewer: React.FC<PerspectiveViewerProps> = React.memo(\n PerspectiveViewerImpl,\n);\n", "// \u250F\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2513\n// \u2503 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588 \u2588 \u2588 \u2588 \u2588 \u2588\u2584 \u2580\u2588\u2588\u2588 \u2588 \u2503\n// \u2503 \u2584\u2584\u2584\u2584\u2584\u2588 \u2588\u2584\u2584\u2584\u2584\u2584 \u2584\u2584\u2584\u2584\u2584\u2588 \u2580\u2580\u2580\u2580\u2580\u2588\u2580\u2580\u2580\u2580\u2580 \u2588 \u2580\u2580\u2580\u2580\u2580\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258C\u2590\u2588\u2588\u2588 \u2588\u2588\u2588\u2584 \u2580\u2588 \u2588 \u2580\u2580\u2580\u2580\u2580 \u2503\n// \u2503 \u2588\u2580\u2580\u2580\u2580\u2580 \u2588\u2580\u2580\u2580\u2580\u2580 \u2588\u2580\u2588\u2588\u2580\u2580 \u2584\u2584\u2584\u2584\u2584 \u2588 \u2584\u2584\u2584\u2584\u2584\u2588 \u2584\u2584\u2584\u2584\u2584\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u258C\u2590\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2584 \u2588 \u2584\u2584\u2584\u2584\u2584 \u2503\n// \u2503 \u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588 \u2580\u2588\u2584 \u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588 \u2588\u2588\u2588\u258C\u2590\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2584 \u2588 \u2503\n// \u2523\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u252B\n// \u2503 Copyright (c) 2017, the Perspective Authors. \u2503\n// \u2503 \u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C\u254C \u2503\n// \u2503 This file is part of the Perspective library, distributed under the terms \u2503\n// \u2503 of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). \u2503\n// \u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u251B\n\nimport * as React from \"react\";\n\n/**\n * Subscribe `cb` to a Custom Event on `el` for the lifetime of the component,\n * projecting the event through `map` (by default, `e.detail`).\n */\nexport function usePspListener<A>(\n el: HTMLElement | undefined | null,\n event: string,\n cb?: (x: A) => void,\n map: (e: CustomEvent) => A = (e) => e.detail,\n) {\n React.useEffect(() => {\n if (!cb || !el) return;\n const ctx = new AbortController();\n const callback = (e: Event) => cb(map(e as CustomEvent));\n el?.addEventListener(event, callback, { signal: ctx.signal });\n return () => ctx.abort();\n }, [el, cb]);\n}\n"],
|
|
5
|
+
"mappings": "AAYA,UAAYA,MAAW,QCAvB,UAAYC,MAAW,QAMhB,SAASC,EACZC,EACAC,EACAC,EACAC,EAA8BC,GAAMA,EAAE,OACxC,CACQ,YAAU,IAAM,CAClB,GAAI,CAACF,GAAM,CAACF,EAAI,OAChB,IAAMK,EAAM,IAAI,gBACVC,EAAYF,GAAaF,EAAGC,EAAIC,CAAgB,CAAC,EACvD,OAAAJ,GAAI,iBAAiBC,EAAOK,EAAU,CAAE,OAAQD,EAAI,MAAO,CAAC,EACrD,IAAMA,EAAI,MAAM,CAC3B,EAAG,CAACL,EAAIE,CAAE,CAAC,CACf,CDdA,SAASK,EAAsBC,EAA+B,CAC1D,GAAM,CAACC,EAAQC,CAAS,EACd,WAAwD,IAAI,EAEtE,OAAM,YAAU,IACL,IAAM,CACTD,GAAQ,OAAO,CACnB,EACD,CAACA,CAAM,CAAC,EAEL,YAAU,IAAM,CAClB,GAAI,CAACA,EACD,OAGJ,IAAIE,EAAY,GAChB,OAAC,SAAY,CACT,GAAI,CAACH,EAAM,OAAQ,CACf,MAAMC,EAAO,MAAM,EACnB,MACJ,CAEA,MAAMA,EAAO,KAAKD,EAAM,MAAM,EAC1B,EAAAG,GAAa,CAACH,EAAM,UAIpB,WAAYA,EAAM,OAClB,MAAMC,EAAO,iBAAiBD,EAAM,OAAQ,CACxC,eAAgB,EACpB,CAAC,EAED,MAAMC,EAAO,QACTD,EAAM,OACN,CACI,eAAgB,EACpB,CACJ,EAER,GAAG,EAEI,IAAM,CACTG,EAAY,EAChB,CACJ,EAAG,CAACF,EAAQD,EAAM,OAAQ,KAAK,UAAUA,EAAM,MAAM,CAAC,CAAC,EAEvDI,EAAeH,EAAQ,oBAAqBD,EAAM,OAAO,EACzDI,EAAeH,EAAQ,qBAAsBD,EAAM,QAAQ,EAC3DI,EACIH,EACA,4BACAD,EAAM,eACLK,GAAMA,EAAE,OAAO,UAAU,CAC9B,EAGI,gBAAC,sBACG,IAAKH,EACL,GAAIF,EAAM,GACV,UAAWA,EAAM,UACjB,OAAQA,EAAM,OACd,KAAMA,EAAM,KACZ,MAAOA,EAAM,MACb,SAAUA,EAAM,SAChB,MAAOA,EAAM,MACjB,CAER,CAkIO,IAAMM,EAA4D,OACrEP,CACJ",
|
|
6
6
|
"names": ["React", "React", "usePspListener", "el", "event", "cb", "map", "e", "ctx", "callback", "PerspectiveViewerImpl", "props", "viewer", "setViewer", "cancelled", "usePspListener", "e", "PerspectiveViewer"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@perspective-dev/react",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.5.0",
|
|
4
4
|
"description": "React component wrappers for `<perspective-viewer>`",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"perspective",
|
|
@@ -32,15 +32,15 @@
|
|
|
32
32
|
"@types/react": ">17 <20",
|
|
33
33
|
"react": ">17 <20",
|
|
34
34
|
"react-dom": ">17 <20",
|
|
35
|
-
"@perspective-dev/viewer": "^5.
|
|
36
|
-
"@perspective-dev/client": "^5.
|
|
35
|
+
"@perspective-dev/viewer": "^5.5.0",
|
|
36
|
+
"@perspective-dev/client": "^5.5.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"superstore-arrow": "3.2.0",
|
|
40
40
|
"typescript": ">=5 <6",
|
|
41
41
|
"typedoc": "^0.28.7",
|
|
42
42
|
"zx": ">=8 <9",
|
|
43
|
-
"@perspective-dev/esbuild-plugin": "^5.
|
|
43
|
+
"@perspective-dev/esbuild-plugin": "^5.5.0"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "node ./build.mjs",
|
package/src/viewer.tsx
CHANGED
|
@@ -43,9 +43,16 @@ function PerspectiveViewerImpl(props: PerspectiveViewerProps) {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
if ("panels" in props.config) {
|
|
46
|
-
await viewer.restoreWorkspace(props.config
|
|
46
|
+
await viewer.restoreWorkspace(props.config, {
|
|
47
|
+
wait_for_table: true,
|
|
48
|
+
});
|
|
47
49
|
} else {
|
|
48
|
-
await viewer.restore(
|
|
50
|
+
await viewer.restore(
|
|
51
|
+
props.config as pspViewer.ViewerConfigUpdate,
|
|
52
|
+
{
|
|
53
|
+
wait_for_table: true,
|
|
54
|
+
},
|
|
55
|
+
);
|
|
49
56
|
}
|
|
50
57
|
})();
|
|
51
58
|
|