Repository navigation
Releases: ProductCloudOS/editor
Release list
2.0.0
[2.0.0] - 2026-07-12
Architectural release. The layout, rendering, hit-testing, and interaction
state subsystems were rebuilt around a single immutable layout structure
(see docs/refactor-v2.md). The persisted document JSON format is unchanged
in both directions.
Fixed
- Clicking a point on page 2+ no longer selects an object at the same
in-page coordinates on an earlier page (hit-testing is page-qualified
end to end; stale per-page state is invalidated on every relayout). - Text can be added after a table that spans a page boundary: the caret
binds after the table, clicking a continuation page no longer jumps to
the document start, and the continuation page is no longer deleted out
from under the table. - Tables can span three or more pages (the old layout model could not
represent this). - Exported PDFs now include the continuation-page slices of page-spanning
tables, and text after such tables is positioned to match the canvas;
both are drawn from the same layout structure as the screen. - Typing in a table cell is recorded by undo/redo (the cell registration
path was never wired). - A text selection left in one section is no longer painted at its old
offsets when another section is active.
Changed
- Layout is a pure pass producing an immutable per-page fragment tree;
the canvas painter and PDF generator both consume it. Pages are added
and removed synchronously inside the render cycle from the tree's
derived page count — the event/timeout machinery this replaces
(text-overflow round-trip, deferred renders, empty-page checks and
their suppress flags) is deleted. - Selection and active-section state are derived from the model on demand
instead of being mirrored by event listeners. A freshly initialised or
loaded editor reports the caret at position 0 rather than a 'none'
selection, and getSelectionFormatting() returns the caret's formatting. - addPage()/removePage() are legacy page-list mutations: the page count is
re-derived from content on the next render cycle, so an added empty page
is reconciled away (use insertPageBreak()) and removing a
content-required page is undone.
Removed (BREAKING)
- The package no longer exports internal machinery (text model, layout,
regions, clipboard, PDF-import pipeline classes, EventEmitter,
Document/Page, and associated types). The supported surface is:
PCEditor; the options/events/selection/document-format types; the
embedded-object classes and their config types; content-facing types
used in PCEditor signatures; the ruler controls; all property-editor
panes; PDF-import option/result/error types; font-registration types.
1.0.8
Release Notes
Tables
- Tall table rows now split across page boundaries. Previously a data row taller than the space remaining on a page was pushed wholesale onto the next page, leaving large gaps at the bottom of pages. Rows are now fragmented at the page break (down to a minimum useful fragment height) so the page is filled and the remainder continues on the following page. This applies in both the on-screen renderer and PDF output.
- Merged and header rows are protected from splitting. Rows containing a vertical cell merge (rowSpan > 1) and header rows are never fragmented — they continue to move as a whole unit, preserving merged-cell layout and repeated headers on continuation pages.
- First-page placement respects splittable rows. The "does at least one data row fit on the first page" check now accounts for the minimum splittable fragment, so tables start filling the current page rather than skipping to the next one unnecessarily.
- Cell-range selection highlighting was updated to track the visible bounds of partially rendered (split) rows, so selection highlights line up correctly when a row spans a page break.
Table cells
- Paragraph formatting in table cells now persists. Cell-level paragraph formatting — alignment, bullet lists, and numbering — is now serialized and restored with the document. Previously this formatting was lost on save/reload.
Tests
- Added unit coverage for the new pagination behaviour: splitting an oversized data row across slices, keeping the first split fragment within the first-page height, preserving whole-row behaviour for merged rows, and round-tripping bullet-list formatting in table cells.
1.0.7
Release Notes
Demo App Improvements
- Left pane minimum width now matches the minimum pane content width, preventing controls from being clipped.
- Resizing the left pane now displays the current width in the status bar.
- Demo app loads additional open Google fonts on startup.
- Left pane can no longer be resized below its minimum width.
- Export round-trip test now includes a checksum comparison to verify content integrity across export/import cycles.
Text Editing
- Bullet, indent, and alignment formatting now correctly targets text inside text boxes and table cells instead of the parent paragraph.
- Paragraph formatting (alignment, bullets, indent) is now applied to all paragraphs in a text selection, including partially selected paragraphs.
Formatting Pane
- Colour pickers rearranged: "Text:" with colour picker on one row, "Highlight:" with colour picker and clear button on the next, labels right-aligned.
- All labels across all panes now consistently use a colon suffix.
- Font family and font size controls placed on the same row as their labels, with labels in a right-aligned column.
- View pane buttons now wrap correctly at minimum width.
Font Support
- External applications can now register custom fonts via the editor API (
registerFont()). Available fonts are retrievable with built-in fonts as the default list. - Custom fonts are embedded in exported PDFs when used in the document.
Text Box Pane
- Reworked layout: all labels have colon suffixes, Type/Background/Border Style/Padding controls are on the same row as their labels, Apply button removed — changes apply immediately on blur.
- Text box padding setting now works correctly.
Table Operations
- Fixed table row loop creation failing when no loop previously existed.
- Table row loop indicators now match the text flow style (purple "Loop" label, selectable).
- Repeating sections on table rows now span the full cell selection range instead of a single row.
- Unified table row loop visual style with text flow repeating sections (consistent colour, label size, outlined style, clickable labels).
Repeating Section Pane
- Repeating section pane now only appears when a repeating section is actually selected.
- Repeating section pane styling now matches other panes.
Conditional Sections (New Feature)
- Full conditional section system for dynamically showing/hiding content based on merge data:
- Predicate expressions with support for truthiness (
isActive), negation (!isArchived), comparisons (==,!=,>,<,>=,<=), regex match (=~,!~), logical operators (&&,||), parentheses, string/number/boolean literals, and dot-notation data access (customer.isVIP). - Automatic type coercion — ordering operators convert strings to numbers; equality operators coerce when both sides look numeric; regex match coerces left side to string.
- Text flow conditional sections — orange indicators with "If" label on the right margin, click-to-select, property pane for editing predicates.
- Table row conditionals — orange "If" badge on tables, same predicate system.
- Merge pipeline integration — conditional sections evaluated after repeating section expansion; false predicates remove the content.
- ConditionalSectionPane — property editor for predicate expressions, shown on selection.
- Full serialization — conditional sections persist in document JSON and survive export/import round-trips.
- See Predicate Expressions for the full syntax reference.
- Predicate expressions with support for truthiness (
Header & Footer
- Embedded objects (images, text boxes, tables) now work correctly in headers and footers:
- Click events properly select objects in header/footer sections (auto-switches active section).
- Relative positioning allows movement via drag.
- Correct cursor feedback (move cursor for relative objects, text cursor for editing).
- Fixed hit target registration order so header objects are not cleared during body rendering.
Embedded Object Management
- Selected embedded objects (text boxes, images, substitution fields, page number fields, tables) can now be deleted by pressing Backspace or Delete when selected but not in edit mode.
Image Pane
- Reworked layout:
- Position section with "Position" heading and "Type:" label (matching text box pane style).
- Fit Mode, Resize Mode, and Alt Text each on a single row with inline label and control.
- Apply Changes button removed — all controls apply immediately on blur/change.
- Visual separators between position, display, alt text, and source sections.
Table Pane
- Reworked layout:
- Structure section: "Rows:" and "Columns:" labels in a right-aligned column. Row and column buttons on separate rows. Separator before header controls.
- Header Rows and Header Cols on separate rows with aligned labels. Apply Headers button removed — changes apply on blur.
- Defaults section: Padding and Border on separate rows with aligned labels. Apply Defaults button removed — changes apply on blur.
- Cell Formatting section: Background and Style as inline label+control rows. Separator after merge/split buttons. "Apply to Cell(s)" button removed — all controls (background, borders, width, colour, style) apply immediately on change/blur.
1.0.6
Release Notes
Bug Fixes
- Cross-page table selection (T20): Fixed tables on page 1 being erroneously selected when clicking at overlapping coordinates on page 2. Four code paths in
CanvasManager fell back to obj.renderedPosition (page 1 position) when no table slice existed on the clicked page. Now verifies renderedPageIndex matches before
using the fallback. - Bullet list button state (T21): Fixed the bullet/numbered list toggle buttons staying active in the Formatting pane after removing list formatting. The
updateListButtons() method only toggled the active class when list formatting was present — it never cleared it when formatting was removed. - Table cell merge focus (T18): After merging cells, focus now moves to the anchor (top-left) cell of the merged range, preventing text input into covered cells.
- Table formatting round-trip: Fixed formatting runs in table cells and text boxes being deserialized as single-character entries instead of ranges. Formatted
text in cells now correctly survives export/import cycles.
Table Cell Merge/Split (T18)
- Added tableMergeCells() and tableSplitCell() public API methods to PCEditor
- Added "Merge Cells" and "Split Cell" buttons to the Cell Formatting section of the Table pane
- Buttons auto-enable/disable based on current selection: "Merge Cells" enables when multiple cells are selected (Shift+click or drag), "Split Cell" enables when
a merged cell is focused - Wired table-cell-selection-changed event through CanvasManager → PCEditor → TablePane to keep button states current
Cursor Improvements (T19)
- Windows I-beam visibility: Replaced the native text CSS cursor (which renders white on some Windows browsers over white canvas) with a custom black I-beam SVG
cursor across all text regions - Context-appropriate cursors: Embedded objects (images, tables, text boxes) now show the default arrow cursor when not in edit mode. Text boxes switch to the
I-beam only after double-clicking into edit mode. Tables switch to the I-beam when focused for cell editing.
UI Cleanup (T22)
- Removed the "Row Loop" section from the Table pane (row loops are created through the unified Repeating Section API instead)
1.0.5
Release Notes
Bug Fixes
- Text box editing: Fixed double-click to enter text box edit mode. The root cause was an infinite recursion in pane update cycles (show() → update() → show())
that crashed the event chain, plus a focus ordering issue where setFocus(textBox) was immediately undone by selectInlineElement() calling setFocus(null). Both
issues resolved in TextBoxPane, ImagePane, TablePane, and HyperlinkPane. - PDF image export: Images now render correctly in PDF exports. Previously, SVG and other non-JPEG/PNG formats silently fell back to placeholder rectangles. The
PDF generator now converts unsupported formats to PNG via canvas before embedding. - Table/text box formatting round-trip: Fixed formatting runs in table cells and text boxes being deserialized as single-character entries instead of ranges. A
bold word in a table cell now correctly survives export/import (previously only the first character retained formatting). - Formatting consistency: Fixed getFormattingAt() to merge overrides with defaults, preventing false run boundaries from inconsistent optional properties
(undefined vs 'normal'). - Demo error: Removed reference to non-existent updateTableTools function that was causing console errors on every selection change.
Document Size Optimization
- Run-based formatting compression: Body text, table cells, and text boxes now all use a shared getCompressedRuns() method that only serializes formatting at
change boundaries, eliminating per-character redundancy. - Table cell default omission: Cell properties (borders, padding, background, font, alignment, spans) are omitted from export when they match table defaults. An
empty cell now serializes to just {} instead of ~250 bytes of redundant defaults. - Row/cell ID removal: Internal row and cell IDs are no longer exported since there are no cross-references in the file format. IDs are regenerated on import.
Old exports with IDs remain backward-compatible. - Row default omission: Row-level properties (height, minHeight, isHeader) omitted when matching defaults.
- Net result: A 3×3 empty table dropped from ~15KB to ~2KB. Empty documents remain at ~455 bytes.
Configurable Logging
- Logger utility: New centralized Logger with log, warn, and error methods. log/warn only output when enabled; error always outputs.
- Editor option: enableLogging option on EditorOptions (default: false) and runtime editor.setLogging(enabled) API.
- Consistent prefixing: All library logs use [pc-editor:ClassName] format for easy filtering. Demo logs use [Editor Event]/[Demo] prefixes.
- API call tracing: 33 public PCEditor methods now log their invocations when logging is enabled.
Pane Layout Improvements
- Flexible spacer columns: All pane rows, button groups, and inline form groups include a zero-width ::after spacer that absorbs extra horizontal space, keeping
controls at their natural width when the sidebar is widened. - Minimum pane width: All panes share a consistent minimum width (--pc-pane-min-width: 220px).
- Select dropdown max width: Combo dropdowns have a max width (--pc-pane-select-max-width: 200px) preventing infinite horizontal stretch.
- Document Settings pane: Margin controls use a 5-column grid (label, edit, label, edit, stretch) with right-aligned colon labels. Margins apply on blur instead
of via an Apply button. Page Size and Orientation fields use a matching label-value grid layout. - Document Info pane: Converted to the same right-aligned colon label grid layout.
Table Row Loops
- Unified repeating section API: createRepeatingSection() now detects when a table is being edited and automatically creates a row loop on the focused cell's
row, instead of requiring a separate API. - Table pane integration: Added "Row Loop" section to the Table pane with an array field input and Create Row Loop button.
Demo App Enhancements
- Resizable sidebar: The side panel can now be dragged horizontally to test pane layout at different widths.
- Logging toggle: View menu item to toggle console logging on/off (demo defaults to on).
- Export round-trip test: View menu item opens a modal that exports the document, re-imports it, exports again, and displays byte sizes and difference to verify
serialization fidelity.
1.0.4
Added the following optional modules as library components:
| File | Description |
|---|---|
| index.ts | Barrel exports for all panes |
| types.ts | Shared types (PaneAttachOptions, etc.) |
| BasePane.ts | Base class extending BaseControl with form helpers |
| panes.css | Structural CSS with CSS variables for customization |
| FormattingPane.ts | Bold, italic, font, color, alignment, lists |
| HyperlinkPane.ts | URL and title editing |
| SubstitutionFieldPane.ts | Field name, default value, format config |
| RepeatingSectionPane.ts | Array field path for loops |
| TableRowLoopPane.ts | Table row repetition settings |
| TextBoxPane.ts | Position, background, border, padding |
| ImagePane.ts | Position, fit, resize mode, alt text |
| TablePane.ts | Structure, cells, borders, headers |
| ViewSettingsPane.ts | Rulers, control chars, grid toggles |
| DocumentSettingsPane.ts | Margins, page size, orientation |
| MergeDataPane.ts | JSON data textarea |
| DocumentInfoPane.ts | Read-only page/size info |
1.0.3
Fixed the following bugs:
[x] If you select an entire Table (all cells) you cannot deselect it
[x] The image resize arrow does not work on all corners sometimes and you have to click out of the image and click on it again to fix it. (also true for text boxes)
[x] If image is original size it shows outside the image object boundary
[x] Minus row and minus column doesn't work sometimes
[x] Header doesn't stay at top of table when new rows and columns are added above or before them
[x] If you try to select a row or column in a table and remove it the whole pdf blows up and has to be refreshed
[x] The select icon on page numbers doesn't go away when deselected (or when the focus moves to another section like the header)
[x] When resizing an image after selecting the header, the header stayed selected and even while editing image had to double click image to fix
[x] Blue select doesn't fully cover selected text when centre alignment or right alignment is added
[x] Numbers and dot points don't automatically generate sized correctly when pressing enter and only resize once text has been added (should use the 'current' format)
[x] Once list formatting is removed the icon in the formatting section continues to be selected.
[x] Can't test links in PDF.
[x] A3 setting does not seem to work.
[x] Landscape does not seem to work.
[x] 'I' icon doesn't appear when cursor hovers over text.
[x] WHile editing the header I can select and resize an object in the main content area