mirror of https://github.com/buster-so/buster.git
925 lines
23 KiB
TypeScript
925 lines
23 KiB
TypeScript
'use client';
|
|
|
|
import React, { useState } from 'react';
|
|
import dynamic from 'next/dynamic';
|
|
import { InputTextArea } from '@/components/ui/inputs/InputTextArea';
|
|
import type { ReportElements } from '@buster/server-shared/reports';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { mainApiV2 } from '@/api/buster_rest/instances';
|
|
import { useDebounceEffect } from '@/hooks';
|
|
import { useThemesConfig } from '@/components/ui/report/ThemeWrapper/useThemesConfig';
|
|
import { cn } from '@/lib/utils';
|
|
import { Tooltip } from '@/components/ui/tooltip';
|
|
|
|
import DynamicReportEditor from '@/components/ui/report/DynamicReportEditor';
|
|
|
|
// Status indicator component with dynamic backgrounds
|
|
|
|
export const ReportPlayground: React.FC = () => {
|
|
const [markdown, setMarkdown] = useState<string>('');
|
|
const [hasBeenSuccessFullAtLeastOnce, setHasBeenSuccessFullAtLeastOnce] = useState(false);
|
|
|
|
const { data, refetch, isLoading, isFetched, error } = useQuery({
|
|
queryKey: ['report-playground', markdown],
|
|
queryFn: () => {
|
|
return mainApiV2
|
|
.post<{ elements: ReportElements }>('/temp/validate-markdown', { markdown })
|
|
.then((res) => {
|
|
setHasBeenSuccessFullAtLeastOnce(true);
|
|
return res.data;
|
|
});
|
|
},
|
|
enabled: false
|
|
});
|
|
|
|
useDebounceEffect(
|
|
() => {
|
|
if (markdown.length > 0) {
|
|
refetch();
|
|
}
|
|
},
|
|
[markdown, refetch],
|
|
{ wait: 150 }
|
|
);
|
|
|
|
const logValueChanges = (value: ReportElements) => {
|
|
console.log('value', value);
|
|
};
|
|
|
|
const usedValue: ReportElements = hasBeenSuccessFullAtLeastOnce ? data?.elements || [] : value;
|
|
|
|
return (
|
|
<div className="grid max-h-screen min-h-screen grid-cols-[270px_1fr] gap-5 rounded border p-7">
|
|
<div className="flex h-full flex-col space-y-5">
|
|
<InputTextArea
|
|
className="flex-1 resize-none"
|
|
placeholder="Put markdown here"
|
|
value={markdown}
|
|
onChange={(e) => setMarkdown(e.target.value)}
|
|
/>
|
|
<ValidationStatus isLoading={isLoading} error={error} isFetched={isFetched} data={data} />
|
|
{data && (
|
|
<div className="max-h-[28vh] min-h-0 flex-1">
|
|
<div className="flex h-full flex-col">
|
|
<h3 className="mb-2 text-sm font-medium text-gray-700">Successful Response:</h3>
|
|
<pre className="flex-1 overflow-auto rounded border bg-gray-50 p-3 font-mono text-xs">
|
|
{JSON.stringify(data.elements, null, 2)}
|
|
</pre>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<ThemePicker />
|
|
</div>
|
|
<div className="bg-background h-full max-h-[calc(100vh-56px)] overflow-y-auto rounded border shadow">
|
|
<DynamicReportEditor value={usedValue} readOnly={false} onValueChange={logValueChanges} />
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
interface ValidationStatusProps {
|
|
isLoading: boolean;
|
|
error: unknown;
|
|
isFetched: boolean;
|
|
data: { elements: ReportElements } | undefined;
|
|
}
|
|
|
|
const ValidationStatus: React.FC<ValidationStatusProps> = ({
|
|
isLoading,
|
|
error,
|
|
isFetched,
|
|
data
|
|
}) => {
|
|
// Determine status and styling
|
|
const getStatusConfig = () => {
|
|
if (isLoading) {
|
|
return {
|
|
bgClass: 'bg-blue-50 border-blue-200',
|
|
textClass: 'text-blue-700',
|
|
iconBg: 'bg-blue-600',
|
|
icon: (
|
|
<div className="h-4 w-4 animate-spin rounded-full border-2 border-blue-600 border-t-transparent"></div>
|
|
),
|
|
message: 'Validating markdown...'
|
|
};
|
|
}
|
|
|
|
if (error && !isLoading) {
|
|
return {
|
|
bgClass: 'bg-red-50 border-red-200',
|
|
textClass: 'text-red-700',
|
|
iconBg: 'bg-red-600',
|
|
icon: (
|
|
<div className="flex h-4 w-4 items-center justify-center rounded-full bg-red-600">
|
|
<span className="text-xs text-white">✕</span>
|
|
</div>
|
|
),
|
|
message: `Validation failed: ${error instanceof Error ? error.message : error || 'Unknown error'}`
|
|
};
|
|
}
|
|
|
|
if (isFetched && !error && !isLoading && data) {
|
|
return {
|
|
bgClass: 'bg-green-50 border-green-400',
|
|
textClass: 'text-green-700',
|
|
iconBg: 'bg-green-600',
|
|
icon: (
|
|
<div className="flex h-4 w-4 items-center justify-center rounded-full bg-green-600">
|
|
<span className="text-xs text-white">✓</span>
|
|
</div>
|
|
),
|
|
message: 'Markdown validated successfully'
|
|
};
|
|
}
|
|
|
|
// Default/ready state
|
|
return {
|
|
bgClass: 'bg-gray-50 border-gray-200',
|
|
textClass: 'text-gray-600',
|
|
iconBg: 'bg-gray-400',
|
|
icon: <div className="h-4 w-4 rounded-full bg-gray-400"></div>,
|
|
message: 'Ready to validate'
|
|
};
|
|
};
|
|
|
|
const config = getStatusConfig();
|
|
|
|
return (
|
|
<div
|
|
className={`flex min-h-8 items-center justify-center rounded border p-4 transition-colors duration-200 ${config.bgClass}`}>
|
|
<div className={`flex items-center space-x-2 ${config.textClass}`}>
|
|
{config.icon}
|
|
<span className="text-sm font-medium">{config.message}</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const ThemePicker = React.memo(() => {
|
|
const { activeTheme, setActiveTheme, allThemes } = useThemesConfig();
|
|
|
|
const themesList = Object.values(allThemes);
|
|
|
|
return (
|
|
<div className="bg-background flex gap-x-2 overflow-x-auto rounded border p-2">
|
|
{themesList.map((theme) => {
|
|
const firstThreeColors = Object.values(theme.light).slice(0, 3);
|
|
|
|
const isActive = activeTheme.id === theme.id;
|
|
return (
|
|
<Tooltip key={theme.id} title={theme.id}>
|
|
<div
|
|
className={cn(
|
|
'min-h-7 min-w-7 cursor-pointer rounded-full border transition-all duration-200 hover:scale-110',
|
|
isActive && 'border-primary shadow-2xl'
|
|
)}
|
|
style={{
|
|
background: `linear-gradient(0deg, hsl(${firstThreeColors[0]}) 0%, hsl(${firstThreeColors[0]}) 33%, hsl(${firstThreeColors[1]}) 33%, hsl(${firstThreeColors[1]}) 66%, hsl(${firstThreeColors[2]}) 66%, hsl(${firstThreeColors[2]}) 100%)`
|
|
}}
|
|
onClick={() => setActiveTheme(theme)}
|
|
title={theme.id}
|
|
/>
|
|
</Tooltip>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
});
|
|
|
|
ThemePicker.displayName = 'ThemePicker';
|
|
|
|
const value: ReportElements = [
|
|
{
|
|
children: [{ text: 'Welcome to the Plate Playground!' }],
|
|
type: 'h1'
|
|
},
|
|
{
|
|
children: [
|
|
{ text: 'Experience a modern rich-text editor built with ' },
|
|
{ children: [{ text: 'Slate' }], type: 'a', url: 'https://slatejs.org' },
|
|
{ text: ' and ' },
|
|
{ children: [{ text: 'React' }], type: 'a', url: 'https://reactjs.org' },
|
|
{
|
|
text: ". This playground showcases just a part of Plate's capabilities. "
|
|
},
|
|
{
|
|
children: [{ text: 'Explore the documentation' }],
|
|
type: 'a',
|
|
url: '/docs'
|
|
},
|
|
{ text: ' to discover more.' }
|
|
],
|
|
type: 'p'
|
|
},
|
|
|
|
{
|
|
children: [{ text: 'Getting Started with Numbered Lists' }],
|
|
type: 'h2'
|
|
},
|
|
{
|
|
children: [{ text: 'Here are the steps to create amazing content with Plate:' }],
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Set up your Plate editor with the desired plugins' }],
|
|
indent: 1,
|
|
listStyleType: 'decimal',
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Configure your editor theme and styling' }],
|
|
indent: 1,
|
|
listStyleType: 'decimal',
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Start typing and explore the rich formatting options' }],
|
|
indent: 1,
|
|
listStyleType: 'decimal',
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Use keyboard shortcuts for faster editing' }],
|
|
indent: 1,
|
|
listStyleType: 'decimal',
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Share your content with the world!' }],
|
|
indent: 1,
|
|
listStyleType: 'decimal',
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: 'You can also create nested numbered lists by increasing the indent level:'
|
|
}
|
|
],
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Main topic one' }],
|
|
indent: 1,
|
|
listStyleType: 'decimal',
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Subtopic A' }],
|
|
indent: 2,
|
|
listStyleType: 'decimal',
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Subtopic B' }],
|
|
indent: 2,
|
|
listStyleType: 'decimal',
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Main topic two' }],
|
|
indent: 1,
|
|
listStyleType: 'decimal',
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Another subtopic' }],
|
|
indent: 2,
|
|
listStyleType: 'decimal',
|
|
type: 'p'
|
|
},
|
|
|
|
// {
|
|
// children: [
|
|
// {
|
|
// text: 'Block-level suggestions are also supported for broader feedback.',
|
|
// },
|
|
// ],
|
|
// suggestion: {
|
|
// suggestionId: 'suggestionBlock1',
|
|
// type: 'block',
|
|
// userId: 'charlie',
|
|
// },
|
|
// type: 'p',
|
|
// },
|
|
// AI Section
|
|
{
|
|
children: [{ text: 'AI-Powered Editing' }],
|
|
type: 'h2'
|
|
},
|
|
{
|
|
children: [
|
|
{ text: 'Boost your productivity with integrated ' },
|
|
{
|
|
children: [{ text: 'AI SDK' }],
|
|
type: 'a',
|
|
url: '/docs/ai'
|
|
},
|
|
{ text: '. Press ' },
|
|
{ kbd: true, text: '⌘+J' },
|
|
{ text: ' or ' },
|
|
{ kbd: true, text: 'Space' },
|
|
{ text: ' in an empty line to:' }
|
|
],
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Generate content (continue writing, summarize, explain)' }],
|
|
indent: 1,
|
|
listStyleType: 'disc',
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Edit existing text (improve, fix grammar, change tone)' }],
|
|
indent: 1,
|
|
listStyleType: 'disc',
|
|
type: 'p'
|
|
},
|
|
// Core Features Section (Combined)
|
|
{
|
|
children: [{ text: 'Rich Content Editing' }],
|
|
type: 'h2'
|
|
},
|
|
{
|
|
children: [
|
|
{ text: 'Structure your content with ' },
|
|
{
|
|
children: [{ text: 'headings' }],
|
|
type: 'a',
|
|
url: '/docs/heading'
|
|
},
|
|
{ text: ', ' },
|
|
{
|
|
children: [{ text: 'lists' }],
|
|
type: 'a',
|
|
url: '/docs/list'
|
|
},
|
|
{ text: ', and ' },
|
|
{
|
|
children: [{ text: 'quotes' }],
|
|
type: 'a',
|
|
url: '/docs/blockquote'
|
|
},
|
|
{ text: '. Apply ' },
|
|
{
|
|
children: [{ text: 'marks' }],
|
|
type: 'a',
|
|
url: '/docs/basic-marks'
|
|
},
|
|
{ text: ' like ' },
|
|
{ bold: true, text: 'bold' },
|
|
{ text: ', ' },
|
|
{ italic: true, text: 'italic' },
|
|
{ text: ', ' },
|
|
{ text: 'underline', underline: true },
|
|
{ text: ', ' },
|
|
{ strikethrough: true, text: 'strikethrough' },
|
|
{ text: ', and ' },
|
|
{ code: true, text: 'code' },
|
|
{ text: '. Use ' },
|
|
{
|
|
children: [{ text: 'autoformatting' }],
|
|
type: 'a',
|
|
url: '/docs/autoformat'
|
|
},
|
|
{ text: ' for ' },
|
|
{
|
|
children: [{ text: 'Markdown' }],
|
|
type: 'a',
|
|
url: '/docs/markdown'
|
|
},
|
|
{ text: '-like shortcuts (e.g., ' },
|
|
{ kbd: true, text: '* ' },
|
|
{ text: ' for lists, ' },
|
|
{ kbd: true, text: '# ' },
|
|
{ text: ' for H1).' }
|
|
],
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [
|
|
{
|
|
text: 'Blockquotes are great for highlighting important information.'
|
|
}
|
|
],
|
|
type: 'p'
|
|
}
|
|
],
|
|
type: 'blockquote'
|
|
},
|
|
{
|
|
children: [
|
|
{ children: [{ text: 'function hello() {' }], type: 'code_line' },
|
|
{
|
|
children: [{ text: " console.info('Code blocks are supported!');" }],
|
|
type: 'code_line'
|
|
},
|
|
{ children: [{ text: '}' }], type: 'code_line' }
|
|
],
|
|
lang: 'javascript',
|
|
type: 'code_block'
|
|
},
|
|
{
|
|
children: [
|
|
{ text: 'Create ' },
|
|
{
|
|
children: [{ text: 'links' }],
|
|
type: 'a',
|
|
url: '/docs/link'
|
|
},
|
|
{ text: ', ' },
|
|
{
|
|
children: [{ text: '@mention' }],
|
|
type: 'a',
|
|
url: '/docs/mention'
|
|
},
|
|
{ text: ' users like ' },
|
|
{ children: [{ text: '' }], type: 'mention', value: 'Alice' },
|
|
{ text: ', or insert ' },
|
|
{
|
|
children: [{ text: 'emojis' }],
|
|
type: 'a',
|
|
url: '/docs/emoji'
|
|
},
|
|
{ text: ' ✨. Use the ' },
|
|
{
|
|
children: [{ text: 'slash command' }],
|
|
type: 'a',
|
|
url: '/docs/slash-command'
|
|
},
|
|
{ text: ' (/) for quick access to elements.' }
|
|
],
|
|
type: 'p'
|
|
},
|
|
// Table Section
|
|
{
|
|
children: [{ text: 'How Plate Compares' }],
|
|
type: 'h3'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: 'Plate offers many features out-of-the-box as free, open-source plugins.'
|
|
}
|
|
],
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [
|
|
{
|
|
children: [{ children: [{ bold: true, text: 'Feature' }], type: 'p' }],
|
|
type: 'th'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [{ bold: true, text: 'Plate (Free & OSS)' }],
|
|
type: 'p'
|
|
}
|
|
],
|
|
type: 'th'
|
|
},
|
|
{
|
|
children: [{ children: [{ bold: true, text: 'Tiptap' }], type: 'p' }],
|
|
type: 'th'
|
|
}
|
|
],
|
|
type: 'tr'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [{ children: [{ text: 'AI' }], type: 'p' }],
|
|
type: 'td'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
attributes: { align: 'center' },
|
|
children: [{ text: '✅' }],
|
|
type: 'p'
|
|
}
|
|
],
|
|
type: 'td'
|
|
},
|
|
{
|
|
children: [{ children: [{ text: 'Paid Extension' }], type: 'p' }],
|
|
type: 'td'
|
|
}
|
|
],
|
|
type: 'tr'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [{ children: [{ text: 'Comments' }], type: 'p' }],
|
|
type: 'td'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
attributes: { align: 'center' },
|
|
children: [{ text: '✅' }],
|
|
type: 'p'
|
|
}
|
|
],
|
|
type: 'td'
|
|
},
|
|
{
|
|
children: [{ children: [{ text: 'Paid Extension' }], type: 'p' }],
|
|
type: 'td'
|
|
}
|
|
],
|
|
type: 'tr'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [{ children: [{ text: 'Suggestions' }], type: 'p' }],
|
|
type: 'td'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
attributes: { align: 'center' },
|
|
children: [{ text: '✅' }],
|
|
type: 'p'
|
|
}
|
|
],
|
|
type: 'td'
|
|
},
|
|
{
|
|
children: [{ children: [{ text: 'Paid (Comments Pro)' }], type: 'p' }],
|
|
type: 'td'
|
|
}
|
|
],
|
|
type: 'tr'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [{ children: [{ text: 'Emoji Picker' }], type: 'p' }],
|
|
type: 'td'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
attributes: { align: 'center' },
|
|
children: [{ text: '✅' }],
|
|
type: 'p'
|
|
}
|
|
],
|
|
type: 'td'
|
|
},
|
|
{
|
|
children: [{ children: [{ text: 'Paid Extension' }], type: 'p' }],
|
|
type: 'td'
|
|
}
|
|
],
|
|
type: 'tr'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [{ children: [{ text: 'Table of Contents' }], type: 'p' }],
|
|
type: 'td'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
attributes: { align: 'center' },
|
|
children: [{ text: '✅' }],
|
|
type: 'p'
|
|
}
|
|
],
|
|
type: 'td'
|
|
},
|
|
{
|
|
children: [{ children: [{ text: 'Paid Extension' }], type: 'p' }],
|
|
type: 'td'
|
|
}
|
|
],
|
|
type: 'tr'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [{ children: [{ text: 'Drag Handle' }], type: 'p' }],
|
|
type: 'td'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
attributes: { align: 'center' },
|
|
children: [{ text: '✅' }],
|
|
type: 'p'
|
|
}
|
|
],
|
|
type: 'td'
|
|
},
|
|
{
|
|
children: [{ children: [{ text: 'Paid Extension' }], type: 'p' }],
|
|
type: 'td'
|
|
}
|
|
],
|
|
type: 'tr'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [{ children: [{ text: 'Collaboration (Yjs)' }], type: 'p' }],
|
|
type: 'td'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
attributes: { align: 'center' },
|
|
children: [{ text: '✅' }],
|
|
type: 'p'
|
|
}
|
|
],
|
|
type: 'td'
|
|
},
|
|
{
|
|
children: [{ children: [{ text: 'Hocuspocus (OSS/Paid)' }], type: 'p' }],
|
|
type: 'td'
|
|
}
|
|
],
|
|
type: 'tr'
|
|
}
|
|
],
|
|
type: 'table'
|
|
},
|
|
// Column layouts
|
|
{
|
|
children: [{ text: 'Column Layouts' }],
|
|
type: 'h3'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: 'Organize content using flexible column layouts. The three-column layout below demonstrates equal-width columns:'
|
|
}
|
|
],
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [
|
|
{
|
|
children: [{ text: 'Column 1' }],
|
|
type: 'h4'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: 'This is the first column with some sample content. You can add any type of content here including text, images, lists, and more.'
|
|
}
|
|
],
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'First item' }],
|
|
indent: 1,
|
|
listStyleType: 'disc',
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Second item' }],
|
|
indent: 1,
|
|
listStyleType: 'disc',
|
|
type: 'p'
|
|
}
|
|
],
|
|
type: 'column',
|
|
width: '33.33%'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [{ text: 'Column 2' }],
|
|
type: 'h4'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: 'The middle column showcases different content types. Here you can see how '
|
|
},
|
|
{ bold: true, text: 'bold text' },
|
|
{ text: ' and ' },
|
|
{ italic: true, text: 'italic text' },
|
|
{ text: ' work within columns.' }
|
|
],
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [
|
|
{
|
|
text: 'Important note: columns are fully responsive and work great on all devices.'
|
|
}
|
|
],
|
|
type: 'p'
|
|
}
|
|
],
|
|
type: 'blockquote'
|
|
}
|
|
],
|
|
type: 'column',
|
|
width: '33.33%'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [{ text: 'Column 3' }],
|
|
type: 'h4'
|
|
},
|
|
{
|
|
children: [
|
|
{ text: 'The third column demonstrates links and other elements. Visit ' },
|
|
{
|
|
children: [{ text: 'Plate documentation' }],
|
|
type: 'a',
|
|
url: '/docs'
|
|
},
|
|
{ text: ' for more information about column layouts.' }
|
|
],
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'You can also add code: ' }],
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ code: true, text: 'console.log("Hello from column 3!");' }],
|
|
type: 'p'
|
|
}
|
|
],
|
|
type: 'column',
|
|
width: '33.33%'
|
|
}
|
|
],
|
|
type: 'column_group'
|
|
},
|
|
{
|
|
children: [{ text: "Here's a two-column layout with different proportions:" }],
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [
|
|
{
|
|
children: [{ text: 'Main Content (70%)' }],
|
|
type: 'h4'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: 'This wider column contains the main content. It takes up 70% of the available width, making it perfect for primary content like articles, detailed descriptions, or main features.'
|
|
}
|
|
],
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'You can include complex content structures:' }],
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [
|
|
{ children: [{ text: 'const createLayout = () => {' }], type: 'code_line' },
|
|
{ children: [{ text: ' return {' }], type: 'code_line' },
|
|
{ children: [{ text: ' columns: 2,' }], type: 'code_line' },
|
|
{ children: [{ text: ' widths: ["70%", "30%"]' }], type: 'code_line' },
|
|
{ children: [{ text: ' };' }], type: 'code_line' },
|
|
{ children: [{ text: '};' }], type: 'code_line' }
|
|
],
|
|
lang: 'javascript',
|
|
type: 'code_block'
|
|
}
|
|
],
|
|
type: 'column',
|
|
width: '70%'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
children: [{ text: 'Sidebar (30%)' }],
|
|
type: 'h4'
|
|
},
|
|
{
|
|
children: [{ text: 'This narrower column works well for:' }],
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Sidebars' }],
|
|
indent: 1,
|
|
listStyleType: 'disc',
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Navigation menus' }],
|
|
indent: 1,
|
|
listStyleType: 'disc',
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Call-to-action buttons' }],
|
|
indent: 1,
|
|
listStyleType: 'disc',
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [{ text: 'Quick facts' }],
|
|
indent: 1,
|
|
listStyleType: 'disc',
|
|
type: 'p'
|
|
},
|
|
{
|
|
children: [
|
|
{ text: 'The smaller width makes it perfect for supplementary information.' }
|
|
],
|
|
type: 'p'
|
|
}
|
|
],
|
|
type: 'column',
|
|
width: '30%'
|
|
}
|
|
],
|
|
type: 'column_group'
|
|
},
|
|
// Media Section
|
|
{
|
|
children: [{ text: 'Images and Media' }],
|
|
type: 'h3'
|
|
},
|
|
{
|
|
children: [
|
|
{
|
|
text: 'Embed rich media like images directly in your content. Supports '
|
|
},
|
|
{
|
|
children: [{ text: 'Media uploads' }],
|
|
type: 'a',
|
|
url: '/docs/media'
|
|
},
|
|
{
|
|
text: ' and '
|
|
},
|
|
{
|
|
children: [{ text: 'drag & drop' }],
|
|
type: 'a',
|
|
url: '/docs/dnd'
|
|
},
|
|
{
|
|
text: ' for a smooth experience.'
|
|
}
|
|
],
|
|
type: 'p'
|
|
},
|
|
{
|
|
attributes: { align: 'center' },
|
|
caption: [
|
|
{
|
|
children: [{ text: 'Images with captions provide context.' }],
|
|
type: 'p'
|
|
}
|
|
],
|
|
children: [{ text: '' }],
|
|
type: 'img',
|
|
url: 'https://images.unsplash.com/photo-1712688930249-98e1963af7bd?q=80&w=600&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
|
|
width: '75%'
|
|
},
|
|
{
|
|
children: [{ text: '' }],
|
|
isUpload: true,
|
|
name: 'sample.pdf',
|
|
type: 'file',
|
|
url: 'https://s26.q4cdn.com/900411403/files/doc_downloads/test.pdf'
|
|
},
|
|
{
|
|
children: [{ text: '' }],
|
|
type: 'audio',
|
|
url: 'https://samplelib.com/lib/preview/mp3/sample-3s.mp3'
|
|
},
|
|
{
|
|
children: [{ text: 'Table of Contents' }],
|
|
type: 'h3'
|
|
},
|
|
{
|
|
children: [{ text: '' }],
|
|
type: 'toc'
|
|
},
|
|
{
|
|
children: [{ text: '' }],
|
|
type: 'p'
|
|
}
|
|
];
|