@b10cks/client 1.11.0 → 2.0.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
@@ -57,10 +57,12 @@ declare type ApiQueryParams = Omit<IBBaseQueryParams, 'token'> & Record<string,
57
57
  declare type ApiResourceResponse<T> = IBResponse<T> | T;
58
58
 
59
59
  /**
60
- * Wire a DOM element as a selectable block: click selects it in the editor,
61
- * and editor-driven select/hover toggle outline classes. Honors the configured
62
- * scroll offset and only scrolls when the element isn't already in view.
63
- * Returns a cleanup function. No-op outside preview mode.
60
+ * Wire a DOM element as a selectable block. A click selects it in the editor
61
+ * and never reaches links or buttons inside it. Only the innermost editable
62
+ * under the pointer or matching the editor's selection is highlighted, with a
63
+ * label. Toggles `b10cks-selected`, `b10cks-hover`, and `b10cks-hidden` (while
64
+ * the editor hides the block) on the element. Returns a
65
+ * cleanup function. No-op outside preview mode.
64
66
  */
65
67
  export declare function attachEditable(el: HTMLElement, options: AttachEditableOptions): () => void;
66
68
 
@@ -84,16 +86,52 @@ export declare interface AttachEditableFieldOptions {
84
86
  * targets a complex value.
85
87
  */
86
88
  mode?: EditableFieldMode;
89
+ /** Label for `select` mode. Defaults to the field name. */
90
+ label?: string;
87
91
  }
88
92
 
89
93
  export declare interface AttachEditableOptions {
90
94
  id: string;
95
+ /** Shown on the selection and hover label. A slug like `hero_section` reads as `Hero section`. */
96
+ label?: string;
91
97
  onSelectChange?: (selected: boolean) => void;
92
98
  onHoverChange?: (hovered: boolean) => void;
93
99
  /** Scroll the element into view when it becomes selected. Default true. */
94
100
  scrollOnSelect?: boolean;
95
101
  }
96
102
 
