@hwp-editor/react 1.1.0 → 1.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/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { CSSProperties, JSX } from 'react';
3
- import { HwpEngine, DocumentHandle, CatEnvelope, Segment, SegmentRef, DocumentSpecV2, EditorStore, EditorState, Capabilities, ValidationReport } from '@hwp-editor/core';
3
+ import { HwpEngine, DocumentHandle, Component, EditorStore, EditorState, CatEnvelope, Capabilities, ValidationReport, EditOp, ImageAsset, SegmentRef, StyleTable, Blocks, Segment, ProfileName, DocumentSpecV2 } from '@hwp-editor/core';
4
4
 
5
5
  /**
6
6
  * The editor's string table: one flat `<area>.<thing>` key map per locale,
@@ -31,6 +31,117 @@ import { HwpEngine, DocumentHandle, CatEnvelope, Segment, SegmentRef, DocumentSp
31
31
  declare const en: {
32
32
  "toolbar.toolsAria": string;
33
33
  "toolbar.readOnly": string;
34
+ "toolbar.pendingList": string;
35
+ "toolbar.clearPending": string;
36
+ "toolbar.removePending": (p: {
37
+ index: number;
38
+ }) => string;
39
+ "pending.kind.add-col": string;
40
+ "pending.kind.add-row": string;
41
+ "pending.kind.add-table": string;
42
+ "pending.kind.apply-style": string;
43
+ "pending.kind.clone-table": string;
44
+ "pending.kind.create-bookmark": string;
45
+ "pending.kind.create-field": string;
46
+ "pending.kind.create-hyperlink": string;
47
+ "pending.kind.create-style": string;
48
+ "pending.kind.delete-bookmark": string;
49
+ "pending.kind.delete-col": string;
50
+ "pending.kind.delete-field": string;
51
+ "pending.kind.delete-image": string;
52
+ "pending.kind.delete-para": string;
53
+ "pending.kind.delete-row": string;
54
+ "pending.kind.delete-table": string;
55
+ "pending.kind.indent-para": string;
56
+ "pending.kind.insert-blocks": string;
57
+ "pending.kind.insert-image": string;
58
+ "pending.kind.insert-para": string;
59
+ "pending.kind.insert-para-before": string;
60
+ "pending.kind.merge-cells": string;
61
+ "pending.kind.move-para": string;
62
+ "pending.kind.outdent-para": string;
63
+ "pending.kind.replace": string;
64
+ "pending.kind.seal": string;
65
+ "pending.kind.set-align": string;
66
+ "pending.kind.set-cell": string;
67
+ "pending.kind.set-field": string;
68
+ "pending.kind.set-format": string;
69
+ "pending.kind.set-meta": string;
70
+ "pending.kind.set-page": string;
71
+ "pending.kind.set-para": string;
72
+ "pending.kind.split-cell": string;
73
+ "pending.kind.style-tables": string;
74
+ "pending.kind.update-style": string;
75
+ "pending.target.at": (p: {
76
+ section: number;
77
+ paragraph: number;
78
+ }) => string;
79
+ "pending.target.run": (p: {
80
+ section: number;
81
+ paragraph: number;
82
+ run: number;
83
+ }) => string;
84
+ "pending.target.chars": (p: {
85
+ range: string;
86
+ start: number;
87
+ end: number;
88
+ }) => string;
89
+ "pending.target.id": (p: {
90
+ id: string;
91
+ }) => string;
92
+ "pending.target.wholeRun": (p: {
93
+ id: string;
94
+ }) => string;
95
+ "pending.target.wholePiece": (p: {
96
+ id: string;
97
+ }) => string;
98
+ "pending.target.document": string;
99
+ "pending.target.table": (p: {
100
+ index: number;
101
+ }) => string;
102
+ "pending.target.before": (p: {
103
+ range: string;
104
+ }) => string;
105
+ "pending.target.after": (p: {
106
+ range: string;
107
+ }) => string;
108
+ "pending.target.moveTo": (p: {
109
+ range: string;
110
+ destination: string;
111
+ before: boolean;
112
+ }) => string;
113
+ "pending.target.replaceFind": (p: {
114
+ find: string;
115
+ range: string;
116
+ }) => string;
117
+ "pending.target.styleOn": (p: {
118
+ style: string;
119
+ range: string;
120
+ }) => string;
121
+ "image.deleteAllHint": string;
122
+ "fields.deleteAllHint": string;
123
+ "fields.deleteAllBookmarksHint": string;
124
+ "segment.legacyHyperlinkSeparator": string;
125
+ "document.invalidDimension": string;
126
+ "unit.positive": string;
127
+ "table.legacySeparatorHint": string;
128
+ "fields.legacySeparatorHint": string;
129
+ "image.queueLimit": (p: {
130
+ count: number;
131
+ miB: number;
132
+ }) => string;
133
+ "unit.invalid": string;
134
+ "segment.hyperlinkHint": string;
135
+ "image.dimensionsHint": string;
136
+ "image.invalidDimensions": string;
137
+ "image.referenceMismatch": string;
138
+ "fields.initialValueAria": string;
139
+ "fields.bookmarkAnchorAria": string;
140
+ "fields.deleteFieldNameAria": string;
141
+ "fields.deleteBookmarkNameAria": string;
142
+ "table.sourceTable": (p: {
143
+ index: number;
144
+ }) => string;
34
145
  "toolbar.pendingEdits": (p: {
35
146
  count: number;
36
147
  }) => string;
@@ -57,9 +168,85 @@ declare const en: {
57
168
  "tabs.para": string;
58
169
  "tabs.table": string;
59
170
  "tabs.fields": string;
171
+ "tabs.templates": string;
172
+ "tabs.lint": string;
173
+ "tabs.components": string;
174
+ "components.panelAria": string;
175
+ "components.catalogueAria": string;
176
+ "components.hint": string;
177
+ "components.insert": (p: {
178
+ name: string;
179
+ }) => string;
180
+ "components.positionLabel": string;
181
+ "components.positionAria": string;
182
+ "components.positionBefore": string;
183
+ "components.positionAfter": string;
184
+ "components.positionBeforeLocked": string;
185
+ "components.paramAria": (p: {
186
+ name: string;
187
+ }) => string;
188
+ "components.paramLabel": (p: {
189
+ name: string;
190
+ param: string;
191
+ }) => string;
192
+ "components.moveUp": (p: {
193
+ name: string;
194
+ }) => string;
195
+ "components.moveDown": (p: {
196
+ name: string;
197
+ }) => string;
198
+ "components.remove": (p: {
199
+ name: string;
200
+ }) => string;
201
+ "components.noSelection": string;
202
+ "components.noAddress": string;
203
+ "components.disabledVersion": (p: {
204
+ version: string;
205
+ }) => string;
206
+ "components.disabledChannel": string;
207
+ "components.noReport": string;
208
+ "components.insertedOpsDropped": (p: {
209
+ count: number;
210
+ }) => string;
211
+ "components.reportTruncated": string;
212
+ "components.tooWide": (p: {
213
+ width: string;
214
+ available: string;
215
+ }) => string;
216
+ "components.tooWideUnmeasured": (p: {
217
+ width: string;
218
+ }) => string;
219
+ "components.tooWideUnknown": string;
220
+ "components.insertionRefused": (p: {
221
+ reason?: string;
222
+ }) => string;
223
+ "components.preflightImage": string;
224
+ "components.preflightSectionBreak": string;
225
+ "components.preflightEquation": (p: {
226
+ name: string;
227
+ }) => string;
228
+ "components.pendingEdits": string;
229
+ "components.refused": (p: {
230
+ code: string;
231
+ source: string;
232
+ field: string;
233
+ value: string;
234
+ step: string;
235
+ }) => string;
236
+ "components.unknownStyle": (p: {
237
+ style: string;
238
+ }) => string;
239
+ "components.invalidDefinition": string;
240
+ "components.step.param": string;
241
+ "components.step.style": string;
242
+ "components.step.invalid": string;
243
+ "components.step.load": string;
60
244
  "error.prefix.load": string;
245
+ "error.prefix.refresh": string;
61
246
  "error.prefix.apply": string;
62
247
  "error.prefix.compose": string;
248
+ "error.prefix.template": string;
249
+ "error.prefix.lint": string;
63
250
  "error.kind.timeout": string;
64
251
  "error.kind.unavailable": string;
65
252
  "error.kind.protected": string;
@@ -76,8 +263,19 @@ declare const en: {
76
263
  "compose.cancel": string;
77
264
  "compose.submit": string;
78
265
  "compose.submitting": string;
266
+ "compose.loadingInFlight": string;
79
267
  /** Filename stem used when the compose form has no title. */
