fika-editor 3.0.1 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/README.md +8 -0
  2. package/dist/embed/183.js +144 -0
  3. package/dist/embed/_e2e-statika.json +10909 -0
  4. package/dist/embed/agentic-manifest.json +188 -13
  5. package/dist/embed/chunks/1131.css +1 -1
  6. package/dist/embed/chunks/1131.js +1 -1
  7. package/dist/embed/chunks/1668.js +1 -1
  8. package/dist/embed/chunks/1904.js +1 -1
  9. package/dist/embed/chunks/2020.js +43 -37
  10. package/dist/embed/chunks/2289.js +1 -1
  11. package/dist/embed/chunks/2595.js +1 -0
  12. package/dist/embed/chunks/2796.js +1 -1
  13. package/dist/embed/chunks/2807.js +1 -1
  14. package/dist/embed/chunks/3030.js +1 -1
  15. package/dist/embed/chunks/3729.js +3 -3
  16. package/dist/embed/chunks/4467.js +1 -1
  17. package/dist/embed/chunks/4552.js +1 -1
  18. package/dist/embed/chunks/4625.js +1 -1
  19. package/dist/embed/chunks/4891.js +2 -2
  20. package/dist/embed/chunks/4950.js +1 -1
  21. package/dist/embed/chunks/4975.js +5 -5
  22. package/dist/embed/chunks/5792.js +1 -1
  23. package/dist/embed/chunks/627.js +1 -1
  24. package/dist/embed/chunks/6567.js +1 -1
  25. package/dist/embed/chunks/717.js +2 -2
  26. package/dist/embed/chunks/7175.js +1 -1
  27. package/dist/embed/chunks/7311.js +1 -1
  28. package/dist/embed/chunks/7594.js +1 -1
  29. package/dist/embed/chunks/7854.js +1 -1
  30. package/dist/embed/chunks/788.js +1 -1
  31. package/dist/embed/chunks/7916.js +1 -1
  32. package/dist/embed/chunks/8212.js +1 -1
  33. package/dist/embed/chunks/8239.js +1 -1
  34. package/dist/embed/chunks/8645.js +1 -1
  35. package/dist/embed/chunks/8716.js +3 -3
  36. package/dist/embed/chunks/9121.js +1 -1
  37. package/dist/embed/chunks/9465.js +2 -2
  38. package/dist/embed/fika-embed.css +1 -1
  39. package/dist/embed/fika-embed.js +9 -2
  40. package/dist/types/components/Button.d.ts +2 -1
  41. package/dist/types/components/ColorSwatches.d.ts +2 -1
  42. package/dist/types/components/Draggable.d.ts +9 -4
  43. package/dist/types/components/Slider.d.ts +1 -0
  44. package/dist/types/configs/animation.d.ts +2 -0
  45. package/dist/types/configs/font.d.ts +0 -2
  46. package/dist/types/configs/templates.d.ts +1 -5
  47. package/dist/types/configs/transitions.d.ts +28 -0
  48. package/dist/types/embed/agentic/templates.d.ts +2 -1
  49. package/dist/types/embed/agentic/types.d.ts +64 -1
  50. package/dist/types/embed/types.d.ts +8 -0
  51. package/dist/types/hooks/useScreening.d.ts +5 -3
  52. package/dist/types/i18n/i18n-types.d.ts +206 -38
  53. package/dist/types/paint/rasterResources.d.ts +7 -0
  54. package/dist/types/paint/scheduler.d.ts +17 -0
  55. package/dist/types/paint/slidePainter.d.ts +17 -0
  56. package/dist/types/paint/textPainter.d.ts +31 -0
  57. package/dist/types/store/importConfirm.d.ts +6 -1
  58. package/dist/types/store/index.d.ts +2 -2
  59. package/dist/types/store/slides.d.ts +30 -8
  60. package/dist/types/types/injectKey.d.ts +6 -0
  61. package/dist/types/types/slides.d.ts +3 -2
  62. package/dist/types/utils/canvasHitTest.d.ts +14 -2
  63. package/dist/types/utils/commitQueue.d.ts +13 -0
  64. package/dist/types/utils/cssLength.d.ts +8 -0
  65. package/dist/types/utils/database.d.ts +6 -1
  66. package/dist/types/utils/element.d.ts +18 -0
  67. package/dist/types/utils/elementOutline.d.ts +33 -3
  68. package/dist/types/utils/exportFonts.d.ts +7 -3
  69. package/dist/types/utils/imageBitmapCache.d.ts +14 -2
  70. package/dist/types/utils/imageSize.d.ts +9 -0
  71. package/dist/types/utils/importApply.d.ts +10 -0
  72. package/dist/types/utils/importTransition.d.ts +19 -0
  73. package/dist/types/utils/layerStack.d.ts +24 -0
  74. package/dist/types/utils/liveElementOffset.d.ts +6 -5
  75. package/dist/types/utils/liveElementSize.d.ts +20 -1
  76. package/dist/types/utils/mediaIntern.d.ts +21 -0
  77. package/dist/types/utils/placeholderLayout.d.ts +25 -6
  78. package/dist/types/utils/prosemirror/commitEditor.d.ts +3 -0
  79. package/dist/types/utils/prosemirror/index.d.ts +1 -0
  80. package/dist/types/utils/screening.d.ts +10 -0
  81. package/dist/types/utils/shapePaint.d.ts +23 -0
  82. package/dist/types/utils/simpleShape.d.ts +5 -0
  83. package/dist/types/utils/slideOrder.d.ts +10 -0
  84. package/dist/types/utils/snap.d.ts +9 -0
  85. package/dist/types/utils/tableCellStyle.d.ts +12 -0
  86. package/dist/types/utils/tableStyleTarget.d.ts +3 -0
  87. package/dist/types/utils/textContrast.d.ts +25 -1
  88. package/dist/types/utils/textFit.d.ts +39 -13
  89. package/dist/types/views/Editor/Canvas/LayerStackPanel.d.ts +14 -0
  90. package/dist/types/views/Editor/Canvas/Operate/ResizeHandler.d.ts +2 -1
  91. package/dist/types/views/Editor/Thumbnails/paneSize.d.ts +7 -3
  92. package/dist/types/views/Editor/Thumbnails/useThumbnailVirtualizer.d.ts +1 -0
  93. package/dist/types/views/Editor/Toolbar/common/ElementOutline.d.ts +2 -0
  94. package/dist/types/views/components/ThumbnailSlide/CanvasSlideThumb.d.ts +11 -0
  95. package/dist/types/views/components/ThumbnailSlide/index.d.ts +3 -0
  96. package/dist/types/views/components/ThumbnailSlide/paintedSlide.d.ts +1 -1
  97. package/dist/types/views/components/element/TableElement/CustomTextarea.d.ts +2 -1
  98. package/dist/types/views/components/element/hooks/useAutoShapeTextHeight.d.ts +3 -1
  99. package/docs/RELEASE.md +2 -0
  100. package/package.json +22 -21
  101. package/dist/embed/350.js +0 -164
  102. package/dist/embed/chunks/1932.js +0 -1
  103. package/dist/embed/chunks/5901.js +0 -1
  104. package/dist/types/previewRaster/index.d.ts +0 -9
  105. package/dist/types/previewRaster/painters/background.d.ts +0 -2
  106. package/dist/types/previewRaster/painters/booth.d.ts +0 -13
  107. package/dist/types/previewRaster/painters/chart.d.ts +0 -2
  108. package/dist/types/previewRaster/painters/code.d.ts +0 -2
  109. package/dist/types/previewRaster/painters/image.d.ts +0 -2
  110. package/dist/types/previewRaster/painters/index.d.ts +0 -3
  111. package/dist/types/previewRaster/painters/line.d.ts +0 -2
  112. package/dist/types/previewRaster/painters/media.d.ts +0 -2
  113. package/dist/types/previewRaster/painters/shape.d.ts +0 -2
  114. package/dist/types/previewRaster/painters/table.d.ts +0 -2
  115. package/dist/types/previewRaster/painters/text.d.ts +0 -2
  116. package/dist/types/previewRaster/planSlideRaster.d.ts +0 -19
  117. package/dist/types/previewRaster/rasterCache.d.ts +0 -19
  118. package/dist/types/previewRaster/scheduler.d.ts +0 -4
  119. package/dist/types/previewRaster/stagePool.d.ts +0 -36
  120. package/dist/types/previewRaster/stats.d.ts +0 -10
  121. package/dist/types/previewRaster/subscribeSlides.d.ts +0 -10
  122. package/dist/types/previewRaster/types.d.ts +0 -12
  123. package/dist/types/utils/elementPaint.d.ts +0 -129
  124. package/dist/types/views/components/element/ChartElement/chartBooth.d.ts +0 -2
  125. /package/dist/embed/{350.css → 183.css} +0 -0
  126. /package/dist/types/{previewRaster → utils}/diffPaintedSlide.d.ts +0 -0
