uhuu-components 0.4.1 → 0.4.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.
package/index.d.ts CHANGED
@@ -22,6 +22,13 @@ export interface StaticFlowItemMeta {
22
22
  orphans?: number;
23
23
  /** An item split between the lines of its `Static.FlowText`: fewest lines on the piece that starts the next page. Default 2. */
24
24
  widows?: number;
25
+ /**
26
+ * The screen view (`PageEditor` `view="screen"`): where print would scale the item onto a page of
27
+ * its own (taller than its page, and not split by a `Static.FlowText`), it is drawn whole at full
28
+ * size and its sheet grows to hold it. Taller than any page, it starts right under what precedes
29
+ * it. Print ignores it, and so does an item inside a `Static.FlowColumns` column group.
30
+ */
31
+ growSheet?: boolean;
25
32
  }
26
33
 
27
34
  /**
@@ -69,6 +76,13 @@ export type StaticFlowTextIssue =
69
76
  export interface StaticFlowItemGroup {
70
77
  key: string;
71
78
  repeatHeader?: boolean;
79
+ /**
80
+ * The screen view (`PageEditor` `view="screen"`): the group is one unit, its header and every item
81
+ * on one sheet. It fits the room left, or moves whole to a page that holds it; taller than any
82
+ * page, it starts right under what precedes it and its sheet grows (`--uhuu-sheet-growth`). Print
83
+ * ignores it, and so does a `Static.FlowColumns` column group.
84
+ */
85
+ growSheet?: boolean;
72
86
  }
73
87
 
