fika-editor 3.2.9 → 3.3.0
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.
- package/dist/embed/{824.js → 6104.js} +18 -18
- package/dist/embed/agentic-manifest.json +46 -10
- package/dist/embed/chunks/1131.js +1 -1
- package/dist/embed/chunks/2407.js +1 -1
- package/dist/embed/chunks/2807.js +1 -1
- package/dist/embed/chunks/3888.js +1 -1
- package/dist/embed/chunks/5216.js +1 -1
- package/dist/embed/chunks/574.js +1 -1
- package/dist/embed/chunks/655.js +1 -0
- package/dist/embed/chunks/862.js +1 -1
- package/dist/embed/chunks/9657.js +1 -1
- package/dist/embed/chunks/9800.js +1 -1
- package/dist/embed/fika-embed.css +1 -1
- package/dist/embed/fika-embed.js +18 -4
- package/dist/layout/types/slides.js +1 -0
- package/dist/layout/utils/resizeDeck.js +257 -0
- package/dist/types/components/Button.d.ts +2 -2
- package/dist/types/configs/theme.d.ts +2 -0
- package/dist/types/embed/agentic/canvasContext.d.ts +4 -0
- package/dist/types/embed/agentic/canvasOperations.d.ts +3 -0
- package/dist/types/embed/agentic/types.d.ts +118 -0
- package/dist/types/embed/index.d.ts +3 -0
- package/dist/types/embed/render.d.ts +4 -0
- package/dist/types/embed/types.d.ts +3 -2
- package/dist/types/hooks/textCreationDefaults.d.ts +2 -0
- package/dist/types/hooks/useAnimationFrameCallback.d.ts +6 -0
- package/dist/types/hooks/useResizeDeck.d.ts +1 -0
- package/dist/types/i18n/cs/myna/index.d.ts +3 -0
- package/dist/types/i18n/en/myna/index.d.ts +3 -0
- package/dist/types/i18n/i18n-react.d.ts +2 -0
- package/dist/types/i18n/i18n-types.d.ts +2888 -1341
- package/dist/types/i18n/i18n-util.async.d.ts +1 -0
- package/dist/types/i18n/i18n-util.d.ts +1 -0
- package/dist/types/i18n/pl/myna/index.d.ts +3 -0
- package/dist/types/i18n/sk/myna/index.d.ts +3 -0
- package/dist/types/paint/slidePainter.d.ts +11 -0
- package/dist/types/store/slides.d.ts +241 -1
- package/dist/types/types/slides.d.ts +53 -0
- package/dist/types/utils/applyDesignTheme.d.ts +1 -1
- package/dist/types/utils/canvasFit.d.ts +17 -0
- package/dist/types/utils/canvasHitTest.d.ts +4 -0
- package/dist/types/utils/designColorRoles.d.ts +10 -0
- package/dist/types/utils/element.d.ts +27 -0
- package/dist/types/utils/elementPaint.d.ts +129 -0
- package/dist/types/utils/frameDomClip.d.ts +3 -0
- package/dist/types/utils/nestedFrames.d.ts +19 -0
- package/dist/types/utils/pageGuides.d.ts +6 -0
- package/dist/types/utils/renderMetrics.d.ts +2 -0
- package/dist/types/utils/resizeDeck.d.ts +11 -0
- package/dist/types/utils/selectInsertedElements.d.ts +2 -0
- package/dist/types/utils/transferPageElements.d.ts +3 -0
- package/dist/types/views/Editor/Canvas/MynaRulers.d.ts +17 -0
- package/dist/types/views/Editor/Canvas/ViewportBackground.d.ts +3 -1
- package/dist/types/views/Editor/Canvas/hooks/useDragElement.d.ts +2 -1
- package/dist/types/views/Editor/Canvas/hooks/useDrop.d.ts +1 -1
- package/dist/types/views/Editor/Canvas/hooks/useViewportSize.d.ts +1 -0
- package/dist/types/views/Editor/Canvas/index.d.ts +4 -1
- package/dist/types/views/Editor/EditorHeader/index.d.ts +4 -2
- package/dist/types/views/Editor/index.d.ts +3 -2
- package/dist/types/views/Myna/MynaAssetsPanel.d.ts +28 -0
- package/dist/types/views/Myna/MynaDownload.d.ts +4 -0
- package/dist/types/views/Myna/MynaDrawer.d.ts +9 -0
- package/dist/types/views/Myna/MynaElementsPanel.d.ts +12 -0
- package/dist/types/views/Myna/MynaFrameTitles.d.ts +6 -0
- package/dist/types/views/Myna/MynaFramesHierarchy.d.ts +1 -0
- package/dist/types/views/Myna/MynaFramesPanel.d.ts +6 -0
- package/dist/types/views/Myna/MynaHeader.d.ts +5 -0
- package/dist/types/views/Myna/MynaInspector.d.ts +2 -0
- package/dist/types/views/Myna/MynaLayersPanel.d.ts +1 -0
- package/dist/types/views/Myna/MynaPageCanvas.d.ts +14 -0
- package/dist/types/views/Myna/MynaPageLayoutControls.d.ts +1 -0
- package/dist/types/views/Myna/MynaPageOutline.d.ts +1 -0
- package/dist/types/views/Myna/MynaPageOverflow.d.ts +9 -0
- package/dist/types/views/Myna/MynaPagesPanel.d.ts +14 -0
- package/dist/types/views/Myna/MynaQrPanel.d.ts +1 -0
- package/dist/types/views/Myna/MynaTemplateLibrary.d.ts +3 -0
- package/dist/types/views/Myna/MynaViewSettings.d.ts +2 -0
- package/dist/types/views/Myna/MynaWorkspace.d.ts +1 -0
- package/dist/types/views/Myna/MynaZoomControl.d.ts +3 -0
- package/dist/types/views/Myna/WorkspaceLabels.d.ts +8 -0
- package/dist/types/views/Myna/WorkspaceObjects.d.ts +9 -0
- package/dist/types/views/Myna/catalog.d.ts +233 -0
- package/dist/types/views/Myna/exportPages.d.ts +2 -0
- package/dist/types/views/Myna/inspectorLabels.d.ts +30 -0
- package/dist/types/views/Myna/libraryMessages.d.ts +28 -0
- package/dist/types/views/Myna/pageLayout.d.ts +22 -0
- package/dist/types/views/Myna/pageSnapping.d.ts +41 -0
- package/dist/types/views/Myna/pdf.d.ts +10 -0
- package/dist/types/views/Myna/photoFrameLabels.d.ts +28 -0
- package/dist/types/views/Myna/photoFrameUpload.d.ts +5 -0
- package/dist/types/views/Myna/photoFrames.d.ts +11 -0
- package/dist/types/views/Myna/qrCode.d.ts +7 -0
- package/dist/types/views/Myna/qrMessages.d.ts +18 -0
- package/dist/types/views/Myna/svg.d.ts +21 -0
- package/dist/types/views/Myna/svgWatermark.d.ts +2 -0
- package/dist/types/views/Myna/templateLibrary.d.ts +26 -0
- package/dist/types/views/Myna/viewStore.d.ts +14 -0
- package/dist/types/views/Myna/workspaceLabels.d.ts +10 -0
- package/dist/types/views/Myna/workspaceSelectors.d.ts +17 -0
- package/docs/AGENTIC_BRIDGE.md +23 -0
- package/docs/EMBED.md +33 -0
- package/docs/MYNA.md +247 -0
- package/package.json +15 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
function bounds(el) {
|
|
2
|
+
if (el.type === 'line') {
|
|
3
|
+
const points = [el.start, el.end, el.broken, el.broken2, el.curve, ...(el.cubic ?? [])].filter((p) => !!p);
|
|
4
|
+
return { left: el.left + Math.min(...points.map(p => p[0])), right: el.left + Math.max(...points.map(p => p[0])), top: el.top + Math.min(...points.map(p => p[1])), bottom: el.top + Math.max(...points.map(p => p[1])) };
|
|
5
|
+
}
|
|
6
|
+
const angle = (el.rotate ?? 0) * Math.PI / 180;
|
|
7
|
+
const w = Math.abs(el.width * Math.cos(angle)) + Math.abs(el.height * Math.sin(angle));
|
|
8
|
+
const h = Math.abs(el.width * Math.sin(angle)) + Math.abs(el.height * Math.cos(angle));
|
|
9
|
+
return { left: el.left + (el.width - w) / 2, right: el.left + (el.width + w) / 2, top: el.top + (el.height - h) / 2, bottom: el.top + (el.height + h) / 2 };
|
|
10
|
+
}
|
|
11
|
+
function union(a, b) {
|
|
12
|
+
return { left: Math.min(a.left, b.left), right: Math.max(a.right, b.right), top: Math.min(a.top, b.top), bottom: Math.max(a.bottom, b.bottom) };
|
|
13
|
+
}
|
|
14
|
+
function isBackdrop(el, canvas) {
|
|
15
|
+
return el.type === 'shape' && !el.text && !el.rotate && !el.fixedRatio && el.left <= 1 && el.top <= 1 && el.width >= canvas.width - 2 && el.height >= canvas.height - 2;
|
|
16
|
+
}
|
|
17
|
+
function isDecor(el, canvas) {
|
|
18
|
+
return el.type === 'shape' && !el.text && !el.groupId && (el.name === 'Decor' || el.left < -1 || el.top < -1 || el.left + el.width > canvas.width + 1 || el.top + el.height > canvas.height + 1);
|
|
19
|
+
}
|
|
20
|
+
function edgeBand(el, canvas) {
|
|
21
|
+
if (el.type !== 'shape' || el.text || el.groupId || el.rotate || el.fixedRatio)
|
|
22
|
+
return;
|
|
23
|
+
if (Math.abs(el.top) <= 1 && Math.abs(el.height - canvas.height) <= 2 && el.width < canvas.width * 0.3
|
|
24
|
+
&& (Math.abs(el.left) <= 1 || Math.abs(el.left + el.width - canvas.width) <= 1))
|
|
25
|
+
return 'vertical';
|
|
26
|
+
if (Math.abs(el.left) <= 1 && Math.abs(el.width - canvas.width) <= 2 && el.height < canvas.height * 0.2
|
|
27
|
+
&& (Math.abs(el.top) <= 1 || Math.abs(el.top + el.height - canvas.height) <= 1))
|
|
28
|
+
return 'horizontal';
|
|
29
|
+
}
|
|
30
|
+
/** Piecewise affine map: occupied tracks retain their scale; only empty gutters expand.
|
|
31
|
+
* Group bounds occupy a single track, so labels never detach from their diagram.
|
|
32
|
+
*/
|
|
33
|
+
function axisTracks(intervals, source) {
|
|
34
|
+
const merged = [];
|
|
35
|
+
for (const [start, end] of intervals.sort((a, b) => a[0] - b[0])) {
|
|
36
|
+
const lo = Math.max(0, start), hi = Math.min(source, end);
|
|
37
|
+
if (hi <= lo)
|
|
38
|
+
continue;
|
|
39
|
+
const last = merged.at(-1);
|
|
40
|
+
if (last && lo <= last[1] + 1)
|
|
41
|
+
last[1] = Math.max(last[1], hi);
|
|
42
|
+
else
|
|
43
|
+
merged.push([lo, hi]);
|
|
44
|
+
}
|
|
45
|
+
const gaps = [];
|
|
46
|
+
let cursor = 0;
|
|
47
|
+
for (const [lo, hi] of merged) {
|
|
48
|
+
if (lo > cursor)
|
|
49
|
+
gaps.push([cursor, lo]);
|
|
50
|
+
cursor = hi;
|
|
51
|
+
}
|
|
52
|
+
if (cursor < source)
|
|
53
|
+
gaps.push([cursor, source]);
|
|
54
|
+
const free = gaps.reduce((sum, [lo, hi]) => sum + hi - lo, 0);
|
|
55
|
+
return { gaps, free };
|
|
56
|
+
}
|
|
57
|
+
function axisMap(intervals, source, target, scale) {
|
|
58
|
+
const { gaps, free } = axisTracks(intervals, source);
|
|
59
|
+
const extra = target - source * scale;
|
|
60
|
+
return (position) => position * scale + (free > 0
|
|
61
|
+
? extra * gaps.reduce((sum, [lo, hi]) => sum + Math.max(0, Math.min(position, hi) - lo), 0) / free
|
|
62
|
+
: extra / 2);
|
|
63
|
+
}
|
|
64
|
+
/** Recognize a full-width heading above independent body columns. Each column
|
|
65
|
+
* gets its own vertical tracks; a long item in the left column cannot prevent
|
|
66
|
+
* the right column from distributing its rows through the available height.
|
|
67
|
+
*/
|
|
68
|
+
function bodyColumns(boxes, from) {
|
|
69
|
+
if (boxes.length < 3)
|
|
70
|
+
return;
|
|
71
|
+
const top = Math.min(...boxes.map(b => b.top));
|
|
72
|
+
const headers = boxes.filter(b => Math.abs(b.top - top) < 1 && b.right - b.left >= from.width * 0.55 && b.bottom <= from.height * 0.26);
|
|
73
|
+
if (!headers.length)
|
|
74
|
+
return;
|
|
75
|
+
const headerBottom = Math.max(...headers.map(b => b.bottom));
|
|
76
|
+
const body = boxes.filter(b => !headers.includes(b));
|
|
77
|
+
if (body.some(b => b.top < headerBottom))
|
|
78
|
+
return;
|
|
79
|
+
const bodyTop = Math.min(...body.map(b => b.top));
|
|
80
|
+
const ranges = [];
|
|
81
|
+
for (const box of [...body].sort((a, b) => a.left - b.left)) {
|
|
82
|
+
const last = ranges.at(-1);
|
|
83
|
+
if (last && box.left <= last.right + from.width * 0.025) {
|
|
84
|
+
last.right = Math.max(last.right, box.right);
|
|
85
|
+
last.boxes.push(box);
|
|
86
|
+
}
|
|
87
|
+
else
|
|
88
|
+
ranges.push({ left: box.left, right: box.right, boxes: [box] });
|
|
89
|
+
}
|
|
90
|
+
if (ranges.length > 4)
|
|
91
|
+
return;
|
|
92
|
+
const margin = Math.min(from.height * 0.06, Math.max(top, from.height * 0.03));
|
|
93
|
+
const columns = ranges.map(range => {
|
|
94
|
+
const height = Math.max(...range.boxes.map(b => b.bottom)) - bodyTop;
|
|
95
|
+
const intervals = range.boxes.map(b => [b.top - bodyTop, b.bottom - bodyTop]);
|
|
96
|
+
const { free } = axisTracks(intervals, height);
|
|
97
|
+
return { ...range, height, intervals, minHeight: height - free + Math.min(free, height * 0.08) };
|
|
98
|
+
});
|
|
99
|
+
return { bodyTop, margin, columns, minHeight: bodyTop + margin + Math.max(...columns.map(c => c.minHeight)) };
|
|
100
|
+
}
|
|
101
|
+
function scalePixels(html, scale) {
|
|
102
|
+
// CSS lengths only: do not rewrite lesson text containing quantities in px.
|
|
103
|
+
return html.replace(/style=(['"])(.*?)\1/gi, (_, quote, css) => `style=${quote}${css.replace(/(-?\d+(?:\.\d+)?)px\b/g, (_m, n) => `${Number((Number(n) * scale).toFixed(4))}px`)}${quote}`);
|
|
104
|
+
}
|
|
105
|
+
function scaleNumber(record, key, scale) {
|
|
106
|
+
const obj = record;
|
|
107
|
+
if (typeof obj[key] === 'number')
|
|
108
|
+
obj[key] = obj[key] * scale;
|
|
109
|
+
}
|
|
110
|
+
function scaleTypography(el, scale) {
|
|
111
|
+
if (scale === 1)
|
|
112
|
+
return;
|
|
113
|
+
const text = el.type === 'text' ? el : el.type === 'shape' ? el.text : undefined;
|
|
114
|
+
if (text) {
|
|
115
|
+
text.content = scalePixels(text.content, scale);
|
|
116
|
+
text.inset = (text.inset ?? [10, 10, 10, 10]).map(v => v * scale);
|
|
117
|
+
text.paragraphSpace = (text.paragraphSpace ?? 5);
|
|
118
|
+
for (const key of ['wordSpace', 'paragraphSpace', 'placeholderFontSize', 'placeholderLayoutHeight'])
|
|
119
|
+
scaleNumber(text, key, scale);
|
|
120
|
+
if (el.type === 'text' && el.structuredText) {
|
|
121
|
+
// HTML is the source of truth; discard the stale import cache.
|
|
122
|
+
delete el.structuredText;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (el.type === 'table') {
|
|
126
|
+
el.cellMinHeight *= scale;
|
|
127
|
+
for (const row of el.data)
|
|
128
|
+
for (const cell of row) {
|
|
129
|
+
cell.text = scalePixels(cell.text, scale);
|
|
130
|
+
if (cell.style?.fontsize)
|
|
131
|
+
cell.style.fontsize = cell.style.fontsize.replace(/^(\d+(?:\.\d+)?)(px|pt)$/i, (_, value, unit) => `${Number(value) * scale}${unit}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (el.type === 'chart')
|
|
135
|
+
el.options = { ...el.options, fontSize: (el.options?.fontSize ?? 12) * scale };
|
|
136
|
+
if (el.type === 'code')
|
|
137
|
+
el.fontSize *= scale;
|
|
138
|
+
if (el.type === 'latex')
|
|
139
|
+
el.strokeWidth *= scale;
|
|
140
|
+
if ('outline' in el && el.outline)
|
|
141
|
+
scaleNumber(el.outline, 'width', scale);
|
|
142
|
+
if ('shadow' in el && el.shadow)
|
|
143
|
+
for (const key of ['h', 'v', 'blur'])
|
|
144
|
+
scaleNumber(el.shadow, key, scale);
|
|
145
|
+
}
|
|
146
|
+
/** Resize a deck without distorting media or changing reading order.
|
|
147
|
+
* Uniformly scale content and typography, redistribute available space through
|
|
148
|
+
* empty tracks, and keep decorative edge shapes attached to their canvas edge.
|
|
149
|
+
* Overlaps, rotations, z-order and grouped compositions remain intact.
|
|
150
|
+
*/
|
|
151
|
+
export function resizeDeckSlides(slides, from, to) {
|
|
152
|
+
for (const n of [from.width, from.height, to.width, to.height]) {
|
|
153
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
154
|
+
throw new Error('Canvas dimensions must be finite and positive.');
|
|
155
|
+
}
|
|
156
|
+
const result = structuredClone(slides);
|
|
157
|
+
if (from.width === to.width && from.height === to.height)
|
|
158
|
+
return result;
|
|
159
|
+
for (const slide of result) {
|
|
160
|
+
// Guides describe page coordinates; resize them proportionally along their own axis.
|
|
161
|
+
if (slide.guides)
|
|
162
|
+
slide.guides = slide.guides.map(guide => ({ ...guide,
|
|
163
|
+
position: guide.position * (guide.axis === 'x' ? to.width / from.width : to.height / from.height),
|
|
164
|
+
}));
|
|
165
|
+
const groups = new Map();
|
|
166
|
+
for (const el of slide.elements) {
|
|
167
|
+
if ((el.type === 'line' && !el.groupId) || isBackdrop(el, from) || isDecor(el, from) || edgeBand(el, from))
|
|
168
|
+
continue;
|
|
169
|
+
const key = el.groupId ?? el.id, box = bounds(el);
|
|
170
|
+
groups.set(key, groups.has(key) ? union(groups.get(key), box) : box);
|
|
171
|
+
}
|
|
172
|
+
const boxes = [...groups.values()];
|
|
173
|
+
const vertical = boxes.map(b => [b.top, b.bottom]);
|
|
174
|
+
const { free } = axisTracks(vertical, from.height);
|
|
175
|
+
// Width sets the preferred type size. Consume spare vertical gutters before
|
|
176
|
+
// shrinking text; reversing a ratio change should not progressively shrink it.
|
|
177
|
+
const minHeight = from.height - free + Math.min(free, from.height * 0.08);
|
|
178
|
+
const body = bodyColumns(boxes, from);
|
|
179
|
+
const scale = Math.min(to.width / from.width, to.height / Math.max(1, body?.minHeight ?? minHeight));
|
|
180
|
+
const x = axisMap(boxes.map(b => [b.left, b.right]), from.width, to.width, scale);
|
|
181
|
+
const y = axisMap(boxes.map(b => [b.top, b.bottom]), from.height, to.height, scale);
|
|
182
|
+
const columnMaps = body?.columns.map(column => ({ ...column,
|
|
183
|
+
map: axisMap(column.intervals, column.height, Math.max(1, to.height - (body.bodyTop + body.margin) * scale), scale),
|
|
184
|
+
}));
|
|
185
|
+
const mapY = (px, py) => {
|
|
186
|
+
if (!body || !columnMaps)
|
|
187
|
+
return y(py);
|
|
188
|
+
if (py < body.bodyTop - 1)
|
|
189
|
+
return py * scale;
|
|
190
|
+
const column = columnMaps.find(c => px >= c.left - 1 && px <= c.right + 1);
|
|
191
|
+
return column ? body.bodyTop * scale + column.map(py - body.bodyTop) : y(py);
|
|
192
|
+
};
|
|
193
|
+
for (const el of slide.elements) {
|
|
194
|
+
if (el.type === 'shape' && isBackdrop(el, from)) {
|
|
195
|
+
el.left = 0;
|
|
196
|
+
el.top = 0;
|
|
197
|
+
el.width = to.width;
|
|
198
|
+
el.height = to.height;
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
const band = edgeBand(el, from);
|
|
202
|
+
if (el.type === 'shape' && band) {
|
|
203
|
+
if (band === 'vertical') {
|
|
204
|
+
el.width *= scale;
|
|
205
|
+
el.height = to.height;
|
|
206
|
+
el.top = 0;
|
|
207
|
+
el.left = el.left < from.width / 2 ? 0 : to.width - el.width;
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
el.height *= scale;
|
|
211
|
+
el.width = to.width;
|
|
212
|
+
el.left = 0;
|
|
213
|
+
el.top = el.top < from.height / 2 ? 0 : to.height - el.height;
|
|
214
|
+
}
|
|
215
|
+
scaleTypography(el, scale);
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
const left = el.left, top = el.top;
|
|
219
|
+
if (el.type === 'line') {
|
|
220
|
+
// Remap connector geometry with the same tracks as its attached objects.
|
|
221
|
+
const group = el.groupId ? groups.get(el.groupId) : undefined;
|
|
222
|
+
const lineX = group ? (v) => x(group.left) + (v - group.left) * scale : x;
|
|
223
|
+
const lineY = group ? (_px, v) => mapY(group.left, group.top) + (v - group.top) * scale : mapY;
|
|
224
|
+
el.left = lineX(left);
|
|
225
|
+
el.top = lineY(left, top);
|
|
226
|
+
el.width *= scale;
|
|
227
|
+
const point = (p) => [lineX(left + p[0]) - el.left, lineY(left + p[0], top + p[1]) - el.top];
|
|
228
|
+
el.start = point(el.start);
|
|
229
|
+
el.end = point(el.end);
|
|
230
|
+
if (el.broken)
|
|
231
|
+
el.broken = point(el.broken);
|
|
232
|
+
if (el.broken2)
|
|
233
|
+
el.broken2 = point(el.broken2);
|
|
234
|
+
if (el.curve)
|
|
235
|
+
el.curve = point(el.curve);
|
|
236
|
+
if (el.cubic)
|
|
237
|
+
el.cubic = [point(el.cubic[0]), point(el.cubic[1])];
|
|
238
|
+
}
|
|
239
|
+
else if (isDecor(el, from)) {
|
|
240
|
+
const cx = left + el.width / 2, cy = top + el.height / 2;
|
|
241
|
+
el.left = cx > from.width / 2 ? to.width - (from.width - left) * scale : left * scale;
|
|
242
|
+
el.top = cy > from.height / 2 ? to.height - (from.height - top) * scale : top * scale;
|
|
243
|
+
el.width *= scale;
|
|
244
|
+
el.height *= scale;
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
const box = groups.get(el.groupId ?? el.id);
|
|
248
|
+
el.left = x(box.left) + (left - box.left) * scale;
|
|
249
|
+
el.top = mapY(box.left, box.top) + (top - box.top) * scale;
|
|
250
|
+
el.width *= scale;
|
|
251
|
+
el.height *= scale;
|
|
252
|
+
}
|
|
253
|
+
scaleTypography(el, scale);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return result;
|
|
257
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
1
|
+
import type { ReactNode, MouseEvent } from 'react';
|
|
2
2
|
export type IButtonProps = {
|
|
3
3
|
checked?: boolean;
|
|
4
4
|
disabled?: boolean;
|
|
@@ -6,7 +6,7 @@ export type IButtonProps = {
|
|
|
6
6
|
size?: 'small' | 'normal';
|
|
7
7
|
first?: boolean;
|
|
8
8
|
last?: boolean;
|
|
9
|
-
onClick?: () => void;
|
|
9
|
+
onClick?: (event: MouseEvent<HTMLButtonElement>) => void;
|
|
10
10
|
children?: ReactNode;
|
|
11
11
|
style?: React.CSSProperties;
|
|
12
12
|
className?: string;
|
|
@@ -7,6 +7,8 @@ export interface PresetTheme {
|
|
|
7
7
|
background: string;
|
|
8
8
|
fontColor: string;
|
|
9
9
|
featureFontColor?: string;
|
|
10
|
+
/** Retain pale panels and accent roles when restyling host-authored decks. */
|
|
11
|
+
preserveColorRoles?: boolean;
|
|
10
12
|
fontname: string;
|
|
11
13
|
colors: string[];
|
|
12
14
|
/** Series palette when `colors` includes near-background swatches (Ink #171717). */
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Slide } from '../../types/slides';
|
|
2
|
+
import type { FikaCanvasContext, FikaCanvasReadOptions } from './types';
|
|
3
|
+
/** Bounded summaries never contain image data, SVG paths, or full rich-text HTML. */
|
|
4
|
+
export declare function summarizeCanvas(slides: Slide[], activePageId: string | undefined, selectedIds: string[], width: number, ratio: number, options?: FikaCanvasReadOptions): FikaCanvasContext;
|
|
@@ -1205,7 +1205,123 @@ export interface FikaAgentApi {
|
|
|
1205
1205
|
import: FikaAgentImportApi;
|
|
1206
1206
|
export: FikaAgentExportApi;
|
|
1207
1207
|
}
|
|
1208
|
+
export type FikaCanvasOperation = {
|
|
1209
|
+
op: 'title';
|
|
1210
|
+
title: string;
|
|
1211
|
+
} | {
|
|
1212
|
+
op: 'viewport';
|
|
1213
|
+
width: number;
|
|
1214
|
+
height: number;
|
|
1215
|
+
} | {
|
|
1216
|
+
op: 'page';
|
|
1217
|
+
id?: string;
|
|
1218
|
+
name?: string;
|
|
1219
|
+
x?: number;
|
|
1220
|
+
y?: number;
|
|
1221
|
+
background?: string;
|
|
1222
|
+
} | {
|
|
1223
|
+
op: 'pageUpdate';
|
|
1224
|
+
id: string;
|
|
1225
|
+
patch: Partial<Slide>;
|
|
1226
|
+
} | {
|
|
1227
|
+
op: 'text';
|
|
1228
|
+
pageId?: string;
|
|
1229
|
+
id?: string;
|
|
1230
|
+
x: number;
|
|
1231
|
+
y: number;
|
|
1232
|
+
width: number;
|
|
1233
|
+
height: number;
|
|
1234
|
+
text: string;
|
|
1235
|
+
fontSize?: number;
|
|
1236
|
+
fontName?: string;
|
|
1237
|
+
color?: string;
|
|
1238
|
+
bold?: boolean;
|
|
1239
|
+
align?: 'left' | 'center' | 'right' | 'justify';
|
|
1240
|
+
} | {
|
|
1241
|
+
op: 'textUpdate';
|
|
1242
|
+
pageId?: string;
|
|
1243
|
+
id: string;
|
|
1244
|
+
text: string;
|
|
1245
|
+
style?: TextRunStyle;
|
|
1246
|
+
} | {
|
|
1247
|
+
op: 'shape';
|
|
1248
|
+
pageId?: string;
|
|
1249
|
+
id?: string;
|
|
1250
|
+
x: number;
|
|
1251
|
+
y: number;
|
|
1252
|
+
width: number;
|
|
1253
|
+
height: number;
|
|
1254
|
+
shape: 'rect' | 'ellipse';
|
|
1255
|
+
fill?: string;
|
|
1256
|
+
} | {
|
|
1257
|
+
op: 'element';
|
|
1258
|
+
pageId?: string;
|
|
1259
|
+
element: Partial<PPTElement> & {
|
|
1260
|
+
type: PPTElement['type'];
|
|
1261
|
+
};
|
|
1262
|
+
} | {
|
|
1263
|
+
op: 'update';
|
|
1264
|
+
pageId?: string;
|
|
1265
|
+
id: string;
|
|
1266
|
+
patch: Partial<PPTElement>;
|
|
1267
|
+
} | {
|
|
1268
|
+
op: 'remove';
|
|
1269
|
+
pageId?: string;
|
|
1270
|
+
id: string;
|
|
1271
|
+
};
|
|
1272
|
+
export interface FikaCanvasApplyResult {
|
|
1273
|
+
results: Array<{
|
|
1274
|
+
op: FikaCanvasOperation['op'];
|
|
1275
|
+
id?: string;
|
|
1276
|
+
pageId?: string;
|
|
1277
|
+
}>;
|
|
1278
|
+
}
|
|
1279
|
+
export interface FikaCanvasReadOptions {
|
|
1280
|
+
pageId?: string;
|
|
1281
|
+
offset?: number;
|
|
1282
|
+
limit?: number;
|
|
1283
|
+
textLimit?: number;
|
|
1284
|
+
}
|
|
1285
|
+
export interface FikaCanvasContext {
|
|
1286
|
+
viewport: {
|
|
1287
|
+
width: number;
|
|
1288
|
+
height: number;
|
|
1289
|
+
};
|
|
1290
|
+
activePageId?: string;
|
|
1291
|
+
selectedIds: string[];
|
|
1292
|
+
pageCount: number;
|
|
1293
|
+
pages: Array<{
|
|
1294
|
+
id: string;
|
|
1295
|
+
name?: string;
|
|
1296
|
+
x: number;
|
|
1297
|
+
y: number;
|
|
1298
|
+
elementCount: number;
|
|
1299
|
+
}>;
|
|
1300
|
+
pageId?: string;
|
|
1301
|
+
elementCount: number;
|
|
1302
|
+
offset: number;
|
|
1303
|
+
nextOffset?: number;
|
|
1304
|
+
elements: Array<{
|
|
1305
|
+
id: string;
|
|
1306
|
+
type: string;
|
|
1307
|
+
name?: string;
|
|
1308
|
+
x: number;
|
|
1309
|
+
y: number;
|
|
1310
|
+
width: number;
|
|
1311
|
+
height?: number;
|
|
1312
|
+
parentFrameId?: string;
|
|
1313
|
+
groupId?: string;
|
|
1314
|
+
frame?: {
|
|
1315
|
+
clipContent: boolean;
|
|
1316
|
+
};
|
|
1317
|
+
text?: string;
|
|
1318
|
+
}>;
|
|
1319
|
+
}
|
|
1208
1320
|
export interface FikaCommandPayloadMap {
|
|
1321
|
+
'canvas.get': FikaCanvasReadOptions | undefined;
|
|
1322
|
+
'canvas.apply': {
|
|
1323
|
+
operations: FikaCanvasOperation[];
|
|
1324
|
+
};
|
|
1209
1325
|
'deck.get': undefined;
|
|
1210
1326
|
'deck.set': FikaDeckInput | FikaDocument;
|
|
1211
1327
|
'deck.patch': FikaDeckPatch | Partial<FikaDocument>;
|
|
@@ -1902,6 +2018,8 @@ export interface FikaCommandPayloadMap {
|
|
|
1902
2018
|
'view.exitPresentation': undefined;
|
|
1903
2019
|
}
|
|
1904
2020
|
export interface FikaCommandResultDataMap {
|
|
2021
|
+
'canvas.get': FikaCanvasContext;
|
|
2022
|
+
'canvas.apply': FikaCanvasApplyResult;
|
|
1905
2023
|
'deck.get': FikaDeckDocument;
|
|
1906
2024
|
'deck.set': FikaDeckDocument;
|
|
1907
2025
|
'deck.patch': FikaDeckDocument;
|
|
@@ -12,3 +12,6 @@ export type { Locales as FikaLocales } from '../i18n/locale';
|
|
|
12
12
|
export type { ChartData, ChartOptions, ChartType, Note, NoteReply, PPTAnimation, PPTAudioElement, PPTChartElement, PPTElement, PPTElementLink, PPTImageElement, PPTLatexElement, PPTLineElement, PPTShapeElement, PPTTableElement, PPTTextElement, PPTVideoElement, ShapeText, Slide, SlideBackground, SlideTemplate, SlideTheme, TableCell, TableCellStyle, TextAlign, TurningMode, } from '../types/slides';
|
|
13
13
|
export type { FikaDesignTheme } from '../configs/designThemes';
|
|
14
14
|
export { getFikaDefaultDesignThemes } from '../configs/designThemes';
|
|
15
|
+
export { resizeDeckSlides, type SlideCanvas } from '../utils/resizeDeck';
|
|
16
|
+
/** Myna design-mode capabilities and editable starter document. */
|
|
17
|
+
export { createMynaDocument, MYNA_FORMATS } from '../views/Myna/catalog';
|
|
@@ -21,6 +21,10 @@ export interface FikaRenderSlideOptions {
|
|
|
21
21
|
format?: 'image/png' | 'image/jpeg' | 'image/webp';
|
|
22
22
|
/** Encoder quality for lossy formats (0–1). Default 0.9. */
|
|
23
23
|
quality?: number;
|
|
24
|
+
/** Omit the page background for PNG/WebP without changing element colors. */
|
|
25
|
+
transparentBackground?: boolean;
|
|
26
|
+
/** Load original image pixels, using the host media resolver if needed. Fail if an image cannot load. */
|
|
27
|
+
fullResolutionImages?: boolean;
|
|
24
28
|
}
|
|
25
29
|
export interface FikaDeckAtlasOptions extends Omit<FikaRenderSlideOptions, 'width'> {
|
|
26
30
|
/** Width of one slide tile in CSS px. Default 640. */
|
|
@@ -61,8 +61,8 @@ export interface FikaHeaderMenuItem {
|
|
|
61
61
|
/** Fired when the entry is clicked (the dropdown closes first). */
|
|
62
62
|
onSelect?: (id: string) => void;
|
|
63
63
|
}
|
|
64
|
-
/** `editor
|
|
65
|
-
export type FikaViewMode = 'editor' | 'presentation';
|
|
64
|
+
/** `editor`: presentation editor; `presentation`: viewer; `canva` (alias `myna`): Myna design workspace. */
|
|
65
|
+
export type FikaViewMode = 'editor' | 'presentation' | 'canva' | 'myna';
|
|
66
66
|
export interface FikaMountOptions {
|
|
67
67
|
/** Replacement design catalog in display order. Omit for Fika defaults; [] hides presets. Does not restyle the loaded document. */
|
|
68
68
|
designThemes?: readonly FikaDesignTheme[];
|
|
@@ -135,6 +135,7 @@ export interface FikaMountOptions {
|
|
|
135
135
|
*/
|
|
136
136
|
openPanelOnTextSelection?: boolean;
|
|
137
137
|
/**
|
|
138
|
+
* `canva` (or `myna`) mounts the Myna graphic design workspace.
|
|
138
139
|
* `presentation` mounts a presentation-only viewer: once the deck resolves,
|
|
139
140
|
* the fullscreen slideshow starts immediately and the editor never renders.
|
|
140
141
|
* Exiting the slideshow re-enters it, so the page stays a pure viewer.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function useResizeDeck(): (width: number, height: number) => void;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Locales, TranslationFunctions } from './i18n-types';
|
|
2
2
|
declare const TypesafeI18n: import("react").FunctionComponent<import("typesafe-i18n/react").TypesafeI18nProps<Locales>>, I18nContext: import("react").Context<import("typesafe-i18n/react").I18nContextType<Locales, {
|
|
3
3
|
screen: import("./i18n-types").NamespaceScreenTranslation;
|
|
4
|
+
myna: import("./i18n-types").NamespaceMynaTranslation;
|
|
4
5
|
export: import("./i18n-types").NamespaceExportTranslation;
|
|
5
6
|
editor: import("./i18n-types").NamespaceEditorTranslation;
|
|
6
7
|
mobile: import("./i18n-types").NamespaceMobileTranslation;
|
|
@@ -12,6 +13,7 @@ declare const TypesafeI18n: import("react").FunctionComponent<import("typesafe-i
|
|
|
12
13
|
export { TypesafeI18n, I18nContext };
|
|
13
14
|
export declare function useI18nContext(): import("typesafe-i18n/react").I18nContextType<Locales, {
|
|
14
15
|
screen: import("./i18n-types").NamespaceScreenTranslation;
|
|
16
|
+
myna: import("./i18n-types").NamespaceMynaTranslation;
|
|
15
17
|
export: import("./i18n-types").NamespaceExportTranslation;
|
|
16
18
|
editor: import("./i18n-types").NamespaceEditorTranslation;
|
|
17
19
|
mobile: import("./i18n-types").NamespaceMobileTranslation;
|