@@ -73,7 +73,16 @@ export interface VisualHitRect {
73
73
  height: number;
74
74
  rotate: number;
75
75
  zIndex: number;
76
+ /**
77
+ * Empty placeholder slot (dashed prompt, no authored content). It is a
78
+ * background affordance: any element carrying visible content that
79
+ * overlaps it wins the pointer regardless of z-order — users click the
80
+ * text they SEE, not the dashed frame behind it.
81
+ */
82
+ yieldToContent?: boolean;
76
83
  }
84
+ /** True when the element paints authored content the user can click "on". */
85
+ export declare function elementHasClickableContent(element: PPTElement): boolean;
77
86
  /**
78
87
  * Map a slide element to a hit rectangle in `.viewport-wrapper` visual pixels.
79
88
  *
@@ -121,16 +130,19 @@ export type VisualHitPlanInput = {
121
130
  export type VisualHitPlan = {
122
131
  hitRects: VisualHitRect[];
123
132
  occluderRects: VisualHitRect[];
133
+ /** Rects of elements painting authored content — they beat empty placeholder slots. */
134
+ contentRects: VisualHitRect[];
124
135
  };
125
136
  /**
126
137
  * Selected / editing / clipping boxes leave HitLayer so Operate or the live
127
138
  * editor can own the pointer. Those boxes must still punch holes in every
128
139
  * *lower* hit rect — otherwise the first click works, then hover/click/drag
129
- * fall through to the card underneath.
140
+ * fall through to the card underneath. Empty placeholder slots additionally
141
+ * yield to ANY overlapping content rect regardless of z-order.
130
142
  */
