Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6d7d2e7
[lexical-playground] Feature: Add PagesExtension and enhance print st…
ibastawisi Apr 9, 2026
ade5af8
[lexical-playground] Add print styles to hide page-break elements
ibastawisi Apr 9, 2026
80740b8
[lexical-playground] Refactor PageNode and PageContentNode to use $co…
ibastawisi Apr 10, 2026
e09860b
[lexical-playground] Refactor PageSetupNode to utilize NodeState
ibastawisi Apr 10, 2026
63857b2
[lexical-playground] Remove unused DOM conversion and export methods …
ibastawisi Apr 10, 2026
50ed58c
Refactor PageSetupNode to RootNode state
etrepum Apr 10, 2026
6e576a4
Lift measurement from PageNode statics to extension state
etrepum Apr 10, 2026
e2c0b16
clean up measurement update
etrepum Apr 10, 2026
a214ad5
Make the extension mostly self-contained
etrepum Apr 10, 2026
d6a2899
provide signal for observing pageSetup
etrepum Apr 10, 2026
7671a82
Split extension into PagesExtension and PagesReactExtension, refactor…
etrepum Apr 10, 2026
d92bd21
remove unneeded import
etrepum Apr 10, 2026
609254d
set onnxruntime-node-install=skip to avoid fetching binaries we do no…
etrepum Apr 10, 2026
7ce8871
use $create in PageContentNode
etrepum Apr 10, 2026
5028abc
Merge branch 'main' into pages
etrepum Apr 10, 2026
6a7f25d
Export marginsIsEqual function for margin comparison and update PageS…
ibastawisi Apr 11, 2026
e6cab8d
Refactor PageSetupDropdown to prevent event propagation on item click…
ibastawisi Apr 11, 2026
fd290eb
Remove unused page setup node selection handling from PagesExtension.
ibastawisi Apr 11, 2026
928c1c0
Refactor PagesExtension to streamline page measurement and structure …
ibastawisi Apr 11, 2026
27a481e
Refactor PageNode and PagesExtension to remove the measurement logic …
ibastawisi Apr 11, 2026
3cc6e96
use editor context in dev tools generateContent
etrepum Apr 11, 2026
4dab534
Merge branch 'main' into pages
etrepum Apr 11, 2026
eb3c183
Merge branch 'main' into pages
etrepum Apr 11, 2026
e95b85f
Add CSS rule to hide page-break elements in paged mode
ibastawisi Apr 11, 2026
20e33f2
Refactor PagesExtension registration to ensure page dimensions are up…
ibastawisi Apr 11, 2026
370029a
Enhance PagesExtension functionality by adding node selection and imp…
ibastawisi Apr 11, 2026
2fc5f67
Merge remote-tracking branch 'origin/main' into pages
etrepum Apr 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,5 @@ npm-debug.log*
.idea/**/shelf

.idea

.claude
2 changes: 2 additions & 0 deletions packages/lexical-playground/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import {EmojisExtension} from './plugins/EmojisExtension';
import {ImagesExtension} from './plugins/ImagesExtension';
import {PlaygroundMarkdownShortcutsExtension} from './plugins/MarkdownShortcutsExtension';
import {MaxLengthExtension} from './plugins/MaxLengthPlugin';
import {PagesExtension} from './plugins/PagesExtension';
import PasteLogPlugin from './plugins/PasteLogPlugin';
import TestRecorderPlugin from './plugins/TestRecorderPlugin';
import TypingPerfPlugin from './plugins/TypingPerfPlugin';
Expand Down Expand Up @@ -174,6 +175,7 @@ const AppExtension = defineExtension({
HashtagExtension,
DateTimeExtension,
MaxLengthExtension,
PagesExtension,
DragDropPasteExtension,
EmojisExtension,
configExtension(LinkExtension, {validateUrl}),
Expand Down
68 changes: 67 additions & 1 deletion packages/lexical-playground/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ header h1 {
.editor-shell {
margin: 20px auto;
border-radius: 2px;
max-width: 1100px;
max-width: 1128px;
color: #000;
position: relative;
line-height: 1.7;
Expand Down Expand Up @@ -95,6 +95,52 @@ header h1 {
z-index: -1;
}

@media print {
* {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}

*,
*:before,
*:after {
filter: unset !important;
color-scheme: light !important;
}

body {
padding: 0 !important;
margin: 0 !important;
background: none !important;
}

body
*:not(
[data-lexical-editor],
[data-lexical-editor] *,
:has([data-lexical-editor])
) {
display: none !important;
}

.editor-shell {
margin: 0 !important;
border-radius: 0 !important;
max-width: none !important;
}

[data-lexical-editor] {
padding: 0 !important;
margin: 0 !important;
border: none !important;
box-shadow: none !important;
max-width: none !important;
width: 100% !important;
height: auto !important;
zoom: 1 !important;
}
}

.test-recorder-output {
margin: 20px auto 20px auto;
width: 100%;
Expand Down Expand Up @@ -609,6 +655,11 @@ i.page-break,
background-image: url(images/icons/scissors.svg);
}

i.page-setup,
.icon.page-setup {
background-image: url(images/icons/file-earmark-text.svg);
}

.link-editor .button.active,
.toolbar .button.active {
background-color: rgb(223, 232, 250);
Expand Down Expand Up @@ -829,6 +880,21 @@ i.page-break,
min-width: 150px;
}

.dropdown .item.dropdown-submenu-trigger .dropdown-submenu-chevron {
flex-shrink: 0;
margin-left: 8px;
transform: rotate(0deg);
transition: transform 0.15s ease;
}

.dropdown .item.dropdown-submenu-trigger.expanded .dropdown-submenu-chevron {
transform: rotate(180deg);
}

.dropdown .item.dropdown-submenu-item {
padding-left: 24px;
}

.dropdown .item .icon {
display: flex;
width: 20px;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,9 @@
.selected[type='page-break']::before {
opacity: 1;
}

@media print {
[type='page-break'] {
visibility: hidden;
}
}
77 changes: 77 additions & 0 deletions packages/lexical-playground/src/nodes/PageNode/PageContentNode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import type {LexicalNode, SerializedElementNode} from 'lexical';

import {ElementNode} from 'lexical';

import {$isPageNode, PageNode} from './PageNode';

export type SerializedPageContentNode = SerializedElementNode;

export class PageContentNode extends ElementNode {
$config() {
return this.config('page-content', {
extends: ElementNode,
});
}

createDOM(): HTMLElement {
const dom = document.createElement('div');
dom.className = 'PlaygroundEditorTheme__pageContent';
return dom;
}

updateDOM(): boolean {
return false;
}

getPageNode(): PageNode {
const parent = this.getParent();
if (!$isPageNode(parent))
throw new Error('PageContentNode: Parent is not a PageNode');
return parent;
}

isShadowRoot(): boolean {
return true;
}

excludeFromCopy(): boolean {
return true;
}

canInsertTextBefore(): boolean {
return false;
}

canInsertTextAfter(): boolean {
return false;
}

exportJSON(): SerializedPageContentNode {
return {
...super.exportJSON(),
type: 'page-content',
version: 1,
};
}

canBeEmpty(): boolean {
return false;
}
}

export function $createPageContentNode(): PageContentNode {
return new PageContentNode();
}

export function $isPageContentNode(
node: LexicalNode | null | undefined,
): node is PageContentNode {
return node instanceof PageContentNode;
}
Loading