74
88
  export interface StaticFlowFragmentContext<TItem = unknown> {
@@ -133,6 +147,11 @@ export interface StaticFlowChunk {
133
147
  layout?: StaticFlowLayoutFragment[];
134
148
  /** The pieces of items split between lines on this page, by item index. */
135
149
  splits?: Record<number, StaticFlowTextSplit>;
150
+ /**
151
+ * How much taller than its page this sheet is drawn, in px, to hold an item with `growSheet`
152
+ * (the screen view). The sheet exposes it as `--uhuu-sheet-growth`.
153
+ */
154
+ growth?: number;
136
155
  }
137
156
 
138
157
  export interface StaticFlowColumn {
@@ -194,6 +213,11 @@ export interface StaticFlowMeasureApi {
194
213
  readHeaderGroupKey: (element: HTMLElement) => string | undefined;
195
214
  /** @internal Library measurement detail; retained for compatibility. */
196
215
  readHeaderGroupRepeats: (itemElements: HTMLElement[]) => Record<string, boolean>;
216
+ /**
217
+ * @internal The header groups whose items carry `data-uhuu-flow-header-grow-sheet`
218
+ * (`getItemGroup` `growSheet`, the screen view), for `headerGroupGrows`.
219
+ */
220
+ readHeaderGroupGrows: (itemElements: HTMLElement[]) => Record<string, boolean>;
197
221
  /** `unwrapped`: heights from `readUnwrappedHeights`, used for the headers it covers. */
198
222
  readHeaderGroupHeights: (
199
223
  root: HTMLElement,
@@ -268,11 +292,14 @@ export interface StaticFlowPlanInput {
268
292
  headerGroupKeys?: Array<string | null | undefined>;
269
293
  headerGroupHeights?: Record<string, number>;
270
294
  headerGroupRepeats?: Record<string, boolean>;
295
+ /** Header groups that are one unit on one sheet (`getItemGroup` `growSheet`, the screen view). */
296
+ headerGroupGrows?: Record<string, boolean>;
271
297
  onUnplaceableItem?: (item: StaticFlowUnplaceableItem) => void;
298
+ /** @internal Filled with the planner's work counters (hosts tuning their own canvas). */
272
299
  metrics?: StaticFlowPlanMetrics;
273
300
  /**
274
- * Line metrics per item (`flowMeasure.readFlowTextLines`); `undefined` for items that do not
275
- * split. An item that does not fit the room left is split at a line (chunks gain `splits`).
301
+ * @internal Line metrics per item, as `flowMeasure.readFlowTextLines` reads them (hosts that run
302
+ * their own Flow canvas); `undefined` for items that do not split. An item that does not fit the room left is split at a line (chunks gain `splits`).
276
303
  * Without `lines` the plan is item-level. `planFlowColumnChunks` does not split.
277
304
  */
278
305
  lines?: Array<StaticFlowItemLines | undefined>;
@@ -293,7 +320,8 @@ export interface StaticFlowColumnPlanInput extends StaticFlowPlanInput {
293
320
 
294
321
  export interface ImageBlockDialog {
295
322
  path: string;
296
- type: "image" | "satellite";
323
+ /** The dialog to open. A frame message (`frameEditDialog`) has `frame` instead. */
324
+ type?: "image" | "satellite";
297
325
  [key: string]: unknown;
298
326
  }
299
327
 
@@ -317,16 +345,35 @@ export interface ImageBlockProps {
317
345
  style?: CSSProperties;
318
346
  imageStyle?: CSSProperties;
319
347
  backgroundColor?: string;
348
+ /**
349
+ * `auto` (an image in the flow of the page), `bleed` (positioned on the page by its geometry, into
350
+ * the bleed where it touches an edge) or `spread` (one half of an image across two facing pages).
351
+ * Unset: `spread` when `side` is set, `bleed` when any of `width`, `height`, `left`, `right`,
352
+ * `top`, `bottom` is set, else `auto`.
353
+ */
320
354
  mode?: "bleed" | "spread" | "auto";
321
- side?: "start" | "end";
355
+ /**
356
+ * `spread`: which page of the pair this half is on: `start` (or `left`) the left page, `end` (or
357
+ * `right`) the right one. `left` / `right` as a cover spread's `spread.side` names them.
358
+ */
359
+ side?: "start" | "end" | "left" | "right";
360
+ /** Geometry in mm from the trim box, as every page dimension: the image's width. */
322
361
  width?: number;
362
+ /** Geometry in mm: the image's height. */
323
363
  height?: number;
364
+ /** Geometry in mm: distance from the left trim edge (0 runs into the bleed). */
324
365
  left?: number;
366
+ /** Geometry in mm: distance from the right trim edge (0 runs into the bleed). */
325
367
  right?: number;
368
+ /** Geometry in mm: distance from the top trim edge (0 runs into the bleed). */
326
369
  top?: number;
370
+ /** Geometry in mm: distance from the bottom trim edge (0 runs into the bleed). */
327
371
  bottom?: number;
372
+ /** Page width in mm; default from the page setup (ConfigContext). */
328
373
  pageWidth?: number;
374
+ /** Page height in mm; default from the page setup. */
329
375
  pageHeight?: number;
376
+ /** Bleed in mm; default from the page setup. */
330
377
  bleed?: number;
331
378
  dialog?: ImageBlockDialog;
332
379
  annotation?: ImageBlockAnnotation;
@@ -337,7 +384,10 @@ export interface ImageBlockProps {
337
384
  * Extra props (className, handlers, data attributes) merged into the click target that `dialog`
338
385
  * binds. Applied in `auto` mode, where ImageBlock renders that element itself. In `bleed` and
339
386
  * `spread` modes the image is positioned on the page and its element is the library's: there
340
- * `dialogProps` is not applied; style the block through `className` / `imageClassName`.
387
+ * `dialogProps` is not applied, and neither are `className`, `style`, `imageStyle`, `imageProps`,
388
+ * `renderImage` and `placeholder` (development builds warn). Style the image with
389
+ * `imageClassName`; `children` render over it only with `dialog`, `annotation`, `overlaySvg` or
390
+ * `options`.
341
391
  */
342
392
  dialogProps?: Record<string, unknown>;
343
393
  placeholder?: ReactNode;
@@ -414,6 +464,246 @@ export interface ImageUrlOptions {
414
464
  */
415
465
  export function imageUrl(src: ImageSource, options?: ImageUrlOptions): string | undefined;
416
466
 
467
+ // --- Image frames (src/uhuu/frame/). See docs/frame-block.md. ---
468
+ // The read helpers are the vendored `uhuu.frame.v1` module (src/uhuu/frame/vendor, generated from
469
+ // uhuu-editor-dialogs). dist ships this file alone, so the module's types are mirrored here;
470
+ // test/frame-vendor.test.mjs checks the mirror against the vendored source.
471
+
472
+ /** `value.uhuuFrame.schema` of a frame. */
473
+ export const FRAME_SCHEMA: "uhuu.frame.v1";
474
+ /** Key of the frame record inside a frame value. Namespaced so it cannot collide with template keys. */
475
+ export const FRAME_KEY: "uhuuFrame";
476
+
477
+ /** Which legacy image wins when an old value carries both a generated image and a pick. */
478
+ export type FrameLegacyPrecedence = "generated" | "pick";
479
+
480
+ /** A transform applied to a source's image (crop, AI enhance, …). Its base is the previous step. */
481
+ export interface FrameStep {
482
+ type: string;
483
+ url: string;
484
+ width?: number;
485
+ height?: number;
486
+ mimeType?: string;
487
+ /** Replayable parameters or result metadata (crop box, AI asset id, …). */
488
+ state?: Record<string, unknown>;
489
+ }
490
+
491
+ /** An overlay drawn over a source's image by the page (annotation). Never composited into the image. */
492
+ export interface FrameLayer {
493
+ state: unknown;
494
+ /** The image the overlay was drawn on. */
495
+ baseUrl?: string;
496
+ /** The image under the overlay changed after it was drawn. */
497
+ stale?: boolean;
498
+ }
499
+
500
+ /** One dialog's own entry: its last image, the state it reopens with, its steps and layers. */
501
+ export interface FrameSource {
502
+ /** Absent for state-only saves (a map saved without a design image). */
503
+ url?: string;
504
+ /** Key the dialog used for its URL (`image` for generated dialogs); reproduced when it reopens. */
505
+ urlKey?: string;
506
+ width?: number;
507
+ height?: number;
508
+ mimeType?: string;
509
+ /** Everything else the dialog saved, URL keys removed. */
510
+ state?: Record<string, unknown>;
511
+ steps?: FrameStep[];
512
+ layers?: Record<string, FrameLayer>;
513
+ }
514
+
515
+ /** One-level undo: the active source before the last action and the entry it changed. */
516
+ export interface FrameUndo {
517
+ active: string | null;
518
+ /** Source entry the action changed; absent when only `active` moved. */
519
+ type?: string;
520
+ /** That entry before the action; `null` when the action created it. */
521
+ before?: FrameSource | null;
522
+ }
523
+
524
+ /** `value.uhuuFrame`: every source the slot holds and the one it shows. */
525
+ export interface FrameRecord {
526
+ schema: "uhuu.frame.v1";
527
+ active: string | null;
528
+ sources: Record<string, FrameSource>;
529
+ previous?: FrameUndo;
530
+ }
531
+
532
+ /**
533
+ * A frame value as stored in the payload. Its top level mirrors the active source in the shape it
534
+ * saved before frames — a map's image under `image`, a pick's under `contentUrl`, both also under
535
+ * `url` — so `imageUrl(value)` and the readers templates already have keep working.
536
+ */
537
+ export type FrameValue = Record<string, unknown> & { uhuuFrame: FrameRecord };
538
+
539
+ export interface FrameOptions {
540
+ /** Source types the field declares, in order. Resolves a legacy generated shape with no identifying key (a bare `{ image }`). */
541
+ sources?: readonly string[];
542
+ /** Default `'generated'`. Implenia IM passes `'pick'`. */
543
+ legacyPrecedence?: FrameLegacyPrecedence;
544
+ /**
545
+ * A legacy generated value whose upload failed keeps its render as a `data:` URL
546
+ * (`dataImage`). `'show'` (default) shows it, as Implenia IM, implenia-teaser and jbre's
547
+ * cadastral do; `'ignore'` treats the source as having no image, as wuw, evernest, go and
548
+ * jbre's map do (their placeholder shows). New saves never carry one.
549
+ */
550
+ legacyDataImage?: 'show' | 'ignore';
551
+ /**
552
+ * Also draw the overlay a source dialog keeps in its own state (cadastral's
553
+ * `annotationSvg`). Off by default: the cadastral dialog bakes that outline into its image.
554
+ */
555
+ intrinsicOverlays?: boolean;
556
+ /** A legacy overlay saved at a separate path (`annotationPath`); folded into the active source. */
557
+ legacyLayer?: unknown;
558
+ /** Layer type the legacy overlay becomes. Default `'annotation'`. */
559
+ legacyLayerType?: string;
560
+ }
561
+
562
+ export interface FrameDisplay {
563
+ /** The image to show; `''` when there is none. */
564
+ url: string;
565
+ width?: number;
566
+ height?: number;
567
+ mimeType?: string;
568
+ /** Active source type. */
569
+ source: string | null;
570
+ /** Number of transforms applied on top of the source image. */
571
+ steps: number;
572
+ }
573
+
574
+ export interface FrameOverlay {
575
+ /** Layer type, or the source type for an overlay the source dialog drew itself (cadastral). */
576
+ key: string;
577
+ svg: string;
578
+ stale: boolean;
579
+ /** Drawn by the source dialog as part of its own output. */
580
+ intrinsic: boolean;
581
+ }
582
+
583
+ /** The image an image-accepting dialog opens with (`eventData.input`). */
584
+ export interface FrameImageInput {
585
+ url: string;
586
+ width?: number;
587
+ height?: number;
588
+ mimeType?: string;
589
+ /** Frame source the image comes from. */
590
+ source?: string;
591
+ }
592
+
593
+ /** True when `value` carries a `uhuu.frame.v1` record. */
594
+ export function isFrameValue(value: unknown): value is FrameValue;
595
+
596
+ /**
597
+ * The frame record of any value: a frame (validated), or a value saved before frames (URL string,
598
+ * ImageObject, a generated dialog's output) read into one in memory. Never writes. `null` for an
599
+ * empty slot. A frame whose mirrored `contentUrl` was patched by a writer that does not know frames
600
+ * reads that patch as the newest pick.
601
+ */
602
+ export function normalizeFrame(value: unknown, options?: FrameOptions): FrameRecord | null;
603
+
604
+ /** What the page should show for this value: URL, size and the source it comes from. */
605
+ export function frameDisplay(value: unknown, options?: FrameOptions): FrameDisplay;
606
+
607
+ /** The image URL to show for a frame or legacy value; `''` when there is none. */
608
+ export function frameImage(value: unknown, options?: FrameOptions): string;
609
+
610
+ /** The active source type, or `null`. */
611
+ export function frameActive(value: unknown, options?: FrameOptions): string | null;
612
+
613
+ /** The input an image-accepting dialog opens with; `null` when nothing is shown. */
614
+ export function frameInput(value: unknown, options?: FrameOptions): FrameImageInput | null;
615
+
616
+ /**
617
+ * The overlays to draw over the shown image, bottom to top: the source dialog's own overlay
618
+ * (cadastral's `annotationSvg`), then the active source's layers. Stale layers are included.
619
+ */
620
+ export function frameOverlays(value: unknown, options?: FrameOptions): FrameOverlay[];
621
+
622
+ /**
623
+ * The value a source dialog reopens with, in the shape it saved (`{ list, home, mapbox, image }` for
624
+ * the map). `undefined` when the source has never been saved.
625
+ */
626
+ export function frameSourceView(value: unknown, type: string, options?: FrameOptions): Record<string, unknown> | undefined;
627
+
628
+ /** Any value as a stored frame, showing what it showed before. `null` for an empty slot. */
629
+ export function toFrameValue(value: unknown, options?: FrameOptions): FrameValue | null;
630
+
631
+ /**
632
+ * The options every reader of a slot passes, from its declaration: its sources, legacy
633
+ * precedence, failed-upload rule, and the overlay saved at `annotationPath` (read from `payload`).
634
+ */
635
+ export function frameOptionsOf(declaration: Partial<FrameDeclaration>, payload?: unknown): FrameOptions;
636
+
637
+ /** The image shown now and the overlay saved at `annotationPath`: what an editor without frames annotates. */
638
+ export interface FrameLegacyCurrent {
639
+ image?: string;
640
+ annotation?: unknown;
641
+ }
642
+
643
+ /**
644
+ * `{ path, frame, types }`: the message `$uhuu.editFrame` sends, for an `ImageBlock` `dialog` or an
645
+ * SDK without `editFrame`. `types` is the chooser an editor without frames shows. `null` without a
646
+ * `path` or a source with a `type`.
647
+ */
648
+ export function frameEditDialog(
649
+ declaration: FrameDeclaration,
650
+ current?: FrameLegacyCurrent | null,
651
+ ): { path: string; frame: Omit<FrameDeclaration, "path">; types: Record<string, unknown>[] } | null;
652
+
653
+ /** Opens a frame from a template's own click handler: `$uhuu.editFrame` when the SDK has it, else `editDialog` with `frameEditDialog`'s message. No host, no call. */
654
+ export function openFrame(declaration: FrameDeclaration, current?: FrameLegacyCurrent | null): void;
655
+
656
+ /** One dialog a frame offers: its type, its title in the chooser, and that dialog's own options. */
657
+ export interface FrameDialogEntry {
658
+ type: string;
659
+ title?: string;
660
+ /** The dialog's configuration (coordinates, styles, zoom, `visualGallery`, …). */
661
+ config?: Record<string, unknown>;
662
+ /** Other options for that dialog (`imageGalleryPath`, `galleryUpload`, …). */
663
+ [key: string]: unknown;
664
+ }
665
+
666
+ /** What `$uhuu.editFrame` takes (uhuu-sdk): the slot and the dialogs it offers. */
667
+ export interface FrameDeclaration {
668
+ /** Where the frame is saved. */
669
+ path: string;
670
+ /** The dialogs that create the image (`map`, `satellite`, `cadastral`, `image`, …), in chooser order. */
671
+ sources: FrameDialogEntry[];
672
+ /** Overlays drawn over the shown image (`annotation`). */
673
+ layers?: FrameDialogEntry[];
674
+ /** Transforms offered on the shown image (`image-editor`, `ai-marketing-studio`). Default: all the editor offers; `false` for none. */
675
+ transforms?: string[] | false;
676
+ /** Crop aspect ratio, width / height. */
677
+ ratio?: number;
678
+ /** Which image an old document shows when it holds both a generated image and a pick. Default `'generated'`. */
679
+ legacyPrecedence?: FrameLegacyPrecedence;
680
+ /** Whether an old map whose upload failed shows its unsaved render (`'show'`, default) or the placeholder (`'ignore'`). */
681
+ legacyDataImage?: 'show' | 'ignore';
682
+ /** An overlay saved at its own path before frames. Pass its value as FrameBlock's `annotation`. */
683
+ annotationPath?: string;
684
+ }
685
+
686
+ export interface FrameBlockProps extends FrameDeclaration, Omit<ImageBlockProps, "src" | "dialog" | "annotation"> {
687
+ /** The value at `path`: a frame, or anything saved there before frames. */
688
+ value?: unknown;
689
+ /** Also draw a source's own outline (cadastral `annotationSvg`); off because the cadastral image has it baked in. */
690
+ intrinsicOverlays?: boolean;
691
+ /** The overlay value saved at `annotationPath`; read as the active source's layer until the frame holds its own. */
692
+ annotation?: ImageBlockAnnotationValue | null;
693
+ /** Rendered instead of the frame's image: a template adapter's own URL. */
694
+ src?: string;
695
+ /** `imageUrl` options for the shown image (`print`, `size`, `printSize`, `format`). */
696
+ imageUrlOptions?: ImageUrlOptions;
697
+ }
698
+
699
+ /**
700
+ * An image slot several dialogs write (map, satellite, cadastral, gallery pick, crop, annotation),
701
+ * stored as a `uhuu.frame.v1` value. Renders the shown image through `imageUrl` with every overlay
702
+ * of the active source over it, and opens `$uhuu.editFrame` on click in the editor (`editDialog`
703
+ * with the legacy `types` on an older SDK; nothing in renderer mode). Layout props are ImageBlock's.
704
+ */
705
+ export const FrameBlock: ComponentType<FrameBlockProps>;
706
+
417
707
  // --- Brand-kit runtime (src/uhuu/brand-kit/). See docs/brand-kit-runtime.md. ---
418
708
 
419
709
  export interface BrandKitFontFile {
@@ -650,6 +940,7 @@ export interface BrandKitOption {
650
940
  name: string;
651
941
  }
652
942
 
943
+ /** @deprecated Nothing takes or returns it; use `PageItem`. Removed in 0.5.0. */
653
944
  export interface PageEditorItem {
654
945
  id?: string;
655
946
  templateId?: string;
@@ -929,30 +1220,69 @@ export interface PageEditorProps {
929
1220
  * browser and wins over this one.
930
1221
  */
931
1222
  toolbarPosition?: ToolbarPosition;
1223
+ /**
1224
+ * What the pages are drawn for: `print` (default), the document as it prints, or `screen`, the
1225
+ * document read on screen (a host's "Print" switch). Pages read it with `Static.useView()` and
1226
+ * decide what changes (a table kept whole); a `Static.Flow` item with meta `growSheet` is drawn
1227
+ * whole on a taller sheet instead of scaled to fit a page. The renderer always draws `print`;
1228
+ * any other value draws `print` and warns.
1229
+ */
1230
+ view?: StaticView;
1231
+ /** Called with the page list after every change a user makes (add, remove, reorder, rename). */
932
1232
  onItemsChange?: (items: PageItem[], state: PageEditorState) => void;
1233
+ /** Called with the saved editor state after every change, as it is written to the payload. */
933
1234
  onStateChange?: (state: PageEditorState) => void;
934
1235
  /**
935
- * What prints over every page. Default: the shell's page number ("Page N / total", untranslated).
936
- * `false` or `null`: nothing, for templates that number their own pages.
1236
+ * Shows a page-management error (a page that cannot be added or removed). Default: the shell's
1237
+ * own notice dialog.
937
1238
  */
938
1239
  notifyError?: (message: string) => void;
1240
+ /** Development only (dev tools on): draws a reference image under each page to compare against. */
939
1241
  referenceRenderer?: (page: StandalonePage & { pageNum: number }) => ReactNode;
1242
+ /** Replaces the whole sheet of each page (Pagination and Sheet included); cover spreads excepted. */
940
1243
  renderPage?: (args: { page: StandalonePage & { pageNum: number }; parent?: PageItem }) => ReactNode;
1244
+ /** Extra items in the toolbar's menu, before the shell's own. */
941
1245
  menuItems?: ReactNode;
1246
+ /**
1247
+ * The grid class of the reorder dialog's page thumbnails. It replaces the shell's
1248
+ * `uhuu-page-order-grid-cols` (it does not merge).
1249
+ */
942
1250
  gridColsClass?: string;
1251
+ /**
1252
+ * Called with the item a user is about to add: return it (or a changed copy, async allowed) to
1253
+ * add it, or `null` to cancel.
1254
+ */
943
1255
  resolveNewItem?: (draft: PageItem) => Promise<PageItem | null | void> | PageItem | null | void;
1256
+ /**
1257
+ * What prints over every page. Default: the shell's page number ("Page N / total", untranslated).
1258
+ * `false` or `null`: nothing, for templates that number their own pages.
1259
+ */
944
1260
  renderOverlay?: false | null | ((context: {
1261
+ /** 1-based position in the flow-expanded document, as page components get it. */
1262
+ pageNum: number;
1263
+ /** Sheets in the flow-expanded document. */
1264
+ totalPages: number;
1265
+ /** @deprecated Use `pageNum`. */
945
1266
  pageNo: number;
1267
+ /** @deprecated Use `totalPages`. */
946
1268
  total: number;
947
1269
  pageId: string;
948
1270
  parent?: PageItem;
949
1271
  }) => ReactNode);
950
1272
  reorderTitle?: LocalizedText;
951
1273
  reorderDescription?: LocalizedText;
1274
+ /** The payload key the page list and its state are saved under. Default `uhuu_page_editor`. */
952
1275
  stateKey?: string;
1276
+ /**
1277
+ * Development only: the brand-kit switcher in the dev tools menu (dev tools on). It lists
1278
+ * `brandKits` and calls back; it does not load a kit: wire the choice to `BrandKitProvider`.
1279
+ */
953
1280
  brandKits?: BrandKitOption[];
1281
+ /** Development only: the kit the dev switcher marks as active. */
954
1282
  activeBrandKitId?: string;
1283
+ /** Development only: a kit chosen in the dev switcher. */
955
1284
  onSelectBrandKit?: (id: string) => void;
1285
+ /** Development only: a kit URL or id typed into the dev switcher. */
956
1286
  onAddBrandKit?: (input: string) => void;
957
1287
  }
958
1288
 
@@ -971,17 +1301,47 @@ export interface TemplateDataProviderProps {
971
1301
  }
972
1302
 
973
1303
  export interface IntegrationAdapterConfig {
974
- dataBinding?: Record<string, unknown>;
975
- integration?: Record<string, unknown>;
976
- resolver?: Record<string, unknown> | ((integration: unknown, payload?: unknown) => unknown);
977
- galleryPath?: string | ((integration: unknown) => string | null);
1304
+ /** The page's `dataBinding` prop: dialog paths are built from its integration binding. */
1305
+ dataBinding?: PageDataBinding | Record<string, unknown>;
1306
+ /** The integration's data the resolver reads. */
1307
+ integration?: unknown;
1308
+ /**
1309
+ * Required: how `data` is read from `integration`. A map of keys to paths
1310
+ * (`"listing ?? pba_listing"`) or functions, or one function `(integration, payload) => data`.
1311
+ */
1312
+ resolver?: Record<string, string | ((integration: any) => unknown)> | ((integration: any, payload?: unknown) => unknown);
1313
+ /** The gallery image dialogs browse: a path, or read from the integration. */
1314
+ galleryPath?: string | ((integration: any) => string | null);
1315
+ /** @deprecated Never read: `data` is what `resolver` returns. Removed in 0.5.0. */
978
1316
  defaults?: Record<string, unknown>;
979
1317
  [key: string]: unknown;
980
1318
  }
981
1319
 
982
- export interface IntegrationAdapter {
983
- dialog: (...args: unknown[]) => Record<string, unknown> | null;
984
- dialogProps: (...args: unknown[]) => Record<string, unknown>;
1320
+ /** A dialog `useIntegrationAdapter` builds, its `path` under the page's integration binding. */
1321
+ export interface IntegrationDialog {
1322
+ path: string;
1323
+ subPath?: string | null;
1324
+ imageGalleryPath?: string | null;
1325
+ type?: string;
1326
+ imagePath?: string;
1327
+ ratio?: number;
1328
+ rows?: number;
1329
+ value?: unknown;
1330
+ payload?: unknown;
1331
+ [key: string]: unknown;
1332
+ }
1333
+
1334
+ export interface IntegrationAdapter<TData = any> {
1335
+ /** What `resolver` returned. */
1336
+ data: TData;
1337
+ /** The dialog for a field under the integration (`null` without an integration binding). */
1338
+ dialog: (subPath: string, options?: Record<string, unknown>, value?: unknown) => IntegrationDialog | null;
1339
+ /** `getDialogProps` of that dialog: spread onto the element that renders the field. */
1340
+ dialogProps: (subPath: string, options?: Record<string, unknown>, value?: unknown) => DialogBindingProps;
1341
+ galleryPath: string | null;
1342
+ /** The integration instance the page is bound to. */
1343
+ instanceId: string | null;
1344
+ integration: unknown;
985
1345
  [key: string]: unknown;
986
1346
  }
987
1347
 
@@ -1037,7 +1397,7 @@ export const EditorShell: {
1037
1397
  PageEditor: ComponentType<PageEditorProps>;
1038
1398
  InteractiveModeProvider: ComponentType<InteractiveModeProviderProps>;
1039
1399
  useInteractive: () => InteractiveModeContextValue;
1040
- useIntegrationAdapter: (config: IntegrationAdapterConfig) => IntegrationAdapter;
1400
+ useIntegrationAdapter: <TData = any>(config: IntegrationAdapterConfig) => IntegrationAdapter<TData>;
1041
1401
  /**
1042
1402
  * Document-level options for top-level payload keys, defined and drawn as page options are. A
1043
1403
  * choice is an edit in the uhuu document editor. Joins the nearest InteractiveModeProvider's
@@ -1119,7 +1479,31 @@ export interface StaticCoverSpreadProps {
1119
1479
  export interface StaticPaginationProps {
1120
1480
  children: ReactNode;
1121
1481
  className?: string;
1122
- setup: Record<string, unknown>;
1482
+ setup: StaticPageSetup;
1483
+ }
1484
+
1485
+ /**
1486
+ * A page setup (`Static.Pagination` `setup`, `PageEditor` `pageFormat`), in mm. `format`
1487
+ * (`"A4"`, `"LETTER"`, …) with `orientation`, or `width` and `height`; a custom size outside
1488
+ * 10–4000 mm falls back to A4.
1489
+ */
1490
+ export interface StaticPageSetup {
1491
+ format?: string;
1492
+ // `string & {}`: suggestions for the known values without rejecting a string variable.
1493
+ orientation?: "portrait" | "landscape" | (string & {});
1494
+ width?: number;
1495
+ height?: number;
1496
+ bleed?: number;
1497
+ /** Draws the bleed and trim guides on screen. */
1498
+ showBleed?: boolean;
1499
+ /** `single_page` (default) or `two_pages` (facing pages side by side). */
1500
+ preview?: "single_page" | "two_pages" | (string & {});
1501
+ /** A print stylesheet URL, or its CSS text, added for printing. */
1502
+ printCssUrl?: string;
1503
+ printCssRaw?: string;
1504
+ /** Perfect-binding spine/glue, for a cover spread. */
1505
+ binding?: BindingConfig | null;
1506
+ [key: string]: unknown;
1123
1507
  }
1124
1508
 
1125
1509
  export interface StaticFlowAreaProps {
@@ -1137,11 +1521,18 @@ export interface StaticFlowAreaProps {
1137
1521
  * Room kept free at the bottom of every sheet the flow continues from, so a break never sits on
1138
1522
  * the sheet's edge; the sheet the flow ends on keeps its full area, and a flow that fits one
1139
1523
  * sheet lays out as without it. A CSS length with an absolute unit (`"20mm"`, `"12px"`) or a
1140
- * number of px. `Static.FlowColumns` does not keep it.
1524
+ * number of px (not mm: write `"20mm"`); any other value keeps no room and warns. `Static.FlowColumns`
1525
+ * does not keep it.
1141
1526
  */
1142
1527
  breakReserve?: number | string;
1143
1528
  }
1144
1529
 
1530
+ /**
1531
+ * What the pages are drawn for: `print`, the document as it prints, or `screen`, the document read
1532
+ * on screen (`PageEditor` `view`).
1533
+ */
1534
+ export type StaticView = "print" | "screen";
1535
+
1145
1536
  export interface StaticFlowPageProps {
1146
1537
  children: ReactNode;
1147
1538
  header?: ReactNode;
@@ -1157,18 +1548,26 @@ export interface StaticFlowPageProps {
1157
1548
  breakReserve?: number | string;
1158
1549
  }
1159
1550
 
1160
- export interface StaticFlowProps<TItem = unknown> {
1551
+ /**
1552
+ * `TType`: the item types `metaDefaults` keys and `getItemType` returns, so a misspelled type key is
1553
+ * a type error (`Static.Flow<Row, "heading" | "row">`). Default: any string.
1554
+ */
1555
+ export interface StaticFlowProps<TItem = unknown, TType extends string = string> {
1556
+ /** Stable and unique within the page. */
1161
1557
  id: string;
1162
1558
  items: TItem[];
1163
1559
  getKey: (item: TItem, index: number) => Key;
1560
+ /** The third argument describes this item's visible fragment (page, position, split piece). */
1164
1561
  renderItem: (
1165
1562
  item: TItem,
1166
1563
  index: number,
1167
1564
  fragment: StaticFlowFragmentContext<TItem>
1168
1565
  ) => ReactNode;
1169
1566
  getItemMeta?: (item: TItem, index: number) => StaticFlowItemMeta | undefined;
1170
- metaDefaults?: Partial<Record<string, StaticFlowItemMeta>>;
1171
- getItemType?: (item: TItem, index: number) => string | undefined;
1567
+ /** Meta per item type, under `getItemMeta`; the type is `getItemType`'s, else `item.type`. */
1568
+ metaDefaults?: Partial<Record<TType, StaticFlowItemMeta>>;
1569
+ getItemType?: (item: TItem, index: number) => TType | undefined;
1570
+ /** Opt into a separately measured, repeatable group header (`renderGroupHeader`). */
1172
1571
  getItemGroup?: (
1173
1572
  item: TItem,
1174
1573
  index: number
@@ -1227,7 +1626,7 @@ export interface StaticFlowColumnsContainerProps {
1227
1626
  style?: CSSProperties;
1228
1627
  }
1229
1628
 
1230
- export interface StaticFlowColumnsProps<TItem = unknown> extends StaticFlowProps<TItem> {
1629
+ export interface StaticFlowColumnsProps<TItem = unknown, TType extends string = string> extends StaticFlowProps<TItem, TType> {
1231
1630
  /** One-level story layout. Recursive columns are intentionally unsupported. */
1232
1631
  layout: StaticFlowLayoutNode[];
1233
1632
  getColumnGroupProps?: (
@@ -1263,6 +1662,7 @@ export type MarkdownFlowItem = {
1263
1662
  };
1264
1663
 
1265
1664
  export interface StaticFlowDocumentProps {
1665
+ /** Rendered HTML to paginate. Convert markdown or Notion content to HTML first. */
1266
1666
  html: string;
1267
1667
  header?: ReactNode;
1268
1668
  footer?: ReactNode;
@@ -1274,15 +1674,27 @@ export interface StaticFlowDocumentProps {
1274
1674
  measureContinuation?: boolean;
1275
1675
  /** See `StaticFlowAreaProps.breakReserve`. */
1276
1676
  breakReserve?: number | string;
1677
+ /** Stable flow id within the page. Default `"flow-document"`. */
1277
1678
  id?: string;
1278
1679
  idPrefix?: string;
1279
1680
  flowClassName?: string;
1280
1681
  itemClassName?: string | ((item: HtmlFlowItem, index: number) => string | undefined);
1682
+ /**
1683
+ * Break meta per tag, merged over the built-in defaults (shallow, by tag): headings keep with
1684
+ * the next block; `table`, lists, `pre`, `blockquote`, `figure` and `img` avoid breaking inside.
1685
+ */
1281
1686
  metaDefaults?: Partial<Record<string, StaticFlowItemMeta>>;
1282
1687
  getItemMeta?: (item: HtmlFlowItem, index: number) => StaticFlowItemMeta | undefined;
1688
+ /** Replaces the default renderer of sanitized HTML (to map HTML to your own components). */
1283
1689
  renderItem?: (item: HtmlFlowItem, index: number) => ReactNode;
1690
+ /**
1691
+ * The sanitizer the default renderer applies. Default: the built-in DOM URL allow-list. Pass your
1692
+ * own (DOMPurify), or `false` only for trusted HTML (development warns once).
1693
+ */
1284
1694
  sanitize?: ((html: string) => string) | false;
1695
+ /** Wraps the body in an `Editable` with this dialog, so a click edits the HTML. */
1285
1696
  editable?: { path: string; type?: string; [key: string]: unknown };
1697
+ /** A parser to use without a DOM (server rendering, tests). Default: the DOM parser. */
1286
1698
  parseHtml?: (html: string) => unknown[];
1287
1699
  }
1288
1700
 
@@ -1358,8 +1770,8 @@ export const Static: {
1358
1770
  Sheet: ComponentType<StaticSheetProps>;
1359
1771
  FlowArea: ComponentType<StaticFlowAreaProps>;
1360
1772
  FlowPage: ComponentType<StaticFlowPageProps>;
1361
- Flow: <TItem = unknown>(props: StaticFlowProps<TItem>) => ReactElement | null;
1362
- FlowColumns: <TItem = unknown>(props: StaticFlowColumnsProps<TItem>) => ReactElement | null;
1773
+ Flow: <TItem = unknown, TType extends string = string>(props: StaticFlowProps<TItem, TType>) => ReactElement | null;
1774
+ FlowColumns: <TItem = unknown, TType extends string = string>(props: StaticFlowColumnsProps<TItem, TType>) => ReactElement | null;
1363
1775
  /**
1364
1776
  * Text a `Static.Flow` item may split between lines when it does not fit the room left on its
1365
1777
  * sheet (one per item; `orphans`/`widows` in the item's meta). Renders `<as data-uhuu-flow-text>`.
@@ -1393,4 +1805,10 @@ export const Static: {
1393
1805
  * stops waiting.
1394
1806
  */
1395
1807
  usePaginationHold: (pending?: boolean, label?: string) => void;
1808
+ /**
1809
+ * The view the pages are drawn for (`PageEditor` `view`): `print` or `screen`. Outside a
1810
+ * PageEditor, and always in the renderer, `print`. A template keeps content whole on screen that
1811
+ * print splits across pages (a table's rows), and gives such an item meta `growSheet`.
1812
+ */
1813
+ useView: () => StaticView;
1396
1814
  };
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.4.1",
2
+ "version": "0.4.3",
3
3
  "name": "uhuu-components",
4
4
  "main": "uhuu-components.umd.cjs",
5
5
  "module": "uhuu-components.es.js",