131
143
  export declare function collectVisualHitPlan(input: VisualHitPlanInput): VisualHitPlan;
132
144
  export declare function pointInAnyVisualHitRect(x: number, y: number, rects: VisualHitRect[]): boolean;
133
- /** Occluders that sit on top of `rect` (same stack level included). */
145
+ /** Occluders that sit on top of `rect` (same stack level included). Empty placeholder slots yield to every occluder. */
134
146
  export declare function occludersAboveRect(rect: VisualHitRect, occluders: VisualHitRect[]): VisualHitRect[];
135
147
  /**
136
148
  * Skip rebuilding hit rects when only HTML content changed,
@@ -0,0 +1,13 @@
1
+ type Flusher = () => void;
2
+ /** Pending editor/table drafts. Returns an unregister function. */
3
+ export declare function registerCommitFlusher(flush: Flusher): () => void;
4
+ /** Runs after drafts are persisted — canvas list sync, etc. */
5
+ export declare function registerAfterCommitDrain(flush: Flusher): () => void;
6
+ /** Persist in-flight drafts without leaving the editor. */
7
+ export declare function flushCommitQueue(): void;
8
+ /**
9
+ * Persist every in-flight draft, then sync dependents off the store.
10
+ * Presentation (and any other Activity hide) must call this before unmounting editors.
11
+ */
12
+ export declare function drainCommitQueue(): void;
13
+ export {};
@@ -0,0 +1,8 @@
1
+ /** Compact a CSS length so pixel-units can split it (`13.5 pt` → `13.5pt`). */
2
+ export declare const compactCssLength: (raw: string) => string;
3
+ /** Convert a CSS length to px. Unknown / keyword / % values return undefined. */
4
+ export declare const cssLengthToPx: (raw: string | null | undefined, basePx: number) => number | undefined;
5
+ export declare const cssLengthParts: (raw: string | null | undefined, basePx: number) => {
6
+ px?: number;
7
+ em?: number;
8
+ };
@@ -1,6 +1,6 @@
1
1
  import Dexie, { type EntityTable } from 'dexie';
2
2
  import type { Patch } from 'immer';
