@sqlrooms/cells 0.29.0-rc.3 → 0.29.0-rc.5
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/components/SqlCellContent.d.ts.map +1 -1
- package/dist/components/SqlCellContent.js +3 -7
- package/dist/components/SqlCellContent.js.map +1 -1
- package/dist/components/SqlCellResults.d.ts.map +1 -1
- package/dist/components/SqlCellResults.js +0 -1
- package/dist/components/SqlCellResults.js.map +1 -1
- package/dist/components/VegaCellContent.d.ts.map +1 -1
- package/dist/components/VegaCellContent.js +4 -39
- package/dist/components/VegaCellContent.js.map +1 -1
- package/dist/components/VegaCellHeader.d.ts +0 -3
- package/dist/components/VegaCellHeader.d.ts.map +1 -1
- package/dist/components/VegaCellHeader.js +4 -6
- package/dist/components/VegaCellHeader.js.map +1 -1
- package/dist/components/VegaConfigPanel.d.ts +0 -5
- package/dist/components/VegaConfigPanel.d.ts.map +1 -1
- package/dist/components/VegaConfigPanel.js +6 -37
- package/dist/components/VegaConfigPanel.js.map +1 -1
- package/dist/hooks/useVegaCellQuery.d.ts +0 -4
- package/dist/hooks/useVegaCellQuery.d.ts.map +1 -1
- package/dist/hooks/useVegaCellQuery.js +2 -15
- package/dist/hooks/useVegaCellQuery.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/package.json +19 -19
- package/dist/components/SelectionListener.d.ts +0 -15
- package/dist/components/SelectionListener.d.ts.map +0 -1
- package/dist/components/SelectionListener.js +0 -74
- package/dist/components/SelectionListener.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqlCellContent.d.ts","sourceRoot":"","sources":["../../src/components/SqlCellContent.tsx"],"names":[],"mappings":"AAIA,OAAO,
|
|
1
|
+
{"version":3,"file":"SqlCellContent.d.ts","sourceRoot":"","sources":["../../src/components/SqlCellContent.tsx"],"names":[],"mappings":"AAIA,OAAO,KAA6B,MAAM,OAAO,CAAC;AAElD,OAAO,KAAK,EACV,kBAAkB,EAElB,OAAO,EAER,MAAM,UAAU,CAAC;AAQlB,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,OAAO,CAAC;IACd,eAAe,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,KAAK,CAAC,YAAY,CAAC;CACpE,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAyKxD,CAAC"}
|
|
@@ -3,7 +3,7 @@ import { getCoreDuckDbConnectionId } from '@sqlrooms/db';
|
|
|
3
3
|
import { useRoomStoreApi } from '@sqlrooms/room-store';
|
|
4
4
|
import { produce } from 'immer';
|
|
5
5
|
import { CornerDownRightIcon } from 'lucide-react';
|
|
6
|
-
import { useCallback,
|
|
6
|
+
import { useCallback, useMemo } from 'react';
|
|
7
7
|
import { useCellsStore } from '../hooks';
|
|
8
8
|
import { SqlCellConnectionSelector } from './SqlCellConnectionSelector';
|
|
9
9
|
import { SqlCellDependentsMenu } from './SqlCellDependentsMenu';
|
|
@@ -51,8 +51,8 @@ export const SqlCellContent = ({ id, cell, renderContainer, }) => {
|
|
|
51
51
|
c.data.sql = query;
|
|
52
52
|
}
|
|
53
53
|
}));
|
|
54
|
-
|
|
55
|
-
}, [id, storeApi]);
|
|
54
|
+
runCell(id);
|
|
55
|
+
}, [id, runCell, storeApi]);
|
|
56
56
|
const handleConnectorChange = useCallback((connectorId) => {
|
|
57
57
|
updateCell(id, (c) => produce(c, (draft) => {
|
|
58
58
|
if (draft.type === 'sql') {
|
|
@@ -82,10 +82,6 @@ export const SqlCellContent = ({ id, cell, renderContainer, }) => {
|
|
|
82
82
|
}
|
|
83
83
|
: undefined;
|
|
84
84
|
const isRunning = status?.state === 'running';
|
|
85
|
-
const handleRunRef = useRef(handleRun);
|
|
86
|
-
useEffect(() => {
|
|
87
|
-
handleRunRef.current = handleRun;
|
|
88
|
-
}, [handleRun]);
|
|
89
85
|
const content = (_jsxs("div", { className: "flex flex-col", children: [_jsx(SqlCellEditor, { sql: cell.data.sql, connector: connector, tableSchemas: tableSchemas, onChange: handleSqlChange, onRunQuery: handleRunQuery }), _jsx(SqlCellResults, { cellId: id, cellResult: cellResult, resultName: resultName, isRunning: isRunning, errorMessage: status?.state === 'error' ? status.message : undefined, resultVersion: resultVersion, fetchCellResultPage: fetchCellResultPage })] }));
|
|
90
86
|
const footer = (_jsxs("div", { className: "text-muted-foreground flex items-center gap-1 px-2 py-1 text-xs", children: [_jsx(CornerDownRightIcon, { className: "h-3 w-3" }), _jsx(SqlCellDependentsMenu, { cellId: id, artifactId: artifactId, cellsData: cellsData, artifacts: artifacts, getDownstream: getDownstream }), _jsx(SqlCellResultNameEditor, { cellId: id, value: resultName, onChange: handleResultNameChange })] }));
|
|
91
87
|
return renderContainer({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqlCellContent.js","sourceRoot":"","sources":["../../src/components/SqlCellContent.tsx"],"names":[],"mappings":"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","sourcesContent":["import {getCoreDuckDbConnectionId} from '@sqlrooms/db';\nimport {useRoomStoreApi} from '@sqlrooms/room-store';\nimport {type Draft, produce} from 'immer';\nimport {CornerDownRightIcon} from 'lucide-react';\nimport React, {useCallback, useEffect, useMemo, useRef} from 'react';\nimport {useCellsStore} from '../hooks';\nimport type {\n CellContainerProps,\n CellsRootState,\n SqlCell,\n SqlCellStatus,\n} from '../types';\nimport {SqlCellConnectionSelector} from './SqlCellConnectionSelector';\nimport {SqlCellDependentsMenu} from './SqlCellDependentsMenu';\nimport {SqlCellEditor} from './SqlCellEditor';\nimport {SqlCellResultNameEditor} from './SqlCellResultNameEditor';\nimport {SqlCellResults} from './SqlCellResults';\nimport {SqlCellRunButton} from './SqlCellRunButton';\n\nexport type SqlCellContentProps = {\n id: string;\n cell: SqlCell;\n renderContainer: (props: CellContainerProps) => React.ReactElement;\n};\n\nexport const SqlCellContent: React.FC<SqlCellContentProps> = ({\n id,\n cell,\n renderContainer,\n}) => {\n const storeApi = useRoomStoreApi<CellsRootState>();\n const updateCell = useCellsStore((s) => s.cells.updateCell);\n const runCell = useCellsStore((s) => s.cells.runCell);\n const cancelCell = useCellsStore((s) => s.cells.cancelCell);\n const getDownstream = useCellsStore((s) => s.cells.getDownstream);\n const artifactId = useCellsStore((s) => s.cells.getArtifactIdForCell(id));\n const cellsData = useCellsStore((s) => s.cells.config.data);\n const artifacts = useCellsStore((s) => s.cells.config.artifacts);\n const cellStatus = useCellsStore((s) => s.cells.status[id]);\n const resultVersion = useCellsStore((s) => s.cells.resultVersion?.[id] ?? 0);\n const pageVersion = useCellsStore((s) => s.cells.pageVersion?.[id] ?? 0);\n const getCellResult = useCellsStore((s) => s.cells.getCellResult);\n const fetchCellResultPage = useCellsStore((s) => s.cells.fetchCellResultPage);\n const dbConnections = useCellsStore((s) => s.db.config.connections);\n const connector = useCellsStore((s) => s.db.connector);\n const tableSchemas = useCellsStore((s) => s.db.tables);\n\n // Re-read the cache whenever resultVersion or pageVersion changes\n const cellResult = useMemo(\n () => getCellResult(id),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [getCellResult, id, resultVersion, pageVersion],\n );\n\n const handleSqlChange = useCallback(\n (v: string | undefined) => {\n updateCell(id, (c) =>\n produce(c, (draft) => {\n if (draft.type === 'sql') {\n draft.data.sql = v || '';\n }\n }),\n );\n },\n [id, updateCell],\n );\n\n const handleRun = useCallback(() => {\n runCell(id);\n }, [id, runCell]);\n\n const handleRunQuery = useCallback(\n (query: string) => {\n // Sync the actual query being executed to store before running\n // to avoid race condition with onChange callback\n storeApi.setState(\n produce(storeApi.getState(), (draft: Draft<CellsRootState>) => {\n const c = draft.cells?.config?.data?.[id];\n if (c && c.type === 'sql') {\n c.data.sql = query;\n }\n }),\n );\n handleRunRef.current();\n },\n [id, storeApi],\n );\n\n const handleConnectorChange = useCallback(\n (connectorId: string) => {\n updateCell(id, (c) =>\n produce(c, (draft) => {\n if (draft.type === 'sql') {\n draft.data.connectorId = connectorId || undefined;\n }\n }),\n );\n },\n [id, updateCell],\n );\n\n const handleCancel = useCallback(() => {\n cancelCell(id);\n }, [id, cancelCell]);\n\n const handleResultNameChange = useCallback(\n (value: string) => {\n updateCell(id, (c) =>\n produce(c, (draft) => {\n if (draft.type === 'sql') {\n draft.data.resultName = value;\n }\n }),\n );\n },\n [id, updateCell],\n );\n\n const resultName = cell.data.resultName || '';\n const selectedConnectorId =\n cell.data.connectorId || getCoreDuckDbConnectionId();\n\n const status =\n cellStatus?.type === 'sql'\n ? {\n state: (cellStatus as SqlCellStatus).status,\n message: (cellStatus as SqlCellStatus).lastError,\n resultName:\n (cellStatus as SqlCellStatus).resultView ||\n (cellStatus as SqlCellStatus).resultName,\n lastRunTime: (cellStatus as SqlCellStatus).lastRunTime,\n }\n : undefined;\n\n const isRunning = status?.state === 'running';\n\n const handleRunRef = useRef(handleRun);\n useEffect(() => {\n handleRunRef.current = handleRun;\n }, [handleRun]);\n\n const content = (\n <div className=\"flex flex-col\">\n <SqlCellEditor\n sql={cell.data.sql}\n connector={connector}\n tableSchemas={tableSchemas}\n onChange={handleSqlChange}\n onRunQuery={handleRunQuery}\n />\n <SqlCellResults\n cellId={id}\n cellResult={cellResult}\n resultName={resultName}\n isRunning={isRunning}\n errorMessage={status?.state === 'error' ? status.message : undefined}\n resultVersion={resultVersion}\n fetchCellResultPage={fetchCellResultPage}\n />\n </div>\n );\n\n const footer = (\n <div className=\"text-muted-foreground flex items-center gap-1 px-2 py-1 text-xs\">\n <CornerDownRightIcon className=\"h-3 w-3\" />\n <SqlCellDependentsMenu\n cellId={id}\n artifactId={artifactId}\n cellsData={cellsData}\n artifacts={artifacts}\n getDownstream={getDownstream}\n />\n <SqlCellResultNameEditor\n cellId={id}\n value={resultName}\n onChange={handleResultNameChange}\n />\n </div>\n );\n\n return renderContainer({\n header: (\n <div className=\"flex w-full items-center gap-2\">\n <SqlCellConnectionSelector\n connectors={dbConnections}\n selectedConnectorId={selectedConnectorId}\n onChange={handleConnectorChange}\n />\n <SqlCellRunButton\n onRun={handleRun}\n onCancel={handleCancel}\n status={status}\n runLabel=\"Run\"\n />\n </div>\n ),\n content,\n footer,\n });\n};\n"]}
|
|
1
|
+
{"version":3,"file":"SqlCellContent.js","sourceRoot":"","sources":["../../src/components/SqlCellContent.tsx"],"names":[],"mappings":"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","sourcesContent":["import {getCoreDuckDbConnectionId} from '@sqlrooms/db';\nimport {useRoomStoreApi} from '@sqlrooms/room-store';\nimport {type Draft, produce} from 'immer';\nimport {CornerDownRightIcon} from 'lucide-react';\nimport React, {useCallback, useMemo} from 'react';\nimport {useCellsStore} from '../hooks';\nimport type {\n CellContainerProps,\n CellsRootState,\n SqlCell,\n SqlCellStatus,\n} from '../types';\nimport {SqlCellConnectionSelector} from './SqlCellConnectionSelector';\nimport {SqlCellDependentsMenu} from './SqlCellDependentsMenu';\nimport {SqlCellEditor} from './SqlCellEditor';\nimport {SqlCellResultNameEditor} from './SqlCellResultNameEditor';\nimport {SqlCellResults} from './SqlCellResults';\nimport {SqlCellRunButton} from './SqlCellRunButton';\n\nexport type SqlCellContentProps = {\n id: string;\n cell: SqlCell;\n renderContainer: (props: CellContainerProps) => React.ReactElement;\n};\n\nexport const SqlCellContent: React.FC<SqlCellContentProps> = ({\n id,\n cell,\n renderContainer,\n}) => {\n const storeApi = useRoomStoreApi<CellsRootState>();\n const updateCell = useCellsStore((s) => s.cells.updateCell);\n const runCell = useCellsStore((s) => s.cells.runCell);\n const cancelCell = useCellsStore((s) => s.cells.cancelCell);\n const getDownstream = useCellsStore((s) => s.cells.getDownstream);\n const artifactId = useCellsStore((s) => s.cells.getArtifactIdForCell(id));\n const cellsData = useCellsStore((s) => s.cells.config.data);\n const artifacts = useCellsStore((s) => s.cells.config.artifacts);\n const cellStatus = useCellsStore((s) => s.cells.status[id]);\n const resultVersion = useCellsStore((s) => s.cells.resultVersion?.[id] ?? 0);\n const pageVersion = useCellsStore((s) => s.cells.pageVersion?.[id] ?? 0);\n const getCellResult = useCellsStore((s) => s.cells.getCellResult);\n const fetchCellResultPage = useCellsStore((s) => s.cells.fetchCellResultPage);\n const dbConnections = useCellsStore((s) => s.db.config.connections);\n const connector = useCellsStore((s) => s.db.connector);\n const tableSchemas = useCellsStore((s) => s.db.tables);\n\n // Re-read the cache whenever resultVersion or pageVersion changes\n const cellResult = useMemo(\n () => getCellResult(id),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [getCellResult, id, resultVersion, pageVersion],\n );\n\n const handleSqlChange = useCallback(\n (v: string | undefined) => {\n updateCell(id, (c) =>\n produce(c, (draft) => {\n if (draft.type === 'sql') {\n draft.data.sql = v || '';\n }\n }),\n );\n },\n [id, updateCell],\n );\n\n const handleRun = useCallback(() => {\n runCell(id);\n }, [id, runCell]);\n\n const handleRunQuery = useCallback(\n (query: string) => {\n // Sync the actual query being executed to store before running\n // to avoid race condition with onChange callback\n storeApi.setState(\n produce(storeApi.getState(), (draft: Draft<CellsRootState>) => {\n const c = draft.cells?.config?.data?.[id];\n if (c && c.type === 'sql') {\n c.data.sql = query;\n }\n }),\n );\n runCell(id);\n },\n [id, runCell, storeApi],\n );\n\n const handleConnectorChange = useCallback(\n (connectorId: string) => {\n updateCell(id, (c) =>\n produce(c, (draft) => {\n if (draft.type === 'sql') {\n draft.data.connectorId = connectorId || undefined;\n }\n }),\n );\n },\n [id, updateCell],\n );\n\n const handleCancel = useCallback(() => {\n cancelCell(id);\n }, [id, cancelCell]);\n\n const handleResultNameChange = useCallback(\n (value: string) => {\n updateCell(id, (c) =>\n produce(c, (draft) => {\n if (draft.type === 'sql') {\n draft.data.resultName = value;\n }\n }),\n );\n },\n [id, updateCell],\n );\n\n const resultName = cell.data.resultName || '';\n const selectedConnectorId =\n cell.data.connectorId || getCoreDuckDbConnectionId();\n\n const status =\n cellStatus?.type === 'sql'\n ? {\n state: (cellStatus as SqlCellStatus).status,\n message: (cellStatus as SqlCellStatus).lastError,\n resultName:\n (cellStatus as SqlCellStatus).resultView ||\n (cellStatus as SqlCellStatus).resultName,\n lastRunTime: (cellStatus as SqlCellStatus).lastRunTime,\n }\n : undefined;\n\n const isRunning = status?.state === 'running';\n\n const content = (\n <div className=\"flex flex-col\">\n <SqlCellEditor\n sql={cell.data.sql}\n connector={connector}\n tableSchemas={tableSchemas}\n onChange={handleSqlChange}\n onRunQuery={handleRunQuery}\n />\n <SqlCellResults\n cellId={id}\n cellResult={cellResult}\n resultName={resultName}\n isRunning={isRunning}\n errorMessage={status?.state === 'error' ? status.message : undefined}\n resultVersion={resultVersion}\n fetchCellResultPage={fetchCellResultPage}\n />\n </div>\n );\n\n const footer = (\n <div className=\"text-muted-foreground flex items-center gap-1 px-2 py-1 text-xs\">\n <CornerDownRightIcon className=\"h-3 w-3\" />\n <SqlCellDependentsMenu\n cellId={id}\n artifactId={artifactId}\n cellsData={cellsData}\n artifacts={artifacts}\n getDownstream={getDownstream}\n />\n <SqlCellResultNameEditor\n cellId={id}\n value={resultName}\n onChange={handleResultNameChange}\n />\n </div>\n );\n\n return renderContainer({\n header: (\n <div className=\"flex w-full items-center gap-2\">\n <SqlCellConnectionSelector\n connectors={dbConnections}\n selectedConnectorId={selectedConnectorId}\n onChange={handleConnectorChange}\n />\n <SqlCellRunButton\n onRun={handleRun}\n onCancel={handleCancel}\n status={status}\n runLabel=\"Run\"\n />\n </div>\n ),\n content,\n footer,\n });\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqlCellResults.d.ts","sourceRoot":"","sources":["../../src/components/SqlCellResults.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,eAAe,EAAE,YAAY,EAAC,MAAM,uBAAuB,CAAC;AACzE,OAAO,KAAoC,MAAM,OAAO,CAAC;AAGzD,OAAO,EAAC,cAAc,EAAC,MAAM,UAAU,CAAC;AAExC,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,CACnB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,eAAe,EAC3B,OAAO,EAAE,YAAY,KAClB,IAAI,CAAC;CACX;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,
|
|
1
|
+
{"version":3,"file":"SqlCellResults.d.ts","sourceRoot":"","sources":["../../src/components/SqlCellResults.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,eAAe,EAAE,YAAY,EAAC,MAAM,uBAAuB,CAAC;AACzE,OAAO,KAAoC,MAAM,OAAO,CAAC;AAGzD,OAAO,EAAC,cAAc,EAAC,MAAM,UAAU,CAAC;AAExC,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,CACnB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,eAAe,EAC3B,OAAO,EAAE,YAAY,KAClB,IAAI,CAAC;CACX;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAyGxD,CAAC"}
|
|
@@ -32,7 +32,6 @@ export const SqlCellResults = ({ cellId, cellResult, resultName, isRunning, erro
|
|
|
32
32
|
useEffect(() => {
|
|
33
33
|
if (resultVersion !== prevResultVersion.current) {
|
|
34
34
|
prevResultVersion.current = resultVersion;
|
|
35
|
-
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
36
35
|
setPagination((prev) => prev.pageIndex === 0 ? prev : { ...prev, pageIndex: 0 });
|
|
37
36
|
setSorting((prev) => (prev.length === 0 ? prev : []));
|
|
38
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqlCellResults.js","sourceRoot":"","sources":["../../src/components/SqlCellResults.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAE9B,OAAc,EAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAC;AACzD,OAAO,EAAC,EAAE,EAAC,MAAM,cAAc,CAAC;AAChC,OAAO,EAAC,wBAAwB,EAAC,MAAM,4BAA4B,CAAC;AAiBpE;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAkC,CAAC,EAC5D,MAAM,EACN,UAAU,EACV,UAAU,EACV,SAAS,EACT,YAAY,EACZ,aAAa,EACb,mBAAmB,GACpB,EAAE,EAAE;IACH,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,cAAc,GAAG,iBAAiB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAEjE,oDAAoD;IACpD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAe,EAAE,CAAC,CAAC;IACzD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAkB;QAC5D,SAAS,EAAE,CAAC;QACZ,QAAQ,EAAE,EAAE;KACb,CAAC,CAAC;IAEH,2EAA2E;IAC3E,uDAAuD;IACvD,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAEnC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;YAC1B,aAAa,CAAC,OAAO,GAAG,KAAK,CAAC;YAC9B,OAAO;QACT,CAAC;QACD,IAAI,UAAU,EAAE,CAAC;YACf,mBAAmB,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QACnD,CAAC;IACH,CAAC,EAAE,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,UAAU,CAAC,CAAC,CAAC;IAEnE,uDAAuD;IACvD,MAAM,iBAAiB,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;IAChD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,aAAa,KAAK,iBAAiB,CAAC,OAAO,EAAE,CAAC;YAChD,iBAAiB,CAAC,OAAO,GAAG,aAAa,CAAC;YAC1C,
|
|
1
|
+
{"version":3,"file":"SqlCellResults.js","sourceRoot":"","sources":["../../src/components/SqlCellResults.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n DataTablePaginated,\n QueryDataTableActionsMenu,\n useArrowDataTable,\n} from '@sqlrooms/data-table';\nimport type {PaginationState, SortingState} from '@tanstack/react-table';\nimport React, {useEffect, useRef, useState} from 'react';\nimport {cn} from '@sqlrooms/ui';\nimport {CollapsibleSectionButton} from './CollapsibleSectionButton';\nimport {CellResultData} from '../types';\n\nexport interface SqlCellResultsProps {\n cellId: string;\n cellResult?: CellResultData | undefined;\n resultName?: string;\n isRunning?: boolean;\n errorMessage?: string;\n resultVersion: number;\n fetchCellResultPage: (\n cellId: string,\n pagination: PaginationState,\n sorting: SortingState,\n ) => void;\n}\n\n/**\n * SQL query results display with collapse/expand functionality\n */\nexport const SqlCellResults: React.FC<SqlCellResultsProps> = ({\n cellId,\n cellResult,\n resultName,\n isRunning,\n errorMessage,\n resultVersion,\n fetchCellResultPage,\n}) => {\n const [isCollapsed, setIsCollapsed] = useState(false);\n const arrowTableData = useArrowDataTable(cellResult?.arrowTable);\n\n // Pagination and sorting state for the result table\n const [sorting, setSorting] = useState<SortingState>([]);\n const [pagination, setPagination] = useState<PaginationState>({\n pageIndex: 0,\n pageSize: 10,\n });\n\n // Fetch new page when pagination or sorting changes (not on initial render\n // since executeSqlCell already fetches the first page)\n const isFirstRender = useRef(true);\n\n useEffect(() => {\n if (isFirstRender.current) {\n isFirstRender.current = false;\n return;\n }\n if (resultName) {\n fetchCellResultPage(cellId, pagination, sorting);\n }\n }, [pagination, sorting, cellId, fetchCellResultPage, resultName]);\n\n // Reset pagination when a new result arrives (new run)\n const prevResultVersion = useRef(resultVersion);\n useEffect(() => {\n if (resultVersion !== prevResultVersion.current) {\n prevResultVersion.current = resultVersion;\n setPagination((prev) =>\n prev.pageIndex === 0 ? prev : {...prev, pageIndex: 0},\n );\n setSorting((prev) => (prev.length === 0 ? prev : []));\n }\n }, [resultVersion]);\n\n if (!errorMessage && (!resultName || !arrowTableData)) {\n return null;\n }\n\n return (\n <div className=\"group relative w-full\">\n <CollapsibleSectionButton\n isCollapsed={isCollapsed}\n onToggle={() => setIsCollapsed(!isCollapsed)}\n />\n {isCollapsed ? (\n <div className=\"ml-5 px-2 py-1 text-xs\">\n {errorMessage ? (\n <span className=\"font-normal text-red-600\">{errorMessage}</span>\n ) : cellResult?.totalRows !== undefined ? (\n <span className=\"text-muted-foreground font-normal\">\n {cellResult.totalRows.toLocaleString()} rows\n </span>\n ) : null}\n </div>\n ) : (\n <>\n {errorMessage ? (\n <div className=\"relative max-h-[400px] overflow-auto p-4\">\n <span className=\"font-mono text-xs whitespace-pre-wrap text-red-600\">\n {errorMessage}\n </span>\n </div>\n ) : resultName && arrowTableData ? (\n <div className=\"relative min-h-[200px] overflow-hidden\">\n <DataTablePaginated\n className=\"absolute inset-0 h-full w-full\"\n fontSize=\"text-xs\"\n data={arrowTableData.data}\n columns={arrowTableData.columns}\n numRows={cellResult?.totalRows}\n pagination={pagination}\n onPaginationChange={setPagination}\n sorting={sorting}\n onSortingChange={setSorting}\n isFetching={isRunning}\n footerActions={\n <QueryDataTableActionsMenu\n query={`SELECT * FROM ${resultName}`}\n />\n }\n />\n <div\n aria-hidden={!isRunning}\n className={cn(\n 'bg-background/45 pointer-events-none absolute inset-0 z-10 transition-opacity duration-200',\n isRunning ? 'animate-pulse opacity-100' : 'opacity-0',\n )}\n />\n </div>\n ) : null}\n </>\n )}\n </div>\n );\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VegaCellContent.d.ts","sourceRoot":"","sources":["../../src/components/VegaCellContent.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,kBAAkB,EAAE,QAAQ,EAAC,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"VegaCellContent.d.ts","sourceRoot":"","sources":["../../src/components/VegaCellContent.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAC,kBAAkB,EAAE,QAAQ,EAAC,MAAM,UAAU,CAAC;AAY3D,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,QAAQ,CAAC;IACf,eAAe,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,KAAK,CAAC,YAAY,CAAC;CACpE,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAyF1D,CAAC"}
|
|
@@ -2,11 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useDebouncedValue } from '@sqlrooms/ui';
|
|
3
3
|
import { VegaLiteChart } from '@sqlrooms/vega';
|
|
4
4
|
import { produce } from 'immer';
|
|
5
|
-
import {
|
|
5
|
+
import { useState } from 'react';
|
|
6
6
|
import { useCellsStore } from '../hooks';
|
|
7
7
|
import { useVegaCellQuery } from '../hooks/useVegaCellQuery';
|
|
8
8
|
import { useVegaCellDataSource } from '../hooks/useVegaCellDataSource';
|
|
9
|
-
import { SelectionListener } from './SelectionListener';
|
|
10
9
|
import { VegaConfigPanel } from './VegaConfigPanel';
|
|
11
10
|
import { VegaCellHeader } from './VegaCellHeader';
|
|
12
11
|
import { toDataSourceCell, toDataSourceTable } from '../helpers';
|
|
@@ -18,9 +17,6 @@ const DEFAULT_SPEC = {
|
|
|
18
17
|
};
|
|
19
18
|
export const VegaCellContent = ({ id, cell, renderContainer, }) => {
|
|
20
19
|
const updateCell = useCellsStore((s) => s.cells.updateCell);
|
|
21
|
-
const crossFilterEnabled = cell.data.crossFilter?.enabled !== false;
|
|
22
|
-
const brushField = cell.data.crossFilter?.brushField;
|
|
23
|
-
const brushFieldType = cell.data.crossFilter?.brushFieldType;
|
|
24
20
|
const [isEditing, setIsEditing] = useState(false);
|
|
25
21
|
// Local state with debounced persistence
|
|
26
22
|
const [localSpec, handleSpecChange] = useDebouncedValue(cell.data.vegaSpec ?? DEFAULT_SPEC, (spec) => {
|
|
@@ -30,11 +26,8 @@ export const VegaCellContent = ({ id, cell, renderContainer, }) => {
|
|
|
30
26
|
}));
|
|
31
27
|
}, 300);
|
|
32
28
|
const { selectedSqlId, selectedTableRef, selectedSqlStatus, baseSqlQuery, lastRunTime, hasDataSource, } = useVegaCellDataSource(cell);
|
|
33
|
-
const { selectedSqlQuery
|
|
34
|
-
cellId: id,
|
|
29
|
+
const { selectedSqlQuery } = useVegaCellQuery({
|
|
35
30
|
baseSqlQuery,
|
|
36
|
-
selectedSqlId,
|
|
37
|
-
crossFilterEnabled,
|
|
38
31
|
});
|
|
39
32
|
// Encode selection value: "cell:<id>" or "table:<schema.table>"
|
|
40
33
|
const selectValue = selectedSqlId
|
|
@@ -42,36 +35,8 @@ export const VegaCellContent = ({ id, cell, renderContainer, }) => {
|
|
|
42
35
|
: selectedTableRef
|
|
43
36
|
? toDataSourceTable(selectedTableRef)
|
|
44
37
|
: undefined;
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
if (draft.type === 'vega') {
|
|
48
|
-
if (!draft.data.crossFilter)
|
|
49
|
-
draft.data.crossFilter = {};
|
|
50
|
-
draft.data.crossFilter.enabled = enabled;
|
|
51
|
-
}
|
|
52
|
-
}));
|
|
53
|
-
}, [id, updateCell]);
|
|
54
|
-
const handleBrushFieldChange = useCallback((field) => {
|
|
55
|
-
updateCell(id, (c) => produce(c, (draft) => {
|
|
56
|
-
if (draft.type === 'vega') {
|
|
57
|
-
if (!draft.data.crossFilter)
|
|
58
|
-
draft.data.crossFilter = {};
|
|
59
|
-
draft.data.crossFilter.brushField = field;
|
|
60
|
-
}
|
|
61
|
-
}));
|
|
62
|
-
}, [id, updateCell]);
|
|
63
|
-
const handleBrushFieldTypeChange = useCallback((fieldType) => {
|
|
64
|
-
updateCell(id, (c) => produce(c, (draft) => {
|
|
65
|
-
if (draft.type === 'vega') {
|
|
66
|
-
if (!draft.data.crossFilter)
|
|
67
|
-
draft.data.crossFilter = {};
|
|
68
|
-
draft.data.crossFilter.brushFieldType = fieldType;
|
|
69
|
-
}
|
|
70
|
-
}));
|
|
71
|
-
}, [id, updateCell]);
|
|
72
|
-
const header = (_jsx(VegaCellHeader, { cellId: id, selectValue: selectValue, onEditToggle: () => setIsEditing((prev) => !prev), hasDataSource: hasDataSource, crossFilterEnabled: crossFilterEnabled, brushField: brushField, crossFilterPredicate: crossFilterPredicate }));
|
|
73
|
-
const showSelectionListener = crossFilterEnabled && brushField && selectedSqlId && selectedSqlStatus;
|
|
74
|
-
const content = (_jsxs("div", { className: "flex h-[400px]", children: [isEditing && (_jsx(VegaConfigPanel, { sqlQuery: baseSqlQuery, lastRunTime: lastRunTime, spec: localSpec, crossFilterEnabled: crossFilterEnabled, onSpecChange: handleSpecChange, onCrossFilterToggle: handleCrossFilterToggle, onBrushFieldChange: handleBrushFieldChange, onBrushFieldTypeChange: handleBrushFieldTypeChange })), _jsx("div", { onDoubleClick: () => hasDataSource && setIsEditing((prev) => !prev), className: "flex h-full w-full p-2", children: !hasDataSource ? (_jsx("div", { className: "flex h-full w-full items-center justify-center text-gray-400", children: "Please select a data source first." })) : !selectedSqlStatus && !selectedTableRef ? (_jsx("div", { className: "flex h-full w-full items-center justify-center text-gray-400", children: "No chart data available, please run the SQL cell first." })) : (_jsx(VegaLiteChart, { sqlQuery: selectedSqlQuery, spec: localSpec, className: "h-full w-full", aspectRatio: isEditing ? undefined : DEFAULT_ASPECT_RATIO, children: showSelectionListener && (_jsx(SelectionListener, { cellId: id, sqlId: selectedSqlId, brushField: brushField, brushFieldType: brushFieldType })) })) })] }));
|
|
38
|
+
const header = (_jsx(VegaCellHeader, { cellId: id, selectValue: selectValue, onEditToggle: () => setIsEditing((prev) => !prev), hasDataSource: hasDataSource }));
|
|
39
|
+
const content = (_jsxs("div", { className: "flex h-[400px]", children: [isEditing && (_jsx(VegaConfigPanel, { sqlQuery: baseSqlQuery, lastRunTime: lastRunTime, spec: localSpec, onSpecChange: handleSpecChange })), _jsx("div", { onDoubleClick: () => hasDataSource && setIsEditing((prev) => !prev), className: "flex h-full w-full p-2", children: !hasDataSource ? (_jsx("div", { className: "flex h-full w-full items-center justify-center text-gray-400", children: "Please select a data source first." })) : !selectedSqlStatus && !selectedTableRef ? (_jsx("div", { className: "flex h-full w-full items-center justify-center text-gray-400", children: "No chart data available, please run the SQL cell first." })) : (_jsx(VegaLiteChart, { sqlQuery: selectedSqlQuery, spec: localSpec, className: "h-full w-full", aspectRatio: isEditing ? undefined : DEFAULT_ASPECT_RATIO })) })] }));
|
|
75
40
|
return renderContainer({
|
|
76
41
|
header,
|
|
77
42
|
content,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VegaCellContent.js","sourceRoot":"","sources":["../../src/components/VegaCellContent.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useDebouncedValue} from '@sqlrooms/ui';\nimport {VegaLiteChart} from '@sqlrooms/vega';\nimport {produce} from 'immer';\nimport {useCallback, useState} from 'react';\nimport {useCellsStore} from '../hooks';\nimport {useVegaCellQuery} from '../hooks/useVegaCellQuery';\nimport {useVegaCellDataSource} from '../hooks/useVegaCellDataSource';\nimport type {CellContainerProps, VegaCell} from '../types';\nimport {SelectionListener} from './SelectionListener';\nimport {VegaConfigPanel} from './VegaConfigPanel';\nimport {VegaCellHeader} from './VegaCellHeader';\nimport {toDataSourceCell, toDataSourceTable} from '../helpers';\n\nconst DEFAULT_ASPECT_RATIO = 3 / 2;\nconst DEFAULT_SPEC = {\n data: {name: 'queryResult'},\n mark: 'bar',\n padding: 20,\n} as const;\n\nexport type VegaCellContentProps = {\n id: string;\n cell: VegaCell;\n renderContainer: (props: CellContainerProps) => React.ReactElement;\n};\n\nexport const VegaCellContent: React.FC<VegaCellContentProps> = ({\n id,\n cell,\n renderContainer,\n}) => {\n const updateCell = useCellsStore((s) => s.cells.updateCell);\n\n const crossFilterEnabled = cell.data.crossFilter?.enabled !== false;\n const brushField = cell.data.crossFilter?.brushField;\n const brushFieldType = cell.data.crossFilter?.brushFieldType;\n\n const [isEditing, setIsEditing] = useState(false);\n\n // Local state with debounced persistence\n const [localSpec, handleSpecChange] = useDebouncedValue(\n cell.data.vegaSpec ?? DEFAULT_SPEC,\n (spec) => {\n updateCell(id, (c) =>\n produce(c, (draft) => {\n if (draft.type === 'vega') draft.data.vegaSpec = spec;\n }),\n );\n },\n 300,\n );\n\n const {\n selectedSqlId,\n selectedTableRef,\n selectedSqlStatus,\n baseSqlQuery,\n lastRunTime,\n hasDataSource,\n } = useVegaCellDataSource(cell);\n\n const {selectedSqlQuery, crossFilterPredicate} = useVegaCellQuery({\n cellId: id,\n baseSqlQuery,\n selectedSqlId,\n crossFilterEnabled,\n });\n\n // Encode selection value: \"cell:<id>\" or \"table:<schema.table>\"\n const selectValue = selectedSqlId\n ? toDataSourceCell(selectedSqlId)\n : selectedTableRef\n ? toDataSourceTable(selectedTableRef)\n : undefined;\n\n const handleCrossFilterToggle = useCallback(\n (enabled: boolean) => {\n updateCell(id, (c) =>\n produce(c, (draft) => {\n if (draft.type === 'vega') {\n if (!draft.data.crossFilter) draft.data.crossFilter = {};\n draft.data.crossFilter.enabled = enabled;\n }\n }),\n );\n },\n [id, updateCell],\n );\n\n const handleBrushFieldChange = useCallback(\n (field: string | undefined) => {\n updateCell(id, (c) =>\n produce(c, (draft) => {\n if (draft.type === 'vega') {\n if (!draft.data.crossFilter) draft.data.crossFilter = {};\n draft.data.crossFilter.brushField = field;\n }\n }),\n );\n },\n [id, updateCell],\n );\n\n const handleBrushFieldTypeChange = useCallback(\n (fieldType: string | undefined) => {\n updateCell(id, (c) =>\n produce(c, (draft) => {\n if (draft.type === 'vega') {\n if (!draft.data.crossFilter) draft.data.crossFilter = {};\n draft.data.crossFilter.brushFieldType = fieldType;\n }\n }),\n );\n },\n [id, updateCell],\n );\n\n const header = (\n <VegaCellHeader\n cellId={id}\n selectValue={selectValue}\n onEditToggle={() => setIsEditing((prev) => !prev)}\n hasDataSource={hasDataSource}\n crossFilterEnabled={crossFilterEnabled}\n brushField={brushField}\n crossFilterPredicate={crossFilterPredicate}\n />\n );\n\n const showSelectionListener =\n crossFilterEnabled && brushField && selectedSqlId && selectedSqlStatus;\n\n const content = (\n <div className=\"flex h-[400px]\">\n {isEditing && (\n <VegaConfigPanel\n sqlQuery={baseSqlQuery}\n lastRunTime={lastRunTime}\n spec={localSpec}\n crossFilterEnabled={crossFilterEnabled}\n onSpecChange={handleSpecChange}\n onCrossFilterToggle={handleCrossFilterToggle}\n onBrushFieldChange={handleBrushFieldChange}\n onBrushFieldTypeChange={handleBrushFieldTypeChange}\n />\n )}\n <div\n onDoubleClick={() => hasDataSource && setIsEditing((prev) => !prev)}\n className=\"flex h-full w-full p-2\"\n >\n {!hasDataSource ? (\n <div className=\"flex h-full w-full items-center justify-center text-gray-400\">\n Please select a data source first.\n </div>\n ) : !selectedSqlStatus && !selectedTableRef ? (\n <div className=\"flex h-full w-full items-center justify-center text-gray-400\">\n No chart data available, please run the SQL cell first.\n </div>\n ) : (\n <VegaLiteChart\n sqlQuery={selectedSqlQuery}\n spec={localSpec}\n className=\"h-full w-full\"\n aspectRatio={isEditing ? undefined : DEFAULT_ASPECT_RATIO}\n >\n {showSelectionListener && (\n <SelectionListener\n cellId={id}\n sqlId={selectedSqlId}\n brushField={brushField}\n brushFieldType={brushFieldType}\n />\n )}\n </VegaLiteChart>\n )}\n </div>\n </div>\n );\n\n return renderContainer({\n header,\n content,\n });\n};\n"]}
|
|
1
|
+
{"version":3,"file":"VegaCellContent.js","sourceRoot":"","sources":["../../src/components/VegaCellContent.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useDebouncedValue} from '@sqlrooms/ui';\nimport {VegaLiteChart} from '@sqlrooms/vega';\nimport {produce} from 'immer';\nimport {useState} from 'react';\nimport {useCellsStore} from '../hooks';\nimport {useVegaCellQuery} from '../hooks/useVegaCellQuery';\nimport {useVegaCellDataSource} from '../hooks/useVegaCellDataSource';\nimport type {CellContainerProps, VegaCell} from '../types';\nimport {VegaConfigPanel} from './VegaConfigPanel';\nimport {VegaCellHeader} from './VegaCellHeader';\nimport {toDataSourceCell, toDataSourceTable} from '../helpers';\n\nconst DEFAULT_ASPECT_RATIO = 3 / 2;\nconst DEFAULT_SPEC = {\n data: {name: 'queryResult'},\n mark: 'bar',\n padding: 20,\n} as const;\n\nexport type VegaCellContentProps = {\n id: string;\n cell: VegaCell;\n renderContainer: (props: CellContainerProps) => React.ReactElement;\n};\n\nexport const VegaCellContent: React.FC<VegaCellContentProps> = ({\n id,\n cell,\n renderContainer,\n}) => {\n const updateCell = useCellsStore((s) => s.cells.updateCell);\n\n const [isEditing, setIsEditing] = useState(false);\n\n // Local state with debounced persistence\n const [localSpec, handleSpecChange] = useDebouncedValue(\n cell.data.vegaSpec ?? DEFAULT_SPEC,\n (spec) => {\n updateCell(id, (c) =>\n produce(c, (draft) => {\n if (draft.type === 'vega') draft.data.vegaSpec = spec;\n }),\n );\n },\n 300,\n );\n\n const {\n selectedSqlId,\n selectedTableRef,\n selectedSqlStatus,\n baseSqlQuery,\n lastRunTime,\n hasDataSource,\n } = useVegaCellDataSource(cell);\n\n const {selectedSqlQuery} = useVegaCellQuery({\n baseSqlQuery,\n });\n\n // Encode selection value: \"cell:<id>\" or \"table:<schema.table>\"\n const selectValue = selectedSqlId\n ? toDataSourceCell(selectedSqlId)\n : selectedTableRef\n ? toDataSourceTable(selectedTableRef)\n : undefined;\n\n const header = (\n <VegaCellHeader\n cellId={id}\n selectValue={selectValue}\n onEditToggle={() => setIsEditing((prev) => !prev)}\n hasDataSource={hasDataSource}\n />\n );\n\n const content = (\n <div className=\"flex h-[400px]\">\n {isEditing && (\n <VegaConfigPanel\n sqlQuery={baseSqlQuery}\n lastRunTime={lastRunTime}\n spec={localSpec}\n onSpecChange={handleSpecChange}\n />\n )}\n <div\n onDoubleClick={() => hasDataSource && setIsEditing((prev) => !prev)}\n className=\"flex h-full w-full p-2\"\n >\n {!hasDataSource ? (\n <div className=\"flex h-full w-full items-center justify-center text-gray-400\">\n Please select a data source first.\n </div>\n ) : !selectedSqlStatus && !selectedTableRef ? (\n <div className=\"flex h-full w-full items-center justify-center text-gray-400\">\n No chart data available, please run the SQL cell first.\n </div>\n ) : (\n <VegaLiteChart\n sqlQuery={selectedSqlQuery}\n spec={localSpec}\n className=\"h-full w-full\"\n aspectRatio={isEditing ? undefined : DEFAULT_ASPECT_RATIO}\n />\n )}\n </div>\n </div>\n );\n\n return renderContainer({\n header,\n content,\n });\n};\n"]}
|
|
@@ -3,9 +3,6 @@ export type VegaCellHeaderProps = {
|
|
|
3
3
|
selectValue: string | undefined;
|
|
4
4
|
onEditToggle: () => void;
|
|
5
5
|
hasDataSource: boolean;
|
|
6
|
-
crossFilterEnabled: boolean;
|
|
7
|
-
brushField: string | undefined;
|
|
8
|
-
crossFilterPredicate: string | null;
|
|
9
6
|
};
|
|
10
7
|
export declare const VegaCellHeader: React.FC<VegaCellHeaderProps>;
|
|
11
8
|
//# sourceMappingURL=VegaCellHeader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VegaCellHeader.d.ts","sourceRoot":"","sources":["../../src/components/VegaCellHeader.tsx"],"names":[],"mappings":"AAOA,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"VegaCellHeader.d.ts","sourceRoot":"","sources":["../../src/components/VegaCellHeader.tsx"],"names":[],"mappings":"AAOA,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAgDxD,CAAC"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Button
|
|
2
|
+
import { Button } from '@sqlrooms/ui';
|
|
3
3
|
import { produce } from 'immer';
|
|
4
|
-
import {
|
|
4
|
+
import { Settings } from 'lucide-react';
|
|
5
5
|
import { fromDataSourceCell, fromDataSourceTable } from '../helpers';
|
|
6
6
|
import { CellSourceSelector } from './CellSourceSelector';
|
|
7
7
|
import { useCellsStore } from '../hooks';
|
|
8
|
-
export const VegaCellHeader = ({ cellId, selectValue, onEditToggle, hasDataSource,
|
|
8
|
+
export const VegaCellHeader = ({ cellId, selectValue, onEditToggle, hasDataSource, }) => {
|
|
9
9
|
const updateCell = useCellsStore((s) => s.cells.updateCell);
|
|
10
10
|
const artifactId = useCellsStore((s) => s.cells.getArtifactIdForCell(cellId));
|
|
11
11
|
const handleDataSourceChange = (value) => {
|
|
@@ -25,8 +25,6 @@ export const VegaCellHeader = ({ cellId, selectValue, onEditToggle, hasDataSourc
|
|
|
25
25
|
}
|
|
26
26
|
}));
|
|
27
27
|
};
|
|
28
|
-
return (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CellSourceSelector, { artifactId: artifactId ?? '', value: selectValue, onValueChange: handleDataSourceChange }), _jsx(Button, { size: "xs", variant: "secondary", className: "h-6", onClick: onEditToggle, disabled: !hasDataSource, children: _jsx(Settings, { className: "h-4 w-4" }) })
|
|
29
|
-
? `Filtered: ${crossFilterPredicate}`
|
|
30
|
-
: `Cross-filter on ${brushField}` }) })] }))] }));
|
|
28
|
+
return (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CellSourceSelector, { artifactId: artifactId ?? '', value: selectValue, onValueChange: handleDataSourceChange }), _jsx(Button, { size: "xs", variant: "secondary", className: "h-6", onClick: onEditToggle, disabled: !hasDataSource, children: _jsx(Settings, { className: "h-4 w-4" }) })] }));
|
|
31
29
|
};
|
|
32
30
|
//# sourceMappingURL=VegaCellHeader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VegaCellHeader.js","sourceRoot":"","sources":["../../src/components/VegaCellHeader.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"VegaCellHeader.js","sourceRoot":"","sources":["../../src/components/VegaCellHeader.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,MAAM,EAAC,MAAM,cAAc,CAAC;AACpC,OAAO,EAAC,OAAO,EAAC,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAC,QAAQ,EAAC,MAAM,cAAc,CAAC;AACtC,OAAO,EAAC,kBAAkB,EAAE,mBAAmB,EAAC,MAAM,YAAY,CAAC;AACnE,OAAO,EAAC,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAC,aAAa,EAAC,MAAM,UAAU,CAAC;AASvC,MAAM,CAAC,MAAM,cAAc,GAAkC,CAAC,EAC5D,MAAM,EACN,WAAW,EACX,YAAY,EACZ,aAAa,GACd,EAAE,EAAE;IACH,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,aAAa,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC;IAE9E,MAAM,sBAAsB,GAAG,CAAC,KAAa,EAAE,EAAE;QAC/C,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CACvB,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE;YACnB,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC1B,OAAO;YACT,CAAC;YAED,MAAM,eAAe,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;YAClD,MAAM,QAAQ,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;YAE5C,IAAI,eAAe,EAAE,CAAC;gBACpB,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,eAAe,CAAC;gBACnC,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;YAC7B,CAAC;iBAAM,IAAI,QAAQ,EAAE,CAAC;gBACpB,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;gBAC/B,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC,CACH,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,CACL,eAAK,SAAS,EAAC,yBAAyB,aACtC,KAAC,kBAAkB,IACjB,UAAU,EAAE,UAAU,IAAI,EAAE,EAC5B,KAAK,EAAE,WAAW,EAClB,aAAa,EAAE,sBAAsB,GACrC,EACF,KAAC,MAAM,IACL,IAAI,EAAC,IAAI,EACT,OAAO,EAAC,WAAW,EACnB,SAAS,EAAC,KAAK,EACf,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,CAAC,aAAa,YAExB,KAAC,QAAQ,IAAC,SAAS,EAAC,SAAS,GAAG,GACzB,IACL,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {Button} from '@sqlrooms/ui';\nimport {produce} from 'immer';\nimport {Settings} from 'lucide-react';\nimport {fromDataSourceCell, fromDataSourceTable} from '../helpers';\nimport {CellSourceSelector} from './CellSourceSelector';\nimport {useCellsStore} from '../hooks';\n\nexport type VegaCellHeaderProps = {\n cellId: string;\n selectValue: string | undefined;\n onEditToggle: () => void;\n hasDataSource: boolean;\n};\n\nexport const VegaCellHeader: React.FC<VegaCellHeaderProps> = ({\n cellId,\n selectValue,\n onEditToggle,\n hasDataSource,\n}) => {\n const updateCell = useCellsStore((s) => s.cells.updateCell);\n const artifactId = useCellsStore((s) => s.cells.getArtifactIdForCell(cellId));\n\n const handleDataSourceChange = (value: string) => {\n updateCell(cellId, (c) =>\n produce(c, (draft) => {\n if (draft.type !== 'vega') {\n return;\n }\n\n const cellIdFromValue = fromDataSourceCell(value);\n const tableRef = fromDataSourceTable(value);\n\n if (cellIdFromValue) {\n draft.data.sqlId = cellIdFromValue;\n delete draft.data.tableRef;\n } else if (tableRef) {\n draft.data.tableRef = tableRef;\n delete draft.data.sqlId;\n }\n }),\n );\n };\n\n return (\n <div className=\"flex items-center gap-2\">\n <CellSourceSelector\n artifactId={artifactId ?? ''}\n value={selectValue}\n onValueChange={handleDataSourceChange}\n />\n <Button\n size=\"xs\"\n variant=\"secondary\"\n className=\"h-6\"\n onClick={onEditToggle}\n disabled={!hasDataSource}\n >\n <Settings className=\"h-4 w-4\" />\n </Button>\n </div>\n );\n};\n"]}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { BrushFieldType } from '../types';
|
|
3
2
|
export declare const VegaConfigPanel: React.FC<{
|
|
4
3
|
spec: any;
|
|
5
4
|
sqlQuery: string;
|
|
6
5
|
lastRunTime?: number;
|
|
7
|
-
crossFilterEnabled: boolean;
|
|
8
6
|
onSpecChange: (spec: any) => void;
|
|
9
|
-
onCrossFilterToggle: (enabled: boolean) => void;
|
|
10
|
-
onBrushFieldChange: (field: string | undefined) => void;
|
|
11
|
-
onBrushFieldTypeChange: (fieldType: BrushFieldType | undefined) => void;
|
|
12
7
|
}>;
|
|
13
8
|
//# sourceMappingURL=VegaConfigPanel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VegaConfigPanel.d.ts","sourceRoot":"","sources":["../../src/components/VegaConfigPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"VegaConfigPanel.d.ts","sourceRoot":"","sources":["../../src/components/VegaConfigPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAgB1B,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC;IACrC,IAAI,EAAE,GAAG,CAAC;IACV,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;CACnC,CA2FA,CAAC"}
|
|
@@ -1,62 +1,31 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Tabs, TabsContent, TabsList, TabsTrigger, Label, Separator,
|
|
2
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger, Label, Separator, } from '@sqlrooms/ui';
|
|
3
3
|
import { useSql } from '@sqlrooms/duckdb';
|
|
4
|
-
import {
|
|
5
|
-
import { readSpecValues, buildCrossFilterSpec, buildFlatSpec, } from '../vegaSpecBuilder';
|
|
4
|
+
import { readSpecValues, buildFlatSpec } from '../vegaSpecBuilder';
|
|
6
5
|
import { FieldSelector } from './FieldSelector';
|
|
7
6
|
import { ColorSelector, colorOptions } from './ColorSelector';
|
|
8
7
|
import { ChartTypeSelector } from './ChartTypeSelector';
|
|
9
8
|
import { AggregationSelector } from './AggregationSelector';
|
|
10
|
-
export const VegaConfigPanel = ({ sqlQuery, lastRunTime, spec,
|
|
9
|
+
export const VegaConfigPanel = ({ sqlQuery, lastRunTime, spec, onSpecChange }) => {
|
|
11
10
|
const result = useSql({ query: sqlQuery, version: lastRunTime });
|
|
12
11
|
const arrowTable = result.data?.arrowTable;
|
|
13
12
|
const fields = arrowTable?.schema?.fields || [];
|
|
14
|
-
const detectBrushFieldType = (fieldName) => {
|
|
15
|
-
const arrowField = arrowTable?.schema?.fields?.find((field) => field.name === fieldName);
|
|
16
|
-
if (!arrowField) {
|
|
17
|
-
return 'numeric';
|
|
18
|
-
}
|
|
19
|
-
const category = getArrowColumnTypeCategory(arrowField.type);
|
|
20
|
-
if (category === 'datetime')
|
|
21
|
-
return 'temporal';
|
|
22
|
-
if (category === 'string')
|
|
23
|
-
return 'string';
|
|
24
|
-
return 'numeric';
|
|
25
|
-
};
|
|
26
13
|
const current = readSpecValues(spec);
|
|
27
|
-
const rebuild = (overrides
|
|
14
|
+
const rebuild = (overrides) => {
|
|
28
15
|
const merged = { ...current, ...overrides };
|
|
29
|
-
|
|
30
|
-
onSpecChange(builder({
|
|
16
|
+
onSpecChange(buildFlatSpec({
|
|
31
17
|
mark: merged.mark ?? 'bar',
|
|
32
18
|
xField: merged.xField,
|
|
33
|
-
xFieldType: merged.xField
|
|
34
|
-
? detectBrushFieldType(merged.xField)
|
|
35
|
-
: undefined,
|
|
36
19
|
yField: merged.yField,
|
|
37
20
|
yAggregate: merged.yAggregate,
|
|
38
21
|
color: merged.color ?? colorOptions[0]?.value,
|
|
39
22
|
}));
|
|
40
|
-
if ('xField' in overrides) {
|
|
41
|
-
onBrushFieldChange(cfEnabled ? overrides.xField : undefined);
|
|
42
|
-
onBrushFieldTypeChange(cfEnabled && overrides.xField
|
|
43
|
-
? detectBrushFieldType(overrides.xField)
|
|
44
|
-
: undefined);
|
|
45
|
-
}
|
|
46
23
|
};
|
|
47
24
|
const handleMarkChange = (mark) => rebuild({ mark });
|
|
48
25
|
const handleXFieldChange = (field) => rebuild({ xField: field });
|
|
49
26
|
const handleYFieldChange = (field) => rebuild({ yField: field, yAggregate: current.yAggregate ?? 'sum' });
|
|
50
27
|
const handleYAggregationChange = (aggregate) => rebuild({ yAggregate: aggregate });
|
|
51
28
|
const handleColorChange = (color) => rebuild({ color });
|
|
52
|
-
|
|
53
|
-
onCrossFilterToggle(enabled);
|
|
54
|
-
rebuild({}, enabled);
|
|
55
|
-
onBrushFieldChange(enabled ? current.xField : undefined);
|
|
56
|
-
onBrushFieldTypeChange(enabled && current.xField
|
|
57
|
-
? detectBrushFieldType(current.xField)
|
|
58
|
-
: undefined);
|
|
59
|
-
};
|
|
60
|
-
return (_jsx("div", { className: "w-80 border-r p-4 text-xs", children: _jsxs("div", { className: "space-y-3", children: [_jsx(ChartTypeSelector, { value: current.mark, onValueChange: handleMarkChange }), _jsx(Separator, {}), _jsxs(Tabs, { defaultValue: "general", className: "w-full", children: [_jsxs(TabsList, { className: "grid w-full grid-cols-2", children: [_jsx(TabsTrigger, { value: "general", className: "text-xs", children: "General" }), _jsx(TabsTrigger, { value: "styles", className: "text-xs", children: "Styles" })] }), _jsxs(TabsContent, { value: "general", className: "mt-4 space-y-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs font-medium text-gray-400", children: "X-Axis" }), _jsx(FieldSelector, { value: current.xField, fields: fields, onValueChange: handleXFieldChange })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs font-medium text-gray-400", children: "Y-Axis" }), _jsxs("div", { className: "grid grid-cols-[2fr_1fr] gap-2", children: [_jsx(FieldSelector, { value: current.yField, fields: fields, onValueChange: handleYFieldChange }), _jsx(AggregationSelector, { value: current.yAggregate, onValueChange: handleYAggregationChange })] })] }), _jsx(Separator, {}), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx(Label, { className: "text-xs font-medium text-gray-400", children: "Cross-filter" }), _jsx(Switch, { checked: crossFilterEnabled, onCheckedChange: handleCrossFilterToggle })] })] }), _jsx(TabsContent, { value: "styles", className: "mt-4 space-y-4", children: _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs font-medium text-gray-400", children: "Color" }), _jsx(ColorSelector, { value: current.color, onValueChange: handleColorChange })] }) })] })] }) }));
|
|
29
|
+
return (_jsx("div", { className: "w-80 border-r p-4 text-xs", children: _jsxs("div", { className: "space-y-3", children: [_jsx(ChartTypeSelector, { value: current.mark, onValueChange: handleMarkChange }), _jsx(Separator, {}), _jsxs(Tabs, { defaultValue: "general", className: "w-full", children: [_jsxs(TabsList, { className: "grid w-full grid-cols-2", children: [_jsx(TabsTrigger, { value: "general", className: "text-xs", children: "General" }), _jsx(TabsTrigger, { value: "styles", className: "text-xs", children: "Styles" })] }), _jsxs(TabsContent, { value: "general", className: "mt-4 space-y-4", children: [_jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs font-medium text-gray-400", children: "X-Axis" }), _jsx(FieldSelector, { value: current.xField, fields: fields, onValueChange: handleXFieldChange })] }), _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs font-medium text-gray-400", children: "Y-Axis" }), _jsxs("div", { className: "grid grid-cols-[2fr_1fr] gap-2", children: [_jsx(FieldSelector, { value: current.yField, fields: fields, onValueChange: handleYFieldChange }), _jsx(AggregationSelector, { value: current.yAggregate, onValueChange: handleYAggregationChange })] })] })] }), _jsx(TabsContent, { value: "styles", className: "mt-4 space-y-4", children: _jsxs("div", { className: "space-y-1", children: [_jsx(Label, { className: "text-xs font-medium text-gray-400", children: "Color" }), _jsx(ColorSelector, { value: current.color, onValueChange: handleColorChange })] }) })] })] }) }));
|
|
61
30
|
};
|
|
62
31
|
//# sourceMappingURL=VegaConfigPanel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VegaConfigPanel.js","sourceRoot":"","sources":["../../src/components/VegaConfigPanel.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Label,\n Separator,\n Switch,\n} from '@sqlrooms/ui';\nimport {useSql} from '@sqlrooms/duckdb';\nimport {getArrowColumnTypeCategory} from '@sqlrooms/duckdb';\nimport type {BrushFieldType} from '../types';\nimport {\n readSpecValues,\n buildCrossFilterSpec,\n buildFlatSpec,\n} from '../vegaSpecBuilder';\nimport {FieldSelector} from './FieldSelector';\nimport {ColorSelector, colorOptions} from './ColorSelector';\nimport {ChartTypeSelector} from './ChartTypeSelector';\nimport {AggregationSelector} from './AggregationSelector';\n\nexport const VegaConfigPanel: React.FC<{\n spec: any;\n sqlQuery: string;\n lastRunTime?: number;\n crossFilterEnabled: boolean;\n onSpecChange: (spec: any) => void;\n onCrossFilterToggle: (enabled: boolean) => void;\n onBrushFieldChange: (field: string | undefined) => void;\n onBrushFieldTypeChange: (fieldType: BrushFieldType | undefined) => void;\n}> = ({\n sqlQuery,\n lastRunTime,\n spec,\n crossFilterEnabled,\n onSpecChange,\n onCrossFilterToggle,\n onBrushFieldChange,\n onBrushFieldTypeChange,\n}) => {\n const result = useSql({query: sqlQuery, version: lastRunTime});\n const arrowTable = result.data?.arrowTable;\n const fields = arrowTable?.schema?.fields || [];\n\n const detectBrushFieldType = (fieldName: string): BrushFieldType => {\n const arrowField = arrowTable?.schema?.fields?.find(\n (field) => field.name === fieldName,\n );\n\n if (!arrowField) {\n return 'numeric';\n }\n\n const category = getArrowColumnTypeCategory(arrowField.type);\n if (category === 'datetime') return 'temporal';\n if (category === 'string') return 'string';\n return 'numeric';\n };\n\n const current = readSpecValues(spec);\n\n const rebuild = (\n overrides: Partial<ReturnType<typeof readSpecValues>>,\n cfEnabled = crossFilterEnabled,\n ) => {\n const merged = {...current, ...overrides};\n const builder = cfEnabled ? buildCrossFilterSpec : buildFlatSpec;\n onSpecChange(\n builder({\n mark: merged.mark ?? 'bar',\n xField: merged.xField,\n xFieldType: merged.xField\n ? detectBrushFieldType(merged.xField)\n : undefined,\n yField: merged.yField,\n yAggregate: merged.yAggregate,\n color: merged.color ?? colorOptions[0]?.value,\n }),\n );\n if ('xField' in overrides) {\n onBrushFieldChange(cfEnabled ? overrides.xField : undefined);\n onBrushFieldTypeChange(\n cfEnabled && overrides.xField\n ? detectBrushFieldType(overrides.xField)\n : undefined,\n );\n }\n };\n\n const handleMarkChange = (mark: string) => rebuild({mark});\n const handleXFieldChange = (field: string) => rebuild({xField: field});\n const handleYFieldChange = (field: string) =>\n rebuild({yField: field, yAggregate: current.yAggregate ?? 'sum'});\n const handleYAggregationChange = (aggregate: string) =>\n rebuild({yAggregate: aggregate});\n const handleColorChange = (color: string) => rebuild({color});\n\n const handleCrossFilterToggle = (enabled: boolean) => {\n onCrossFilterToggle(enabled);\n rebuild({}, enabled);\n onBrushFieldChange(enabled ? current.xField : undefined);\n onBrushFieldTypeChange(\n enabled && current.xField\n ? detectBrushFieldType(current.xField)\n : undefined,\n );\n };\n\n return (\n <div className=\"w-80 border-r p-4 text-xs\">\n <div className=\"space-y-3\">\n <ChartTypeSelector\n value={current.mark}\n onValueChange={handleMarkChange}\n />\n\n <Separator />\n\n <Tabs defaultValue=\"general\" className=\"w-full\">\n <TabsList className=\"grid w-full grid-cols-2\">\n <TabsTrigger value=\"general\" className=\"text-xs\">\n General\n </TabsTrigger>\n <TabsTrigger value=\"styles\" className=\"text-xs\">\n Styles\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"general\" className=\"mt-4 space-y-4\">\n <div className=\"space-y-1\">\n <Label className=\"text-xs font-medium text-gray-400\">\n X-Axis\n </Label>\n <FieldSelector\n value={current.xField}\n fields={fields}\n onValueChange={handleXFieldChange}\n />\n </div>\n <div className=\"space-y-1\">\n <Label className=\"text-xs font-medium text-gray-400\">\n Y-Axis\n </Label>\n <div className=\"grid grid-cols-[2fr_1fr] gap-2\">\n <FieldSelector\n value={current.yField}\n fields={fields}\n onValueChange={handleYFieldChange}\n />\n\n <AggregationSelector\n value={current.yAggregate}\n onValueChange={handleYAggregationChange}\n />\n </div>\n </div>\n\n <Separator />\n\n <div className=\"flex items-center justify-between\">\n <Label className=\"text-xs font-medium text-gray-400\">\n Cross-filter\n </Label>\n <Switch\n checked={crossFilterEnabled}\n onCheckedChange={handleCrossFilterToggle}\n />\n </div>\n </TabsContent>\n\n <TabsContent value=\"styles\" className=\"mt-4 space-y-4\">\n <div className=\"space-y-1\">\n <Label className=\"text-xs font-medium text-gray-400\">Color</Label>\n <ColorSelector\n value={current.color}\n onValueChange={handleColorChange}\n />\n </div>\n </TabsContent>\n </Tabs>\n </div>\n </div>\n );\n};\n"]}
|
|
1
|
+
{"version":3,"file":"VegaConfigPanel.js","sourceRoot":"","sources":["../../src/components/VegaConfigPanel.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Label,\n Separator,\n} from '@sqlrooms/ui';\nimport {useSql} from '@sqlrooms/duckdb';\nimport {readSpecValues, buildFlatSpec} from '../vegaSpecBuilder';\nimport {FieldSelector} from './FieldSelector';\nimport {ColorSelector, colorOptions} from './ColorSelector';\nimport {ChartTypeSelector} from './ChartTypeSelector';\nimport {AggregationSelector} from './AggregationSelector';\n\nexport const VegaConfigPanel: React.FC<{\n spec: any;\n sqlQuery: string;\n lastRunTime?: number;\n onSpecChange: (spec: any) => void;\n}> = ({sqlQuery, lastRunTime, spec, onSpecChange}) => {\n const result = useSql({query: sqlQuery, version: lastRunTime});\n const arrowTable = result.data?.arrowTable;\n const fields = arrowTable?.schema?.fields || [];\n\n const current = readSpecValues(spec);\n\n const rebuild = (overrides: Partial<ReturnType<typeof readSpecValues>>) => {\n const merged = {...current, ...overrides};\n onSpecChange(\n buildFlatSpec({\n mark: merged.mark ?? 'bar',\n xField: merged.xField,\n yField: merged.yField,\n yAggregate: merged.yAggregate,\n color: merged.color ?? colorOptions[0]?.value,\n }),\n );\n };\n\n const handleMarkChange = (mark: string) => rebuild({mark});\n const handleXFieldChange = (field: string) => rebuild({xField: field});\n const handleYFieldChange = (field: string) =>\n rebuild({yField: field, yAggregate: current.yAggregate ?? 'sum'});\n const handleYAggregationChange = (aggregate: string) =>\n rebuild({yAggregate: aggregate});\n const handleColorChange = (color: string) => rebuild({color});\n\n return (\n <div className=\"w-80 border-r p-4 text-xs\">\n <div className=\"space-y-3\">\n <ChartTypeSelector\n value={current.mark}\n onValueChange={handleMarkChange}\n />\n\n <Separator />\n\n <Tabs defaultValue=\"general\" className=\"w-full\">\n <TabsList className=\"grid w-full grid-cols-2\">\n <TabsTrigger value=\"general\" className=\"text-xs\">\n General\n </TabsTrigger>\n <TabsTrigger value=\"styles\" className=\"text-xs\">\n Styles\n </TabsTrigger>\n </TabsList>\n\n <TabsContent value=\"general\" className=\"mt-4 space-y-4\">\n <div className=\"space-y-1\">\n <Label className=\"text-xs font-medium text-gray-400\">\n X-Axis\n </Label>\n <FieldSelector\n value={current.xField}\n fields={fields}\n onValueChange={handleXFieldChange}\n />\n </div>\n <div className=\"space-y-1\">\n <Label className=\"text-xs font-medium text-gray-400\">\n Y-Axis\n </Label>\n <div className=\"grid grid-cols-[2fr_1fr] gap-2\">\n <FieldSelector\n value={current.yField}\n fields={fields}\n onValueChange={handleYFieldChange}\n />\n\n <AggregationSelector\n value={current.yAggregate}\n onValueChange={handleYAggregationChange}\n />\n </div>\n </div>\n </TabsContent>\n\n <TabsContent value=\"styles\" className=\"mt-4 space-y-4\">\n <div className=\"space-y-1\">\n <Label className=\"text-xs font-medium text-gray-400\">Color</Label>\n <ColorSelector\n value={current.color}\n onValueChange={handleColorChange}\n />\n </div>\n </TabsContent>\n </Tabs>\n </div>\n </div>\n );\n};\n"]}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export type VegaCellQuery = {
|
|
2
2
|
selectedSqlQuery: string;
|
|
3
|
-
crossFilterPredicate: string | null;
|
|
4
3
|
};
|
|
5
4
|
/**
|
|
6
5
|
* Builds the final SQL query for a Vega cell with optional cross-filter predicates.
|
|
@@ -8,9 +7,6 @@ export type VegaCellQuery = {
|
|
|
8
7
|
* and applies the WHERE clause to avoid breaking raw SQL with existing clauses.
|
|
9
8
|
*/
|
|
10
9
|
export declare function useVegaCellQuery(params: {
|
|
11
|
-
cellId: string;
|
|
12
10
|
baseSqlQuery: string;
|
|
13
|
-
selectedSqlId: string | undefined;
|
|
14
|
-
crossFilterEnabled: boolean;
|
|
15
11
|
}): VegaCellQuery;
|
|
16
12
|
//# sourceMappingURL=useVegaCellQuery.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useVegaCellQuery.d.ts","sourceRoot":"","sources":["../../src/hooks/useVegaCellQuery.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useVegaCellQuery.d.ts","sourceRoot":"","sources":["../../src/hooks/useVegaCellQuery.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG;IAC1B,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE;IACvC,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,aAAa,CAMhB"}
|
|
@@ -1,25 +1,12 @@
|
|
|
1
|
-
import { useCellsStore } from '../hooks';
|
|
2
1
|
/**
|
|
3
2
|
* Builds the final SQL query for a Vega cell with optional cross-filter predicates.
|
|
4
3
|
* If cross-filtering is enabled and active, wraps the base query as a subquery
|
|
5
4
|
* and applies the WHERE clause to avoid breaking raw SQL with existing clauses.
|
|
6
5
|
*/
|
|
7
6
|
export function useVegaCellQuery(params) {
|
|
8
|
-
const {
|
|
9
|
-
const getCrossFilterPredicate = useCellsStore((s) => s.cells.getCrossFilterPredicate);
|
|
10
|
-
// Subscribe to cross-filter selections so we re-render when siblings change
|
|
11
|
-
const crossFilterGroup = useCellsStore((s) => selectedSqlId ? s.cells.crossFilterSelections[selectedSqlId] : undefined);
|
|
12
|
-
// Needed to satisfy exhaustive-deps for the memoized predicate
|
|
13
|
-
void crossFilterGroup;
|
|
14
|
-
const crossFilterPredicate = selectedSqlId && crossFilterEnabled
|
|
15
|
-
? getCrossFilterPredicate(cellId, selectedSqlId)
|
|
16
|
-
: null;
|
|
17
|
-
const selectedSqlQuery = crossFilterPredicate
|
|
18
|
-
? `SELECT * FROM (${baseSqlQuery.replace(/;\s*$/, '')}) AS _cells_base WHERE ${crossFilterPredicate}`
|
|
19
|
-
: baseSqlQuery;
|
|
7
|
+
const { baseSqlQuery } = params;
|
|
20
8
|
return {
|
|
21
|
-
selectedSqlQuery,
|
|
22
|
-
crossFilterPredicate,
|
|
9
|
+
selectedSqlQuery: baseSqlQuery,
|
|
23
10
|
};
|
|
24
11
|
}
|
|
25
12
|
//# sourceMappingURL=useVegaCellQuery.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useVegaCellQuery.js","sourceRoot":"","sources":["../../src/hooks/useVegaCellQuery.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useVegaCellQuery.js","sourceRoot":"","sources":["../../src/hooks/useVegaCellQuery.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAEhC;IACC,MAAM,EAAC,YAAY,EAAC,GAAG,MAAM,CAAC;IAE9B,OAAO;QACL,gBAAgB,EAAE,YAAY;KAC/B,CAAC;AACJ,CAAC","sourcesContent":["export type VegaCellQuery = {\n selectedSqlQuery: string;\n};\n\n/**\n * Builds the final SQL query for a Vega cell with optional cross-filter predicates.\n * If cross-filtering is enabled and active, wraps the base query as a subquery\n * and applies the WHERE clause to avoid breaking raw SQL with existing clauses.\n */\nexport function useVegaCellQuery(params: {\n baseSqlQuery: string;\n}): VegaCellQuery {\n const {baseSqlQuery} = params;\n\n return {\n selectedSqlQuery: baseSqlQuery,\n };\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -18,7 +18,6 @@ export { getRenderableDependencyEdges } from './dagUtils';
|
|
|
18
18
|
export { findArtifactIdForCell, normalizeCellDependencies, resolveArtifactSchemaName, toDataSourceCell, toDataSourceTable, isDataSourceCell, isDataSourceTable, fromDataSourceCell, fromDataSourceTable, } from './helpers';
|
|
19
19
|
export { useCellsStore } from './hooks';
|
|
20
20
|
export { findSqlDependencies, findSqlDependenciesFromAst, renderSqlWithInputs, runSqlWithCallbacks, } from './sqlHelpers';
|
|
21
|
-
export { buildCrossFilterPredicate, BRUSH_PARAM_NAME, } from './vegaSelectionUtils';
|
|
22
21
|
export * from './types';
|
|
23
22
|
export declare const SqlCell: {
|
|
24
23
|
RunButton: typeof SqlCellRunButtonComponent;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,cAAc,IAAI,uBAAuB,EAAC,MAAM,6BAA6B,CAAC;AACtF,OAAO,EAAC,gBAAgB,IAAI,yBAAyB,EAAC,MAAM,+BAA+B,CAAC;AAE5F,OAAO,EAAC,gBAAgB,EAAC,MAAM,cAAc,CAAC;AAC9C,YAAY,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAC,eAAe,EAAC,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAC,gBAAgB,EAAC,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAC,uBAAuB,IAAI,cAAc,EAAC,CAAC;AACnD,OAAO,EAAC,yBAAyB,IAAI,gBAAgB,EAAC,CAAC;AACvD,OAAO,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAC,kBAAkB,EAAC,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAC,yBAAyB,EAAC,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAC,4BAA4B,EAAC,MAAM,YAAY,CAAC;AACxD,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EACzB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAC,aAAa,EAAC,MAAM,SAAS,CAAC;AACtC,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,cAAc,IAAI,uBAAuB,EAAC,MAAM,6BAA6B,CAAC;AACtF,OAAO,EAAC,gBAAgB,IAAI,yBAAyB,EAAC,MAAM,+BAA+B,CAAC;AAE5F,OAAO,EAAC,gBAAgB,EAAC,MAAM,cAAc,CAAC;AAC9C,YAAY,EAAC,cAAc,EAAC,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAC,eAAe,EAAC,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAC,gBAAgB,EAAC,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAC,uBAAuB,IAAI,cAAc,EAAC,CAAC;AACnD,OAAO,EAAC,yBAAyB,IAAI,gBAAgB,EAAC,CAAC;AACvD,OAAO,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAC,kBAAkB,EAAC,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAC,yBAAyB,EAAC,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAC,4BAA4B,EAAC,MAAM,YAAY,CAAC;AACxD,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EACzB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAC,aAAa,EAAC,MAAM,SAAS,CAAC;AACtC,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,cAAc,SAAS,CAAC;AAExB,eAAO,MAAM,OAAO;;;CAGnB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,6 @@ export { getRenderableDependencyEdges } from './dagUtils';
|
|
|
17
17
|
export { findArtifactIdForCell, normalizeCellDependencies, resolveArtifactSchemaName, toDataSourceCell, toDataSourceTable, isDataSourceCell, isDataSourceTable, fromDataSourceCell, fromDataSourceTable, } from './helpers';
|
|
18
18
|
export { useCellsStore } from './hooks';
|
|
19
19
|
export { findSqlDependencies, findSqlDependenciesFromAst, renderSqlWithInputs, runSqlWithCallbacks, } from './sqlHelpers';
|
|
20
|
-
export { buildCrossFilterPredicate, BRUSH_PARAM_NAME, } from './vegaSelectionUtils';
|
|
21
20
|
export * from './types';
|
|
22
21
|
export const SqlCell = {
|
|
23
22
|
RunButton: SqlCellRunButtonComponent,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,cAAc,IAAI,uBAAuB,EAAC,MAAM,6BAA6B,CAAC;AACtF,OAAO,EAAC,gBAAgB,IAAI,yBAAyB,EAAC,MAAM,+BAA+B,CAAC;AAE5F,OAAO,EAAC,gBAAgB,EAAC,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAC,eAAe,EAAC,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAC,gBAAgB,EAAC,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAC,uBAAuB,IAAI,cAAc,EAAC,CAAC;AACnD,OAAO,EAAC,yBAAyB,IAAI,gBAAgB,EAAC,CAAC;AACvD,OAAO,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAC,kBAAkB,EAAC,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAC,yBAAyB,EAAC,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAC,4BAA4B,EAAC,MAAM,YAAY,CAAC;AACxD,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EACzB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAC,aAAa,EAAC,MAAM,SAAS,CAAC;AACtC,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAC,cAAc,IAAI,uBAAuB,EAAC,MAAM,6BAA6B,CAAC;AACtF,OAAO,EAAC,gBAAgB,IAAI,yBAAyB,EAAC,MAAM,+BAA+B,CAAC;AAE5F,OAAO,EAAC,gBAAgB,EAAC,MAAM,cAAc,CAAC;AAE9C,OAAO,EAAC,eAAe,EAAC,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAC,gBAAgB,EAAC,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAC,uBAAuB,IAAI,cAAc,EAAC,CAAC;AACnD,OAAO,EAAC,yBAAyB,IAAI,gBAAgB,EAAC,CAAC;AACvD,OAAO,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAC,kBAAkB,EAAC,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAC,yBAAyB,EAAC,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAC,4BAA4B,EAAC,MAAM,YAAY,CAAC;AACxD,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EACzB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAC,aAAa,EAAC,MAAM,SAAS,CAAC;AACtC,OAAO,EACL,mBAAmB,EACnB,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,cAAc,SAAS,CAAC;AAExB,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,SAAS,EAAE,yBAAyB;IACpC,OAAO,EAAE,uBAAuB;CACjC,CAAC","sourcesContent":["/**\n * {@include ../README.md}\n * @packageDocumentation\n */\n\nimport {SqlCellContent as SqlCellContentComponent} from './components/SqlCellContent';\nimport {SqlCellRunButton as SqlCellRunButtonComponent} from './components/SqlCellRunButton';\n\nexport {createCellsSlice} from './cellsSlice';\nexport type {CellsRootState} from './types';\nexport {initializeInput} from './components/Input/helpers';\nexport {InputCellContent} from './components/InputCellContent';\nexport {SqlCellContentComponent as SqlCellContent};\nexport {SqlCellRunButtonComponent as SqlCellRunButton};\nexport {TextCellContent} from './components/TextCellContent';\nexport {VegaCellContent} from './components/VegaCellContent';\nexport {CellSourceSelector} from './components/CellSourceSelector';\nexport {createDefaultCellRegistry} from './defaultCellRegistry';\nexport {getRenderableDependencyEdges} from './dagUtils';\nexport {\n findArtifactIdForCell,\n normalizeCellDependencies,\n resolveArtifactSchemaName,\n toDataSourceCell,\n toDataSourceTable,\n isDataSourceCell,\n isDataSourceTable,\n fromDataSourceCell,\n fromDataSourceTable,\n} from './helpers';\nexport {useCellsStore} from './hooks';\nexport {\n findSqlDependencies,\n findSqlDependenciesFromAst,\n renderSqlWithInputs,\n runSqlWithCallbacks,\n} from './sqlHelpers';\nexport * from './types';\n\nexport const SqlCell = {\n RunButton: SqlCellRunButtonComponent,\n Content: SqlCellContentComponent,\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sqlrooms/cells",
|
|
3
|
-
"version": "0.29.0-rc.
|
|
3
|
+
"version": "0.29.0-rc.5",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/sqlrooms/sqlrooms.git"
|
|
7
|
+
},
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"author": "SQLRooms Contributors",
|
|
10
|
+
"sideEffects": false,
|
|
4
11
|
"type": "module",
|
|
5
12
|
"main": "dist/index.js",
|
|
6
13
|
"module": "dist/index.js",
|
|
@@ -8,32 +15,25 @@
|
|
|
8
15
|
"files": [
|
|
9
16
|
"dist"
|
|
10
17
|
],
|
|
11
|
-
"author": "SQLRooms Contributors",
|
|
12
|
-
"license": "MIT",
|
|
13
|
-
"repository": {
|
|
14
|
-
"type": "git",
|
|
15
|
-
"url": "git+https://github.com/sqlrooms/sqlrooms.git"
|
|
16
|
-
},
|
|
17
|
-
"sideEffects": false,
|
|
18
18
|
"scripts": {
|
|
19
|
-
"dev": "tsc -w",
|
|
20
19
|
"build": "tsc",
|
|
20
|
+
"dev": "tsc -w",
|
|
21
|
+
"lint": "eslint .",
|
|
21
22
|
"test": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest",
|
|
22
23
|
"test:watch": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest --watch",
|
|
23
|
-
"lint": "eslint .",
|
|
24
24
|
"typecheck": "tsc --noEmit",
|
|
25
25
|
"typedoc": "typedoc"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@paralleldrive/cuid2": "^2.2.2",
|
|
29
|
-
"@sqlrooms/data-table": "0.29.0-rc.
|
|
30
|
-
"@sqlrooms/db": "0.29.0-rc.
|
|
31
|
-
"@sqlrooms/duckdb": "0.29.0-rc.
|
|
32
|
-
"@sqlrooms/room-store": "0.29.0-rc.
|
|
33
|
-
"@sqlrooms/sql-editor": "0.29.0-rc.
|
|
34
|
-
"@sqlrooms/ui": "0.29.0-rc.
|
|
35
|
-
"@sqlrooms/utils": "0.29.0-rc.
|
|
36
|
-
"@sqlrooms/vega": "0.29.0-rc.
|
|
29
|
+
"@sqlrooms/data-table": "0.29.0-rc.5",
|
|
30
|
+
"@sqlrooms/db": "0.29.0-rc.5",
|
|
31
|
+
"@sqlrooms/duckdb": "0.29.0-rc.5",
|
|
32
|
+
"@sqlrooms/room-store": "0.29.0-rc.5",
|
|
33
|
+
"@sqlrooms/sql-editor": "0.29.0-rc.5",
|
|
34
|
+
"@sqlrooms/ui": "0.29.0-rc.5",
|
|
35
|
+
"@sqlrooms/utils": "0.29.0-rc.5",
|
|
36
|
+
"@sqlrooms/vega": "0.29.0-rc.5",
|
|
37
37
|
"@tanstack/react-table": "^8.21.3",
|
|
38
38
|
"apache-arrow": "17.0.0",
|
|
39
39
|
"immer": "^11.0.1",
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"react": "^18 || ^19",
|
|
53
53
|
"react-dom": "^18 || ^19"
|
|
54
54
|
},
|
|
55
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "2763a4d37b79117916c988a8350f87dc926b33d5"
|
|
56
56
|
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import type { BrushFieldType } from '../types';
|
|
3
|
-
type SelectionListenerProps = {
|
|
4
|
-
cellId: string;
|
|
5
|
-
sqlId: string;
|
|
6
|
-
brushField: string;
|
|
7
|
-
brushFieldType?: BrushFieldType;
|
|
8
|
-
};
|
|
9
|
-
/**
|
|
10
|
-
* Attaches a debounced Vega signal listener for the brush param
|
|
11
|
-
* and reports selection changes to the cross-filter state.
|
|
12
|
-
*/
|
|
13
|
-
export declare const SelectionListener: React.FC<SelectionListenerProps>;
|
|
14
|
-
export {};
|
|
15
|
-
//# sourceMappingURL=SelectionListener.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SelectionListener.d.ts","sourceRoot":"","sources":["../../src/components/SelectionListener.tsx"],"names":[],"mappings":"AACA,OAAO,KAA0B,MAAM,OAAO,CAAC;AAE/C,OAAO,KAAK,EAAC,cAAc,EAAuB,MAAM,UAAU,CAAC;AAGnE,KAAK,sBAAsB,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CAAC,sBAAsB,CA8E9D,CAAC"}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { useVegaChartContext } from '@sqlrooms/vega';
|
|
2
|
-
import { useEffect, useRef } from 'react';
|
|
3
|
-
import { useCellsStore } from '../hooks';
|
|
4
|
-
import { BRUSH_PARAM_NAME } from '../vegaSelectionUtils';
|
|
5
|
-
/**
|
|
6
|
-
* Attaches a debounced Vega signal listener for the brush param
|
|
7
|
-
* and reports selection changes to the cross-filter state.
|
|
8
|
-
*/
|
|
9
|
-
export const SelectionListener = ({ cellId, sqlId, brushField, brushFieldType, }) => {
|
|
10
|
-
const { embed } = useVegaChartContext();
|
|
11
|
-
const setCrossFilterSelection = useCellsStore((s) => s.cells.setCrossFilterSelection);
|
|
12
|
-
const timerRef = useRef(null);
|
|
13
|
-
useEffect(() => {
|
|
14
|
-
if (!embed?.view) {
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
const handler = (_name, value) => {
|
|
18
|
-
if (timerRef.current) {
|
|
19
|
-
clearTimeout(timerRef.current);
|
|
20
|
-
}
|
|
21
|
-
timerRef.current = setTimeout(() => {
|
|
22
|
-
if (!value || Object.keys(value).length === 0) {
|
|
23
|
-
setCrossFilterSelection(cellId, sqlId, null);
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
const fieldValue = value.x ?? value[brushField];
|
|
27
|
-
if (Array.isArray(fieldValue) && fieldValue.length === 2) {
|
|
28
|
-
const selection = {
|
|
29
|
-
field: brushField,
|
|
30
|
-
fieldType: brushFieldType,
|
|
31
|
-
type: 'interval',
|
|
32
|
-
value: fieldValue,
|
|
33
|
-
};
|
|
34
|
-
setCrossFilterSelection(cellId, sqlId, selection);
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
setCrossFilterSelection(cellId, sqlId, null);
|
|
38
|
-
}
|
|
39
|
-
}, 200);
|
|
40
|
-
};
|
|
41
|
-
try {
|
|
42
|
-
embed.view.addSignalListener(BRUSH_PARAM_NAME, handler);
|
|
43
|
-
}
|
|
44
|
-
catch (error) {
|
|
45
|
-
// Signal doesn't exist yet (view is still rendering a spec without the brush param).
|
|
46
|
-
// Will retry when embed reference changes after the new spec is compiled.
|
|
47
|
-
console.warn('Failed to add signal listener:', error);
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
return () => {
|
|
51
|
-
if (timerRef.current) {
|
|
52
|
-
clearTimeout(timerRef.current);
|
|
53
|
-
}
|
|
54
|
-
try {
|
|
55
|
-
embed.view.removeSignalListener(BRUSH_PARAM_NAME, handler);
|
|
56
|
-
}
|
|
57
|
-
catch (error) {
|
|
58
|
-
// View may have been finalized
|
|
59
|
-
console.warn('Failed to remove signal listener:', error);
|
|
60
|
-
}
|
|
61
|
-
// Clear this chart's selection from crossFilterSelections
|
|
62
|
-
setCrossFilterSelection(cellId, sqlId, null);
|
|
63
|
-
};
|
|
64
|
-
}, [
|
|
65
|
-
embed,
|
|
66
|
-
cellId,
|
|
67
|
-
sqlId,
|
|
68
|
-
brushField,
|
|
69
|
-
brushFieldType,
|
|
70
|
-
setCrossFilterSelection,
|
|
71
|
-
]);
|
|
72
|
-
return null;
|
|
73
|
-
};
|
|
74
|
-
//# sourceMappingURL=SelectionListener.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SelectionListener.js","sourceRoot":"","sources":["../../src/components/SelectionListener.tsx"],"names":[],"mappings":"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","sourcesContent":["import {SignalListenerHandler, useVegaChartContext} from '@sqlrooms/vega';\nimport React, {useEffect, useRef} from 'react';\nimport {useCellsStore} from '../hooks';\nimport type {BrushFieldType, CrossFilterSelection} from '../types';\nimport {BRUSH_PARAM_NAME} from '../vegaSelectionUtils';\n\ntype SelectionListenerProps = {\n cellId: string;\n sqlId: string;\n brushField: string;\n brushFieldType?: BrushFieldType;\n};\n\n/**\n * Attaches a debounced Vega signal listener for the brush param\n * and reports selection changes to the cross-filter state.\n */\nexport const SelectionListener: React.FC<SelectionListenerProps> = ({\n cellId,\n sqlId,\n brushField,\n brushFieldType,\n}) => {\n const {embed} = useVegaChartContext();\n const setCrossFilterSelection = useCellsStore(\n (s) => s.cells.setCrossFilterSelection,\n );\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n if (!embed?.view) {\n return;\n }\n\n const handler: SignalListenerHandler = (_name, value) => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n\n timerRef.current = setTimeout(() => {\n if (!value || Object.keys(value).length === 0) {\n setCrossFilterSelection(cellId, sqlId, null);\n return;\n }\n\n const fieldValue = value.x ?? value[brushField];\n\n if (Array.isArray(fieldValue) && fieldValue.length === 2) {\n const selection: CrossFilterSelection = {\n field: brushField,\n fieldType: brushFieldType,\n type: 'interval',\n value: fieldValue,\n };\n setCrossFilterSelection(cellId, sqlId, selection);\n } else {\n setCrossFilterSelection(cellId, sqlId, null);\n }\n }, 200);\n };\n\n try {\n embed.view.addSignalListener(BRUSH_PARAM_NAME, handler);\n } catch (error) {\n // Signal doesn't exist yet (view is still rendering a spec without the brush param).\n // Will retry when embed reference changes after the new spec is compiled.\n console.warn('Failed to add signal listener:', error);\n return;\n }\n\n return () => {\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n }\n\n try {\n embed.view.removeSignalListener(BRUSH_PARAM_NAME, handler);\n } catch (error) {\n // View may have been finalized\n console.warn('Failed to remove signal listener:', error);\n }\n\n // Clear this chart's selection from crossFilterSelections\n setCrossFilterSelection(cellId, sqlId, null);\n };\n }, [\n embed,\n cellId,\n sqlId,\n brushField,\n brushFieldType,\n setCrossFilterSelection,\n ]);\n\n return null;\n};\n"]}
|