mirror of https://github.com/buster-so/buster.git
update nodes
This commit is contained in:
parent
f32a41b048
commit
76c87fb47c
|
@ -42,6 +42,10 @@ export const ReportPlayground: React.FC = () => {
|
|||
{ wait: 150 }
|
||||
);
|
||||
|
||||
const logValueChanges = (value: ReportElements) => {
|
||||
console.log('value', value);
|
||||
};
|
||||
|
||||
const usedValue: ReportElements = hasBeenSuccessFullAtLeastOnce ? data?.elements || [] : value;
|
||||
|
||||
return (
|
||||
|
@ -68,7 +72,7 @@ export const ReportPlayground: React.FC = () => {
|
|||
<ThemePicker />
|
||||
</div>
|
||||
<div className="bg-background h-full max-h-[calc(100vh-56px)] overflow-y-auto rounded border shadow">
|
||||
<DynamicReportEditor value={usedValue} readOnly={false} />
|
||||
<DynamicReportEditor value={usedValue} readOnly={false} onValueChange={logValueChanges} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -69,7 +69,7 @@ function DropdownMenuItem({
|
|||
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-default 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",
|
||||
"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}
|
||||
|
|
|
@ -2,14 +2,12 @@ import dynamic from 'next/dynamic';
|
|||
import { ReportEditorSkeleton } from './ReportEditorSkeleton';
|
||||
import { ReportEditor } from './ReportEditor';
|
||||
|
||||
// export const DynamicReportEditor = dynamic(
|
||||
// () => import('@/components/ui/report/ReportEditor').then((mod) => mod.ReportEditor),
|
||||
// {
|
||||
// ssr: false,
|
||||
// loading: () => <ReportEditorSkeleton />
|
||||
// }
|
||||
// );
|
||||
|
||||
const DynamicReportEditor = ReportEditor;
|
||||
export const DynamicReportEditor = dynamic(
|
||||
() => import('@/components/ui/report/ReportEditor').then((mod) => mod.ReportEditor),
|
||||
{
|
||||
ssr: false,
|
||||
loading: () => <ReportEditorSkeleton />
|
||||
}
|
||||
);
|
||||
|
||||
export default DynamicReportEditor;
|
||||
|
|
|
@ -46,7 +46,7 @@ export function CodeBlockElement(props: PlateElementProps<TCodeBlockElement>) {
|
|||
{isLangSupported(element.lang) && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
className="size-6 text-xs"
|
||||
size={'small'}
|
||||
onClick={() => formatCodeBlock(editor, { element })}
|
||||
title="Format code"
|
||||
prefix={<BracketsCurly />}></Button>
|
||||
|
@ -61,7 +61,7 @@ export function CodeBlockElement(props: PlateElementProps<TCodeBlockElement>) {
|
|||
);
|
||||
}
|
||||
|
||||
function CodeBlockCombobox() {
|
||||
const CodeBlockCombobox = React.memo(() => {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const readOnly = useReadOnly();
|
||||
const editor = useEditorRef();
|
||||
|
@ -83,8 +83,8 @@ function CodeBlockCombobox() {
|
|||
return (
|
||||
<PopoverBase open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="ghost" aria-expanded={open} role="combobox">
|
||||
{languages.find((language) => language.value === value)?.label ?? 'Plain Text'}
|
||||
<Button variant="ghost" size={'small'} aria-expanded={open} role="combobox">
|
||||
{languages.find((language) => language.value === value)?.label ?? 'Plain text'}
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[200px] p-0" onCloseAutoFocus={() => setSearchValue('')}>
|
||||
|
@ -120,7 +120,9 @@ function CodeBlockCombobox() {
|
|||
</PopoverContent>
|
||||
</PopoverBase>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
CodeBlockCombobox.displayName = 'CodeBlockCombobox';
|
||||
|
||||
function CopyButton({
|
||||
value,
|
||||
|
@ -137,6 +139,7 @@ function CopyButton({
|
|||
return (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size={'small'}
|
||||
prefix={hasCopied ? <Check /> : <Copy2 />}
|
||||
onClick={() => {
|
||||
void navigator.clipboard.writeText(typeof value === 'function' ? value() : value);
|
||||
|
@ -159,7 +162,7 @@ export function CodeSyntaxLeaf(props: PlateLeafProps<TCodeSyntaxLeaf>) {
|
|||
|
||||
const languages: { label: string; value: string }[] = [
|
||||
// { label: 'Auto', value: 'auto' },
|
||||
{ label: 'Plain Text', value: 'plaintext' },
|
||||
{ label: 'Plain text', value: 'plaintext' },
|
||||
// { label: 'ABAP', value: 'abap' },
|
||||
// { label: 'Agda', value: 'agda' },
|
||||
// { label: 'Arduino', value: 'arduino' },
|
||||
|
|
|
@ -340,7 +340,7 @@ function InlineComboboxGroupLabel({
|
|||
return (
|
||||
<ComboboxGroupLabel
|
||||
{...props}
|
||||
className={cn('text-muted-foreground mt-1.5 mb-2 px-3 text-xs font-medium', className)}
|
||||
className={cn('text-muted-foreground font-base mt-1.5 mb-2 px-3 text-xs', className)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -9,13 +9,19 @@ import type { PlateElementProps } from 'platejs/react';
|
|||
import { parseTwitterUrl, parseVideoUrl } from '@platejs/media';
|
||||
import { MediaEmbedPlugin, useMediaState } from '@platejs/media/react';
|
||||
import { ResizableProvider, useResizableValue } from '@platejs/resizable';
|
||||
import { PlateElement, withHOC } from 'platejs/react';
|
||||
import { PlateElement, useFocused, useReadOnly, useSelected, withHOC } from 'platejs/react';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
import { Caption, CaptionTextarea } from './CaptionNode';
|
||||
import { MediaToolbar } from './MediaToolbar';
|
||||
import { mediaResizeHandleVariants, Resizable, ResizeHandle } from './ResizeHandle';
|
||||
import { Code3 } from '../../icons';
|
||||
import { PopoverAnchor, PopoverBase, PopoverContent } from '../../popover';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Title } from '../../typography';
|
||||
import { Input } from '../../inputs';
|
||||
import { Button } from '../../buttons';
|
||||
|
||||
export const MediaEmbedElement = withHOC(
|
||||
ResizableProvider,
|
||||
|
@ -34,10 +40,15 @@ export const MediaEmbedElement = withHOC(
|
|||
});
|
||||
const width = useResizableValue('width');
|
||||
const provider = embed?.provider;
|
||||
const hasElement = !!embed?.url;
|
||||
|
||||
if (!hasElement) {
|
||||
return <MediaEmbedPlaceholder {...props} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<MediaToolbar plugin={MediaEmbedPlugin}>
|
||||
<PlateElement className="py-2.5" {...props}>
|
||||
<PlateElement className="media-embed py-2.5" {...props}>
|
||||
<figure className="group relative m-0 w-full cursor-default" contentEditable={false}>
|
||||
<Resizable
|
||||
align={align}
|
||||
|
@ -113,3 +124,45 @@ export const MediaEmbedElement = withHOC(
|
|||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const MediaEmbedPlaceholder = (props: PlateElementProps<TMediaEmbedElement>) => {
|
||||
const readOnly = useReadOnly();
|
||||
const selected = useSelected();
|
||||
const focused = useFocused();
|
||||
|
||||
const isFocused = focused && selected && !readOnly;
|
||||
|
||||
return (
|
||||
<PlateElement className="media-embed py-2.5" {...props}>
|
||||
<PopoverBase open={isFocused}>
|
||||
<PopoverAnchor>
|
||||
<div
|
||||
className={cn(
|
||||
'bg-muted hover:bg-primary/10 flex cursor-pointer items-center rounded-sm p-3 pr-9 select-none'
|
||||
)}
|
||||
contentEditable={false}>
|
||||
<div className="text-muted-foreground/80 relative mr-3 flex [&_svg]:size-6">
|
||||
<Code3 />
|
||||
</div>
|
||||
|
||||
<div className="text-muted-foreground text-sm whitespace-nowrap">Add a media embed</div>
|
||||
</div>
|
||||
{props.children}
|
||||
</PopoverAnchor>
|
||||
|
||||
<PopoverContent
|
||||
className="w-[250px] p-0"
|
||||
onOpenAutoFocus={(e) => {
|
||||
console.log('onOpenAutoFocus', e);
|
||||
e.preventDefault();
|
||||
}}>
|
||||
<Title as="h4">Add a media embed</Title>
|
||||
<div className="bg-gray-light h-0.5 w-full" />
|
||||
|
||||
<Input placeholder="Enter a URL" />
|
||||
<Button block>Add media</Button>
|
||||
</PopoverContent>
|
||||
</PopoverBase>
|
||||
</PlateElement>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -41,6 +41,11 @@ const CONTENT: Record<
|
|||
accept: ['video/*'],
|
||||
content: 'Add a video',
|
||||
icon: <FilmPlay />
|
||||
},
|
||||
[KEYS.mediaEmbed]: {
|
||||
accept: ['*'],
|
||||
content: 'Add a media embed',
|
||||
icon: <FilmPlay />
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -18,20 +18,6 @@ import {
|
|||
} from '@platejs/table/react';
|
||||
import { PopoverAnchor } from '@radix-ui/react-popover';
|
||||
import { cva } from 'class-variance-authority';
|
||||
// import {
|
||||
// ArrowDown,
|
||||
// ArrowLeft,
|
||||
// ArrowRight,
|
||||
// ArrowUp,
|
||||
// CombineIcon,
|
||||
// EraserIcon,
|
||||
// Grid2X2Icon,
|
||||
// GripVertical,
|
||||
// PaintBucketIcon,
|
||||
// SquareSplitHorizontalIcon,
|
||||
// Trash2Icon,
|
||||
// XIcon
|
||||
// } from 'lucide-react';
|
||||
import {
|
||||
ArrowDown,
|
||||
ArrowLeft,
|
||||
|
|
|
@ -11,7 +11,8 @@ import { insertEquation, insertInlineEquation } from '@platejs/math';
|
|||
import {
|
||||
insertAudioPlaceholder,
|
||||
insertFilePlaceholder,
|
||||
insertMedia,
|
||||
insertPlaceholder,
|
||||
insertImagePlaceholder,
|
||||
insertVideoPlaceholder
|
||||
} from '@platejs/media';
|
||||
import { SuggestionPlugin } from '@platejs/suggestion/react';
|
||||
|
@ -41,16 +42,19 @@ const insertBlockMap: Record<string, (editor: PlateEditor, type: string) => void
|
|||
[KEYS.codeBlock]: (editor) => insertCodeBlock(editor, { select: true }),
|
||||
[KEYS.equation]: (editor) => insertEquation(editor, { select: true }),
|
||||
[KEYS.file]: (editor) => insertFilePlaceholder(editor, { select: true }),
|
||||
[KEYS.img]: (editor) =>
|
||||
insertMedia(editor, {
|
||||
select: true,
|
||||
type: KEYS.img
|
||||
}),
|
||||
[KEYS.mediaEmbed]: (editor) =>
|
||||
insertMedia(editor, {
|
||||
select: true,
|
||||
type: KEYS.mediaEmbed
|
||||
}),
|
||||
[KEYS.img]: (editor) => {
|
||||
insertImagePlaceholder(editor, {
|
||||
select: true
|
||||
});
|
||||
},
|
||||
[KEYS.mediaEmbed]: (editor) => {
|
||||
editor.tf.insertNodes(
|
||||
editor.api.create.block({
|
||||
type: KEYS.mediaEmbed
|
||||
}),
|
||||
{ select: true }
|
||||
);
|
||||
},
|
||||
[KEYS.table]: (editor) => editor.getTransforms(TablePlugin).insert.table({}, { select: true }),
|
||||
[KEYS.toc]: (editor) => insertToc(editor, { select: true }),
|
||||
[KEYS.video]: (editor) => insertVideoPlaceholder(editor, { select: true })
|
||||
|
|
|
@ -12,25 +12,31 @@ import {
|
|||
import { KEYS } from 'platejs';
|
||||
|
||||
import { AudioElement } from '../elements/AudioNode';
|
||||
import { MediaEmbedElement } from '../elements/MediaEmbedNode';
|
||||
import { MediaEmbedElement, MediaEmbedPlaceholder } from '../elements/MediaEmbedNode';
|
||||
import { FileElement } from '../elements/MediaFileNode';
|
||||
import { ImageElement } from '../elements/MediaImageNode';
|
||||
import { PlaceholderElement } from '../elements/MediaPlaceholderElement';
|
||||
import { MediaPreviewDialog } from '../elements/MediaPreviewDialog';
|
||||
import { MediaUploadToast } from '../elements/MediaUploadToast';
|
||||
import { VideoElement } from '../elements/MediaVideoNode';
|
||||
import { MediaPluginOptions } from '@platejs/media';
|
||||
|
||||
export const MediaKit = [
|
||||
ImagePlugin.configure({
|
||||
options: { disableUploadInsert: true },
|
||||
render: { afterEditable: MediaPreviewDialog, node: ImageElement }
|
||||
}),
|
||||
MediaEmbedPlugin.withComponent(MediaEmbedElement),
|
||||
// VideoPlugin.withComponent(VideoElement),
|
||||
// AudioPlugin.withComponent(AudioElement),
|
||||
// FilePlugin.withComponent(FileElement),
|
||||
MediaEmbedPlugin.configure({
|
||||
node: {
|
||||
component: MediaEmbedElement,
|
||||
isSelectable: true,
|
||||
isElement: true
|
||||
},
|
||||
options: {}
|
||||
}),
|
||||
|
||||
PlaceholderPlugin.configure({
|
||||
options: { disableEmptyPlaceholder: true },
|
||||
options: { disableEmptyPlaceholder: false },
|
||||
render: { afterEditable: MediaUploadToast, node: PlaceholderElement }
|
||||
}),
|
||||
CaptionPlugin.configure({
|
||||
|
@ -40,4 +46,7 @@ export const MediaKit = [
|
|||
}
|
||||
}
|
||||
})
|
||||
// VideoPlugin.withComponent(VideoElement),
|
||||
// AudioPlugin.withComponent(AudioElement),
|
||||
// FilePlugin.withComponent(FileElement),
|
||||
];
|
||||
|
|
|
@ -262,7 +262,7 @@ export const ToolbarMenuGroup = ({
|
|||
className
|
||||
)}>
|
||||
{label && (
|
||||
<DropdownMenuLabel className="text-muted-foreground text-xs font-semibold select-none">
|
||||
<DropdownMenuLabel className="text-muted-foreground font-base text-xs select-none">
|
||||
{label}
|
||||
</DropdownMenuLabel>
|
||||
)}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
|
||||
export const FONT_BASE_THEME = {
|
||||
'--font-heading': 'ui-sans-serif, -apple-system, BlinkMacSystemFont',
|
||||
'--font-sans': 'ui-sans-serif, -apple-system, BlinkMacSystemFont',
|
||||
'--font-mono':
|
||||
'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
|
||||
// '--font-heading': 'ui-sans-serif, -apple-system, BlinkMacSystemFont',
|
||||
// '--font-sans': 'ui-sans-serif, -apple-system, BlinkMacSystemFont',
|
||||
// '--font-mono':
|
||||
// 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
|
||||
'--spacing': '0.25rem',
|
||||
'--breakpoint-xl': '80rem',
|
||||
'--breakpoint-2xl': '96rem',
|
||||
|
@ -89,7 +89,8 @@ export const THEME_RESET_COLORS = {
|
|||
'popover-foreground': '240 10% 3.9%',
|
||||
primary: '240 5.9% 10%',
|
||||
'primary-foreground': '0 0% 98%',
|
||||
ring: '240 10% 3.9%',
|
||||
// Set ring to a super light gray (almost white)
|
||||
ring: '0 0% 96%',
|
||||
secondary: '240 4.8% 95.9%',
|
||||
'secondary-foreground': '240 5.9% 10%'
|
||||
},
|
||||
|
|
|
@ -78,21 +78,25 @@ export const HeaderElementSchema = z
|
|||
})
|
||||
.merge(AttributesSchema);
|
||||
|
||||
const ListStylesAttributesSchema = z.object({
|
||||
listStyleType: z
|
||||
.enum(['disc', 'circle', 'square', 'decimal', 'decimal-leading-zero', 'todo'])
|
||||
.optional(),
|
||||
listRestart: z.boolean().optional(),
|
||||
listRestartPolite: z.boolean().optional(),
|
||||
listStart: z.number().int().min(0).optional(),
|
||||
indent: z.number().int().min(0).optional(),
|
||||
checked: z.boolean().optional(), //used with todo list style
|
||||
});
|
||||
|
||||
// Paragraph element with optional list styling and indentation
|
||||
export const ParagraphElementSchema = z
|
||||
.object({
|
||||
type: z.literal('p'),
|
||||
listStyleType: z
|
||||
.enum(['disc', 'circle', 'square', 'decimal', 'decimal-leading-zero'])
|
||||
.optional(),
|
||||
listRestart: z.boolean().optional(),
|
||||
listRestartPolite: z.boolean().optional(),
|
||||
listStart: z.number().int().min(0).optional(),
|
||||
|
||||
indent: z.number().int().min(0).optional(),
|
||||
children: z.array(z.union([TextSchema, AnchorSchema, MentionSchema])),
|
||||
})
|
||||
.merge(AttributesSchema);
|
||||
.merge(AttributesSchema)
|
||||
.merge(ListStylesAttributesSchema);
|
||||
|
||||
// Blockquote element
|
||||
export const BlockquoteElementSchema = z
|
||||
|
|
Loading…
Reference in New Issue