mirror of https://github.com/buster-so/buster.git
added some additional packages for reports
This commit is contained in:
parent
f7a8572a8e
commit
27bdd9bbe4
|
@ -38,6 +38,10 @@
|
|||
"@faker-js/faker": "^10.0.0",
|
||||
"@modelcontextprotocol/sdk": "^1.17.4",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@platejs/dnd": "^49.2.10",
|
||||
"@platejs/resizable": "^49.0.0",
|
||||
"@platejs/selection": "^49.2.4",
|
||||
"@platejs/table": "catalog:",
|
||||
"@radix-ui/react-avatar": "^1.1.10",
|
||||
"@radix-ui/react-checkbox": "^1.3.3",
|
||||
"@radix-ui/react-collapsible": "^1.1.12",
|
||||
|
@ -53,6 +57,7 @@
|
|||
"@radix-ui/react-slot": "^1.2.3",
|
||||
"@radix-ui/react-switch": "^1.2.6",
|
||||
"@radix-ui/react-tabs": "^1.1.13",
|
||||
"@radix-ui/react-toolbar": "^1.1.10",
|
||||
"@radix-ui/react-tooltip": "^1.2.8",
|
||||
"@radix-ui/react-visually-hidden": "^1.2.3",
|
||||
"@shikijs/langs": "^3.12.1",
|
||||
|
|
|
@ -140,9 +140,11 @@ export const useGetMetricData = <TData = BusterMetricDataExtended>(
|
|||
{
|
||||
id = '',
|
||||
versionNumber: versionNumberProp,
|
||||
reportFileId,
|
||||
}: {
|
||||
id: string | undefined;
|
||||
versionNumber?: number | 'LATEST';
|
||||
reportFileId?: string;
|
||||
},
|
||||
params?: Omit<UseQueryOptions<BusterMetricData, RustApiError, TData>, 'queryKey' | 'queryFn'>
|
||||
) => {
|
||||
|
@ -167,6 +169,7 @@ export const useGetMetricData = <TData = BusterMetricDataExtended>(
|
|||
id,
|
||||
version_number: chosenVersionNumber || undefined,
|
||||
password,
|
||||
report_file_id: reportFileId,
|
||||
});
|
||||
const isLatest = versionNumberProp === 'LATEST' || !versionNumberProp;
|
||||
if (isLatest) {
|
||||
|
|
|
@ -39,11 +39,10 @@ export const getMetric = async ({
|
|||
|
||||
export const getMetricData = async ({
|
||||
id,
|
||||
version_number,
|
||||
password,
|
||||
...params
|
||||
}: GetMetricDataRequest): Promise<MetricDataResponse> => {
|
||||
return mainApi
|
||||
.get<MetricDataResponse>(`/metric_files/${id}/data`, { params: { password, version_number } })
|
||||
.get<MetricDataResponse>(`/metric_files/${id}/data`, { params })
|
||||
.then((res) => res.data);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import type { VerificationStatus } from '@buster/server-shared/share';
|
||||
import { Link, useNavigate } from '@tanstack/react-router';
|
||||
import { useNavigate } from '@tanstack/react-router';
|
||||
import React, { useMemo } from 'react';
|
||||
import {
|
||||
useAddMetricsToDashboard,
|
||||
|
@ -17,6 +17,8 @@ import { useSaveToCollectionsDropdownContent } from '@/components/features/dropd
|
|||
import { useSaveToDashboardDropdownContent } from '@/components/features/dropdowns/SaveToDashboardDropdown';
|
||||
import { StatusBadgeIndicator } from '@/components/features/metrics/StatusBadgeIndicator';
|
||||
import { useStatusDropdownContent } from '@/components/features/metrics/StatusBadgeIndicator/useStatusDropdownContent';
|
||||
import { useDownloadMetricDataCSV } from '@/components/features/metrics/useDownloadMetricDataCSV';
|
||||
import { useDownloadPNGSelectMenu } from '@/components/features/metrics/useDownloadMetricDataPNG';
|
||||
import { getShareAssetConfig } from '@/components/features/ShareMenu/helpers';
|
||||
import { ShareMenuContent } from '@/components/features/ShareMenu/ShareMenuContent';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
|
@ -38,8 +40,6 @@ import {
|
|||
} from '@/components/ui/icons';
|
||||
import { useBusterNotifications } from '@/context/BusterNotifications';
|
||||
import { useIsChatMode } from '@/context/Chats/useMode';
|
||||
import { useDownloadMetricDataCSV } from '@/context/Metrics/useDownloadMetricDataCSV';
|
||||
import { useDownloadPNGSelectMenu } from '@/context/Metrics/useDownloadMetricDataPNG';
|
||||
import { useMetricEditToggle } from '@/layouts/AssetContainer/MetricAssetContainer';
|
||||
import { canEdit, getIsEffectiveOwner, getIsOwner } from '@/lib/share';
|
||||
import { ASSET_ICONS } from '../icons/assetIcons';
|
||||
|
|
|
@ -1,19 +1,22 @@
|
|||
import { useNavigate } from '@tanstack/react-router';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { useGetMetric } from '@/api/buster_rest/metrics';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { useGetMetric, useGetMetricData } from '@/api/buster_rest/metrics';
|
||||
import {
|
||||
createDropdownItem,
|
||||
DropdownContent,
|
||||
type IDropdownItem,
|
||||
type IDropdownItems,
|
||||
} from '@/components/ui/dropdown';
|
||||
import { History, Pencil, Star, WandSparkle } from '@/components/ui/icons';
|
||||
import { Download4, History, Pencil, SquareChart, Star, WandSparkle } from '@/components/ui/icons';
|
||||
import { Star as StarFilled } from '@/components/ui/icons/NucleoIconFilled';
|
||||
import type { BusterMetric } from '../../../api/asset_interfaces/metric';
|
||||
import { useBusterNotifications } from '../../../context/BusterNotifications';
|
||||
import { ensureElementExists } from '../../../lib/element';
|
||||
import { downloadElementToImage } from '../../../lib/exportUtils';
|
||||
import { FollowUpWithAssetContent } from '../assets/FollowUpWithAsset';
|
||||
import { useFavoriteStar } from '../favorites';
|
||||
import { useListMetricVersionDropdownItems } from '../versionHistory/useListMetricVersionDropdownItems';
|
||||
import { METRIC_CHART_CONTAINER_ID } from './MetricChartCard/config';
|
||||
import { METRIC_CHART_TITLE_INPUT_ID } from './MetricChartCard/MetricViewChartHeader';
|
||||
|
||||
export const useMetricVersionHistorySelectMenu = ({
|
||||
|
@ -132,3 +135,81 @@ export const useRenameMetricOnPage = ({
|
|||
[navigate, metricId, metricVersionNumber]
|
||||
);
|
||||
};
|
||||
|
||||
export const useDownloadMetricDataCSV = ({
|
||||
metricId,
|
||||
metricVersionNumber,
|
||||
}: {
|
||||
metricId: string;
|
||||
metricVersionNumber: number | undefined;
|
||||
}) => {
|
||||
const [isDownloading, setIsDownloading] = useState(false);
|
||||
const { data: metricData } = useGetMetricData(
|
||||
{ id: metricId, versionNumber: metricVersionNumber },
|
||||
{ enabled: false }
|
||||
);
|
||||
const { data: name } = useGetMetric({ id: metricId }, { select: (x) => x.name });
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
label: 'Download as CSV',
|
||||
value: 'download-csv',
|
||||
icon: <Download4 />,
|
||||
loading: isDownloading,
|
||||
onClick: async () => {
|
||||
const data = metricData?.data;
|
||||
if (data && name) {
|
||||
setIsDownloading(true);
|
||||
const exportJSONToCSV = await import('@/lib/exportUtils').then(
|
||||
(mod) => mod.exportJSONToCSV
|
||||
);
|
||||
await exportJSONToCSV(data, name);
|
||||
setIsDownloading(false);
|
||||
}
|
||||
},
|
||||
}),
|
||||
[metricData, isDownloading, name]
|
||||
);
|
||||
};
|
||||
|
||||
export const useDownloadPNGSelectMenu = ({
|
||||
metricId,
|
||||
metricVersionNumber,
|
||||
}: {
|
||||
metricId: string;
|
||||
metricVersionNumber: number | undefined;
|
||||
}) => {
|
||||
const { openErrorMessage } = useBusterNotifications();
|
||||
const { data: name } = useGetMetric(
|
||||
{ id: metricId, versionNumber: metricVersionNumber },
|
||||
{ select: (x) => x.name }
|
||||
);
|
||||
const { data: selectedChartType } = useGetMetric(
|
||||
{ id: metricId },
|
||||
{ select: (x) => x.chart_config?.selectedChartType }
|
||||
);
|
||||
|
||||
const canDownload = selectedChartType && selectedChartType !== 'table';
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
label: 'Download as PNG',
|
||||
value: 'download-png',
|
||||
disabled: true,
|
||||
icon: <SquareChart />,
|
||||
onClick: async () => {
|
||||
const node = document.getElementById(METRIC_CHART_CONTAINER_ID(metricId)) as HTMLElement;
|
||||
if (node) {
|
||||
try {
|
||||
return await downloadElementToImage(node, `${name}.png`);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
openErrorMessage('Failed to download PNG');
|
||||
},
|
||||
}),
|
||||
[canDownload, metricId, name, openErrorMessage]
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,237 @@
|
|||
'use client';
|
||||
|
||||
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
||||
import type * as React from 'react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { THEME_RESET_STYLE } from '@/styles/theme-reset';
|
||||
import { Check3 as Check, ChevronRight } from '../icons/NucleoIconOutlined';
|
||||
import RadioUnchecked from '../icons/NucleoIconOutlined/radio-unchecked';
|
||||
|
||||
function DropdownMenu({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
|
||||
return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />;
|
||||
}
|
||||
|
||||
function DropdownMenuPortal({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
|
||||
return <DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />;
|
||||
}
|
||||
|
||||
function DropdownMenuTrigger({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {
|
||||
return <DropdownMenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...props} />;
|
||||
}
|
||||
|
||||
function DropdownMenuContent({
|
||||
className,
|
||||
sideOffset = 4,
|
||||
style,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.Portal>
|
||||
<DropdownMenuPrimitive.Content
|
||||
data-slot="dropdown-menu-content"
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md',
|
||||
className
|
||||
)}
|
||||
style={{ ...THEME_RESET_STYLE, ...style }}
|
||||
{...props}
|
||||
/>
|
||||
</DropdownMenuPrimitive.Portal>
|
||||
);
|
||||
}
|
||||
|
||||
function DropdownMenuGroup({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
|
||||
return <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />;
|
||||
}
|
||||
|
||||
function DropdownMenuItem({
|
||||
className,
|
||||
inset,
|
||||
variant = 'default',
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
|
||||
inset?: boolean;
|
||||
variant?: 'default' | 'destructive';
|
||||
}) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.Item
|
||||
data-slot="dropdown-menu-item"
|
||||
data-inset={inset}
|
||||
data-variant={variant}
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function DropdownMenuCheckboxItem({
|
||||
className,
|
||||
children,
|
||||
checked,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.CheckboxItem
|
||||
data-slot="dropdown-menu-checkbox-item"
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
checked={checked}
|
||||
{...props}
|
||||
>
|
||||
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
||||
<DropdownMenuPrimitive.ItemIndicator>
|
||||
<div className="text-icon-color size-4">
|
||||
<Check />
|
||||
</div>
|
||||
</DropdownMenuPrimitive.ItemIndicator>
|
||||
</span>
|
||||
{children}
|
||||
</DropdownMenuPrimitive.CheckboxItem>
|
||||
);
|
||||
}
|
||||
|
||||
function DropdownMenuRadioGroup({
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
|
||||
return <DropdownMenuPrimitive.RadioGroup data-slot="dropdown-menu-radio-group" {...props} />;
|
||||
}
|
||||
|
||||
function DropdownMenuRadioItem({
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.RadioItem
|
||||
data-slot="dropdown-menu-radio-item"
|
||||
className={cn(
|
||||
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
||||
<DropdownMenuPrimitive.ItemIndicator>
|
||||
<div className="text-icon-color size-4">
|
||||
<RadioUnchecked />
|
||||
</div>
|
||||
</DropdownMenuPrimitive.ItemIndicator>
|
||||
</span>
|
||||
{children}
|
||||
</DropdownMenuPrimitive.RadioItem>
|
||||
);
|
||||
}
|
||||
|
||||
function DropdownMenuLabel({
|
||||
className,
|
||||
inset,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
|
||||
inset?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.Label
|
||||
data-slot="dropdown-menu-label"
|
||||
data-inset={inset}
|
||||
className={cn('px-2 py-1.5 text-sm font-medium data-[inset]:pl-8', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function DropdownMenuSeparator({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.Separator
|
||||
data-slot="dropdown-menu-separator"
|
||||
className={cn('bg-border -mx-1 my-1 h-px', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {
|
||||
return (
|
||||
<span
|
||||
data-slot="dropdown-menu-shortcut"
|
||||
className={cn('text-muted-foreground ml-auto text-xs tracking-widest', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function DropdownMenuSub({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
|
||||
return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />;
|
||||
}
|
||||
|
||||
function DropdownMenuSubTrigger({
|
||||
className,
|
||||
inset,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
|
||||
inset?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.SubTrigger
|
||||
data-slot="dropdown-menu-sub-trigger"
|
||||
data-inset={inset}
|
||||
className={cn(
|
||||
'focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<div className="text-icon-color ml-auto size-4">
|
||||
<ChevronRight />
|
||||
</div>
|
||||
</DropdownMenuPrimitive.SubTrigger>
|
||||
);
|
||||
}
|
||||
|
||||
function DropdownMenuSubContent({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
|
||||
return (
|
||||
<DropdownMenuPrimitive.SubContent
|
||||
data-slot="dropdown-menu-sub-content"
|
||||
className={cn(
|
||||
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export {
|
||||
DropdownMenu,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuShortcut,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuSubContent,
|
||||
};
|
|
@ -0,0 +1 @@
|
|||
export * from './dropdown-menu';
|
|
@ -1,8 +1,6 @@
|
|||
import { getEquationHtml } from '@platejs/math';
|
||||
|
||||
import type { SlateElementProps, TEquationElement } from 'platejs';
|
||||
import { SlateElement } from 'platejs';
|
||||
import * as React from 'react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { NodeTypeIcons } from '../config/icons';
|
||||
|
||||
|
@ -86,6 +84,7 @@ export function InlineEquationElementStatic(props: SlateElementProps<TEquationEl
|
|||
props.element.texExpression.length === 0 && 'hidden',
|
||||
'font-mono leading-none'
|
||||
)}
|
||||
// biome-ignore lint/security/noDangerouslySetInnerHtml: no other option
|
||||
dangerouslySetInnerHTML={{ __html: html }}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import React, { useMemo, useRef } from 'react';
|
||||
import { useGetMetric, useGetMetricData } from '@/api/buster_rest/metrics';
|
||||
import { MetricCard } from '@/components/ui/metric';
|
||||
import React, { useRef } from 'react';
|
||||
import { MetricChartCard } from '@/components/features/metrics/MetricChartCard';
|
||||
import { useInViewport } from '@/hooks/useInViewport';
|
||||
import { useChatLayoutContextSelector } from '@/layouts/ChatLayout';
|
||||
import { assetParamsToRoute } from '@/lib/assets/assetParamsToRoute';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useGetChatId } from '../../../../../context/Chats/useGetChatId';
|
||||
import { useGetReportParams } from '../../../../../context/Reports/useGetReportParams';
|
||||
import { useMetricContentThreeDotMenuItems } from './useMetricContentThreeDotMenuItems';
|
||||
|
||||
export const MetricContent = React.memo(
|
||||
|
@ -13,7 +11,6 @@ export const MetricContent = React.memo(
|
|||
metricVersionNumber,
|
||||
isExportMode = false,
|
||||
readOnly = false,
|
||||
className,
|
||||
}: {
|
||||
metricId: string;
|
||||
metricVersionNumber: number | undefined;
|
||||
|
@ -21,52 +18,19 @@ export const MetricContent = React.memo(
|
|||
isExportMode?: boolean;
|
||||
className?: string;
|
||||
}) => {
|
||||
const chatId = useChatLayoutContextSelector((x) => x.chatId);
|
||||
const reportId = useChatLayoutContextSelector((x) => x.reportId) || '';
|
||||
const reportVersionNumber = useChatLayoutContextSelector((x) => x.reportVersionNumber);
|
||||
const chatId = useGetChatId();
|
||||
const { reportId, reportVersionNumber } = useGetReportParams();
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const hasBeenInViewport = useRef(false);
|
||||
|
||||
const [inViewport] = useInViewport(ref, {
|
||||
threshold: 0.33,
|
||||
threshold: 0.25,
|
||||
});
|
||||
if (inViewport && !hasBeenInViewport.current) {
|
||||
hasBeenInViewport.current = true;
|
||||
}
|
||||
const renderChart = inViewport || isExportMode || hasBeenInViewport.current;
|
||||
|
||||
const {
|
||||
data: metric,
|
||||
isFetched: isFetchedMetric,
|
||||
error: metricError,
|
||||
} = useGetMetric(
|
||||
{
|
||||
id: metricId,
|
||||
versionNumber: metricVersionNumber,
|
||||
},
|
||||
{ enabled: !!metricId }
|
||||
);
|
||||
const {
|
||||
data: metricData,
|
||||
isFetched: isFetchedMetricData,
|
||||
error: metricDataError,
|
||||
} = useGetMetricData({
|
||||
id: metricId,
|
||||
versionNumber: metricVersionNumber,
|
||||
reportFileId: reportId || undefined,
|
||||
});
|
||||
|
||||
const link = useMemo(() => {
|
||||
return assetParamsToRoute({
|
||||
type: 'metric',
|
||||
chatId,
|
||||
assetId: metricId,
|
||||
reportId,
|
||||
metricId,
|
||||
versionNumber: metricVersionNumber || undefined,
|
||||
});
|
||||
}, [chatId, reportId, metricId, metricVersionNumber]);
|
||||
|
||||
const threeDotMenuItems = useMetricContentThreeDotMenuItems({
|
||||
metricId,
|
||||
metricVersionNumber,
|
||||
|
@ -75,24 +39,13 @@ export const MetricContent = React.memo(
|
|||
chatId,
|
||||
});
|
||||
|
||||
const error: string | undefined =
|
||||
metric?.error || metricDataError?.message || metricError?.message || undefined;
|
||||
|
||||
return (
|
||||
<MetricCard
|
||||
className={cn('transition-all duration-100', className)}
|
||||
ref={ref}
|
||||
metricLink={link}
|
||||
animate={!isExportMode}
|
||||
<MetricChartCard
|
||||
metricId={metricId}
|
||||
readOnly={readOnly}
|
||||
isDragOverlay={false}
|
||||
metric={metric}
|
||||
metricData={metricData}
|
||||
renderChart={renderChart}
|
||||
loading={(!isFetchedMetric || !isFetchedMetricData) && !metricError}
|
||||
error={error}
|
||||
threeDotMenuItems={threeDotMenuItems}
|
||||
useHeaderLink={!readOnly}
|
||||
versionNumber={metricVersionNumber}
|
||||
readOnly
|
||||
headerSecondaryContent={!readOnly && <div>TODO: Three dot menu</div>}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
import type { TElement } from 'platejs';
|
||||
import { type PlateEditor, useEditorRef, useElement } from 'platejs/react';
|
||||
import React, { useMemo } from 'react';
|
||||
import type { DropdownItem, DropdownItems } from '@/components/ui/dropdown';
|
||||
import { ArrowUpRight, Code, SquareChartPen, Table, Trash } from '@/components/ui/icons';
|
||||
import {
|
||||
useDownloadMetricDataCSV,
|
||||
useDownloadPNGSelectMenu,
|
||||
useRenameMetricOnPage,
|
||||
} from '@/context/Metrics/metricDropdownItems';
|
||||
} from '@/components/features/metrics/threeDotMenuHooks';
|
||||
import {
|
||||
createDropdownItem,
|
||||
createDropdownItems,
|
||||
type IDropdownItem,
|
||||
type IDropdownItems,
|
||||
} from '@/components/ui/dropdown';
|
||||
import { ArrowUpRight, Code, SquareChartPen, Table, Trash } from '@/components/ui/icons';
|
||||
import { assetParamsToRoute } from '@/lib/assets/assetParamsToRoute';
|
||||
|
||||
export const useMetricContentThreeDotMenuItems = ({
|
||||
|
@ -22,7 +27,7 @@ export const useMetricContentThreeDotMenuItems = ({
|
|||
metricVersionNumber: number | undefined;
|
||||
reportVersionNumber: number | undefined;
|
||||
reportId: string;
|
||||
}): DropdownItems => {
|
||||
}): IDropdownItems => {
|
||||
const editor = useEditorRef();
|
||||
const element = useElement();
|
||||
|
||||
|
@ -72,10 +77,7 @@ export const useMetricContentThreeDotMenuItems = ({
|
|||
};
|
||||
|
||||
const useOpenChartItem = ({
|
||||
reportId,
|
||||
metricId,
|
||||
chatId,
|
||||
reportVersionNumber,
|
||||
metricVersionNumber,
|
||||
}: {
|
||||
reportId: string;
|
||||
|
@ -83,25 +85,25 @@ const useOpenChartItem = ({
|
|||
metricVersionNumber: number | undefined;
|
||||
chatId: string | undefined;
|
||||
reportVersionNumber: number | undefined;
|
||||
}): DropdownItem => {
|
||||
const route = assetParamsToRoute({
|
||||
assetId: metricId,
|
||||
type: 'metric',
|
||||
reportVersionNumber,
|
||||
metricVersionNumber,
|
||||
reportId,
|
||||
metricId,
|
||||
chatId,
|
||||
});
|
||||
}): IDropdownItem => {
|
||||
return useMemo(
|
||||
() => ({
|
||||
value: 'open-chart',
|
||||
label: 'Open chart',
|
||||
icon: <ArrowUpRight />,
|
||||
link: route,
|
||||
linkIcon: 'arrow-right',
|
||||
}),
|
||||
[route]
|
||||
() =>
|
||||
createDropdownItem({
|
||||
value: 'open-chart',
|
||||
label: 'Open chart',
|
||||
icon: <ArrowUpRight />,
|
||||
link: {
|
||||
to: '/app/metrics/$metricId/chart',
|
||||
params: {
|
||||
metricId,
|
||||
},
|
||||
search: {
|
||||
metric_version_number: metricVersionNumber,
|
||||
},
|
||||
},
|
||||
linkIcon: 'arrow-right',
|
||||
}),
|
||||
[]
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -111,17 +113,18 @@ const useRemoveFromReportItem = ({
|
|||
}: {
|
||||
editor: PlateEditor;
|
||||
element: TElement;
|
||||
}): DropdownItem => {
|
||||
}): IDropdownItem => {
|
||||
return useMemo(
|
||||
() => ({
|
||||
value: 'remove-from-report',
|
||||
label: 'Remove from report',
|
||||
icon: <Trash />,
|
||||
onClick: () => {
|
||||
const path = editor.api.findPath(element);
|
||||
editor.tf.removeNodes({ at: path });
|
||||
},
|
||||
}),
|
||||
() =>
|
||||
createDropdownItem({
|
||||
value: 'remove-from-report',
|
||||
label: 'Remove from report',
|
||||
icon: <Trash />,
|
||||
onClick: () => {
|
||||
const path = editor.api.findPath(element);
|
||||
editor.tf.removeNodes({ at: path });
|
||||
},
|
||||
}),
|
||||
[]
|
||||
);
|
||||
};
|
||||
|
@ -138,36 +141,51 @@ const useNavigatetoMetricItem = ({
|
|||
metricVersionNumber: number | undefined;
|
||||
chatId: string | undefined;
|
||||
reportVersionNumber: number | undefined;
|
||||
}): DropdownItem[] => {
|
||||
}): IDropdownItem[] => {
|
||||
return useMemo(() => {
|
||||
const baseParams = {
|
||||
assetId: metricId,
|
||||
type: 'metric' as const,
|
||||
reportVersionNumber,
|
||||
metricVersionNumber,
|
||||
reportId,
|
||||
chatId,
|
||||
};
|
||||
|
||||
const editChartRoute = assetParamsToRoute({
|
||||
...baseParams,
|
||||
page: 'chart',
|
||||
});
|
||||
|
||||
const resultsChartRoute = assetParamsToRoute({
|
||||
...baseParams,
|
||||
page: 'results',
|
||||
});
|
||||
|
||||
const sqlChartRoute = assetParamsToRoute({
|
||||
...baseParams,
|
||||
page: 'sql',
|
||||
});
|
||||
|
||||
return [
|
||||
{ value: 'edit-chart', label: 'Edit chart', icon: <SquareChartPen />, link: editChartRoute },
|
||||
{ value: 'results-chart', label: 'Results chart', icon: <Table />, link: resultsChartRoute },
|
||||
{ value: 'sql-chart', label: 'SQL chart', icon: <Code />, link: sqlChartRoute },
|
||||
];
|
||||
return createDropdownItems([
|
||||
{
|
||||
value: 'edit-chart',
|
||||
label: 'Edit chart',
|
||||
icon: <SquareChartPen />,
|
||||
link: {
|
||||
to: '/app/metrics/$metricId/chart',
|
||||
params: {
|
||||
metricId,
|
||||
},
|
||||
search: {
|
||||
metric_version_number: metricVersionNumber,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
value: 'results-chart',
|
||||
label: 'Results chart',
|
||||
icon: <Table />,
|
||||
link: {
|
||||
to: '/app/metrics/$metricId/results',
|
||||
params: {
|
||||
metricId,
|
||||
},
|
||||
search: {
|
||||
metric_version_number: metricVersionNumber,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
value: 'sql-chart',
|
||||
label: 'SQL chart',
|
||||
icon: <Code />,
|
||||
link: {
|
||||
to: '/app/metrics/$metricId/sql',
|
||||
params: {
|
||||
metricId,
|
||||
},
|
||||
search: {
|
||||
metric_version_number: metricVersionNumber,
|
||||
},
|
||||
},
|
||||
},
|
||||
]);
|
||||
}, [reportId, metricId, chatId, reportVersionNumber, metricVersionNumber]);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,370 @@
|
|||
'use client';
|
||||
|
||||
import * as ToolbarPrimitive from '@radix-ui/react-toolbar';
|
||||
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
||||
import { cva, type VariantProps } from 'class-variance-authority';
|
||||
import * as React from 'react';
|
||||
import {
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuSeparator,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import { ChevronDown } from '@/components/ui/icons/NucleoIconOutlined';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { TooltipBase as Tooltip, TooltipTrigger } from '@/components/ui/tooltip';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
export const Toolbar = React.forwardRef<
|
||||
React.ElementRef<typeof ToolbarPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof ToolbarPrimitive.Root>
|
||||
>(function Toolbar({ className, ...props }, ref) {
|
||||
return (
|
||||
<ToolbarPrimitive.Root
|
||||
ref={ref}
|
||||
className={cn('relative flex items-center select-none', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
export function ToolbarToggleGroup({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof ToolbarPrimitive.ToolbarToggleGroup>) {
|
||||
return (
|
||||
<ToolbarPrimitive.ToolbarToggleGroup
|
||||
className={cn('flex items-center', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function ToolbarLink({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof ToolbarPrimitive.Link>) {
|
||||
return (
|
||||
<ToolbarPrimitive.Link
|
||||
className={cn('font-medium underline underline-offset-4', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export function ToolbarSeparator({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof ToolbarPrimitive.Separator>) {
|
||||
return (
|
||||
<ToolbarPrimitive.Separator
|
||||
className={cn('bg-border mx-2 my-1 w-px shrink-0', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// From toggleVariants
|
||||
const toolbarButtonVariants = cva(
|
||||
"inline-flex cursor-pointer items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-checked:bg-accent aria-checked:text-accent-foreground aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||
{
|
||||
defaultVariants: {
|
||||
size: 'default',
|
||||
variant: 'default',
|
||||
},
|
||||
variants: {
|
||||
size: {
|
||||
default: 'h-9 min-w-9 px-2',
|
||||
lg: 'h-10 min-w-10 px-2.5',
|
||||
sm: 'h-8 min-w-8 px-1.5',
|
||||
},
|
||||
variant: {
|
||||
default: 'bg-transparent',
|
||||
outline:
|
||||
'border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground',
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const dropdownArrowVariants = cva(
|
||||
cn(
|
||||
'inline-flex items-center justify-center rounded-r-md text-sm font-medium text-foreground transition-colors disabled:pointer-events-none disabled:opacity-50'
|
||||
),
|
||||
{
|
||||
defaultVariants: {
|
||||
size: 'sm',
|
||||
variant: 'default',
|
||||
},
|
||||
variants: {
|
||||
size: {
|
||||
default: 'h-9 w-6',
|
||||
lg: 'h-10 w-8',
|
||||
sm: 'h-8 w-4',
|
||||
},
|
||||
variant: {
|
||||
default:
|
||||
'bg-transparent hover:bg-muted hover:text-muted-foreground aria-checked:bg-accent aria-checked:text-accent-foreground',
|
||||
outline:
|
||||
'border border-l-0 border-input bg-transparent hover:bg-accent hover:text-accent-foreground',
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export function ToolbarToggleItem({
|
||||
className,
|
||||
size = 'sm',
|
||||
variant,
|
||||
...props
|
||||
}: React.ComponentProps<typeof ToolbarPrimitive.ToggleItem> &
|
||||
VariantProps<typeof toolbarButtonVariants>) {
|
||||
return (
|
||||
<ToolbarPrimitive.ToggleItem
|
||||
className={cn(toolbarButtonVariants({ size, variant }), className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
type ToolbarButtonProps = {
|
||||
isDropdown?: boolean;
|
||||
pressed?: boolean;
|
||||
} & Omit<React.ComponentPropsWithoutRef<typeof ToolbarToggleItem>, 'asChild' | 'value'> &
|
||||
VariantProps<typeof toolbarButtonVariants>;
|
||||
|
||||
const ToolbarButtonBase = React.forwardRef<
|
||||
React.ElementRef<typeof ToolbarPrimitive.Button>,
|
||||
ToolbarButtonProps
|
||||
>(function ToolbarButtonBase(
|
||||
{ children, className, isDropdown, pressed, size = 'sm', variant, ...props },
|
||||
ref
|
||||
) {
|
||||
return typeof pressed === 'boolean' ? (
|
||||
<ToolbarToggleGroup disabled={props.disabled} value="single" type="single">
|
||||
<ToolbarToggleItem
|
||||
className={cn(
|
||||
toolbarButtonVariants({
|
||||
size,
|
||||
variant,
|
||||
}),
|
||||
isDropdown && 'justify-between gap-1 pr-1',
|
||||
className
|
||||
)}
|
||||
value={pressed ? 'single' : ''}
|
||||
{...props}
|
||||
>
|
||||
{isDropdown ? (
|
||||
<>
|
||||
<div className="flex flex-1 items-center gap-2 whitespace-nowrap">{children}</div>
|
||||
<div className="text-muted-foreground size-3.5">
|
||||
<ChevronDown data-icon />
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</ToolbarToggleItem>
|
||||
</ToolbarToggleGroup>
|
||||
) : (
|
||||
<ToolbarPrimitive.Button
|
||||
ref={ref}
|
||||
className={cn(
|
||||
toolbarButtonVariants({
|
||||
size,
|
||||
variant,
|
||||
}),
|
||||
isDropdown && 'pr-1',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</ToolbarPrimitive.Button>
|
||||
);
|
||||
});
|
||||
|
||||
export const ToolbarButton = withTooltip(ToolbarButtonBase);
|
||||
|
||||
export function ToolbarSplitButton({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentPropsWithoutRef<typeof ToolbarButton>) {
|
||||
return (
|
||||
<ToolbarButton
|
||||
className={cn('group flex gap-0 px-0 hover:bg-transparent', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
type ToolbarSplitButtonPrimaryProps = Omit<
|
||||
React.ComponentPropsWithoutRef<typeof ToolbarToggleItem>,
|
||||
'value'
|
||||
> &
|
||||
VariantProps<typeof toolbarButtonVariants>;
|
||||
|
||||
export function ToolbarSplitButtonPrimary({
|
||||
children,
|
||||
className,
|
||||
size = 'sm',
|
||||
variant,
|
||||
...props
|
||||
}: ToolbarSplitButtonPrimaryProps) {
|
||||
return (
|
||||
<span
|
||||
className={cn(
|
||||
toolbarButtonVariants({
|
||||
size,
|
||||
variant,
|
||||
}),
|
||||
'rounded-r-none',
|
||||
'group-data-[pressed=true]:bg-accent group-data-[pressed=true]:text-accent-foreground',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* ToolbarSplitButtonSecondary is a functional component wrapped in React.forwardRef.
|
||||
* It renders a styled <span> with a dropdown arrow, used as the secondary part of a split toolbar button.
|
||||
* The ref is forwarded to the <span> element for parent access.
|
||||
*/
|
||||
export const ToolbarSplitButtonSecondary = React.forwardRef<
|
||||
HTMLSpanElement,
|
||||
React.ComponentPropsWithoutRef<'span'> & VariantProps<typeof dropdownArrowVariants>
|
||||
>(function ToolbarSplitButtonSecondary({ className, size, variant, ...props }, ref) {
|
||||
return (
|
||||
<span
|
||||
ref={ref}
|
||||
className={cn(
|
||||
dropdownArrowVariants({
|
||||
size,
|
||||
variant,
|
||||
}),
|
||||
'group-data-[pressed=true]:bg-accent group-data-[pressed=true]:text-accent-foreground',
|
||||
className
|
||||
)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
{...props}
|
||||
>
|
||||
<div className="text-muted-foreground size-3.5">
|
||||
<ChevronDown data-icon />
|
||||
</div>
|
||||
</span>
|
||||
);
|
||||
});
|
||||
|
||||
export function ToolbarGroup({ children, className }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div className={cn('group/toolbar-group', 'relative hidden has-[button]:flex', className)}>
|
||||
<div className="flex items-center">{children}</div>
|
||||
|
||||
<div className="mx-1.5 py-0.5 group-last/toolbar-group:hidden!">
|
||||
<Separator orientation="vertical" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
type TooltipProps<T extends React.ElementType> = {
|
||||
tooltip?: React.ReactNode;
|
||||
tooltipContentProps?: Omit<React.ComponentPropsWithoutRef<typeof TooltipContent>, 'children'>;
|
||||
tooltipProps?: Omit<React.ComponentPropsWithoutRef<typeof Tooltip>, 'children'>;
|
||||
tooltipTriggerProps?: React.ComponentPropsWithoutRef<typeof TooltipTrigger>;
|
||||
} & React.ComponentProps<T>;
|
||||
|
||||
function withTooltip<T extends React.ElementType>(Component: T) {
|
||||
return React.forwardRef<React.ElementRef<T>, TooltipProps<T>>(function ExtendComponent(
|
||||
{ tooltip, tooltipContentProps, tooltipProps, tooltipTriggerProps, ...props },
|
||||
ref
|
||||
) {
|
||||
const [mounted, setMounted] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
const component = React.createElement(Component, {
|
||||
ref,
|
||||
...(props as React.ComponentProps<T>),
|
||||
});
|
||||
|
||||
if (tooltip && mounted) {
|
||||
return (
|
||||
<Tooltip {...tooltipProps}>
|
||||
<TooltipTrigger asChild {...tooltipTriggerProps}>
|
||||
{component}
|
||||
</TooltipTrigger>
|
||||
|
||||
<TooltipContent {...tooltipContentProps}>{tooltip}</TooltipContent>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
return component;
|
||||
});
|
||||
}
|
||||
|
||||
function TooltipContent({
|
||||
children,
|
||||
className,
|
||||
// CHANGE
|
||||
sideOffset = 4,
|
||||
...props
|
||||
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
|
||||
return (
|
||||
<TooltipPrimitive.Portal>
|
||||
<TooltipPrimitive.Content
|
||||
className={cn(
|
||||
'bg-primary text-primary-foreground z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance',
|
||||
className
|
||||
)}
|
||||
data-slot="tooltip-content"
|
||||
sideOffset={sideOffset}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
{/* CHANGE */}
|
||||
{/* <TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-primary fill-primary" /> */}
|
||||
</TooltipPrimitive.Content>
|
||||
</TooltipPrimitive.Portal>
|
||||
);
|
||||
}
|
||||
|
||||
export function ToolbarMenuGroup({
|
||||
children,
|
||||
className,
|
||||
label,
|
||||
...props
|
||||
}: React.ComponentProps<typeof DropdownMenuRadioGroup> & { label?: string }) {
|
||||
return (
|
||||
<>
|
||||
<DropdownMenuSeparator
|
||||
className={cn(
|
||||
'hidden',
|
||||
'mb-0 shrink-0 peer-has-[[role=menuitem]]/menu-group:block peer-has-[[role=menuitemradio]]/menu-group:block peer-has-[[role=option]]/menu-group:block'
|
||||
)}
|
||||
/>
|
||||
|
||||
<DropdownMenuRadioGroup
|
||||
{...props}
|
||||
className={cn(
|
||||
'hidden',
|
||||
'peer/menu-group group/menu-group my-1.5 has-[[role=menuitem]]:block has-[[role=menuitemradio]]:block has-[[role=option]]:block',
|
||||
className
|
||||
)}
|
||||
>
|
||||
{label && (
|
||||
<DropdownMenuLabel className="text-muted-foreground text-xs font-semibold select-none">
|
||||
{label}
|
||||
</DropdownMenuLabel>
|
||||
)}
|
||||
{children}
|
||||
</DropdownMenuRadioGroup>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export * from './Toolbar';
|
|
@ -1,10 +1,11 @@
|
|||
import { z } from 'zod';
|
||||
import { ShareRoleSchema, VerificationStatusSchema, WorkspaceShareRoleSchema } from '../share';
|
||||
import { ShareRoleSchema, VerificationStatusSchema } from '../share';
|
||||
import { ChartConfigPropsSchema } from './charts';
|
||||
|
||||
export const GetMetricRequestSchema = z.object({
|
||||
id: z.string(),
|
||||
password: z.string().optional(),
|
||||
report_file_id: z.string().optional(),
|
||||
version_number: z.number().optional(), //api will default to latest if not provided
|
||||
});
|
||||
|
||||
|
|
118
pnpm-lock.yaml
118
pnpm-lock.yaml
|
@ -43,7 +43,7 @@ catalogs:
|
|||
specifier: ^49.0.0
|
||||
version: 49.0.0
|
||||
'@platejs/table':
|
||||
specifier: ^49.1.13
|
||||
specifier: 49.1.13
|
||||
version: 49.1.13
|
||||
'@platejs/toc':
|
||||
specifier: ^49.0.0
|
||||
|
@ -877,6 +877,18 @@ importers:
|
|||
'@monaco-editor/react':
|
||||
specifier: ^4.7.0
|
||||
version: 4.7.0(monaco-editor@0.52.2)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@platejs/dnd':
|
||||
specifier: ^49.2.10
|
||||
version: 49.2.10(platejs@49.2.12(@types/react@19.1.12)(immer@10.1.1)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@apps+web-tss+@platejs+ai+react)))(react-dnd-html5-backend@16.0.1)(react-dnd@16.0.1(@types/node@24.0.10)(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react))(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@platejs/resizable':
|
||||
specifier: ^49.0.0
|
||||
version: 49.0.0(platejs@49.2.12(@types/react@19.1.12)(immer@10.1.1)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@apps+web-tss+@platejs+ai+react)))(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@platejs/selection':
|
||||
specifier: ^49.2.4
|
||||
version: 49.2.4(platejs@49.2.12(@types/react@19.1.12)(immer@10.1.1)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@apps+web-tss+@platejs+ai+react)))(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@platejs/table':
|
||||
specifier: 'catalog:'
|
||||
version: 49.1.13(platejs@49.2.12(@types/react@19.1.12)(immer@10.1.1)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@apps+web-tss+@platejs+ai+react)))(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-avatar':
|
||||
specifier: ^1.1.10
|
||||
version: 1.1.10(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
|
@ -922,6 +934,9 @@ importers:
|
|||
'@radix-ui/react-tabs':
|
||||
specifier: ^1.1.13
|
||||
version: 1.1.13(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-toolbar':
|
||||
specifier: ^1.1.10
|
||||
version: 1.1.10(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-tooltip':
|
||||
specifier: ^1.2.8
|
||||
version: 1.2.8(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
|
@ -19136,6 +19151,16 @@ snapshots:
|
|||
react-dnd-html5-backend: 16.0.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
'@platejs/dnd@49.2.10(platejs@49.2.12(@types/react@19.1.12)(immer@10.1.1)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@apps+web-tss+@platejs+ai+react)))(react-dnd-html5-backend@16.0.1)(react-dnd@16.0.1(@types/node@24.0.10)(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react))(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)':
|
||||
dependencies:
|
||||
lodash: 4.17.21
|
||||
platejs: 49.2.12(@types/react@19.1.12)(immer@10.1.1)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@apps+web-tss+@platejs+ai+react))
|
||||
raf: 3.4.1
|
||||
react: link:apps/web-tss/@platejs/ai/react
|
||||
react-dnd: 16.0.1(@types/node@24.0.10)(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react)
|
||||
react-dnd-html5-backend: 16.0.1
|
||||
react-dom: 19.1.1(react@apps+web-tss+@platejs+ai+react)
|
||||
|
||||
'@platejs/docx@49.0.0(platejs@49.2.12(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
platejs: 49.2.12(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1))
|
||||
|
@ -19254,6 +19279,12 @@ snapshots:
|
|||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
'@platejs/resizable@49.0.0(platejs@49.2.12(@types/react@19.1.12)(immer@10.1.1)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@apps+web-tss+@platejs+ai+react)))(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)':
|
||||
dependencies:
|
||||
platejs: 49.2.12(@types/react@19.1.12)(immer@10.1.1)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@apps+web-tss+@platejs+ai+react))
|
||||
react: link:apps/web-tss/@platejs/ai/react
|
||||
react-dom: 19.1.1(react@apps+web-tss+@platejs+ai+react)
|
||||
|
||||
'@platejs/selection@49.2.4(platejs@49.2.12(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
copy-to-clipboard: 3.3.3
|
||||
|
@ -19261,6 +19292,13 @@ snapshots:
|
|||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
'@platejs/selection@49.2.4(platejs@49.2.12(@types/react@19.1.12)(immer@10.1.1)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@apps+web-tss+@platejs+ai+react)))(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)':
|
||||
dependencies:
|
||||
copy-to-clipboard: 3.3.3
|
||||
platejs: 49.2.12(@types/react@19.1.12)(immer@10.1.1)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@apps+web-tss+@platejs+ai+react))
|
||||
react: link:apps/web-tss/@platejs/ai/react
|
||||
react-dom: 19.1.1(react@apps+web-tss+@platejs+ai+react)
|
||||
|
||||
'@platejs/slash-command@49.0.0(platejs@49.2.12(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@platejs/combobox': 49.0.0(platejs@49.2.12(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
|
@ -19292,6 +19330,14 @@ snapshots:
|
|||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
'@platejs/table@49.1.13(platejs@49.2.12(@types/react@19.1.12)(immer@10.1.1)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@apps+web-tss+@platejs+ai+react)))(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)':
|
||||
dependencies:
|
||||
'@platejs/resizable': 49.0.0(platejs@49.2.12(@types/react@19.1.12)(immer@10.1.1)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@apps+web-tss+@platejs+ai+react)))(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
lodash: 4.17.21
|
||||
platejs: 49.2.12(@types/react@19.1.12)(immer@10.1.1)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@apps+web-tss+@platejs+ai+react))
|
||||
react: link:apps/web-tss/@platejs/ai/react
|
||||
react-dom: 19.1.1(react@apps+web-tss+@platejs+ai+react)
|
||||
|
||||
'@platejs/toc@49.0.0(platejs@49.2.12(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
platejs: 49.2.12(@types/react@18.3.23)(immer@10.1.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(scheduler@0.26.0)(slate-dom@0.116.0(slate@0.117.0))(slate@0.117.0)(use-sync-external-store@1.5.0(react@18.3.1))
|
||||
|
@ -20079,6 +20125,23 @@ snapshots:
|
|||
'@types/react': 18.3.23
|
||||
'@types/react-dom': 18.3.7(@types/react@18.3.23)
|
||||
|
||||
'@radix-ui/react-roving-focus@1.1.10(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
'@radix-ui/react-collection': 1.1.7(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-compose-refs': 1.1.2(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-context': 1.1.2(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-direction': 1.1.1(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-id': 1.1.1(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react)
|
||||
react: link:apps/web-tss/@platejs/ai/react
|
||||
react-dom: 19.1.1(react@apps+web-tss+@platejs+ai+react)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.12
|
||||
'@types/react-dom': 19.1.9(@types/react@19.1.12)
|
||||
|
||||
'@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.3
|
||||
|
@ -20335,6 +20398,21 @@ snapshots:
|
|||
'@types/react': 18.3.23
|
||||
'@types/react-dom': 18.3.7(@types/react@18.3.23)
|
||||
|
||||
'@radix-ui/react-toggle-group@1.1.10(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
'@radix-ui/react-context': 1.1.2(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-direction': 1.1.1(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-toggle': 1.1.9(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react)
|
||||
react: link:apps/web-tss/@platejs/ai/react
|
||||
react-dom: 19.1.1(react@apps+web-tss+@platejs+ai+react)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.12
|
||||
'@types/react-dom': 19.1.9(@types/react@19.1.12)
|
||||
|
||||
'@radix-ui/react-toggle@1.1.9(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
|
@ -20346,6 +20424,17 @@ snapshots:
|
|||
'@types/react': 18.3.23
|
||||
'@types/react-dom': 18.3.7(@types/react@18.3.23)
|
||||
|
||||
'@radix-ui/react-toggle@1.1.9(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react)
|
||||
react: link:apps/web-tss/@platejs/ai/react
|
||||
react-dom: 19.1.1(react@apps+web-tss+@platejs+ai+react)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.12
|
||||
'@types/react-dom': 19.1.9(@types/react@19.1.12)
|
||||
|
||||
'@radix-ui/react-toolbar@1.1.10(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
|
@ -20361,6 +20450,21 @@ snapshots:
|
|||
'@types/react': 18.3.23
|
||||
'@types/react-dom': 18.3.7(@types/react@18.3.23)
|
||||
|
||||
'@radix-ui/react-toolbar@1.1.10(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
'@radix-ui/react-context': 1.1.2(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-direction': 1.1.1(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-roving-focus': 1.1.10(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-separator': 1.1.7(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
'@radix-ui/react-toggle-group': 1.1.10(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@apps+web-tss+@platejs+ai+react))(react@apps+web-tss+@platejs+ai+react)
|
||||
react: link:apps/web-tss/@platejs/ai/react
|
||||
react-dom: 19.1.1(react@apps+web-tss+@platejs+ai+react)
|
||||
optionalDependencies:
|
||||
'@types/react': 19.1.12
|
||||
'@types/react-dom': 19.1.9(@types/react@19.1.12)
|
||||
|
||||
'@radix-ui/react-tooltip@1.2.7(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@radix-ui/primitive': 1.1.2
|
||||
|
@ -29847,6 +29951,18 @@ snapshots:
|
|||
'@types/node': 24.0.10
|
||||
'@types/react': 18.3.23
|
||||
|
||||
react-dnd@16.0.1(@types/node@24.0.10)(@types/react@19.1.12)(react@apps+web-tss+@platejs+ai+react):
|
||||
dependencies:
|
||||
'@react-dnd/invariant': 4.0.2
|
||||
'@react-dnd/shallowequal': 4.0.2
|
||||
dnd-core: 16.0.1
|
||||
fast-deep-equal: 3.1.3
|
||||
hoist-non-react-statics: 3.3.2
|
||||
react: link:apps/web-tss/@platejs/ai/react
|
||||
optionalDependencies:
|
||||
'@types/node': 24.0.10
|
||||
'@types/react': 19.1.12
|
||||
|
||||
react-docgen-typescript@2.4.0(typescript@5.9.2):
|
||||
dependencies:
|
||||
typescript: 5.9.2
|
||||
|
|
|
@ -20,7 +20,7 @@ catalog:
|
|||
'@platejs/markdown': ^49.2.14
|
||||
'@platejs/math': ^49.0.0
|
||||
'@platejs/media': ^49.0.0
|
||||
'@platejs/table': ^49.1.13
|
||||
'@platejs/table': 49.1.13
|
||||
'@platejs/toc': ^49.0.0
|
||||
'@platejs/toggle': ^49.0.0
|
||||
'@supabase/supabase-js': ^2.50.0
|
||||
|
|
Loading…
Reference in New Issue