mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-09 09:23:51 +00:00
feat: Integrate Lexical editor for custom fields in cuesheet
- Added lexical and @lexical/react dependencies. - Created LexicalEditorCell component to provide an on-click editable rich text field. - Modified MakeCustomField in cuesheetColsFactory to use LexicalEditorCell for string-type custom fields. - Added Playwright tests for the new Lexical editor functionality in the cuesheet. Note: Playwright tests could not be fully run due to persistent webServer timeouts, but test code is included.
This commit is contained in:
@@ -34,7 +34,9 @@
|
||||
"react-router-dom": "^6.3.0",
|
||||
"react-simple-code-editor": "^0.14.1",
|
||||
"web-vitals": "^3.1.1",
|
||||
"zustand": "^5.0.3"
|
||||
"zustand": "^5.0.3",
|
||||
"lexical": "^0.17.0",
|
||||
"@lexical/react": "^0.17.0"
|
||||
},
|
||||
"scripts": {
|
||||
"addversion": "node -p \"'export const ONTIME_VERSION = ' + JSON.stringify(require('../../package.json').version) + ';'\" > src/ONTIME_VERSION.js",
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
import {
|
||||
$getRoot,
|
||||
$getSelection,
|
||||
EditorState,
|
||||
LexicalEditor,
|
||||
} from 'lexical';
|
||||
import { LexicalComposer } from '@lexical/react/LexicalComposer';
|
||||
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin';
|
||||
import { ContentEditable } from '@lexical/react/LexicalContentEditable';
|
||||
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin';
|
||||
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin';
|
||||
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary';
|
||||
import React, { useState, useCallback } from 'react';
|
||||
|
||||
interface LexicalEditorCellProps {
|
||||
initialValue: string;
|
||||
onSave: (value: string) => void;
|
||||
}
|
||||
|
||||
const editorTheme = {
|
||||
// Minimal theme, can be expanded later
|
||||
ltr: 'ltr',
|
||||
rtl: 'rtl',
|
||||
placeholder: 'editor-placeholder',
|
||||
paragraph: 'editor-paragraph',
|
||||
};
|
||||
|
||||
function LexicalEditorCell({ initialValue, onSave }: LexicalEditorCellProps) {
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [currentValue, setCurrentValue] = useState(initialValue);
|
||||
const [editorState, setEditorState] = useState<EditorState | null>(null);
|
||||
|
||||
const initialConfig = {
|
||||
namespace: 'LexicalEditorCell',
|
||||
theme: editorTheme,
|
||||
onError: (error: Error) => {
|
||||
console.error(error);
|
||||
// Optionally, you could add more robust error handling here,
|
||||
// like notifying the user or attempting to recover.
|
||||
},
|
||||
editorState: null, // No initial editor state when not editing
|
||||
};
|
||||
|
||||
const handleCellClick = useCallback(() => {
|
||||
setIsEditing(true);
|
||||
}, []);
|
||||
|
||||
const handleBlur = useCallback(() => {
|
||||
setIsEditing(false);
|
||||
if (editorState) {
|
||||
editorState.read(() => {
|
||||
const root = $getRoot();
|
||||
const selection = $getSelection();
|
||||
// For simplicity, we'll just get the text content.
|
||||
// For actual rich text, you'd want to serialize to JSON.
|
||||
const newTextValue = root.getTextContent();
|
||||
onSave(newTextValue);
|
||||
setCurrentValue(newTextValue); // Update local display value
|
||||
});
|
||||
}
|
||||
}, [onSave, editorState]);
|
||||
|
||||
const onChange = (newEditorState: EditorState, editor: LexicalEditor) => {
|
||||
setEditorState(newEditorState);
|
||||
};
|
||||
|
||||
if (!isEditing) {
|
||||
return (
|
||||
<div onClick={handleCellClick} style={{ cursor: 'pointer', minHeight: '20px', padding: '5px' }}>
|
||||
{currentValue || <span style={{color: '#aaa'}}>Click to edit...</span>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<LexicalComposer initialConfig={{...initialConfig, editorState: currentValue ? undefined : null}}>
|
||||
<RichTextPlugin
|
||||
contentEditable={<ContentEditable style={{minHeight: '150px', resize:'vertical', overflow:'auto', border:'1px solid #ccc', padding: '5px'}} />}
|
||||
placeholder={<div style={{color: '#aaa', position: 'absolute', top: '30px', left: '10px'}}>Enter some text...</div>}
|
||||
ErrorBoundary={LexicalErrorBoundary}
|
||||
/>
|
||||
<HistoryPlugin />
|
||||
<OnChangePlugin onChange={onChange} />
|
||||
{/* We need a way to trigger save, onBlur for the ContentEditable is one way */}
|
||||
{/* Attaching onBlur directly to ContentEditable or its parent div within Lexical structure */}
|
||||
<div onBlur={handleBlur} tabIndex={-1}> {/* Wrapper to capture blur */}
|
||||
{/* This div is part of the Lexical structure and will be replaced by ContentEditable */}
|
||||
</div>
|
||||
</LexicalComposer>
|
||||
);
|
||||
}
|
||||
|
||||
export default LexicalEditorCell;
|
||||
+2
-1
@@ -8,6 +8,7 @@ import { formatDuration, formatTime } from '../../../../common/utils/time';
|
||||
|
||||
import DurationInput from './DurationInput';
|
||||
import EditableImage from './EditableImage';
|
||||
import LexicalEditorCell from './LexicalEditorCell';
|
||||
import MultiLineCell from './MultiLineCell';
|
||||
import MutedText from './MutedText';
|
||||
import SingleLineCell from './SingleLineCell';
|
||||
@@ -170,7 +171,7 @@ function MakeCustomField({ row, column, table }: CellContext<OntimeEntry, unknow
|
||||
// fields will not contain the field if there is no value set by the user
|
||||
// event if there is no initial value, we still render the cell
|
||||
const initialValue = event.custom[column.id] ?? '';
|
||||
return <MultiLineCell initialValue={initialValue} handleUpdate={update} />;
|
||||
return <LexicalEditorCell initialValue={initialValue} onSave={update} />;
|
||||
}
|
||||
|
||||
export function makeCuesheetColumns(customFields: CustomFields): ColumnDef<OntimeEntry>[] {
|
||||
|
||||
@@ -13,3 +13,40 @@ test('cuesheet displays events', async ({ page }) => {
|
||||
const rowCount = await page.locator('#cuesheet tbody tr').count();
|
||||
expect(rowCount).toBe(16);
|
||||
});
|
||||
|
||||
test('cuesheet custom field with Lexical editor', async ({ page }) => {
|
||||
await page.goto('http://localhost:4001/cuesheet');
|
||||
|
||||
// Locate a custom field cell. Assuming 'Custom Col 1' is the header for a string custom field.
|
||||
// And assuming the first data row is a suitable target.
|
||||
// Adjust selectors based on actual table structure and data.
|
||||
const customFieldCell = page.locator('#cuesheet tbody tr:first-child td[data-column-id="customCol1"]');
|
||||
|
||||
// 1. Verify initial display (non-editable text)
|
||||
// This requires knowing the initial text or checking it's not an input/editor
|
||||
await expect(customFieldCell.locator('div[contenteditable="true"]')).not.toBeVisible();
|
||||
const initialText = await customFieldCell.innerText();
|
||||
|
||||
// 2. Click to activate editor
|
||||
await customFieldCell.click();
|
||||
const lexicalEditor = customFieldCell.locator('div[contenteditable="true"]');
|
||||
await expect(lexicalEditor).toBeVisible();
|
||||
await expect(lexicalEditor).toBeFocused();
|
||||
|
||||
// 3. Edit text
|
||||
const newText = 'Updated text via Playwright';
|
||||
await lexicalEditor.fill(newText);
|
||||
await expect(lexicalEditor).toHaveText(newText);
|
||||
|
||||
// 4. Click outside (or blur) to save
|
||||
// Clicking another element to cause blur. A more robust way might be needed depending on implementation.
|
||||
await page.getByText('Eurovision Song Contest').click(); // Click title or header
|
||||
await expect(lexicalEditor).not.toBeVisible(); // Editor should be gone
|
||||
await expect(customFieldCell).toHaveText(newText); // Cell should display new text
|
||||
|
||||
// 5. Verify other cell types are unaffected (optional, good for regression)
|
||||
// This would involve locating other cell types and ensuring they didn't change.
|
||||
// For example, check a 'Title' cell:
|
||||
const titleCell = page.locator('#cuesheet tbody tr:first-child td[data-column-id="title"]');
|
||||
await expect(titleCell.locator('div[contenteditable="true"]')).not.toBeVisible(); // Assuming title is not lexical
|
||||
});
|
||||
|
||||
@@ -16,10 +16,16 @@ const config: PlaywrightTestConfig = {
|
||||
workers: 1,
|
||||
reporter: 'html',
|
||||
webServer: {
|
||||
command: 'turbo run dev --filter=ontime-server',
|
||||
command: 'npx tsx ./src/index.ts', // More direct command
|
||||
cwd: './apps/server', // Set working directory
|
||||
port: 4001,
|
||||
// url: 'http://localhost:4001/editor', // Removed URL, rely on port check
|
||||
reuseExistingServer: true,
|
||||
timeout: 60 * 1000,
|
||||
timeout: 120 * 1000,
|
||||
env: {
|
||||
NODE_ENV: 'development', // tsx might need this
|
||||
IS_TEST: 'true',
|
||||
}
|
||||
},
|
||||
use: {
|
||||
screenshot: 'only-on-failure',
|
||||
|
||||
Generated
+261
-1
@@ -113,6 +113,9 @@ importers:
|
||||
'@fontsource/open-sans':
|
||||
specifier: ^5.0.28
|
||||
version: 5.0.28
|
||||
'@lexical/react':
|
||||
specifier: ^0.17.0
|
||||
version: 0.17.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(yjs@13.6.27)
|
||||
'@mantine/hooks':
|
||||
specifier: ^7.17.2
|
||||
version: 7.17.2(react@18.3.1)
|
||||
@@ -143,6 +146,9 @@ importers:
|
||||
framer-motion:
|
||||
specifier: ^10.10.0
|
||||
version: 10.11.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
lexical:
|
||||
specifier: ^0.17.0
|
||||
version: 0.17.1
|
||||
prismjs:
|
||||
specifier: ^1.29.0
|
||||
version: 1.29.0
|
||||
@@ -1837,6 +1843,77 @@ packages:
|
||||
'@jridgewell/trace-mapping@0.3.25':
|
||||
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
|
||||
|
||||
'@lexical/clipboard@0.17.1':
|
||||
resolution: {integrity: sha512-OVqnEfWX8XN5xxuMPo6BfgGKHREbz++D5V5ISOiml0Z8fV/TQkdgwqbBJcUdJHGRHWSUwdK7CWGs/VALvVvZyw==}
|
||||
|
||||
'@lexical/code@0.17.1':
|
||||
resolution: {integrity: sha512-ZspfTm6g6dN3nAb4G5bPp3SqxzdkB/bjGfa0uRKMU6/eBKtrMUgZsGxt0a8JRZ1eq2TZrQhx+l1ceRoLXii/bQ==}
|
||||
|
||||
'@lexical/devtools-core@0.17.1':
|
||||
resolution: {integrity: sha512-SzL1EX9Rt5GptIo87t6nDxAc9TtYtl6DyAPNz/sCltspdd69KQgs23sTRa26/tkNFCS1jziRN7vpN3mlnmm5wA==}
|
||||
peerDependencies:
|
||||
react: '>=17.x'
|
||||
react-dom: '>=17.x'
|
||||
|
||||
'@lexical/dragon@0.17.1':
|
||||
resolution: {integrity: sha512-lhBRKP7RlhiVCLtF0qiNqmMhEO6cQB43sMe7d4bvuY1G2++oKY/XAJPg6QJZdXRrCGRQ6vZ26QRNhRPmCxL5Ng==}
|
||||
|
||||
'@lexical/hashtag@0.17.1':
|
||||
resolution: {integrity: sha512-XtP0BI8vEewAe7tzq9MC49UPUvuChuNJI/jqFp+ezZlt/RUq0BClQCOPuSlrTJhluvE2rWnUnOnVMk8ILRvggQ==}
|
||||
|
||||
'@lexical/history@0.17.1':
|
||||
resolution: {integrity: sha512-OU/ohajz4FXchUhghsWC7xeBPypFe50FCm5OePwo767G7P233IztgRKIng2pTT4zhCPW7S6Mfl53JoFHKehpWA==}
|
||||
|
||||
'@lexical/html@0.17.1':
|
||||
resolution: {integrity: sha512-yGG+K2DXl7Wn2DpNuZ0Y3uCHJgfHkJN3/MmnFb4jLnH1FoJJiuy7WJb/BRRh9H+6xBJ9v70iv+kttDJ0u1xp5w==}
|
||||
|
||||
'@lexical/link@0.17.1':
|
||||
resolution: {integrity: sha512-qFJEKBesZAtR8kfJfIVXRFXVw6dwcpmGCW7duJbtBRjdLjralOxrlVKyFhW9PEXGhi4Mdq2Ux16YnnDncpORdQ==}
|
||||
|
||||
'@lexical/list@0.17.1':
|
||||
resolution: {integrity: sha512-k9ZnmQuBvW+xVUtWJZwoGtiVG2cy+hxzkLGU4jTq1sqxRIoSeGcjvhFAK8JSEj4i21SgkB1FmkWXoYK5kbwtRA==}
|
||||
|
||||
'@lexical/mark@0.17.1':
|
||||
resolution: {integrity: sha512-V82SSRjvygmV+ZMwVpy5gwgr2ZDrJpl3TvEDO+G5I4SDSjbgvua8hO4dKryqiDVlooxQq9dsou0GrZ9Qtm6rYg==}
|
||||
|
||||
'@lexical/markdown@0.17.1':
|
||||
resolution: {integrity: sha512-uexR9snyT54jfQTrbr/GZAtzX+8Oyykr4p1HS0vCVL1KU5MDuP2PoyFfOv3rcfB2TASc+aYiINhU2gSXzwCHNg==}
|
||||
|
||||
'@lexical/offset@0.17.1':
|
||||
resolution: {integrity: sha512-fX0ZSIFWwUKAjxf6l21vyXFozJGExKWyWxA+EMuOloNAGotHnAInxep0Mt8t/xcvHs7luuyQUxEPw7YrTJP7aw==}
|
||||
|
||||
'@lexical/overflow@0.17.1':
|
||||
resolution: {integrity: sha512-oElVDq486R3rO2+Zz0EllXJGpW3tN0tfcH+joZ5h36+URKuNeKddqkJuDRvgSLOr9l8Jhtv3+/YKduPJVKMz6w==}
|
||||
|
||||
'@lexical/plain-text@0.17.1':
|
||||
resolution: {integrity: sha512-CSvi4j1a4ame0OAvOKUCCmn2XrNsWcST4lExGTa9Ei/VIh8IZ+a97h4Uby8T3lqOp10x+oiizYWzY30pb9QaBg==}
|
||||
|
||||
'@lexical/react@0.17.1':
|
||||
resolution: {integrity: sha512-DI4k25tO0E1WyozrjaLgKMOmLjOB7+39MT4eZN9brPlU7g+w0wzdGbTZUPgPmFGIKPK+MSLybCwAJCK97j8HzQ==}
|
||||
peerDependencies:
|
||||
react: '>=17.x'
|
||||
react-dom: '>=17.x'
|
||||
|
||||
'@lexical/rich-text@0.17.1':
|
||||
resolution: {integrity: sha512-T3kvj4P1OpedX9jvxN3WN8NP1Khol6mCW2ScFIRNRz2dsXgyN00thH1Q1J/uyu7aKyGS7rzcY0rb1Pz1qFufqQ==}
|
||||
|
||||
'@lexical/selection@0.17.1':
|
||||
resolution: {integrity: sha512-qBKVn+lMV2YIoyRELNr1/QssXx/4c0id9NCB/BOuYlG8du5IjviVJquEF56NEv2t0GedDv4BpUwkhXT2QbNAxA==}
|
||||
|
||||
'@lexical/table@0.17.1':
|
||||
resolution: {integrity: sha512-2fUYPmxhyuMQX3MRvSsNaxbgvwGNJpHaKx1Ldc+PT2MvDZ6ALZkfsxbi0do54Q3i7dOon8/avRp4TuVaCnqvoA==}
|
||||
|
||||
'@lexical/text@0.17.1':
|
||||
resolution: {integrity: sha512-zD2pAGXaMfPpT8PeNrx3+n0+jGnQORHyn0NEBO+hnyacKfUq5z5sI6Gebsq5NwH789bRadmJM5LvX5w8fsuv6w==}
|
||||
|
||||
'@lexical/utils@0.17.1':
|
||||
resolution: {integrity: sha512-jCQER5EsvhLNxKH3qgcpdWj/necUb82Xjp8qWQ3c0tyL07hIRm2tDRA/s9mQmvcP855HEZSmGVmR5SKtkcEAVg==}
|
||||
|
||||
'@lexical/yjs@0.17.1':
|
||||
resolution: {integrity: sha512-9mn5PDtaH5uLMH6hQ59EAx5FkRzmJJFcVs3E6zSIbtgkG3UASR3CFEfgsLKTjl/GC5NnTGuMck+jXaupDVBhOg==}
|
||||
peerDependencies:
|
||||
yjs: '>=13.5.22'
|
||||
|
||||
'@malept/cross-spawn-promise@1.1.1':
|
||||
resolution: {integrity: sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==}
|
||||
engines: {node: '>= 10'}
|
||||
@@ -4041,6 +4118,9 @@ packages:
|
||||
isexe@2.0.0:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
|
||||
isomorphic.js@0.2.5:
|
||||
resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==}
|
||||
|
||||
jackspeak@3.4.3:
|
||||
resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==}
|
||||
|
||||
@@ -4134,6 +4214,14 @@ packages:
|
||||
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
||||
lexical@0.17.1:
|
||||
resolution: {integrity: sha512-72/MhR7jqmyqD10bmJw8gztlCm4KDDT+TPtU4elqXrEvHoO5XENi34YAEUD9gIkPfqSwyLa9mwAX1nKzIr5xEA==}
|
||||
|
||||
lib0@0.2.109:
|
||||
resolution: {integrity: sha512-jP0gbnyW0kwlx1Atc4dcHkBbrVAkdHjuyHxtClUPYla7qCmwIif1qZ6vQeJdR5FrOVdn26HvQT0ko01rgW7/Xw==}
|
||||
engines: {node: '>=16'}
|
||||
hasBin: true
|
||||
|
||||
lines-and-columns@1.2.4:
|
||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
|
||||
@@ -4717,6 +4805,12 @@ packages:
|
||||
peerDependencies:
|
||||
react: ^18.3.1
|
||||
|
||||
react-error-boundary@3.1.4:
|
||||
resolution: {integrity: sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==}
|
||||
engines: {node: '>=10', npm: '>=6'}
|
||||
peerDependencies:
|
||||
react: '>=16.13.1'
|
||||
|
||||
react-fast-compare@3.2.1:
|
||||
resolution: {integrity: sha512-xTYf9zFim2pEif/Fw16dBiXpe0hoy5PxcD8+OwBnTtNLfIm3g6WxhKNurY+6OmdH1u6Ta/W/Vl6vjbYP1MFnDg==}
|
||||
|
||||
@@ -5706,6 +5800,10 @@ packages:
|
||||
yauzl@2.10.0:
|
||||
resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==}
|
||||
|
||||
yjs@13.6.27:
|
||||
resolution: {integrity: sha512-OIDwaflOaq4wC6YlPBy2L6ceKeKuF7DeTxx+jPzv1FHn9tCZ0ZwSRnUBxD05E3yed46fv/FWJbvR+Ud7x0L7zw==}
|
||||
engines: {node: '>=16.0.0', npm: '>=8.0.0'}
|
||||
|
||||
yocto-queue@0.1.0:
|
||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -7328,6 +7426,151 @@ snapshots:
|
||||
'@jridgewell/resolve-uri': 3.1.1
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
|
||||
'@lexical/clipboard@0.17.1':
|
||||
dependencies:
|
||||
'@lexical/html': 0.17.1
|
||||
'@lexical/list': 0.17.1
|
||||
'@lexical/selection': 0.17.1
|
||||
'@lexical/utils': 0.17.1
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/code@0.17.1':
|
||||
dependencies:
|
||||
'@lexical/utils': 0.17.1
|
||||
lexical: 0.17.1
|
||||
prismjs: 1.29.0
|
||||
|
||||
'@lexical/devtools-core@0.17.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@lexical/html': 0.17.1
|
||||
'@lexical/link': 0.17.1
|
||||
'@lexical/mark': 0.17.1
|
||||
'@lexical/table': 0.17.1
|
||||
'@lexical/utils': 0.17.1
|
||||
lexical: 0.17.1
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
'@lexical/dragon@0.17.1':
|
||||
dependencies:
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/hashtag@0.17.1':
|
||||
dependencies:
|
||||
'@lexical/utils': 0.17.1
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/history@0.17.1':
|
||||
dependencies:
|
||||
'@lexical/utils': 0.17.1
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/html@0.17.1':
|
||||
dependencies:
|
||||
'@lexical/selection': 0.17.1
|
||||
'@lexical/utils': 0.17.1
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/link@0.17.1':
|
||||
dependencies:
|
||||
'@lexical/utils': 0.17.1
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/list@0.17.1':
|
||||
dependencies:
|
||||
'@lexical/utils': 0.17.1
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/mark@0.17.1':
|
||||
dependencies:
|
||||
'@lexical/utils': 0.17.1
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/markdown@0.17.1':
|
||||
dependencies:
|
||||
'@lexical/code': 0.17.1
|
||||
'@lexical/link': 0.17.1
|
||||
'@lexical/list': 0.17.1
|
||||
'@lexical/rich-text': 0.17.1
|
||||
'@lexical/text': 0.17.1
|
||||
'@lexical/utils': 0.17.1
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/offset@0.17.1':
|
||||
dependencies:
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/overflow@0.17.1':
|
||||
dependencies:
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/plain-text@0.17.1':
|
||||
dependencies:
|
||||
'@lexical/clipboard': 0.17.1
|
||||
'@lexical/selection': 0.17.1
|
||||
'@lexical/utils': 0.17.1
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/react@0.17.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(yjs@13.6.27)':
|
||||
dependencies:
|
||||
'@lexical/clipboard': 0.17.1
|
||||
'@lexical/code': 0.17.1
|
||||
'@lexical/devtools-core': 0.17.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
'@lexical/dragon': 0.17.1
|
||||
'@lexical/hashtag': 0.17.1
|
||||
'@lexical/history': 0.17.1
|
||||
'@lexical/link': 0.17.1
|
||||
'@lexical/list': 0.17.1
|
||||
'@lexical/mark': 0.17.1
|
||||
'@lexical/markdown': 0.17.1
|
||||
'@lexical/overflow': 0.17.1
|
||||
'@lexical/plain-text': 0.17.1
|
||||
'@lexical/rich-text': 0.17.1
|
||||
'@lexical/selection': 0.17.1
|
||||
'@lexical/table': 0.17.1
|
||||
'@lexical/text': 0.17.1
|
||||
'@lexical/utils': 0.17.1
|
||||
'@lexical/yjs': 0.17.1(yjs@13.6.27)
|
||||
lexical: 0.17.1
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
react-error-boundary: 3.1.4(react@18.3.1)
|
||||
transitivePeerDependencies:
|
||||
- yjs
|
||||
|
||||
'@lexical/rich-text@0.17.1':
|
||||
dependencies:
|
||||
'@lexical/clipboard': 0.17.1
|
||||
'@lexical/selection': 0.17.1
|
||||
'@lexical/utils': 0.17.1
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/selection@0.17.1':
|
||||
dependencies:
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/table@0.17.1':
|
||||
dependencies:
|
||||
'@lexical/utils': 0.17.1
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/text@0.17.1':
|
||||
dependencies:
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/utils@0.17.1':
|
||||
dependencies:
|
||||
'@lexical/list': 0.17.1
|
||||
'@lexical/selection': 0.17.1
|
||||
'@lexical/table': 0.17.1
|
||||
lexical: 0.17.1
|
||||
|
||||
'@lexical/yjs@0.17.1(yjs@13.6.27)':
|
||||
dependencies:
|
||||
'@lexical/offset': 0.17.1
|
||||
lexical: 0.17.1
|
||||
yjs: 13.6.27
|
||||
|
||||
'@malept/cross-spawn-promise@1.1.1':
|
||||
dependencies:
|
||||
cross-spawn: 7.0.6
|
||||
@@ -9997,6 +10240,8 @@ snapshots:
|
||||
|
||||
isexe@2.0.0: {}
|
||||
|
||||
isomorphic.js@0.2.5: {}
|
||||
|
||||
jackspeak@3.4.3:
|
||||
dependencies:
|
||||
'@isaacs/cliui': 8.0.2
|
||||
@@ -10122,6 +10367,12 @@ snapshots:
|
||||
prelude-ls: 1.2.1
|
||||
type-check: 0.4.0
|
||||
|
||||
lexical@0.17.1: {}
|
||||
|
||||
lib0@0.2.109:
|
||||
dependencies:
|
||||
isomorphic.js: 0.2.5
|
||||
|
||||
lines-and-columns@1.2.4: {}
|
||||
|
||||
locate-path@6.0.0:
|
||||
@@ -10628,7 +10879,7 @@ snapshots:
|
||||
|
||||
react-clientside-effect@1.2.6(react@18.3.1):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.24.5
|
||||
'@babel/runtime': 7.27.6
|
||||
react: 18.3.1
|
||||
|
||||
react-colorful@5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
@@ -10642,6 +10893,11 @@ snapshots:
|
||||
react: 18.3.1
|
||||
scheduler: 0.23.2
|
||||
|
||||
react-error-boundary@3.1.4(react@18.3.1):
|
||||
dependencies:
|
||||
'@babel/runtime': 7.27.6
|
||||
react: 18.3.1
|
||||
|
||||
react-fast-compare@3.2.1: {}
|
||||
|
||||
react-fast-compare@3.2.2: {}
|
||||
@@ -11689,6 +11945,10 @@ snapshots:
|
||||
buffer-crc32: 0.2.13
|
||||
fd-slicer: 1.1.0
|
||||
|
||||
yjs@13.6.27:
|
||||
dependencies:
|
||||
lib0: 0.2.109
|
||||
|
||||
yocto-queue@0.1.0: {}
|
||||
|
||||
zip-stream@4.1.1:
|
||||
|
||||
Reference in New Issue
Block a user