mirror of https://github.com/buster-so/buster.git
Add a chart playground
This commit is contained in:
parent
cff68bd6ff
commit
6cfc2ec655
|
@ -0,0 +1,240 @@
|
|||
'use client';
|
||||
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { AppCodeEditor } from '@/components/ui/inputs/AppCodeEditor';
|
||||
import { yamlToJson } from '@/lib/yaml-to-json';
|
||||
import { useRunSQL } from '@/api/buster_rest/sql/queryRequests';
|
||||
import { BusterChart } from '@/components/ui/charts/BusterChart';
|
||||
import {
|
||||
ChartConfigPropsSchema,
|
||||
type ChartConfigProps,
|
||||
type DataResult
|
||||
} from '@buster/server-shared/metrics';
|
||||
import type { ZodError } from 'zod';
|
||||
import type { RunSQLResponse } from '@/api/asset_interfaces';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { Input } from '@/components/ui/inputs';
|
||||
|
||||
type YamlifiedConfig = {
|
||||
sql: string;
|
||||
chartConfig: ChartConfigProps;
|
||||
};
|
||||
|
||||
const initfile = `name: Top 10 Customers by Lifetime Value\ndescription: Shows the customers who have generated the highest total revenue over their entire relationship with the company\ntimeFrame: All time\nsql: \"SELECT \\n CONCAT(p.firstname, ' ', p.lastname) AS customer_name,\\n clv.metric_clv_all_time::numeric AS lifetime_value\\nFROM postgres.ont_ont.customer_all_time_clv clv\\nJOIN postgres.ont_ont.customer c ON clv.customerid = c.customerid\\nLEFT JOIN postgres.ont_ont.person p ON c.personid = p.businessentityid\\nWHERE p.firstname IS NOT NULL AND p.lastname IS NOT NULL\\nORDER BY clv.metric_clv_all_time::numeric DESC\\nLIMIT 10\\n\"\nchartConfig:\n selectedChartType: bar\n columnLabelFormats:\n customer_name:\n columnType: string\n style: string\n numberSeparatorStyle: null\n replaceMissingDataWith: null\n lifetime_value:\n columnType: number\n style: currency\n numberSeparatorStyle: ','\n minimumFractionDigits: 2\n maximumFractionDigits: 2\n replaceMissingDataWith: 0\n currency: USD\n barAndLineAxis:\n x:\n - customer_name\n y:\n - lifetime_value\n barLayout: horizontal\n`;
|
||||
const initDataSourceId = 'cc3ef3bc-44ec-4a43-8dc4-681cae5c996a';
|
||||
|
||||
export default function ChartPlayground() {
|
||||
// State management
|
||||
const [config, setConfig] = useState<string>(initfile);
|
||||
const [dataResponse, setDataResponse] = useState<RunSQLResponse | null>(null);
|
||||
const [dataSourceId, setDataSourceId] = useState<string>(initDataSourceId);
|
||||
|
||||
// SQL mutation hook
|
||||
const {
|
||||
mutateAsync: runSQLMutation,
|
||||
error: runSQLError,
|
||||
isPending: isRunningSQL,
|
||||
isSuccess: hasRunSQL,
|
||||
reset: resetRunSQL
|
||||
} = useRunSQL();
|
||||
|
||||
// Parse YAML config
|
||||
const yamlifiedConfig = useMemo(() => {
|
||||
if (!config.trim()) return null;
|
||||
try {
|
||||
return yamlToJson<YamlifiedConfig>(config);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}, [config]);
|
||||
|
||||
// Parse and validate chart configuration
|
||||
const chartConfigParsed = useMemo(() => {
|
||||
if (!yamlifiedConfig?.chartConfig) {
|
||||
return { data: null, error: null };
|
||||
}
|
||||
|
||||
const parsed = ChartConfigPropsSchema.safeParse(yamlifiedConfig.chartConfig);
|
||||
return {
|
||||
data: parsed.success ? parsed.data : null,
|
||||
error: parsed.success ? null : (parsed.error as ZodError)
|
||||
};
|
||||
}, [yamlifiedConfig]);
|
||||
|
||||
// Derived values
|
||||
const chartConfig = chartConfigParsed.data;
|
||||
const chartConfigError = chartConfigParsed.error;
|
||||
const data: DataResult = dataResponse?.data || [];
|
||||
const columnMetadata = dataResponse?.data_metadata?.column_metadata || [];
|
||||
const hasSQL = !!yamlifiedConfig?.sql;
|
||||
const hasDataSourceId = !!dataSourceId.trim();
|
||||
|
||||
// SQL execution handler
|
||||
const runSQL = useMemoizedFn(async () => {
|
||||
if (!yamlifiedConfig?.sql || !hasDataSourceId) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await runSQLMutation({
|
||||
sql: yamlifiedConfig.sql,
|
||||
data_source_id: dataSourceId
|
||||
});
|
||||
setDataResponse(res);
|
||||
} catch (error) {
|
||||
// Error is handled by the hook
|
||||
}
|
||||
});
|
||||
|
||||
// Status checks
|
||||
const isReadyToRun = hasSQL && hasDataSourceId;
|
||||
const isReadyToChart = chartConfig && data.length > 0 && hasRunSQL;
|
||||
|
||||
// Setup hotkey for running SQL (meta+enter)
|
||||
useHotkeys(
|
||||
'meta+enter',
|
||||
(event) => {
|
||||
event.preventDefault();
|
||||
if (isReadyToRun && !isRunningSQL) {
|
||||
runSQL();
|
||||
}
|
||||
},
|
||||
{
|
||||
enabled: isReadyToRun && !isRunningSQL,
|
||||
enableOnContentEditable: true,
|
||||
enableOnFormTags: true
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="grid h-screen grid-cols-[2fr_3fr] gap-4 p-4">
|
||||
<div className="bg-background flex h-full w-full flex-col space-y-4 overflow-hidden rounded-lg border p-4">
|
||||
<div className="h-full w-full overflow-hidden">
|
||||
<AppCodeEditor value={config} onChange={setConfig} />
|
||||
</div>
|
||||
<div className="flex flex-col space-y-2">
|
||||
<div className="flex items-center space-x-1">
|
||||
<label className="w-fit min-w-28 text-sm font-medium">Data Source ID</label>
|
||||
<Input value={dataSourceId || ''} onChange={(e) => setDataSourceId(e.target.value)} />
|
||||
</div>
|
||||
<Button block onClick={runSQL} loading={isRunningSQL} disabled={!hasSQL}>
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<span>Run SQL</span>
|
||||
<span className="rounded bg-black/10 px-1.5 py-0.5 text-xs opacity-70">⌘↵</span>
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Second column - 40% width */}
|
||||
<div className="bg-background flex h-full flex-col overflow-hidden rounded-lg border shadow-sm">
|
||||
{/* Header */}
|
||||
<div className="bg-muted/30 border-b px-6 py-4">
|
||||
<h3 className="text-foreground text-lg font-semibold">Chart Preview</h3>
|
||||
</div>
|
||||
|
||||
{/* Content Area */}
|
||||
<div className="flex-1 space-y-6 overflow-y-auto p-6">
|
||||
{/* Error States */}
|
||||
{chartConfigError && (
|
||||
<div className="rounded-md border border-red-200 bg-red-50 p-4">
|
||||
<div className="mb-3 flex items-center space-x-2">
|
||||
<div className="h-4 w-4 flex-shrink-0 rounded-full bg-red-400"></div>
|
||||
<h4 className="text-sm font-semibold text-red-800">Chart Configuration Error</h4>
|
||||
</div>
|
||||
<pre className="overflow-x-auto rounded bg-red-100 p-3 text-xs whitespace-pre-wrap text-red-700">
|
||||
{JSON.stringify(chartConfigError as Object, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{runSQLError && (
|
||||
<div className="rounded-md border border-red-200 bg-red-50 p-4">
|
||||
<div className="mb-3 flex items-center space-x-2">
|
||||
<div className="h-4 w-4 flex-shrink-0 rounded-full bg-red-400"></div>
|
||||
<h4 className="text-sm font-semibold text-red-800">SQL Execution Error</h4>
|
||||
</div>
|
||||
<pre className="overflow-x-auto rounded bg-red-100 p-3 text-xs whitespace-pre-wrap text-red-700">
|
||||
{JSON.stringify(runSQLError as Object, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Loading State */}
|
||||
{isRunningSQL && (
|
||||
<div className="rounded-md border border-blue-200 bg-blue-50 p-4">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="h-5 w-5 flex-shrink-0 animate-spin rounded-full border-2 border-blue-400 border-t-transparent"></div>
|
||||
<div>
|
||||
<h4 className="text-sm font-semibold text-blue-800">Executing SQL Query</h4>
|
||||
<p className="mt-1 text-xs text-blue-600">
|
||||
Please wait while we process your query...
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Checklist */}
|
||||
{!(chartConfig && data && hasRunSQL && dataSourceId) && (
|
||||
<div className="rounded-md border border-amber-200 bg-amber-50 p-4">
|
||||
<div className="mb-4 flex items-center space-x-2">
|
||||
<div className="h-4 w-4 flex-shrink-0 rounded-full bg-amber-400"></div>
|
||||
<h4 className="text-sm font-semibold text-amber-800">Setup Checklist</h4>
|
||||
</div>
|
||||
<ul className="space-y-2">
|
||||
<li className="flex items-center space-x-3">
|
||||
<div
|
||||
className={`h-2 w-2 flex-shrink-0 rounded-full ${chartConfig ? 'bg-green-400' : 'bg-yellow-300'}`}></div>
|
||||
<span
|
||||
className={`text-sm ${chartConfig ? 'text-green-700 line-through' : 'text-amber-700'}`}>
|
||||
Chart configuration is {chartConfig ? 'ready' : 'missing'}
|
||||
</span>
|
||||
</li>
|
||||
<li className="flex items-center space-x-3">
|
||||
<div
|
||||
className={`h-2 w-2 flex-shrink-0 rounded-full ${data.length > 0 ? 'bg-green-400' : 'bg-yellow-300'}`}></div>
|
||||
<span
|
||||
className={`text-sm ${data.length > 0 ? 'text-green-700 line-through' : 'text-amber-700'}`}>
|
||||
Data is {data.length > 0 ? 'available' : 'not available'}
|
||||
</span>
|
||||
</li>
|
||||
<li className="flex items-center space-x-3">
|
||||
<div
|
||||
className={`h-2 w-2 flex-shrink-0 rounded-full ${hasRunSQL ? 'bg-green-400' : 'bg-yellow-300'}`}></div>
|
||||
<span
|
||||
className={`text-sm ${hasRunSQL ? 'text-green-700 line-through' : 'text-amber-700'}`}>
|
||||
SQL has {hasRunSQL ? 'been executed' : 'not been run'}
|
||||
</span>
|
||||
</li>
|
||||
<li className="flex items-center space-x-3">
|
||||
<div
|
||||
className={`h-2 w-2 flex-shrink-0 rounded-full ${dataSourceId ? 'bg-green-400' : 'bg-yellow-300'}`}></div>
|
||||
<span
|
||||
className={`text-sm ${dataSourceId ? 'text-green-700 line-through' : 'text-amber-700'}`}>
|
||||
Data Source ID is {dataSourceId ? 'set' : 'not set'}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Chart Display */}
|
||||
{chartConfig && data && hasRunSQL && dataSourceId && (
|
||||
<div className="rounded-md border bg-gradient-to-br from-green-50 to-blue-50 p-6">
|
||||
<div className="mb-4 flex items-center space-x-2">
|
||||
<div className="h-3 w-3 flex-shrink-0 animate-pulse rounded-full bg-green-500"></div>
|
||||
<h4 className="text-sm font-semibold text-green-800">Chart Ready</h4>
|
||||
</div>
|
||||
<div className="rounded-lg bg-white p-4 shadow-sm">
|
||||
<BusterChart {...chartConfig} data={data} columnMetadata={columnMetadata} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -486,8 +486,8 @@ importers:
|
|||
specifier: ^49.0.15
|
||||
version: 49.0.15(@types/react@18.3.23)(class-variance-authority@0.7.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(tailwind-merge@3.3.1)
|
||||
'@uploadthing/react':
|
||||
specifier: ^7.3.1
|
||||
version: 7.3.1(next@14.2.30(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.2))(react@18.3.1)(uploadthing@7.7.2(express@4.21.2)(next@14.2.30(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.2))(tailwindcss@4.1.11))
|
||||
specifier: ^7.3.2
|
||||
version: 7.3.2(next@14.2.30(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.2))(react@18.3.1)(uploadthing@7.7.2(express@4.21.2)(next@14.2.30(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.2))(tailwindcss@4.1.11))
|
||||
ai:
|
||||
specifier: ^4.3.19
|
||||
version: 4.3.19(react@18.3.1)(zod@3.25.1)
|
||||
|
@ -534,8 +534,8 @@ importers:
|
|||
specifier: ^11.1.0
|
||||
version: 11.1.0
|
||||
framer-motion:
|
||||
specifier: ^12.23.11
|
||||
version: 12.23.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
specifier: ^12.23.12
|
||||
version: 12.23.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
hono:
|
||||
specifier: 'catalog:'
|
||||
version: 4.8.4
|
||||
|
@ -591,8 +591,8 @@ importers:
|
|||
specifier: ^8.0.0
|
||||
version: 8.0.0
|
||||
posthog-js:
|
||||
specifier: ^1.258.2
|
||||
version: 1.258.2
|
||||
specifier: ^1.258.3
|
||||
version: 1.258.3
|
||||
react:
|
||||
specifier: ^18.3.1
|
||||
version: 18.3.1
|
||||
|
@ -6136,8 +6136,8 @@ packages:
|
|||
'@uploadthing/mime-types@0.3.5':
|
||||
resolution: {integrity: sha512-iYOmod80XXOSe4NVvaUG9FsS91YGPUaJMTBj52Nwu0G2aTzEN6Xcl0mG1rWqXJ4NUH8MzjVqg+tQND5TPkJWhg==}
|
||||
|
||||
'@uploadthing/react@7.3.1':
|
||||
resolution: {integrity: sha512-yIAFw46ZO/NPb74zpomwn6Hf2ZX/Ws+vNlR4oKNLJ7YtJ+/bqERclzC3xnRVi/pT47ctISlqXQFGiXUn85wg5Q==}
|
||||
'@uploadthing/react@7.3.2':
|
||||
resolution: {integrity: sha512-dssVzrxGBKBHUzJu/CiEGc3hQ49U4sPdnqN5xMmtEdnJP+6OB+a8JUjkwxiJDBQXc3ft9XCmkLCZZoUt1EQSIw==}
|
||||
peerDependencies:
|
||||
next: '*'
|
||||
react: ^17.0.2 || ^18.0.0 || ^19.0.0
|
||||
|
@ -6149,6 +6149,9 @@ packages:
|
|||
'@uploadthing/shared@7.1.8':
|
||||
resolution: {integrity: sha512-OA9ZrTfILOCt1G93wOD7dZmS653z99Nr3isZpIxzBO3y4B2geKFmPjJUZClig2RrAWLKr2VUYToXKfd9D/wP9w==}
|
||||
|
||||
'@uploadthing/shared@7.1.9':
|
||||
resolution: {integrity: sha512-5Gn1wGVSygsBxI6tjOwwEQt/U4m+vbmZCnsuf8pDfZ+MiXe3el03CWMmpbH3KtSu0BwG48wyCKNfHplZsphvOA==}
|
||||
|
||||
'@vercel/edge@1.2.2':
|
||||
resolution: {integrity: sha512-1+y+f6rk0Yc9ss9bRDgz/gdpLimwoRteKHhrcgHvEpjbP1nyT3ByqEMWm2BTcpIO5UtDmIFXc8zdq4LR190PDA==}
|
||||
|
||||
|
@ -8261,8 +8264,8 @@ packages:
|
|||
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
|
||||
engines: {node: '>= 0.6'}
|
||||
|
||||
framer-motion@12.23.11:
|
||||
resolution: {integrity: sha512-VzNi+exyI3bn7Pzvz1Fjap1VO9gQu8mxrsSsNamMidsZ8AA8W2kQsR+YQOciEUbMtkKAWIbPHPttfn5e9jqqJQ==}
|
||||
framer-motion@12.23.12:
|
||||
resolution: {integrity: sha512-6e78rdVtnBvlEVgu6eFEAgG9v3wLnYEboM8I5O5EXvfKC8gxGQB8wXJdhkMy10iVcn05jl6CNw7/HTsTCfwcWg==}
|
||||
peerDependencies:
|
||||
'@emotion/is-prop-valid': '*'
|
||||
react: ^18.0.0 || ^19.0.0
|
||||
|
@ -9849,8 +9852,8 @@ packages:
|
|||
peerDependencies:
|
||||
monaco-editor: '>=0.36'
|
||||
|
||||
motion-dom@12.23.9:
|
||||
resolution: {integrity: sha512-6Sv++iWS8XMFCgU1qwKj9l4xuC47Hp4+2jvPfyTXkqDg2tTzSgX6nWKD4kNFXk0k7llO59LZTPuJigza4A2K1A==}
|
||||
motion-dom@12.23.12:
|
||||
resolution: {integrity: sha512-RcR4fvMCTESQBD/uKQe49D5RUeDOokkGRmz4ceaJKDBgHYtZtntC/s2vLvY38gqGaytinij/yi3hMcWVcEF5Kw==}
|
||||
|
||||
motion-utils@12.23.6:
|
||||
resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==}
|
||||
|
@ -10536,8 +10539,8 @@ packages:
|
|||
resolution: {integrity: sha512-Jtc2612XINuBjIl/QTWsV5UvE8UHuNblcO3vVADSrKsrc6RqGX6lOW1cEo3CM2v0XG4Nat8nI+YM7/f26VxXLw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
posthog-js@1.258.2:
|
||||
resolution: {integrity: sha512-XBSeiN4HjiYsy3tW5zss8WOJF2JXTQXAYw2wZ+zjqQuzzi7kkLEXjIgsVrBnt5Opwhqn0krZVsb0ZBw34dIiyQ==}
|
||||
posthog-js@1.258.3:
|
||||
resolution: {integrity: sha512-bX4Ehzo/yBGY7o23CUAQelX+oUdLn5bKhEjTSiveXsjkZhRURxfKDinYTwI6tjs19FC8BWfHFyO3q3TgT2E7CA==}
|
||||
peerDependencies:
|
||||
'@rrweb/types': 2.0.0-alpha.17
|
||||
rrweb-snapshot: 2.0.0-alpha.17
|
||||
|
@ -19170,9 +19173,9 @@ snapshots:
|
|||
|
||||
'@uploadthing/mime-types@0.3.5': {}
|
||||
|
||||
'@uploadthing/react@7.3.1(next@14.2.30(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.2))(react@18.3.1)(uploadthing@7.7.2(express@4.21.2)(next@14.2.30(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.2))(tailwindcss@4.1.11))':
|
||||
'@uploadthing/react@7.3.2(next@14.2.30(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.2))(react@18.3.1)(uploadthing@7.7.2(express@4.21.2)(next@14.2.30(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.2))(tailwindcss@4.1.11))':
|
||||
dependencies:
|
||||
'@uploadthing/shared': 7.1.8
|
||||
'@uploadthing/shared': 7.1.9
|
||||
file-selector: 0.6.0
|
||||
react: 18.3.1
|
||||
uploadthing: 7.7.2(express@4.21.2)(next@14.2.30(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.54.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.89.2))(tailwindcss@4.1.11)
|
||||
|
@ -19185,6 +19188,12 @@ snapshots:
|
|||
effect: 3.14.21
|
||||
sqids: 0.3.0
|
||||
|
||||
'@uploadthing/shared@7.1.9':
|
||||
dependencies:
|
||||
'@uploadthing/mime-types': 0.3.5
|
||||
effect: 3.16.8
|
||||
sqids: 0.3.0
|
||||
|
||||
'@vercel/edge@1.2.2': {}
|
||||
|
||||
'@vercel/functions@1.6.0(@aws-sdk/credential-provider-web-identity@3.840.0)':
|
||||
|
@ -20879,7 +20888,6 @@ snapshots:
|
|||
dependencies:
|
||||
'@standard-schema/spec': 1.0.0
|
||||
fast-check: 3.23.2
|
||||
optional: true
|
||||
|
||||
electron-to-chromium@1.5.179: {}
|
||||
|
||||
|
@ -21701,9 +21709,9 @@ snapshots:
|
|||
|
||||
forwarded@0.2.0: {}
|
||||
|
||||
framer-motion@12.23.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
framer-motion@12.23.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
dependencies:
|
||||
motion-dom: 12.23.9
|
||||
motion-dom: 12.23.12
|
||||
motion-utils: 12.23.6
|
||||
tslib: 2.8.1
|
||||
optionalDependencies:
|
||||
|
@ -23615,7 +23623,7 @@ snapshots:
|
|||
vscode-uri: 3.1.0
|
||||
yaml: 2.8.0
|
||||
|
||||
motion-dom@12.23.9:
|
||||
motion-dom@12.23.12:
|
||||
dependencies:
|
||||
motion-utils: 12.23.6
|
||||
|
||||
|
@ -24431,7 +24439,7 @@ snapshots:
|
|||
|
||||
postgres@3.4.7: {}
|
||||
|
||||
posthog-js@1.258.2:
|
||||
posthog-js@1.258.3:
|
||||
dependencies:
|
||||
core-js: 3.44.0
|
||||
fflate: 0.4.8
|
||||
|
|
Loading…
Reference in New Issue