103
+ /**
104
+ * Make a rendered rich text field editable in place in the preview. A click
105
+ * selects the field in the editor, which answers with the field's settings
106
+ * when the user may edit it; the element then turns into a Tiptap editor with
107
+ * the CMS schema. Edits stream to the editor as FIELD_UPDATE, and changes made
108
+ * in the editor arrive through {@link RichTextFieldHandle.update} without
109
+ * moving the caret. Escape returns to block selection.
110
+ *
111
+ * Without the editor's go-ahead (older editors, read-only users) the field
112
+ * behaves like `attachEditableField` in `select` mode. No-op outside preview
113
+ * mode, where Tiptap is never loaded.
114
+ */
115
+ export declare function attachRichTextField(el: HTMLElement, options: AttachRichTextFieldOptions): RichTextFieldHandle;
116
+
117
+ export declare interface AttachRichTextFieldOptions {
118
+ /** Id of the block the field belongs to. */
119
+ id: string;
120
+ /** Path to the field within the block. */
121
+ path: FieldPath;
122
+ /** The field's document, as rendered into the element. */
123
+ document: RichTextDocument | null | undefined;
124
+ /** Shown on the field's highlight. Defaults to the field name. */
125
+ label?: string;
126
+ /** The options the element was rendered with, so links and placeholders look the same while editing. */
127
+ render?: RichTextHtmlOptions;
128
+ /**
129
+ * Editing started or stopped. While it runs the editor owns the element's
130
+ * content, so keep rendering the HTML you rendered before it started.
131
+ */
132
+ onEditingChange?: (editing: boolean) => void;
133
+ }
134
+
97
135
  export declare interface B10cksApiClientOptions {
98
136
  baseUrl: string;
99
137
  token: string;
@@ -321,6 +359,19 @@ export declare interface B10cksLinkResolved {
321
359
  */
322
360
  export declare function bindPreviewStore<T>(store: PreviewStore<T>): () => void;
323
361
 
362
+ /** `hide` and `show` set the block's visibility and do nothing when it already is. */
363
+ export declare type BlockAction = 'move-up' | 'move-down' | 'duplicate' | 'delete' | 'insert-before' | 'insert-after' | 'hide' | 'show';
364
+
365
+ /**
366
+ * Ask the editor to run a structural action on a block. The editor validates
367
+ * it, applies it, and answers with CONTENT_UPDATE (and SELECT_UPDATE where the
368
+ * selection moves). `insert-*` opens the editor's block picker.
369
+ */
370
+ export declare type BlockActionEvent = {
371
+ itemId: string;
372
+ action: BlockAction;
373
+ };
374
+
324
375
  /**
325
376
  * Attributes that make a block addressable as a link anchor: `{ id: block.id }`.
326
377
  *
@@ -334,6 +385,21 @@ export declare function blockAnchorAttrs(block: {
334
385
  id?: string;
335
386
  };
336
387
 
388
+ /** Display names of the space's blocks, keyed by block slug. */
389
+ export declare type BlockLabelsEvent = {
390
+ labels: Record<string, string>;
391
+ };
392
+
393
+ /**
394
+ * Drag and drop: move block `itemId` before or after block `targetId`. The
395
+ * editor rejects moves its schema doesn't allow and answers like BLOCK_ACTION.
396
+ */
397
+ export declare type BlockMoveEvent = {
398
+ itemId: string;
399
+ targetId: string;
400
+ position: 'before' | 'after';
401
+ };
402
+
337
403
  /**
338
404
  * Renders a trail as a schema.org `BreadcrumbList`, ready to be serialized into
339
405
  * an `application/ld+json` script tag.
@@ -363,12 +429,28 @@ export declare interface BreadcrumbListJsonLd {
363
429
  itemListElement: BreadcrumbListItem[];
364
430
  }
365
431
 
432
+ /**
433
+ * Bridge protocol version, sent with the ready announcement. Previews that
434
+ * announce without a payload (protocol 0) understand CONTENT_UPDATE,
435
+ * SELECT_UPDATE, HOVER_UPDATE, and CONTENT_PATCH relative to the root only, so
436
+ * the editor must not send them block-relative patches or labels. Protocol 1
437
+ * adds those and the block actions, protocol 2 HIDDEN_BLOCKS and the `hide`
438
+ * and `show` block actions, protocol 3 FIELD_CONFIG for in-place rich text
439
+ * editing.
440
+ */
441
+ export declare const BRIDGE_PROTOCOL = 3;
442
+
366
443
  export declare type BridgeEvent = {
367
444
  type: EventType;
368
445
  payload: EventPayloadMap[EventType];
369
446
  b10cksId?: string;
370
447
  };
371
448
 
449
+ /** Payload of the ready announcement. */
450
+ export declare type BridgeReadyPayload = {
451
+ protocol: number;
452
+ };
453
+
372
454
  /**
373
455
  * Combines a b10cks `full_slug` and `language_iso` into a rooted, locale-prefixed path.
374
456
  *
@@ -381,8 +463,12 @@ export declare interface CollectionFetchOptions {
381
463
  allPages?: boolean;
382
464
  }
383
465
 
384
- /** Granular update: replace the value at `path` within the content tree. */
466
+ /**
467
+ * Granular update: replace the value at `path`. With `itemId`, `path` is
468
+ * relative to that block; without it, relative to the content tree's root.
469
+ */
385
470
  export declare type ContentPatchEvent = {
471
+ itemId?: string;
386
472
  path: FieldPath;
387
473
  value: unknown;
388
474
  };
@@ -430,13 +516,17 @@ export declare type DateFilter = string | {
430
516
 
431
517
  export declare type EditableFieldMode = 'inline' | 'select';
432
518
 
519
+ /** The field a rich text component renders, for its `editable` prop. */
520
+ export declare type EditableRichTextField = Pick<AttachRichTextFieldOptions, 'id' | 'path' | 'label'>;
521
+
433
522
  export declare type Endpoint = 'blocks' | `blocks/${string}` | `breadcrumbs/${string}` | 'contents' | `contents/${string}` | `datasources/${string}/entries` | 'datasources' | 'redirects' | 'search' | 'sitemap' | `sitemaps/${string}` | 'spaces/me';
434
523
 
435
524
  /**
436
- * Inject the preview outline styles once. Selected/hovered blocks get an
437
- * outline; `.b10cks-preview` carries a `scroll-margin-top` so scroll-into-view
438
- * clears a fixed app header. Set the offset via {@link setPreviewScrollOffset}
439
- * or the `--b10cks-scroll-offset` CSS variable.
525
+ * Inject the preview styles once: `.b10cks-preview` carries a
526
+ * `scroll-margin-top` so scroll-into-view clears a fixed app header. Set the
527
+ * offset via {@link setPreviewScrollOffset} or the `--b10cks-scroll-offset`
528
+ * CSS variable. Blocks the editor hides carry `b10cks-hidden` and are dimmed.
529
+ * Selection and hover are drawn in a separate overlay layer.
440
530
  */
441
531
  export declare function ensurePreviewStyles(): void;
442
532
 
@@ -449,12 +539,28 @@ export declare type EventPayloadMap = {
449
539
  HOVER_UPDATE: SelectUpdateEvent;
450
540
  FIELD_UPDATE: FieldUpdateEvent;
451
541
  FIELD_SELECT: FieldSelectEvent;
542
+ FIELD_CONFIG: FieldConfigEvent;
543
+ BLOCK_LABELS: BlockLabelsEvent;
544
+ HIDDEN_BLOCKS: HiddenBlocksEvent;
545
+ BLOCK_ACTION: BlockActionEvent;
546
+ BLOCK_MOVE: BlockMoveEvent;
452
547
  };
453
548
 
454
- export declare type EventType = 'CONTENT_UPDATE' | 'CONTENT_PATCH' | 'SELECT_UPDATE' | 'HOVER_UPDATE' | 'FIELD_UPDATE' | 'FIELD_SELECT';
549
+ export declare type EventType = 'CONTENT_UPDATE' | 'CONTENT_PATCH' | 'SELECT_UPDATE' | 'HOVER_UPDATE' | 'FIELD_UPDATE' | 'FIELD_SELECT' | 'FIELD_CONFIG' | 'BLOCK_LABELS' | 'HIDDEN_BLOCKS' | 'BLOCK_ACTION' | 'BLOCK_MOVE';
455
550
 
456
551
  export declare type FetchClient = (input: URL | string | RequestInfo, init?: RequestInit) => Promise<unknown>;
457
552
 
553
+ /**
554
+ * The editor's answer to FIELD_SELECT for a rich text field the user may edit:
555
+ * the preview can edit it in place, with the field's settings. Not sent for
556
+ * read-only users or other field types. Protocol 3.
557
+ */
558
+ export declare type FieldConfigEvent = {
559
+ itemId: string;
560
+ path: FieldPath;
561
+ richtext: RichTextFieldConfig;
562
+ };
563
+
458
564
  /** Addresses a field within a block, supporting nested objects and arrays. */
459
565
  export declare type FieldPath = (string | number)[];
460
566
 
@@ -499,6 +605,14 @@ export declare interface GetConfigOptions extends Omit<IBContentQueryParams, 'to
499
605
  bypassCache?: boolean;
500
606
  }
501
607
 
608
+ /**
609
+ * Ids of every block in the edited content, at any depth, that is hidden.
610
+ * Sent whenever that set changes. Protocol 2.
611
+ */
612
+ export declare type HiddenBlocksEvent = {
613
+ ids: string[];
614
+ };
615
+
502
616
  export declare interface IBBaseQueryParams extends IBPaginationParams, IBSortParams {
503
617
  vid?: string;
504
618
  version?: string;
@@ -864,6 +978,8 @@ export declare function normalizePathSegment(value: string | null | undefined):
864
978
  export declare class PreviewBridge {
865
979
  private static instance;
866
980
  private readonly listeners;
981
+ /** Last payload received per event type, for consumers that attach late. */
982
+ private readonly received;
867
983
  private initialized;
868
984
  private allowedOrigins;
869
985
  /** Origin of the editor, captured from the first trusted message. */
@@ -874,6 +990,11 @@ export declare class PreviewBridge {
874
990
  destroy(): void;
875
991
  isInPreviewMode(): boolean;
876
992
  on<T extends EventType>(eventType: T, callback: EventCallback<EventPayloadMap[T]>): () => void;
993
+ /**
994
+ * The last payload the editor sent for `eventType`. The editor replays state
995
+ * right after the ready announcement, often before components mount.
996
+ */
997
+ latest<T extends EventType>(eventType: T): EventPayloadMap[T] | undefined;
877
998
  selectItem(selectedItem: string): void;
878
999
  /** Deep-select a nested field (e.g. a rich text field) in the editor. */
879
1000
  selectField(itemId: string, path: FieldPath): void;
@@ -881,6 +1002,16 @@ export declare class PreviewBridge {
881
1002
  updateField(itemId: string, field: string, value: string): void;
882
1003
  /** Stream an inline edit back to the editor, addressed by path. */
883
1004
  updateFieldAt(itemId: string, path: FieldPath, value: unknown): void;
1005
+ /**
1006
+ * Apply a patch to the preview's own content, as if the editor had sent it.
1007
+ * For edits made in the preview itself, which the editor doesn't echo back,
1008
+ * so a content store rendering the page stays current.
1009
+ */
1010
+ patchLocal(patch: ContentPatchEvent): void;
1011
+ /** Ask the editor to move, duplicate, delete, hide, show, or insert next to a block. */
1012
+ blockAction(itemId: string, action: BlockAction): void;
1013
+ /** Ask the editor to move a block before or after another block. */
1014
+ moveBlock(itemId: string, targetId: string, position: BlockMoveEvent['position']): void;
884
1015
  private post;
885
1016
  private handleMessage;
886
1017
  private isOriginTrusted;
@@ -916,7 +1047,11 @@ export declare class PreviewStore<T = Record<string, unknown>> {
916
1047
  * Unknown ids are ignored and do not notify subscribers.
917
1048
  */
918
1049
  applyContentUpdate(update: Record<string, unknown>): void;
919
- patch(path: FieldPath, value: unknown): void;
1050
+ /**
1051
+ * Replace the value at `path`. With `itemId`, `path` is relative to that
1052
+ * block (the root when its id matches). Unknown ids are ignored.
1053
+ */
1054
+ patch(path: FieldPath, value: unknown, itemId?: string): void;
920
1055
  private emit;
921
1056
  }
922
1057
 
@@ -955,13 +1090,104 @@ export declare function renderSitemapXml(entries: IBSitemapEntry[], siteUrl?: st
955
1090
  */
956
1091
  export declare function resolveB10cksLink(link: B10cksLink | undefined | null): B10cksLinkResolved | undefined;
957
1092
 
1093
+ declare interface RichTextDocument {
1094
+ type: string
1095
+ content?: RichTextDocument[]
1096
+ text?: string
1097
+ marks?: RichTextMark[]
1098
+ attrs?: Record<string, unknown>
1099
+ }
1100
+
1101
+ /** Features a rich text field can switch off in the CMS field settings. */
1102
+ declare type RichTextFeature =
1103
+ | 'bold'
1104
+ | 'italic'
1105
+ | 'underline'
1106
+ | 'strike'
1107
+ | 'code'
1108
+ | 'heading'
1109
+ | 'bulletList'
1110
+ | 'orderedList'
1111
+ | 'blockquote'
1112
+ | 'codeBlock'
1113
+ | 'horizontalRule'
1114
+ | 'link'
1115
+ | 'internalLink'
1116
+ | 'table'
1117
+
1118
+ /** How a rich text field is configured in the CMS. */
1119
+ declare interface RichTextFieldConfig {
1120
+ /** A feature is on unless set to `false`, like in the CMS. */
1121
+ features?: Partial<Record<RichTextFeature, boolean>>
1122
+ /** Block formats the toolbar offers, in order. */
1123
+ headingLevels?: RichTextHeadingLevel[]
1124
+ }
1125
+
1126
+ export declare interface RichTextFieldHandle {
1127
+ /** Pass the field's latest document whenever it changes. */
1128
+ update: (document: RichTextDocument | null | undefined) => void;
1129
+ destroy: () => void;
1130
+ }
1131
+
1132
+ declare type RichTextHeadingLevel = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p'
1133
+
1134
+ declare interface RichTextHtmlOptions {
1135
+ internalLinkHandler?: RichTextInternalLinkHandler
1136
+ placeholderHandler?: RichTextPlaceholderHandler
1137
+ /**
1138
+ * URL schemes (without the trailing colon) permitted in link `href` and
1139
+ * image `src` attributes. URLs with any other scheme are replaced with `'#'`
1140
+ * to prevent script-injecting URLs (e.g. `javascript:`) stored in CMS
1141
+ * content from executing. Relative URLs are always allowed.
1142
+ *
1143
+ * Defaults to {@link DEFAULT_ALLOWED_SCHEMES}. To additionally allow
1144
+ * `javascript:` URLs, pass
1145
+ * `[...DEFAULT_ALLOWED_SCHEMES, 'javascript']`.
1146
+ */
1147
+ allowedSchemes?: string[]
1148
+ }
1149
+
1150
+ declare interface RichTextInternalLinkAttrs {
1151
+ url?: string | null
1152
+ href?: string | null
1153
+ title?: string | null
1154
+ target?: string | null
1155
+ rel?: string | null
1156
+ anchor?: string | null
1157
+ content?: string | null
1158
+ cached_url?: string | null
1159
+ linktype?: string | null
1160
+ uuid?: string | null
1161
+ id?: string | null
1162
+ [key: string]: unknown
1163
+ }
1164
+
1165
+ declare type RichTextInternalLinkHandler = (
1166
+ attrs: RichTextInternalLinkAttrs
1167
+ ) => string | null | undefined
1168
+
1169
+ declare interface RichTextMark {
1170
+ type: string
1171
+ attrs?: Record<string, unknown>
1172
+ }
1173
+
1174
+ /**
1175
+ * Resolves a placeholder token to its real value.
1176
+ * Receives the token's `key` (e.g. `"companyName"`) and `label` (the display
1177
+ * hint shown in the editor, e.g. `"{companyName}"`).
1178
+ * Return the replacement string, or null/undefined to leave the token as-is
1179
+ * (rendered as a `<span data-type="placeholder-token">` for client-side use).
1180
+ */
1181
+ declare type RichTextPlaceholderHandler = (key: string, label: string) => string | null | undefined
1182
+
958
1183
  export declare type RootBlock<T> = T & {
959
1184
  id: string;
960
1185
  block: string;
961
1186
  };
962
1187
 
1188
+ /** `selectedItem` is null when the editor clears the selection or hover. */
963
1189
  export declare type SelectUpdateEvent = {
964
- selectedItem: string;
1190
+ selectedItem: string | null;
965
1191
  };
966
1192
 
967
1193
  export declare function serializeFilter(filter: Record<string, unknown>): Record<string, string>;