diff --git a/apps/web/src/app/test/report-playground/ReportPlayground.tsx b/apps/web/src/app/test/report-playground/ReportPlayground.tsx index b29822570..e0dba5c83 100644 --- a/apps/web/src/app/test/report-playground/ReportPlayground.tsx +++ b/apps/web/src/app/test/report-playground/ReportPlayground.tsx @@ -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 = () => {
- +
); diff --git a/apps/web/src/components/ui/dropdown-menu/dropdown-menu.tsx b/apps/web/src/components/ui/dropdown-menu/dropdown-menu.tsx index 3da024305..e6677eac5 100644 --- a/apps/web/src/components/ui/dropdown-menu/dropdown-menu.tsx +++ b/apps/web/src/components/ui/dropdown-menu/dropdown-menu.tsx @@ -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} diff --git a/apps/web/src/components/ui/report/DynamicReportEditor.tsx b/apps/web/src/components/ui/report/DynamicReportEditor.tsx index 67a59a098..6b136ac25 100644 --- a/apps/web/src/components/ui/report/DynamicReportEditor.tsx +++ b/apps/web/src/components/ui/report/DynamicReportEditor.tsx @@ -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: () => -// } -// ); - -const DynamicReportEditor = ReportEditor; +export const DynamicReportEditor = dynamic( + () => import('@/components/ui/report/ReportEditor').then((mod) => mod.ReportEditor), + { + ssr: false, + loading: () => + } +); export default DynamicReportEditor; diff --git a/apps/web/src/components/ui/report/elements/CodeBlockNode.tsx b/apps/web/src/components/ui/report/elements/CodeBlockNode.tsx index 762df7f48..5f02d2be0 100644 --- a/apps/web/src/components/ui/report/elements/CodeBlockNode.tsx +++ b/apps/web/src/components/ui/report/elements/CodeBlockNode.tsx @@ -46,7 +46,7 @@ export function CodeBlockElement(props: PlateElementProps) { {isLangSupported(element.lang) && ( @@ -61,7 +61,7 @@ export function CodeBlockElement(props: PlateElementProps) { ); } -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 ( - setSearchValue('')}> @@ -120,7 +120,9 @@ function CodeBlockCombobox() { ); -} +}); + +CodeBlockCombobox.displayName = 'CodeBlockCombobox'; function CopyButton({ value, @@ -137,6 +139,7 @@ function CopyButton({ return ( + + + + ); +}; diff --git a/apps/web/src/components/ui/report/elements/MediaPlaceholderElement.tsx b/apps/web/src/components/ui/report/elements/MediaPlaceholderElement.tsx index 8e9acc5fe..0c5fe9c52 100644 --- a/apps/web/src/components/ui/report/elements/MediaPlaceholderElement.tsx +++ b/apps/web/src/components/ui/report/elements/MediaPlaceholderElement.tsx @@ -41,6 +41,11 @@ const CONTENT: Record< accept: ['video/*'], content: 'Add a video', icon: + }, + [KEYS.mediaEmbed]: { + accept: ['*'], + content: 'Add a media embed', + icon: } }; diff --git a/apps/web/src/components/ui/report/elements/TableNode/TableNode.tsx b/apps/web/src/components/ui/report/elements/TableNode/TableNode.tsx index 3c7633d08..dbaa041e7 100644 --- a/apps/web/src/components/ui/report/elements/TableNode/TableNode.tsx +++ b/apps/web/src/components/ui/report/elements/TableNode/TableNode.tsx @@ -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, diff --git a/apps/web/src/components/ui/report/elements/transforms.ts b/apps/web/src/components/ui/report/elements/transforms.ts index dab7ca586..0dff33c3c 100644 --- a/apps/web/src/components/ui/report/elements/transforms.ts +++ b/apps/web/src/components/ui/report/elements/transforms.ts @@ -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 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 }) diff --git a/apps/web/src/components/ui/report/plugins/media-kit.tsx b/apps/web/src/components/ui/report/plugins/media-kit.tsx index 7782bcba2..9e172c6d0 100644 --- a/apps/web/src/components/ui/report/plugins/media-kit.tsx +++ b/apps/web/src/components/ui/report/plugins/media-kit.tsx @@ -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), ]; diff --git a/apps/web/src/components/ui/toolbar/Toolbar.tsx b/apps/web/src/components/ui/toolbar/Toolbar.tsx index e925d51a0..e13f5d4d4 100644 --- a/apps/web/src/components/ui/toolbar/Toolbar.tsx +++ b/apps/web/src/components/ui/toolbar/Toolbar.tsx @@ -262,7 +262,7 @@ export const ToolbarMenuGroup = ({ className )}> {label && ( - + {label} )} diff --git a/apps/web/src/styles/theme-reset.ts b/apps/web/src/styles/theme-reset.ts index 72fe4b011..c2a46c497 100644 --- a/apps/web/src/styles/theme-reset.ts +++ b/apps/web/src/styles/theme-reset.ts @@ -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%' }, diff --git a/packages/server-shared/src/reports/report-elements.ts b/packages/server-shared/src/reports/report-elements.ts index 689dba8bd..72c26a898 100644 --- a/packages/server-shared/src/reports/report-elements.ts +++ b/packages/server-shared/src/reports/report-elements.ts @@ -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