80
268
  "compose.defaultFileStem": string;
269
+ "compose.componentsTitle": string;
270
+ "compose.componentsHint": string;
271
+ "compose.componentsEmpty": string;
272
+ "compose.componentPicker": string;
273
+ "compose.addComponent": string;
274
+ "compose.assemblyAria": string;
275
+ "compose.paramAria": (p: {
276
+ component: string;
277
+ param: string;
278
+ }) => string;
81
279
  "presets.official": string;
82
280
  "presets.report": string;
83
281
  "presets.plan": string;
@@ -87,9 +285,69 @@ declare const en: {
87
285
  "presets.press": string;
88
286
  "segment.panelAria": string;
89
287
  "segment.hint": string;
288
+ "segment.paragraphChoices": string;
289
+ "segment.choiceLabel": (p: {
290
+ index: number;
291
+ text: string;
292
+ }) => string;
293
+ "segment.rangeTextAria": string;
294
+ "segment.rangeWholeRunHint": string;
295
+ "segment.rangeUnavailable": string;
296
+ "segment.rangeUnavailableNoRuns": string;
297
+ "segment.rangeInvalid": string;
298
+ "segment.rangeSplit": string;
299
+ "segment.rangeRunCount": (p: {
300
+ count: number;
301
+ }) => string;
302
+ "segment.rangeWholeRunTargets": (p: {
303
+ count: number;
304
+ }) => string;
305
+ "segment.formatRunCount": (p: {
306
+ count: number;
307
+ }) => string;
308
+ "segment.formatUnavailableNoRuns": string;
309
+ "segment.rangeClear": string;
310
+ "segment.placeholderLabel": string;
311
+ "segment.placeholderHint": string;
312
+ "segment.placeholderNameAria": string;
313
+ "segment.placeholderNamePlaceholder": string;
314
+ "segment.placeholderCreate": string;
315
+ "segment.placeholderRefused": string;
316
+ "segment.placeholderNameEmpty": string;
317
+ "segment.placeholderNameInvalid": string;
318
+ "segment.selectedCount": (p: {
319
+ count: number;
320
+ }) => string;
321
+ "segment.selectedRunCount": (p: {
322
+ count: number;
323
+ }) => string;
324
+ "segment.multiTextEditHint": string;
325
+ "segment.rangeTextEditHint": string;
326
+ "segment.runTextEditHint": string;
327
+ "segment.runSelectionParagraphs": (p: {
328
+ count: number;
329
+ }) => string;
330
+ "segment.runSelectionTerminal": string;
331
+ "segment.noParagraphSelection": string;
332
+ "segment.cellSelectionRefused": string;
333
+ "segment.tableSelectionRefused": string;
334
+ "segment.containerSelectionRefused": string;
335
+ "segment.clickRefusedCell": string;
336
+ "segment.clickRefusedTable": string;
337
+ "segment.clickRefusedContainer": string;
338
+ "segment.clickRefusedUnaddressable": string;
339
+ "segment.selectSimilar": string;
340
+ "segment.similarChar": string;
341
+ "segment.similarPara": string;
342
+ "segment.similarCharUnavailable": string;
343
+ "segment.similarParaUnavailable": string;
344
+ "segment.addressedUnavailable": string;
90
345
  "segment.selectedPara": (p: {
91
- section: number;
92
- para: number;
346
+ path: string;
347
+ }) => string;
348
+ "segment.selectedCell": (p: {
349
+ path: string;
350
+ count: number;
93
351
  }) => string;
94
352
  "segment.emptyPara": string;
95
353
  "segment.replaceLabel": string;
@@ -99,13 +357,18 @@ declare const en: {
99
357
  "segment.insertPlaceholder": string;
100
358
  "segment.insertBefore": string;
101
359
  "segment.insertAfter": string;
360
+ "segment.moveUp": string;
361
+ "segment.moveDown": string;
102
362
  "segment.deletePara": string;
363
+ "segment.multiReorderRefused": string;
364
+ "segment.sectionDefinitionLocked": string;
103
365
  "segment.alignLabel": string;
104
366
  "segment.alignGroupAria": string;
105
367
  "segment.alignLeft": string;
106
368
  "segment.alignCenter": string;
107
369
  "segment.alignRight": string;
108
370
  "segment.alignJustify": string;
371
+ "segment.alignDistribute": string;
109
372
  "segment.formatLabel": string;
110
373
  "segment.bold": string;
111
374
  "segment.sizePlaceholder": string;
@@ -117,6 +380,13 @@ declare const en: {
117
380
  "table.tableLabel": (p: {
118
381
  index: number;
119
382
  }) => string;
383
+ "table.indexMismatch": (p: {
384
+ engine: number;
385
+ published: number;
386
+ }) => string;
387
+ "table.htmlTable": (p: {
388
+ index: number;
389
+ }) => string;
120
390
  "table.cellLabel": (p: {
121
391
  row: number;
122
392
  col: number;
@@ -138,6 +408,241 @@ declare const en: {
138
408
  name: string;
139
409
  }) => string;
140
410
  "fields.setValue": string;
411
+ "templates.panelAria": string;
412
+ "templates.disabled": (p: {
413
+ reason: string;
414
+ remedy: string;
415
+ }) => string;
416
+ "templates.remedy": string;
417
+ "templates.versionRequired": (p: {
418
+ version: string;
419
+ }) => string;
420
+ "templates.methodMissing": (p: {
421
+ method: string;
422
+ }) => string;
423
+ "templates.methodUnadvertised": (p: {
424
+ method: string;
425
+ }) => string;
426
+ "templates.methodSlots": string;
427
+ "templates.methodFill": string;
428
+ "templates.methodTemplate": string;
429
+ "templates.methodLint": string;
430
+ "templates.methodList": string;
431
+ "templates.methodCreate": string;
432
+ "templates.kindSlot": string;
433
+ "templates.kindField": string;
434
+ "templates.kindForm": string;
435
+ "templates.kindList": string;
436
+ "templates.invalidSpec": string;
437
+ "templates.invalidJson": string;
438
+ "templates.readSpecFailed": string;
439
+ "templates.invalidSpecSource": string;
440
+ "templates.invalidVariable": (p: {
441
+ variable: string;
442
+ }) => string;
443
+ "templates.invalidVariableKey": (p: {
444
+ variable: string;
445
+ }) => string;
446
+ "templates.invalidEnum": (p: {
447
+ variable: string;
448
+ }) => string;
449
+ "templates.invalidList": (p: {
450
+ variable: string;
451
+ }) => string;
452
+ "templates.invalidListFieldKey": (p: {
453
+ field: string;
454
+ }) => string;
455
+ "templates.openDocument": string;
456
+ "templates.loading": string;
457
+ "templates.documentInputs": string;
458
+ "templates.noInputs": string;
459
+ "templates.specLabel": string;
460
+ "templates.chooseValue": string;
461
+ "templates.previewFill": string;
462
+ "templates.previewSpec": string;
463
+ "templates.rendering": string;
464
+ "templates.previewAria": string;
465
+ "templates.previewReady": (p: {
466
+ pages: number;
467
+ }) => string;
468
+ "templates.previewPage": (p: {
469
+ page: number;
470
+ }) => string;
471
+ "templates.apply": string;
472
+ "templates.hwpOnly": string;
473
+ "templates.pendingEdits": string;
474
+ "templates.listAdd": string;
475
+ "templates.listRemove": (p: {
476
+ row: number;
477
+ }) => string;
478
+ "templates.listFieldAria": (p: {
479
+ row: number;
480
+ field: string;
481
+ }) => string;
482
+ "templates.richBlocksUnsupported": string;
483
+ "templates.embeddedPicker": string;
484
+ "templates.createEmbedded": string;
485
+ "lint.panelAria": string;
486
+ "lint.profile": string;
487
+ "lint.gongmun": string;
488
+ "lint.report": string;
489
+ "lint.run": string;
490
+ "lint.running": string;
491
+ "lint.clean": string;
492
+ "lint.errors": (p: {
493
+ count: number;
494
+ }) => string;
495
+ "lint.warnings": (p: {
496
+ count: number;
497
+ }) => string;
498
+ "lint.location": (p: {
499
+ line: number;
500
+ col: number;
501
+ }) => string;
502
+ "lint.noContext": string;
503
+ "lint.disabled": (p: {
504
+ reason: string;
505
+ remedy: string;
506
+ }) => string;
507
+ "error.staleReplacement": string;
508
+ "error.staleCompose": string;
509
+ "error.stalePreview": string;
510
+ "error.unmatchedReplace": string;
511
+ "error.runRangeConflict": string;
512
+ "error.rangeTagRefused": string;
513
+ "error.stoppedWithoutDiagnostic": string;
514
+ "error.noEngineCause": string;
515
+ "error.badEnvelope": (p: {
516
+ detail: string;
517
+ }) => string;
518
+ "error.readOnlyReplacement": string;
519
+ "error.pendingReplacement": string;
520
+ "error.loadingReplacement": string;
521
+ "error.staleApply": string;
522
+ "error.staleRefresh": string;
523
+ "error.staleRefreshEdit": string;
524
+ "error.staleRevert": string;
525
+ "document.panelAria": string;
526
+ "document.metadata": string;
527
+ "document.metaTitle": string;
528
+ "document.metaAuthor": string;
529
+ "document.metaSubject": string;
530
+ "document.metaKeywords": string;
531
+ "document.valuePlaceholder": string;
532
+ "document.setMeta": string;
533
+ "document.pageSetup": string;
534
+ "document.pageKeyAria": string;
535
+ "document.pageValueAria": string;
536
+ "document.setPage": string;
537
+ "document.page.width": string;
538
+ "document.page.height": string;
539
+ "document.page.marginLeft": string;
540
+ "document.page.marginRight": string;
541
+ "document.page.marginTop": string;
542
+ "document.page.marginBottom": string;
543
+ "document.page.orientation": string;
544
+ "document.orientation.portrait": string;
545
+ "document.orientation.landscape": string;
546
+ "segment.paraShapeLabel": string;
547
+ "segment.paraShapeKeyAria": string;
548
+ "segment.paraShapeValueAria": string;
549
+ "segment.paraShapeUnitAria": string;
550
+ "segment.unitPercent": string;
551
+ "segment.unitPoints": string;
552
+ "segment.setPara": string;
553
+ "segment.hyperlinkLabel": string;
554
+ "segment.hyperlinkUrlPlaceholder": string;
555
+ "segment.hyperlinkUrlAria": string;
556
+ "segment.hyperlinkTextPlaceholder": string;
557
+ "segment.hyperlinkTextAria": string;
558
+ "segment.createHyperlink": string;
559
+ "segment.shape.lineSpacing": string;
560
+ "segment.shape.indent": string;
561
+ "segment.shape.left": string;
562
+ "segment.shape.right": string;
563
+ "segment.shape.top": string;
564
+ "segment.shape.bottom": string;
565
+ "fields.createField": string;
566
+ "fields.anchorPlaceholder": string;
567
+ "fields.anchorAria": string;
568
+ "fields.namePlaceholder": string;
569
+ "fields.nameAria": string;
570
+ "fields.createFieldSubmit": string;
571
+ "fields.deleteField": string;
572
+ "fields.bookmarkNamePlaceholder": string;
573
+ "fields.bookmarkNameAria": string;
574
+ "fields.createBookmark": string;
575
+ "fields.deleteBookmark": string;
576
+ "table.addTable": string;
577
+ "table.cloneTable": string;
578
+ "table.anchorPlaceholder": string;
579
+ "table.anchorAria": string;
580
+ "table.cloneAnchorAria": string;
581
+ "table.cloneModeAria": string;
582
+ "table.cloneBlank": string;
583
+ "table.cloneKeep": string;
584
+ "table.addTableRowsLabel": string;
585
+ "table.addTableRowPlaceholder": string;
586
+ "tabs.document": string;
587
+ "tabs.images": string;
588
+ "image.panelAria": string;
589
+ "image.insert": string;
590
+ "image.delete": string;
591
+ "image.file": string;
592
+ "image.fileHint": string;
593
+ "image.unsupported": string;
594
+ "image.anchor": string;
595
+ "image.deleteAnchor": string;
596
+ "image.width": string;
597
+ "image.height": string;
598
+ "image.reading": string;
599
+ "image.invalidSize": string;
600
+ "image.invalidType": string;
601
+ "image.readError": string;
602
+ "error.prefix.image": string;
603
+ "tabs.styles": string;
604
+ "styles.unavailable": (p: {
605
+ version: string;
606
+ }) => string;
607
+ "styles.unavailableHost": string;
608
+ "styles.checkingHost": string;
609
+ "styles.loading": string;
610
+ "styles.loadFailed": string;
611
+ "styles.retry": string;
612
+ "styles.empty": string;
613
+ "styles.kindUnknown": string;
614
+ "styles.attrsUnresolved": string;
615
+ "styles.usage": (p: {
616
+ count: number;
617
+ }) => string;
618
+ "styles.selectHint": string;
619
+ "styles.definition": string;
620
+ "styles.size": string;
621
+ "styles.font": string;
622
+ "styles.bold": string;
623
+ "styles.lineSpacing": string;
624
+ "styles.updateSubmit": string;
625
+ "styles.applyToSelection": string;
626
+ "styles.promoteName": string;
627
+ "styles.promoteSubmit": string;
628
+ "styles.promoteHint": string;
629
+ "styles.nameInvalid": string;
630
+ "styles.presetLabel": string;
631
+ "styles.presetHint": string;
632
+ "styles.presetSubmit": string;
633
+ "styles.pendingEdits": string;
634
+ "styles.noTableToStyle": string;
635
+ "styles.noTableToStyleNoChange": string;
636
+ "styles.noBodyStyleToUpdate": string;
637
+ "styles.presetUnchanged": string;
638
+ "styles.needsParagraph": string;
639
+ "segment.directFormatting": string;
640
+ "segment.directFormattingHint": string;
641
+ "segment.clearDirect": string;
642
+ "segment.directStyleUnknown": string;
643
+ "segment.directStyleLoading": string;
644
+ "segment.directStyleFailed": string;
645
+ "segment.directStyleUnavailable": string;
141
646
  };
142
647
  /** The shape both locale tables must satisfy, derived from canonical `en`. */
143
648
  type MessageTable = typeof en;
@@ -190,6 +695,12 @@ interface HwpEditorProps {
190
695
  * document the engine reports as protected.
191
696
  */
192
697
  readOnly?: boolean;
698
+ /**
699
+ * Component catalogue the palette offers and the new-document assembly
700
+ * composes from. Defaults to the shipped starters; a host with its own
701
+ * library passes what `loadComponents` returned.
702
+ */
703
+ components?: readonly Component[];
193
704
  /**
194
705
  * Called once per completed document load, after both the read and the
195
706
  * render resolve, with the document that was loaded. Fires again on every
@@ -248,7 +759,7 @@ declare const HwpEditor: react.ForwardRefExoticComponent<HwpEditorProps & react.
248
759
  /**
249
760
  * Multi-page scroll of rendered pages. SVG pages render inline (sanitized);
250
761
  * raster formats fall back to <img>. Clicks resolve to the nearest segment
251
- * (see geometry.ts for the flow-model approximation), and selected/pending
762
+ * (using layout rows, with a flow-model fallback for older hosts), and selected/pending
252
763
  * segments are highlighted with overlay bands.
253
764
  */
254
765
  declare function PageCanvas(): JSX.Element;
@@ -260,6 +771,8 @@ declare function PageCanvas(): JSX.Element;
260
771
  */
261
772
  declare function SegmentInspector(): JSX.Element;
262
773
 
774
+ declare function StylesPanel(): JSX.Element;
775
+
263
776
  /**
264
777
  * Table-aware editor for a selected table segment. The cell grid comes from
265
778
  * the GFM table in the read() envelope; addressing follows the CLI's
@@ -275,17 +788,288 @@ declare function TableGrid(): JSX.Element;
275
788
  declare function FieldsPanel(): JSX.Element;
276
789
 
277
790
  interface ComposePanelProps {
278
- /** Called with the composed document once engine.compose() succeeds. */
279
- onComposed: (document: DocumentHandle) => void;
791
+ /** False when the current editor surface is read-only. */
792
+ canCreate?: boolean;
793
+ /** Components the assembly offers; the shipped starters by default. */
794
+ components?: readonly Component[];
795
+ /**
796
+ * Called with the composed document once engine.compose() succeeds.
797
+ *
798
+ * RETURNING a sentence refuses it: the editor did not take the document, the
799
+ * dialog stays open with the composition, and the sentence is shown there.
800
+ * The creating surface owns the screen while it is open, so a refusal that
801
+ * only reached the editor's notice line would be written behind the modal.
802
+ */
803
+ onComposed: (document: DocumentHandle) => string | void;
280
804
  /** Close without composing. */
281
805
  onClose: () => void;
282
806
  }
283
807
  /**
284
- * New-document flow: preset picker + guided form (title, author,
285
- * markdown-ish sections) → DocumentSpec v2 → engine.compose().
808
+ * New-document flow, from one of two sources:
809
+ *
810
+ * - the preset picker plus guided form (title, author, markdown-ish body), or
811
+ * - an ordered component list, composed through `documentSpecFromComponents`,
812
+ * which substitutes each component's params once and merges the styles the
813
+ * components define (refusing two different definitions of one name).
814
+ *
815
+ * The assembly wins while it holds a row: it is the document's content and
816
+ * carries its own styles, so the type, author and body fields are switched off
817
+ * with a hint rather than silently ignored. The title stays: it is the file
818
+ * name and the document metadata in both sources.
286
819
  */
287
820
  declare function ComposePanel(props: ComposePanelProps): JSX.Element;
288
821
 
822
+ /**
823
+ * The state of the document's styles read, so a consumer telling the user why
824
+ * there are no rows can name the right cause: still loading, failed, a host
825
+ * that advertises the command and does not implement it, or no styles command
826
+ * at all are four different next steps.
827
+ */
828
+ type StylesStatus = "idle" | "loading" | "ready" | "failed" | "unsupported";
829
+ /** The unpublished ids of one insertion, tied to the envelope and selection they were read with. */
830
+ interface InsertedHidden {
831
+ envelope: CatEnvelope;
832
+ selections: readonly SegmentRef[] | undefined;
833
+ ids: readonly string[];
834
+ }
835
+ interface HwpEditorContextValue {
836
+ engine: HwpEngine;
837
+ store: EditorStore;
838
+ /** Current store snapshot (from useSyncExternalStore). */
839
+ state: EditorState;
840
+ /** Last read() envelope for the current document; null before load. */
841
+ envelope: CatEnvelope | null;
842
+ capabilities: Capabilities | null;
843
+ /** False for protected/distribution documents: editing UI is disabled. */
844
+ editable: boolean;
845
+ validation: ValidationReport | null;
846
+ /** Queue an image op with bytes held privately until the next apply. */
847
+ queueImage?: (op: Extract<EditOp, {
848
+ kind: "insert-image";
849
+ }>, asset: ImageAsset) => void;
850
+ /** Queue of pending ops length convenience. */
851
+ applyPendingOps: () => void;
852
+ /**
853
+ * Ids of paragraphs the last insertion created that publish no segment, such
854
+ * as an empty paragraph agent-hwp 1.6.2 names in its edit report (#521). They
855
+ * belong to one envelope and the selection made from it; a panel uses them
856
+ * only while both are still current, so a move or delete of that selection
857
+ * acts on the whole insertion.
858
+ */
859
+ insertedHidden?: InsertedHidden | null;
860
+ /**
861
+ * Replace the current document as one undoable transition. The producer
862
+ * receives the captured current document; results are discarded if it or
863
+ * the loaded file changes while the operation is in flight, and the answer
864
+ * says which happened, so a caller never acts on a replacement the editor
865
+ * threw away.
866
+ */
867
+ replaceDocument: (produce: (current: DocumentHandle) => Promise<DocumentHandle>) => Promise<boolean>;
868
+ /**
869
+ * Re-read + re-render the current document after an external change. A load
870
+ * in flight, or one that starts while the read runs, makes this reject with
871
+ * the sentence saying so: the document it read is not the one on screen, so
872
+ * resolving would report a re-read that never landed.
873
+ */
874
+ refresh: () => Promise<void>;
875
+ /**
876
+ * The current document's `styles-v1` table, or null when this host has no
877
+ * styles command, the read is still running, or it failed. Loaded once per
878
+ * document by the editor, so the Styles panel and the direct-format
879
+ * indicator read one table rather than two snapshots that can disagree. A
880
+ * table read for a PREVIOUS document is never handed out: segment ids are
881
+ * content checksums, so the old table's `used_by` would name paragraphs this
882
+ * document does not have.
883
+ */
884
+ styles: StyleTable | null;
885
+ /**
886
+ * Why `styles` is what it is: `ready` with a table, `loading` while the read
887
+ * runs, `failed` when it threw, `unsupported` when the host advertises the
888
+ * command and the engine object has no `styles` to call, and `idle` when
889
+ * this host serves no styles command at all. Four empty states need four
890
+ * sentences, so a consumer that reports one reads this rather than guessing
891
+ * from `styles === null`.
892
+ */
893
+ stylesStatus: StylesStatus;
894
+ /**
895
+ * The editor's document generation. It moves when a load starts and when
896
+ * the compose flow hands a document back, so an async flow captures it
897
+ * before it awaits and refuses its own result once it has moved on: a slow
898
+ * compose must not replace the file the host selected meanwhile.
899
+ */
900
+ loadEpoch: () => number;
901
+ /**
902
+ * Whether the document the store holds is the one the host last chose: false
903
+ * while `loadEpoch` has moved and the load it announced has not ended. A
904
+ * flow that creates or replaces a document takes this at its press and
905
+ * refuses there, because `loadInFlight` cannot be the decision: it is a
906
+ * render behind a started load, and a composed document's read moves
907
+ * `loadEpoch` without raising it at all, leaving the creating dialog open
908
+ * and enabled while the previous composition is still being read.
909
+ */
910
+ loadSettled: () => boolean;
911
+ /**
912
+ * Whether a load that will read bytes is running. A RENDER HINT, for
913
+ * controls that are better disabled than refused: it is one render behind
914
+ * the generations above, so a panel disables on it and never decides from it
915
+ * whether an action is legal — every refusal compares `loadEpoch` (or the
916
+ * store's document), which is what makes the refusal correct even when this
917
+ * flag is stale.
918
+ */
919
+ loadInFlight: boolean;
920
+ /**
921
+ * Re-read the current document's `styles-v1` table without leaving the
922
+ * document: the failed Styles tab's own retry. The editor also re-reads the
923
+ * table after a successful `refresh`, because the bytes the table describes
924
+ * were just re-read.
925
+ */
926
+ retryStyles: () => void;
927
+ /** Open the compose panel (new-document flow). */
928
+ openCompose: () => void;
929
+ /**
930
+ * Put one sentence on the editor's notice line. A panel that learns an
931
+ * outcome the user must hear but that is not an error — a preset whose
932
+ * document has no table to style — reports it here instead of through
933
+ * `onError`, which promises something went wrong.
934
+ */
935
+ noteNotice: (text: string, error?: unknown) => void;
936
+ /**
937
+ * Moves when the editor takes on a NEW document: a load, or a composed
938
+ * document handed back. An applied edit and an undo leave it where it is,
939
+ * because they move within the document the user is working on. A panel that
940
+ * holds a choice tied to the document (a selected style row, whose id means
941
+ * another style in the next file) retires it on a change here: the host's
942
+ * file name cannot answer that, since a compose replaces the document without
943
+ * changing it and two files can share one name.
944
+ */
945
+ documentOrigin: number;
946
+ /**
947
+ * Message lookup bound to the active locale and host overrides. Every
948
+ * panel localizes through this one channel; a panel that cannot reach `t`
949
+ * cannot be localized at all.
950
+ */
951
+ t: TFunction;
952
+ /**
953
+ * Host error callback, passed straight through from `HwpEditorProps`. A
954
+ * panel that owns its own error state (ComposePanel) has no other way to
955
+ * reach the host; the caught value travels verbatim.
956
+ */
957
+ onError?: ((error: unknown) => void) | undefined;
958
+ }
959
+ declare function useHwpEditorContext(): HwpEditorContextValue;
960
+
961
+ /** Where a component goes relative to the selected paragraph. */
962
+ type InsertPosition = "before" | "after";
963
+ interface ComponentsPanelProps {
964
+ /** Catalogue to offer; the shipped starters by default. */
965
+ components?: readonly Component[];
966
+ /** Localized reason the palette cannot insert; empty when it can. */
967
+ disabledReason?: string;
968
+ /**
969
+ * Localized reason the "before" position is unavailable for this selection;
970
+ * empty when it is. Only before is refused — a section's definition
971
+ * paragraph takes no insertion ahead of it — so the palette stays usable.
972
+ */
973
+ beforeDisabledReason?: string;
974
+ /**
975
+ * Localized reason this component's insertion is refused before it is sent,
976
+ * given a component and returning "" when it can go. The refusals are the
977
+ * certain ones (an image, a section break, an equation into .hwp), and the
978
+ * row is disabled with the sentence rather than failing at the engine.
979
+ */
980
+ refusalFor?: (component: Component) => string;
981
+ /** True while an engine call owns the document. */
982
+ busy?: boolean;
983
+ onInsert?: (component: Component, values: Record<string, string>, position: InsertPosition) => void;
984
+ }
985
+ /** Why this engine cannot insert components, or "" when it can. */
986
+ declare function componentsSupportReason(capabilities: {
987
+ version: string;
988
+ editOps?: "v1";
989
+ } | null, t: ReturnType<typeof useHwpEditorContext>["t"]): string;
990
+ declare function ComponentsPanel({ components, disabledReason, beforeDisabledReason, refusalFor, busy, onInsert, }: ComponentsPanelProps): JSX.Element;
991
+
992
+ /**
993
+ * What the palette does when a component cannot become an op, when the engine
994
+ * is certain to refuse it, or when it refuses the op that was sent.
995
+ *
996
+ * Three things are translated here rather than shown as the engine wrote them:
997
+ *
998
+ * - A component refusal (`ComponentError`) carries a code, the component's
999
+ * name or file and the field that failed, so the sentence a user reads is in
1000
+ * their locale and still names where to look.
1001
+ * - `insert_blocks` refuses a block wider than its insertion point with a
1002
+ * diagnostic that reads the same in every UI locale ("layout_overflow … body
1003
+ * width is 46.40 mm"). The width of the destination is not something the
1004
+ * render layout publishes — a paragraph's painted box is the width of its
1005
+ * text, 163.9 pt against a 170 mm column in the playground's own fixture —
1006
+ * so the engine's own `layout_overflow` diagnostic and the width it prints
1007
+ * are the source of both numbers, and a preflight from the rendered box
1008
+ * would refuse insertions the engine accepts.
1009
+ * - The same refusal has two other classes — a style the target document
1010
+ * does not define, and a block, style or list definition the engine
1011
+ * rejected — and each gets its own sentence and next step here.
1012
+ *
1013
+ * All three classes arrive as the structured `insertion` field both
1014
+ * transports set from core's `classifyInsertionRefusal` (#88). The message is
1015
+ * never parsed for a class: on an unclassified failure it can carry what the
1016
+ * user typed.
1017
+ *
1018
+ * Every other refusal — an insertion before a section's definition paragraph,
1019
+ * an equation into `.hwp`, a compile failure — is one class: the engine's own
1020
+ * cause inside one frame that names the component and the insertion point, so
1021
+ * no transport can leave a caller with a causeless exit code. The three
1022
+ * refusals that are certain before the document is touched are answered
1023
+ * without a round trip at all.
1024
+ *
1025
+ * An insertion the engine was stopped out of is the one case where that
1026
+ * inner cause is NOT the transport's text: the sentence both transports
1027
+ * append for an empty stderr is English, so the locale's own sentence for the
1028
+ * structured `stopped` marker takes the slot (#91).
1029
+ */
1030
+
1031
+ /**
1032
+ * The widest block a component would insert, in mm.
1033
+ *
1034
+ * Only the block types that carry a width of their own are measured: a table
1035
+ * (its `width_mm`, or its column widths), an image and an equation. Nested
1036
+ * cell blocks are measured too, since a cell's content is what overflows a
1037
+ * narrow cell first.
1038
+ */
1039
+ declare function widestBlockMm(blocks: Blocks): number | undefined;
1040
+ /**
1041
+ * The insertion width a `layout_overflow` refusal measured, in mm, from the
1042
+ * structured field a transport sets (#88). The message is not parsed.
1043
+ */
1044
+ declare function overflowingBodyMm(error: unknown): number | undefined;
1045
+ /**
1046
+ * Whether an engine failure is the width refusal `insert_blocks` answers
1047
+ * with, read from the structured `insertion` field (#88). The message is not
1048
+ * parsed: on an unclassified failure it can carry what the user typed.
1049
+ */
1050
+ declare function isLayoutOverflow(error: unknown): boolean;
1051
+ /**
1052
+ * An error to report for a failed insertion, in the user's own language.
1053
+ *
1054
+ * Every transport lands here, so every refused insertion gets a localized
1055
+ * sentence rather than whatever the engine or the server wrote: the specific
1056
+ * classes (too wide, unknown style, rejected definition) say what to change,
1057
+ * and anything else keeps the engine's own reason inside one frame that names
1058
+ * both things a caller can vary — the component and the insertion point. The
1059
+ * transport's text stays on `detail` for a log, and an error that is not an
1060
+ * engine refusal (a timeout, an unavailable binary, a protected document) is
1061
+ * passed through with the handling it already has.
1062
+ */
1063
+ declare function insertionFailure(error: unknown, blocks: Blocks, t: TFunction): unknown;
1064
+ /** A component refusal as the localized sentence for it. */
1065
+ declare function componentRefusalText(error: unknown, t: TFunction): string | null;
1066
+ /**
1067
+ * The message to report for a throw from a component path: the localized
1068
+ * refusal when it is one, otherwise whatever came. The English one-line form
1069
+ * stays on `detail`, which is where a host's log reads it.
1070
+ */
1071
+ declare function componentFailure(error: unknown, t: TFunction): unknown;
1072
+
289
1073
  /**
290
1074
  * Minimal SVG sanitizer for inline rendering of `hwp render --format svg`
291
1075
  * output. The CLI output is trusted, but hosts embedding arbitrary documents
@@ -306,17 +1090,7 @@ declare function sanitizeSvg(svgText: string): string;
306
1090
  */
307
1091
  declare function plainSegmentText(markdownSlice: string): string;
308
1092
 
309
- /**
310
- * Click hit-testing and highlight placement for PageCanvas.
311
- *
312
- * Neither the core segment envelope nor the hwp-cli SVG renderer carries
313
- * per-paragraph page geometry, so positions are estimated with a linear
314
- * text-flow model: paragraphs flow in document order across pages
315
- * proportionally to their markdown length. Clicks map to a global flow
316
- * fraction, then to the nearest segment via the core coordinate helpers;
317
- * highlight bands use the exact inverse mapping, so the visual highlight
318
- * always agrees with what a click would select.
319
- */
1093
+ /** Exact layout rows take precedence; older hosts keep the linear flow model. */
320
1094
 
321
1095
  /** Resolve a page click to the nearest segment. */
322
1096
  declare function nearestSegment(envelope: CatEnvelope, pageIndex: number, yFraction: number, pageCount: number): Segment | undefined;
@@ -337,12 +1111,25 @@ interface SegmentBand {
337
1111
  declare function segmentBand(envelope: CatEnvelope, segment: Segment, pageCount: number): SegmentBand | null;
338
1112
 
339
1113
  /**
340
- * GFM table extraction from the `hwp cat --with-segments` envelope.
1114
+ * Table extraction from the `hwp cat --with-segments` envelope.
1115
+ *
1116
+ * The CLI emits one `table` segment per table control, covering the whole
1117
+ * markdown that table projects to: a GFM pipe table, or the HTML `<table>` a
1118
+ * merged cell or a block-content cell forces. A table's index is its position
1119
+ * among the `table` segments, which is the order hwp-cli's own nth-table walk
1120
+ * (`walk_nth_table_root`) assigns - with one gap: that walk also counts a table
1121
+ * inside a footnote, a header, a footer or a hidden comment, and the envelope
1122
+ * publishes no segment for any of those. One such table shifts every later
1123
+ * published index onto another table, so the panel must not trust the count on
1124
+ * its own. The engine's own count arrives as `bodyTables`, and the table panel
1125
+ * refuses index-addressed ops when the two disagree (#97 item 1). Table indices
1126
+ * are 0-based in document order, matching the `hwp edit --set-cell
1127
+ * "table:row:col=value"` coordinate grammar; within a table, row 0 is the
1128
+ * header row and the `---` separator row is skipped.
341
1129
  *
342
- * The CLI emits one para segment per table, covering the whole markdown
343
- * table block. Table indices are 0-based in document order, matching the
344
- * `hwp edit --set-cell "table:row:col=value"` coordinate grammar; within a
345
- * table, row 0 is the header row and the `---` separator row is skipped.
1130
+ * The row and column numbers this module produces are the ones every table op
1131
+ * addresses, so the grid the panel shows and the coordinate it queues come
1132
+ * from this one parse.
346
1133
  */
347
1134
 
348
1135
  interface TableModel {
@@ -352,18 +1139,43 @@ interface TableModel {
352
1139
  segment: Segment;
353
1140
  /**
354
1141
  * Cell grid. Row 0 is the header row; the markdown separator row is not
355
- * included. Merged cells cannot be represented in markdown, so spans are
356
- * flattened to their anchor cell text.
1142
+ * included.
1143
+ *
1144
+ * `null` when the engine projected this table as HTML instead (a merged cell,
1145
+ * or a cell holding block content). Such a table has no grid to draw here but
1146
+ * still occupies its index slot, because the engine counts it too (#95).
357
1147
  */
358
- rows: string[][];
1148
+ rows: string[][] | null;
359
1149
  }
360
1150
  /** True when a segment's markdown slice is a GFM table block. */
361
1151
  declare function isTableSlice(slice: string): boolean;
362
1152
  /** Parse a GFM table slice into a cell grid; null when not a table. */
363
1153
  declare function parseMarkdownTable(slice: string): string[][] | null;
364
- /** All tables in the envelope, in document order. */
1154
+ /**
1155
+ * Every table in the envelope, in document order, numbered as the engine
1156
+ * numbers them.
1157
+ *
1158
+ * The index comes from the segment's kind, never from whether a grid could be
1159
+ * parsed: the engine's nth-table walk counts a merged-cell table and a plain
1160
+ * one alike, and a panel that skipped the HTML one put every later table one
1161
+ * slot early - set-cell, delete-row, delete-table and clone then reached a
1162
+ * different table than the reader picked (#95).
1163
+ */
365
1164
  declare function findTables(envelope: CatEnvelope): TableModel[];
366
- /** The table whose segment sits at the given source coordinate, if any. */
1165
+ /**
1166
+ * The table a source coordinate names, if any.
1167
+ *
1168
+ * The segment id is the precise answer, and it is what a selection carries: the
1169
+ * engine numbers a table's host paragraph by the top-level paragraph, so two
1170
+ * tables under one paragraph (a table nested in a cell, a text-box table) answer
1171
+ * the same `{section, para}` (#97 item 2d). The coordinate is the fallback for a
1172
+ * ref whose id names no table. When the paragraph holds several tables and the
1173
+ * ref's id names a published segment, it resolves to the innermost table whose
1174
+ * span encloses that segment, so the grid the panel shows and the coordinate it
1175
+ * queues still name the same table. A ref without an id, or whose id names no
1176
+ * segment, or whose segment no candidate encloses, gets the first table at that
1177
+ * coordinate.
1178
+ */
367
1179
  declare function tableAtRef(envelope: CatEnvelope, ref: SegmentRef): TableModel | undefined;
368
1180
 
369
1181
  /**
@@ -381,18 +1193,32 @@ interface FieldSlot {
381
1193
  /** Segment containing the placeholder. */
382
1194
  segment: SegmentRef;
383
1195
  }
384
- /** All `{{name}}` placeholder slots in the envelope, in document order. */
1196
+ /**
1197
+ * All `{{name}}` placeholder slots in the envelope, in document order.
1198
+ *
1199
+ * Each slot names the paragraph that holds it, never an enclosing one: a
1200
+ * table and a cell sit inside a host paragraph whose range covers the whole
1201
+ * table, so a slot resolved to the host would make the inspector's Delete
1202
+ * remove the table as well. `resolveSelection` is the same mapper every other
1203
+ * target goes through, so a slot resolves exactly where a click on it does.
1204
+ * When it refuses - a nested paragraph with no id of its own has no ref that
1205
+ * names it - the slot is left out: `hit` is a segment the resolver rejected,
1206
+ * and shipping its coordinate would resolve to the host it was refused for.
1207
+ */
385
1208
  declare function extractFieldSlots(envelope: CatEnvelope): FieldSlot[];
386
1209
 
387
1210
  /**
388
1211
  * Compose-panel presets → DocumentSpec v2.
389
1212
  *
390
- * Profile values mirror hwp-cli's official presets
391
- * (crates/hwp-convert/src/official.rs): body font, size (1/100 pt there,
392
- * plain pt here), line spacing percent, and page-number footer policy.
1213
+ * The numbers are not here: `DOCUMENT_PROFILES` (each preset's body row) and
1214
+ * `COMPOSE_STYLE_ROWS` (the heading and title rows this panel adds) in
1215
+ * `@hwp-editor/core` are the one copy (issue #54 Decision 2026-11-10), read
1216
+ * here and by the component library, with a binary-gated test that diffs each
1217
+ * engine preset's body row against `hwp new --preset <name>`.
393
1218
  */
394
1219
 
395
- type ComposePreset = "official" | "report" | "plan" | "notice" | "minutes" | "gaejosik" | "press";
1220
+ type ComposePreset = ProfileName;
1221
+ /** The presets the picker offers, in its order. */
396
1222
  declare const COMPOSE_PRESETS: ComposePreset[];
397
1223
  interface ComposeInput {
398
1224
  title: string;
@@ -416,38 +1242,6 @@ declare function bodyToBlocks(body: string): ParagraphBlock[];
416
1242
  /** Build the DocumentSpec v2 for a preset + guided form input. */
417
1243
  declare function buildDocumentSpec(preset: ComposePreset, input: ComposeInput): DocumentSpecV2;
418
1244
 
419
- interface HwpEditorContextValue {
420
- engine: HwpEngine;
421
- store: EditorStore;
422
- /** Current store snapshot (from useSyncExternalStore). */
423
- state: EditorState;
424
- /** Last read() envelope for the current document; null before load. */
425
- envelope: CatEnvelope | null;
426
- capabilities: Capabilities | null;
427
- /** False for protected/distribution documents: editing UI is disabled. */
428
- editable: boolean;
429
- validation: ValidationReport | null;
430
- /** Queue of pending ops length convenience. */
431
- applyPendingOps: () => void;
432
- /** Re-read + re-render the current document after an external change. */
433
- refresh: () => Promise<void>;
434
- /** Open the compose panel (new-document flow). */
435
- openCompose: () => void;
436
- /**
437
- * Message lookup bound to the active locale and host overrides. Every
438
- * panel localizes through this one channel; a panel that cannot reach `t`
439
- * cannot be localized at all.
440
- */
441
- t: TFunction;
442
- /**
443
- * Host error callback, passed straight through from `HwpEditorProps`. A
444
- * panel that owns its own error state (ComposePanel) has no other way to
445
- * reach the host; the caught value travels verbatim.
446
- */
447
- onError?: ((error: unknown) => void) | undefined;
448
- }
449
- declare function useHwpEditorContext(): HwpEditorContextValue;
450
-
451
1245
  /**
452
1246
  * Engine error classification for distinct UI states, mapping a failure
453
1247
  * onto the four states the editor renders distinctly.
@@ -468,4 +1262,4 @@ declare function useHwpEditorContext(): HwpEditorContextValue;
468
1262
  type EngineErrorKind = "timeout" | "unavailable" | "protected" | "generic";
469
1263
  declare function classifyEngineError(message: string): EngineErrorKind;
470
1264
 
471
- export { COMPOSE_PRESETS, type ComposeInput, ComposePanel, type ComposePanelProps, type ComposePreset, type EngineErrorKind, type FieldSlot, FieldsPanel, HwpEditor, type HwpEditorContextValue, type HwpEditorHandle, type HwpEditorMessages, type HwpEditorProps, type Locale, type MessageKey, type MessageTable, PageCanvas, type SegmentBand, SegmentInspector, type TFunction, TableGrid, type TableModel, bodyToBlocks, buildDocumentSpec, classifyEngineError, clickOffset, createT, en, extractFieldSlots, findTables, isTableSlice, ko, nearestSegment, parseMarkdownTable, plainSegmentText, sanitizeSvg, segmentBand, tableAtRef, useHwpEditorContext };
1265
+ export { COMPOSE_PRESETS, ComponentsPanel, type ComponentsPanelProps, type ComposeInput, ComposePanel, type ComposePanelProps, type ComposePreset, type EngineErrorKind, type FieldSlot, FieldsPanel, HwpEditor, type HwpEditorContextValue, type HwpEditorHandle, type HwpEditorMessages, type HwpEditorProps, type InsertPosition, type Locale, type MessageKey, type MessageTable, PageCanvas, type SegmentBand, SegmentInspector, StylesPanel, type TFunction, TableGrid, type TableModel, bodyToBlocks, buildDocumentSpec, classifyEngineError, clickOffset, componentFailure, componentRefusalText, componentsSupportReason, createT, en, extractFieldSlots, findTables, insertionFailure, isLayoutOverflow, isTableSlice, ko, nearestSegment, overflowingBodyMm, parseMarkdownTable, plainSegmentText, sanitizeSvg, segmentBand, tableAtRef, useHwpEditorContext, widestBlockMm };