3
- import type { Slide } from '../types/slides';
3
+ import type { Slide, SlideTemplate, SlideTheme } from '../types/slides';
4
4
  export interface writingBoardImg {
5
5
  id: string;
6
6
  dataURL: string;
@@ -8,6 +8,11 @@ export interface writingBoardImg {
8
8
  export interface Snapshot {
9
9
  id: number;
10
10
  index: number;
11
+ title?: string;
12
+ theme?: SlideTheme;
13
+ viewportSize?: number;
14
+ viewportRatio?: number;
15
+ templates?: SlideTemplate[];
11
16
  slides?: Slide[];
12
17
  patches?: Patch[];
13
18
  inversePatches?: Patch[];
@@ -29,6 +29,11 @@ export declare const getRectRotatedOffset: (element: RotatedElementData) => {
29
29
  offsetX: number;
30
30
  offsetY: number;
31
31
  };
32
+ /**
33
+ * Local control points that define a line's painted path.
34
+ * Includes elbows so a bent/curved stroke is never clipped to the start–end chord.
35
+ */
36
+ export declare const getLineLocalPoints: (element: PPTLineElement) => [number, number][];
32
37
  /**
33
38
  * Axis-aligned bounds of a single element on the canvas.
34
39
  * @param element Element data
@@ -39,6 +44,19 @@ export declare const getElementRange: (element: PPTElement) => {
39
44
  minY: any;
40
45
  maxY: any;
41
46
  };
47
+ export type ElementRangeAlign = {
48
+ minX?: number;
49
+ maxX?: number;
50
+ centerX?: number;
51
+ minY?: number;
52
+ maxY?: number;
53
+ centerY?: number;
54
+ };
55
+ /**
56
+ * Shift left/top so the element's painted AABB matches the given edges or centers.
57
+ * Lines use control-point bounds, not the start–end chord.
58
+ */
59
+ export declare const alignElementToRange: (element: PPTElement, target: ElementRangeAlign) => void;
42
60
  /**
43
61
  * Combined axis-aligned bounds of multiple elements on the canvas.
44
62
  * @param elementList Elements to measure
@@ -1,10 +1,40 @@
1
- import type { LineStyleType, PPTElementOutline } from '../types/slides';
2
- /** Clamp corner radius to half the shorter box side. */
1
+ import { type LineStyleType, type PPTElementOutline, type PPTShapeElement } from '../types/slides';
2
+ /** Clamp a resolved pixel corner radius to half the shorter box side. */
3
3
  export declare const clampOutlineRadius: (radius: number, width: number, height: number) => number;
4
+ /** Pixel radius for paint/CSS. `radius` is 0–1 of max rounding, or legacy px when `> 1`. */
5
+ export declare const resolveOutlineRadiusPx: (radius: number | undefined, width: number, height: number) => number;
6
+ /** Slider / label percent (0–100) for an authored outline radius. */
7
+ export declare const outlineRadiusToPercent: (radius: number | undefined, width: number, height: number) => number;
8
+ export declare const percentToOutlineRadius: (percent: number) => number;
4
9
  export declare const outlineRadiusCss: (radius: number | undefined, width: number, height: number) => string | undefined;
10
+ /**
11
+ * Rounded rect in local units. `rx`/`ry` are elliptical radii of that space
12
+ * (circular after a matching non-uniform scale). Skips zero-length edges so
13
+ * 100% rounding is a pill/circle instead of collapsed quadratic chamfers.
14
+ */
15
+ export declare const roundedRectEllipsePath: (width: number, height: number, rx: number, ry: number) => string;
16
+ /** Circular-corner rounded rect in pixel space. 100% radius → pill / circle. */
17
+ export declare const roundedRectArcPath: (width: number, height: number, radiusPx: number) => string;
5
18
  /** SVG path for a rectangular outline (optionally rounded). */
6
19
  export declare const roundedRectOutlinePath: (width: number, height: number, radius?: number) => string;
7
- /** pptxgenjs `rectRadius` is 0–1 relative to the shorter side. */
20
+ /** Rectangles and rectangle-family formulas the border-radius slider can round. */
21
+ export declare const isRoundableRectShape: (el: Pick<PPTShapeElement, 'path' | 'viewBox' | 'pathFormula'>) => boolean;
22
+ /**
23
+ * Path the editor / painter / hit-test should use. Outline radius is a 0–1
24
+ * fraction of max rounding; viewBox scale keeps the corners circular.
25
+ */
26
+ export declare const resolveShapePaintPath: (el: PPTShapeElement) => string;
27
+ /** Keep ROUND_RECT keypoints / path in sync when the radius slider moves. */
28
+ export declare const shapePropsForOutlineRadius: (el: PPTShapeElement, radius: number) => Partial<PPTShapeElement>;
29
+ export declare const outlineElementPatch: (el: {
30
+ type: string;
31
+ }, outline: PPTElementOutline, radiusChanged?: boolean) => {
32
+ outline: PPTElementOutline;
33
+ } & Partial<PPTShapeElement>;
34
+ /**
35
+ * pptxgenjs-plus `rectRadius` (ECMA-376 `a:gd name="adj"` / 50000).
36
+ * 0 = sharp corners, 1 = maximum rounding, 0.2 = 20%.
37
+ */
8
38
  export declare const outlineRadiusToPptxRectRadius: (radius: number, width: number, height: number) => number;
9
39
  /** pptxtojson emits border colors as a structured solid/gradient object. */
10
40
  export type PptxBorderColor = string | {
@@ -3,9 +3,13 @@
3
3
  *
4
4
  * Collects the non-system font families actually used in the deck, fetches their
5
5
  * woff2 bytes (bundled via `new URL(...)` so Vite emits them), decompresses
6
- * woff2 → TTF (via wawoff2), and returns `AddFontOptions[]` for `pptx.addFont()`.
7
- * PPTX embeds fonts as EOT-wrapped data and pptxgenjs handles TTF/OTF directly,
8
- * so the only required step is woff2 → TTF decompression.
6
+ * woff2 → TTF (via woff-lib, pure TS), and returns `AddFontOptions[]` for
7
+ * `pptx.addFont()`. PPTX embeds fonts as EOT-wrapped data and pptxgenjs handles
8
+ * TTF/OTF directly, so the only required step is woff2 → TTF decompression.
9
+ *
10
+ * woff-lib replaced wawoff2 here: wawoff2 is a Node-targeted Emscripten binary
11
+ * whose `onRuntimeInitialized` promise never resolves when the runtime fails to
12
+ * boot inside a bundled web build, hanging exports forever with no error.
9
13
  */
10
14
  import type pptxgen from 'pptxgenjs-plus';
11
15
  type AddFontOptions = Parameters<pptxgen['addFont']>[0];
@@ -1,6 +1,18 @@
1
1
  import type { Slide } from '../types/slides';
2
- export declare const getCachedImageBitmap: (src: string) => ImageBitmap | undefined;
3
- export declare const loadImageBitmap: (src: string) => Promise<ImageBitmap | null>;
2
+ export declare const PREVIEW_BITMAP_MAX_EDGE = 512;
3
+ export declare const PREVIEW_BITMAP_CACHE_MAX = 640;
4
+ export declare const FULL_BITMAP_CACHE_MAX = 64;
5
+ export type LoadImageBitmapOptions = {
6
+ maxEdge?: number;
7
+ };
8
+ export declare const subscribePreviewBitmaps: (fn: (src: string) => void) => () => void;
9
+ export declare const getCachedImageBitmap: (src: string, options?: LoadImageBitmapOptions) => ImageBitmap | undefined;
10
+ export declare const previewPaintHasMedia: (painted: Set<string> | undefined, srcs: readonly string[]) => boolean;
11
+ export declare const loadImageBitmap: (src: string, options?: LoadImageBitmapOptions) => Promise<ImageBitmap | null>;
12
+ export declare const loadPreviewImageBitmap: (src: string) => Promise<ImageBitmap>;
13
+ export declare const getCachedPreviewImageBitmap: (src: string) => ImageBitmap;
14
+ export declare const collectSlidePreviewSrcs: (slide: Slide) => string[];
4
15
  export declare const collectSlideImageSrcs: (slides: readonly Slide[]) => string[];
16
+ export declare const prefetchPreviewImageBitmaps: (srcs: readonly string[]) => void;
5
17
  export declare const revokeImageBitmapsNotIn: (keep: Iterable<string>) => void;
6
18
  export declare const syncImageBitmapsToSlides: (slides: readonly Slide[]) => void;
@@ -0,0 +1,9 @@
1
+ export type ImageSize = {
2
+ width: number;
3
+ height: number;
4
+ };
5
+ export declare const readImageSize: (buffer: ArrayBuffer | Uint8Array) => ImageSize | null;
6
+ export declare const resizeToMaxEdge: (width: number, height: number, maxEdge: number) => {
7
+ width: number;
8
+ height: number;
9
+ };
@@ -1,3 +1,5 @@
1
+ import type { TurningMode } from '../types/slides';
2
+ import type { ImportTurningModeInput } from './importTransition';
1
3
  export type ImportApplyMode = 'replace' | 'append';
2
4
  export interface ImportApplyOptions {
3
5
  /**
@@ -5,6 +7,14 @@ export interface ImportApplyOptions {
5
7
  * Default is `replace`.
6
8
  */
7
9
  mode?: ImportApplyMode;
10
+ /**
11
+ * Override imported slide transitions. A single mode applies to every slide;
12
+ * an array or index map sets individual slides (missing entries keep the
13
+ * file transition, or `defaultTurningMode` / Rise when the file has none).
14
+ */
15
+ turningMode?: ImportTurningModeInput;
16
+ /** Fallback when a slide has no file transition and no per-slide override. */
17
+ defaultTurningMode?: TurningMode;
8
18
  /**
9
19
  * Legacy alias: `true` replace, `false` append.
10
20
  * An empty deck (0 slides) is always replaced.
@@ -0,0 +1,19 @@
1
+ import type { Slide, TurningMode } from '../types/slides';
2
+ export declare const isTurningMode: (value: unknown) => value is TurningMode;
3
+ /** One mode for every slide, or a per-slide list / index map. */
4
+ export type ImportTurningModeInput = TurningMode | Array<TurningMode | null | undefined> | Record<number, TurningMode>;
5
+ export type ImportTransitionOptions = {
6
+ turningMode?: ImportTurningModeInput;
7
+ /** Used when a slide has no file transition and no per-slide override. */
8
+ defaultTurningMode?: TurningMode;
9
+ };
10
+ export type AppliedImportTransitions = {
11
+ slides: Slide[];
12
+ /** Set when every imported slide received the same explicit override. */
13
+ uniformMode?: TurningMode;
14
+ };
15
+ /**
16
+ * Accept a single mode, an index-aligned array, or a 0- or 1-based index map.
17
+ */
18
+ export declare const parseImportTurningMode: (value: unknown) => ImportTurningModeInput | undefined;
19
+ export declare const applyImportTransitions: (slides: Slide[], options?: ImportTransitionOptions) => AppliedImportTransitions;
@@ -0,0 +1,24 @@
1
+ import type { PPTElement } from '../types/slides';
2
+ /**
3
+ * One row of the Alt+Click layer picker: an element (or a whole group)
4
+ * whose visual box contains the probed point.
5
+ */
6
+ export interface LayerStackEntry {
7
+ /** Representative element — for groups, the topmost member under the point. */
8
+ element: PPTElement;
9
+ /** Ids applied to the selection when this entry is picked (empty when locked). */
10
+ memberIds: string[];
11
+ groupId?: string;
12
+ groupSize?: number;
13
+ locked: boolean;
14
+ }
15
+ /**
16
+ * All layers under a wrapper-space point, top → bottom.
17
+ *
18
+ * Group members collapse into a single entry (picking one selects the whole
19
+ * group, matching canvas click behavior). Hidden elements are skipped; locked
20
+ * elements are listed but marked non-selectable.
21
+ */
22
+ export declare function layerStackAtPoint(elementList: PPTElement[], canvasScale: number, hiddenElementIdList: Iterable<string>, x: number, y: number): LayerStackEntry[];
23
+ /** Index of the next selectable entry below `fromIndex`, wrapping. -1 when none. */
24
+ export declare function nextSelectableLayer(entries: LayerStackEntry[], fromIndex: number): number;
@@ -11,11 +11,11 @@
11
11
  * `.viewport-wrapper` (already sized to the *visual* slide). Position
12
12
  * here is slide × canvasScale.
13
13
  *
14
- * Never use CSS `translate` on the painted box. Auto-size text measures
15
- * and rasterizes differently under a transform than under `left`/`top`,
16
- * so the glyphs shift on pointerup when the transform is removed. Write
17
- * the same `left`/`top` the store will commit — drag and drop are one
18
- * paint path. Scale already does this (`applyLiveSize`).
14
+ * Most elements use `left` / `top` so auto-size text keeps the same
15
+ * measurement and rasterization path during and after the gesture. Complex
16
+ * transparent surfaces can opt into `data-live-translate3d`; those keep
17
+ * their raster on a compositor layer while dragging, then settle to the
18
+ * committed `left` / `top` on pointerup.
19
19
  */
20
20
  export type LiveOffsetPosition = {
21
21
  id: string;
@@ -40,6 +40,7 @@ export type LivePositionCss = {
40
40
  visualTop: string;
41
41
  };
42
42
  export declare const livePositionCss: (left: number, top: number, canvasScale: number) => LivePositionCss;
43
+ export declare const liveTranslate3dCss: (dx: number, dy: number) => string;
43
44
  export declare const applyLivePositionStyles: (nodes: LiveOffsetNodes, left: number, top: number, canvasScale: number) => void;
44
45
  export declare const readLiveMultiOrigin: (canvasScale: number) => {
45
46
  left: number;
@@ -29,5 +29,24 @@ export type LivePaintExtras = {
29
29
  path?: string;
30
30
  viewBox?: readonly number[];
31
31
  };
32
- export declare const applyLiveSize: (id: string, left: number, top: number, width: number, height: number, canvasScale: number, extras?: LivePaintExtras) => void;
32
+ /** True when the element's height is text-driven (auto-height box). */
33
+ export declare const autoHeightInsetSum: (el: {
34
+ type?: string;
35
+ fixedHeight?: boolean;
36
+ vertical?: boolean;
37
+ inset?: readonly number[];
38
+ text?: {
39
+ fixedHeight?: boolean;
40
+ inset?: readonly number[];
41
+ } | null;
42
+ }) => number | null;
43
+ /**
44
+ * Height the auto-height element's text actually needs at its CURRENT live
45
+ * width (call after the width has been painted). scrollHeight reports the
46
+ * true content height even when the container still carries a stale height.
47
+ */
48
+ export declare const measureAutoTextHeight: (id: string, insetSum: number) => number | null;
49
+ export declare const applyLiveSize: (id: string, left: number, top: number, width: number, height: number, canvasScale: number, extras?: LivePaintExtras, options?: {
50
+ forceHeight?: boolean;
51
+ }) => void;
33
52
  export {};
@@ -0,0 +1,21 @@
1
+ import type { Slide } from '../types/slides';
2
+ export declare const isDataUrl: (src: string) => boolean;
3
+ export declare const isBlobUrl: (src: string) => boolean;
4
+ export declare const onMediaInterned: (fn: (from: string, to: string) => void) => () => void;
5
+ /** Data URL and its blob: alias are the same bytes. */
6
+ export declare const bitmapSrcKeys: (src: string) => string[];
7
+ export declare const getInternedBlob: (src: string) => Blob | undefined;
8
+ /** Live interned data URL for a blob: src, or the original if it is already persistable. */
9
+ export declare const persistableMediaSrc: (src: string) => string;
10
+ /**
11
+ * Record an object URL created outside the intern layer (e.g. pasted video)
12
+ * so `getInternedBlob` can still inline its bytes during export.
13
+ */
14
+ export declare const registerMediaBlob: (url: string, blob: Blob) => void;
15
+ export declare const rewritePersistableMediaSrcs: <T extends Slide>(slides: T[]) => T[];
16
+ export declare const startInternSlideMedia: (slide: Slide) => void;
17
+ export declare const internMediaSrc: (src: string) => Promise<string>;
18
+ export declare const visitSlideMediaSrcs: (slide: Slide, visit: (src: string) => void) => void;
19
+ export declare const collectSlideMediaSrcs: (slides: readonly Slide[]) => string[];
20
+ export declare const internSlidesMedia: (slides: Slide[]) => Promise<void>;
21
+ export declare const resetMediaInternForTests: () => void;
@@ -30,11 +30,18 @@ export interface TextBoxLayout {
30
30
  vAlign: TextAlignVertical;
31
31
  /** Flex-column vertical centering without locking box height (content slides title). */
32
32
  flexCenterInLayoutBox: boolean;
33
+ /** Empty placeholder slot (dashed prompt). */
34
+ emptyPlaceholder: boolean;
33
35
  /**
34
- * Definite `height` (not `auto`). True for explicit fixed-height and for an
35
- * *empty* placeholder slot (dashed box + centered prompt). A filled
36
- * auto-height title/subtitle unlocks so the box can grow with the text.
36
+ * Auto-height paint floored at the committed height (empty placeholder
37
+ * slots, filled content-slide titles): `height: auto` + `min-height`. The
38
+ * box grows with the text the same frame the text grows — no clip, and the
39
+ * painted box never lags behind its glyphs.
37
40
  */
41
+ slotFlooredAuto: boolean;
42
+ /** Flex-column paint: fixed boxes, empty slots, centered layout titles. */
43
+ flexColumn: boolean;
44
+ /** Definite px `height` paint: explicit fixed-height boxes only. */
38
45
  lockPaintHeight: boolean;
39
46
  }
40
47
  export declare const V_ALIGN_JUSTIFY: {
@@ -54,11 +61,23 @@ export declare const authoredTextFitSize: (el: Pick<PPTTextElement, 'placeholder
54
61
  export declare const textBoxPaintSize: (el: PPTTextElement, layout: TextBoxLayout) => {
55
62
  width: string;
56
63
  height: string;
64
+ minHeight: string;
57
65
  };
58
66
  export declare const textBoxFlexColumn: (layout: TextBoxLayout) => boolean;
59
67
  export declare const textBoxJustify: (layout: TextBoxLayout) => "center" | "flex-end" | "flex-start";
60
68
  /**
61
- * Empty slots keep the dashed frame. Filled auto-height follows the text —
62
- * including shrinking off the empty-slot floor so Enter can grow the box.
69
+ * The ONE rule for auto-height commits: the box tracks its text but never
70
+ * shrinks below its slot floor. Empty slots keep the dashed frame, filled
71
+ * content-slide titles keep their centered layout slot, every other filled
72
+ * box hugs the text. The floor never exceeds the current height, so an
73
+ * already-short slot is never surprise-grown. Returns null when the store
74
+ * height must not change.
63
75
  */
64
- export declare const shouldBlockPlaceholderHeightShrink: (el: PPTTextElement, measuredHeight: number, contentEmpty: boolean) => boolean;
76
+ export declare const textBoxAutoHeight: (el: PPTTextElement, layout: TextBoxLayout, measuredTextHeight: number) => number | null;
77
+ /** Slot floor for drag-time height measurements (store content, no live editor state). */
78
+ export declare const placeholderHeightFloor: (el: PPTTextElement, slideType?: Slide['type']) => number;
79
+ /**
80
+ * Fixed mode restores a placeholder to its slot: its "fixed size" is the
81
+ * designed slot, not whatever the text last hugged.
82
+ */
83
+ export declare const placeholderFixedRestoreHeight: (el: PPTTextElement) => number;
@@ -1,6 +1,9 @@
1
1
  import { editorHtmlLooksEmpty } from './commitPolicy';
2
2
  export { editorHtmlLooksEmpty, shouldWriteEditorHtml } from './commitPolicy';
3
3
  export declare const richTextHtmlLooksEmpty: typeof editorHtmlLooksEmpty;
4
+ export declare const storeHtmlForElement: (elementId: string) => string;
5
+ /** Activity remounts must not rebuild an empty view over store-owned text. */
6
+ export declare const resolveEditorMountHtml: (elementId: string, value: string) => string;
4
7
  /** Persist the live ProseMirror HTML. History is for explicit flushes, not every key. */
5
8
  export declare function commitLiveEditorToStore(elementId: string, options?: {
6
9
  history?: boolean;
@@ -1,5 +1,6 @@
1
1
  import { type DirectEditorProps, EditorView } from 'prosemirror-view';
2
2
  import { type PluginOptions } from './plugins/index';
3
+ export declare const normalizeFittedFontSizes: (html: string) => string;
3
4
  export declare const createDocument: (content: string) => import("prosemirror-model").Node;
4
5
  /** Same HTML the live editor paints, so static → edit cannot shift glyphs. */
5
6
  export declare const serializeRichTextHtml: (content: string) => string;
@@ -0,0 +1,10 @@
1
+ /** Drain live editors, then enter presentation. No fullscreen — embed/agentic. */
2
+ export declare function beginScreening(options?: {
3
+ fromStart?: boolean;
4
+ }): void;
5
+ /** Editor Present / F5: drain, screen, then request fullscreen. */
6
+ export declare function enterScreening(options?: {
7
+ fromStart?: boolean;
8
+ }): void;
9
+ export declare function enterScreeningFromStart(): void;
10
+ export declare function exitScreening(): void;
@@ -0,0 +1,23 @@
1
+ import type { PPTShapeElement } from '../types/slides';
2
+ export declare const shapePathScale: (element: Pick<PPTShapeElement, 'width' | 'height' | 'viewBox'>) => {
3
+ x: number;
4
+ y: number;
5
+ };
6
+ /** Same transform the live editor SVG applies to `element.path`. */
7
+ export declare const shapePathTransform: (element: Pick<PPTShapeElement, 'width' | 'height' | 'viewBox'>) => string;
8
+ /**
9
+ * Editor-equivalent SVG (+ optional ProseMirror label). SnapDOM this instead of
10
+ * asking Konva to interpret PPTX/catalog arcs — browsers correct `A 50 50`
11
+ * radii, Konva does not.
12
+ */
13
+ export declare const shapePaintHtml: (element: PPTShapeElement, text?: {
14
+ body: string;
15
+ ink: string;
16
+ fontFamily: string;
17
+ align?: string;
18
+ inset?: [number, number, number, number];
19
+ lineHeight?: number;
20
+ letterSpacing?: number;
21
+ paragraphSpace?: number;
22
+ fitScale?: number;
23
+ }) => string;
@@ -0,0 +1,5 @@
1
+ import type { PPTShapeElement } from '../types/slides';
2
+ export declare const shapeTextIsEmpty: (html?: string) => boolean;
3
+ /** Imported PPTX rects and formula rects that fill the viewBox. */
4
+ export declare const isAxisAlignedRectPath: (path: string, viewBox: [number, number]) => boolean;
5
+ export declare const isSimpleShape: (element: PPTShapeElement) => boolean;
@@ -1,3 +1,13 @@
1
1
  import type { Slide } from '../types/slides';
2
2
  /** Reorder slides without cloning unchanged slide objects (elements/background stay referentially equal). */
3
3
  export declare const reorderSlidesPreservingIdentity: (slides: readonly Slide[], oldIndex: number, newIndex: number) => Slide[];
4
+ export declare const insertSlidesPreservingIdentity: (slides: readonly Slide[], index: number, incoming: readonly Slide[]) => Slide[];
5
+ export declare const deleteSlidesPreservingIdentity: (slides: readonly Slide[], slideIds: readonly string[]) => {
6
+ slides: Slide[];
7
+ deletedIndexes: number[];
8
+ };
9
+ export declare const slideIndexAfterDelete: (prevIndex: number, prevSlides: readonly Slide[], deletedIds: ReadonlySet<string>, nextLength: number, deletedIndexes: readonly number[]) => number;
10
+ export declare const moveSlidePreservingIdentity: (slides: readonly Slide[], fromIndex: number, toIndex: number) => {
11
+ slides: Slide[];
12
+ index: number;
13
+ };
@@ -6,6 +6,8 @@ export declare const SNAP_MATCH = 0.51;
6
6
  export declare const SLIDE_MARGIN = 40;
7
7
  export declare const RELATED_GAP = 240;
8
8
  export declare const MAX_CTRL_MEASURES = 8;
9
+ /** Same-row/column objects beat a slightly closer distant line. */
10
+ export declare const RELATION_WEIGHT = 4;
9
11
  export type SnapKind = 'edge' | 'center' | 'canvas' | 'spacing' | 'size' | 'grid' | 'measure';
10
12
  export type SnapMode = 'smart' | 'grid';
11
13
  export interface SnapGuide {
@@ -35,6 +37,8 @@ export interface SnapOptions {
35
37
  gridSize: number;
36
38
  threshold?: number;
37
39
  index?: SnapIndex;
40
+ /** When set, append Ctrl distance badges for the already-queried k-set. */
41
+ ctrlMeasures?: boolean;
38
42
  }
39
43
  /** Search pad for the per-move Flatbush query: snap threshold or related-object reach. */
40
44
  export declare const snapQueryPad: (threshold?: number) => number;
@@ -62,6 +66,11 @@ export interface ResizeSnapOptions extends SnapOptions {
62
66
  resizeHeight?: boolean;
63
67
  }
64
68
  export declare const snapResizePoint: (currentX: number | null, currentY: number | null, others: SnapBox[], options: ResizeSnapOptions) => SnapResult;
69
+ /**
70
+ * Cross-axis for a distance badge: stay on the moving box.
71
+ * Shared row/column uses the overlap; otherwise project onto the moving center.
72
+ */
73
+ export declare const projectMeasureCross: (moving0: number, moving1: number, other0: number, other1: number) => number;
65
74
  /**
66
75
  * Ctrl-held distance badges: adjacent gaps along live guides, both axes to
67
76
  * the most related object, nearest same-row/column neighbors, and slide margins.
@@ -0,0 +1,12 @@
1
+ import type { TableCellStyle } from '../types/slides';
2
+ export { rememberTableStyleTarget, tableStyleTarget } from './tableStyleTarget';
3
+ /**
4
+ * Persist any live cell draft, then patch cell styles on the store grid.
5
+ * Style panels only pass the style fields — they must not clone table data.
6
+ */
7
+ export declare function applyTableCellStyles(style: Partial<TableCellStyle>, options?: {
8
+ elementId?: string;
9
+ cells?: string[];
10
+ allCells?: boolean;
11
+ history?: boolean;
12
+ }): boolean;
@@ -0,0 +1,3 @@
1
+ /** Keep the last in-cell style target so Present/deselect cannot widen the next fill. */
2
+ export declare function rememberTableStyleTarget(elementId: string, cells: string[]): void;
3
+ export declare function tableStyleTarget(elementId: string, cells?: string[]): string[];
@@ -1,4 +1,4 @@
1
- import type { Gradient, PPTElement, PPTTableElement, Slide, SlideBackground } from '../types/slides';
1
+ import type { Gradient, PPTElement, PPTShapeElement, PPTTableElement, PPTTextElement, Slide, SlideBackground } from '../types/slides';
2
2
  /**
3
3
  * Painter's-algorithm text contrast repair for AI-imported decks.
4
4
  *
@@ -122,6 +122,30 @@ export declare const resolveElementDefaultFontColor: (preferred: string, options
122
122
  background?: SlideBackground;
123
123
  fallbackSurface?: string;
124
124
  }) => string;
125
+ export type LiveTextPaintOptions = {
126
+ fill?: string;
127
+ background?: SlideBackground;
128
+ fallbackSurface?: string;
129
+ themeFontColor?: string;
130
+ /** The text/shape being painted. Own fill/gradient win; otherwise under-paints. */
131
+ element?: PPTTextElement | PPTShapeElement;
132
+ /** Painter-order siblings so overlay labels see the chip/card underneath. */
133
+ elements?: PPTElement[];
134
+ };
135
+ /**
136
+ * Surfaces the text actually sits on — same query as import contrast.
137
+ * Own opaque fill/gradient first; otherwise the topmost paint under the box.
138
+ */
139
+ export declare const resolveTextPaintSurfaces: (el: PPTTextElement | PPTShapeElement | undefined, options?: LiveTextPaintOptions) => string[];
140
+ /**
141
+ * Single paint-time contrast pass for the live editor and the preview raster.
142
+ * Surfaces match {@link fixSlideTextContrast}: overlay labels on a chip use
143
+ * the chip, not the slide paper. Default inks rewrite to the same hex.
144
+ */
145
+ export declare const resolveLiveTextPaint: (preferred: string | undefined, html: string, options?: LiveTextPaintOptions) => {
146
+ ink: string;
147
+ html: string;
148
+ };
125
149
  /**
126
150
  * Chart axis / legend / label ink. Same rules as text: default greys / black /
127
151
  * white snap to {@link preferredInk} on the chart fill, else the slide.