@arbidocs/blocks 0.3.111 → 0.3.112

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
@@ -2,11 +2,11 @@ import { UseBoundStore, StoreApi } from 'zustand';
2
2
  import * as react from 'react';
3
3
  import react__default, { ReactNode } from 'react';
4
4
  import * as _arbidocs_react from '@arbidocs/react';
5
- import { AiRunOptions, useArbi } from '@arbidocs/react';
5
+ import { AiRunOptions, useArbi, AiTaskStatus } from '@arbidocs/react';
6
6
  export { AiRunOptions, AiTaskStatus, ArtifactEvent, SearchChunk, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, redlineStats, textToArtifact, toRedlineMarkdown } from '@arbidocs/react';
7
7
  import { ColDef, GridOptions, GridApi, CellValueChangedEvent, GridState } from 'ag-grid-community';
8
8
  import { LucideIcon } from 'lucide-react';
9
- import { Config, CustomField, Field, ComponentConfig } from '@measured/puck';
9
+ import { Data, Config, CustomField, Field, ComponentConfig } from '@measured/puck';
10
10
 
11
11
  /**
12
12
  * The reusable AI-native law-firm prompt library.
@@ -37,7 +37,7 @@ declare function matterToContext(m: {
37
37
  }): MatterContext;
38
38
  /** Firm voice for the prompt library — everything firm-specific lives here. */
39
39
  interface PromptConfig {
40
- /** The firm's name, e.g. "Clarum". */
40
+ /** The firm's name, e.g. "Acme Legal". */
41
41
  firmName: string;
42
42
  /** The legal system adjective used throughout, e.g. "English". */
43
43
  jurisdiction?: string;
@@ -127,20 +127,20 @@ declare function createPromptLibrary(config: PromptConfig): {
127
127
  };
128
128
 
129
129
  /**
130
- * The theme-token model for the legal vertical. Firm-agnostic: the token
131
- * *catalog*, default values and presets are supplied by the firm (via
132
- * {@link createThemeStore}); this module owns the shared types and the logic for
133
- * writing tokens onto the live document.
130
+ * The theme-token model. Firm-agnostic: the token *catalog*, default values and
131
+ * presets are supplied by the consuming app (via {@link createThemeStore}); this
132
+ * module owns the shared types and the logic for writing tokens onto the live
133
+ * document.
134
134
  *
135
- * There are two emit models, selected per-firm by {@link ThemeEmitMode}:
135
+ * There are two emit models, selected per-app by {@link ThemeEmitMode}:
136
136
  *
137
- * - `'flat'` (default — Clarum): each colour key is written as an inline
138
- * `--color-<key>` custom property on `<html>`, plus `--font-*` / `--radius`.
139
- * Inline styles override the compiled `@theme` defaults, so an edit previews
140
- * live across the whole app (and the @arbidocs AI kit) and reverts cleanly.
141
- * Firms whose CSS sets `--color-*` HEX directly (Clarum) rely on this.
137
+ * - `'flat'` (default): each colour key is written as an inline `--color-<key>`
138
+ * custom property on `<html>`, plus `--font-*` / `--radius`. Inline styles
139
+ * override the compiled `@theme` defaults, so an edit previews live across the
140
+ * whole app (and the @arbidocs AI kit) and reverts cleanly. Apps whose CSS sets
141
+ * `--color-*` HEX directly rely on this.
142
142
  *
143
- * - `'cssVars'` (the ARBI monolith): each colour key is written as a raw
143
+ * - `'cssVars'`: each colour key is written as a raw
144
144
  * HSL-triplet custom property (`--<key>: <h s l>`) into an injected
145
145
  * `<style id="arbi-theme-vars">` appended to `<head>`. The monolith's source
146
146
  * of truth is HSL triplets wrapped as `hsl(var(--x))`, with a real `.dark`
@@ -176,7 +176,7 @@ interface ThemePreset {
176
176
  /** How a theme is written onto the document. See the module doc for the models. */
177
177
  type ThemeEmitMode = 'flat' | 'cssVars';
178
178
  interface ApplyThemeOptions {
179
- /** Emit model. Defaults to `'flat'` (Clarum's behaviour). */
179
+ /** Emit model. Defaults to `'flat'`. */
180
180
  mode?: ThemeEmitMode;
181
181
  /**
182
182
  * `cssVars` mode only: dark-variant colour values keyed by token key. Emitted
@@ -250,9 +250,9 @@ interface ThemeStoreConfig {
250
250
  storageKey: string;
251
251
  /**
252
252
  * How edits are written onto the document. Defaults to `'flat'` (inline
253
- * `--color-*`, Clarum). `'cssVars'` emits raw HSL-triplet vars into an injected
254
- * `<style>` so the app's own `hsl(var(--x))` indirection + `.dark` variant
255
- * survive (the ARBI monolith). See {@link applyThemeVars}.
253
+ * `--color-*`). `'cssVars'` emits raw HSL-triplet vars into an injected
254
+ * `<style>` so an app's own `hsl(var(--x))` indirection + `.dark` variant
255
+ * survive. See {@link applyThemeVars}.
256
256
  */
257
257
  mode?: ThemeEmitMode;
258
258
  /**
@@ -623,13 +623,15 @@ declare function PageHeader({ title, eyebrow, description, actions, className, t
623
623
  }): react.JSX.Element;
624
624
 
625
625
  /** Editorial heading block for marketing sections: eyebrow + title + lead. */
626
- declare function SectionHeading({ eyebrow, title, lead, align, className, invert, }: {
626
+ declare function SectionHeading({ eyebrow, title, lead, align, className, invert, eyebrowClassName, }: {
627
627
  eyebrow?: string;
628
628
  title: string;
629
629
  lead?: string;
630
630
  align?: 'left' | 'center';
631
631
  className?: string;
632
632
  invert?: boolean;
633
+ /** Override the eyebrow styling (e.g. a firm brand accent). Default: token classes. */
634
+ eyebrowClassName?: string;
633
635
  }): react.JSX.Element;
634
636
 
635
637
  /** Search + filter bar used above every list view. */
@@ -653,8 +655,12 @@ interface MetricCardProps {
653
655
  direction: 'up' | 'down';
654
656
  good?: boolean;
655
657
  };
656
- /** Icon accent, keyed to the firm's brand token contract. */
657
- accent?: 'ink' | 'emerald' | 'brass';
658
+ /**
659
+ * Icon accent as a theme colour-token key (e.g. `primary`, `success`, or a
660
+ * firm's own brand token). Resolved to `var(--color-<accent>)` at render, so
661
+ * it themes with whatever firm consumes it. `'default'` inherits `foreground`.
662
+ */
663
+ accent?: string;
658
664
  testId?: string;
659
665
  }
660
666
  /** The one true KPI tile. Used across every dashboard and module header. */
@@ -667,6 +673,8 @@ interface BlockImageProps {
667
673
  alt?: string;
668
674
  aspect?: BlockImageAspect;
669
675
  rounded?: BlockImageRounded;
676
+ /** Editorial "photo frame" treatment: a matte border ring + soft shadow. */
677
+ framed?: boolean;
670
678
  className?: string;
671
679
  testId?: string;
672
680
  }
@@ -675,7 +683,7 @@ interface BlockImageProps {
675
683
  * token-clean gradient placeholder (no network needed) so the palette always looks
676
684
  * good in the editor and in demos. Token-only classes so it themes per firm.
677
685
  */
678
- declare function BlockImage({ src, alt, aspect, rounded, className, testId, }: BlockImageProps): react.JSX.Element;
686
+ declare function BlockImage({ src, alt, aspect, rounded, framed, className, testId, }: BlockImageProps): react.JSX.Element;
679
687
 
680
688
  type HeroTone = 'default' | 'muted' | 'ink';
681
689
  type HeroAlign = 'left' | 'center';
@@ -686,16 +694,25 @@ interface HeroCta {
686
694
  interface HeroProps {
687
695
  eyebrow?: string;
688
696
  title: string;
697
+ /** A word/phrase within the title to accent (rendered in the primary colour). */
698
+ emphasis?: string;
689
699
  subtitle?: string;
690
700
  primaryCta?: HeroCta;
691
701
  secondaryCta?: HeroCta;
692
702
  align?: HeroAlign;
693
703
  tone?: HeroTone;
704
+ /** Side visual (ignored when `backgroundImage` is set). */
694
705
  imageUrl?: string;
706
+ /** Full-bleed background image URL/data-URI. Turns the hero into a cover band. */
707
+ backgroundImage?: string;
708
+ /** Darkening scrim over the background image, for legible copy. Default true. */
709
+ overlay?: boolean;
710
+ /** Override the eyebrow styling (e.g. a firm brand accent). Default: token classes. */
711
+ eyebrowClassName?: string;
695
712
  testId?: string;
696
713
  }
697
714
  /** Editorial marketing hero: eyebrow, headline, subtitle, two CTAs and a visual. */
698
- declare function Hero({ eyebrow, title, subtitle, primaryCta, secondaryCta, align, tone, imageUrl, testId, }: HeroProps): react.JSX.Element;
715
+ declare function Hero({ eyebrow, title, emphasis, subtitle, primaryCta, secondaryCta, align, tone, imageUrl, backgroundImage, overlay, eyebrowClassName, testId, }: HeroProps): react.JSX.Element;
699
716
 
700
717
  interface FeatureItem {
701
718
  icon?: LucideIcon;
@@ -740,10 +757,14 @@ interface CTABannerProps {
740
757
  href?: string;
741
758
  };
742
759
  tone?: CTABannerTone;
760
+ /** Full-bleed background image URL/data-URI. Overrides the tone surface. */
761
+ backgroundImage?: string;
762
+ /** Darkening scrim over the background image. Default true. */
763
+ overlay?: boolean;
743
764
  testId?: string;
744
765
  }
745
766
  /** Full-width call-to-action banner. */
746
- declare function CTABanner({ title, subtitle, cta, tone, testId }: CTABannerProps): react.JSX.Element;
767
+ declare function CTABanner({ title, subtitle, cta, tone, backgroundImage, overlay, testId, }: CTABannerProps): react.JSX.Element;
747
768
 
748
769
  interface LogoItem {
749
770
  label: string;
@@ -877,6 +898,170 @@ interface ContainerProps {
877
898
  /** Max-width wrapper that centres and pads a nested Puck slot. */
878
899
  declare function Container({ width, padding, children, testId }: ContainerProps): react.JSX.Element;
879
900
 
901
+ interface PricingPlan {
902
+ name: string;
903
+ price: string;
904
+ period?: string;
905
+ description?: string;
906
+ features?: string[];
907
+ cta?: {
908
+ label?: string;
909
+ href?: string;
910
+ };
911
+ /** Highlight this plan as the recommended one. */
912
+ featured?: boolean;
913
+ }
914
+ interface PricingTableProps {
915
+ plans: PricingPlan[];
916
+ testId?: string;
917
+ }
918
+ /** A row of pricing plan cards with feature lists and a CTA per plan. */
919
+ declare function PricingTable({ plans, testId }: PricingTableProps): react.JSX.Element;
920
+
921
+ interface TabItem {
922
+ label: string;
923
+ content: string;
924
+ }
925
+ interface TabsProps {
926
+ items: TabItem[];
927
+ testId?: string;
928
+ }
929
+ /** A simple tabbed panel: a row of tab buttons over the active tab's content. */
930
+ declare function Tabs({ items, testId }: TabsProps): react.JSX.Element;
931
+
932
+ interface AccordionItem {
933
+ title: string;
934
+ content: string;
935
+ }
936
+ interface AccordionProps {
937
+ items: AccordionItem[];
938
+ /** Allow multiple panels open at once. Default false (single-open). */
939
+ allowMultiple?: boolean;
940
+ testId?: string;
941
+ }
942
+ /** A stack of collapsible title/content panels. */
943
+ declare function Accordion({ items, allowMultiple, testId }: AccordionProps): react.JSX.Element;
944
+
945
+ interface GalleryImage {
946
+ src?: string;
947
+ alt?: string;
948
+ caption?: string;
949
+ }
950
+ interface GalleryProps {
951
+ images: GalleryImage[];
952
+ columns?: '2' | '3' | '4';
953
+ aspect?: BlockImageProps['aspect'];
954
+ rounded?: BlockImageProps['rounded'];
955
+ testId?: string;
956
+ }
957
+ /** A responsive image grid. Each tile previews via BlockImage with a caption. */
958
+ declare function Gallery({ images, columns, aspect, rounded, testId, }: GalleryProps): react.JSX.Element;
959
+
960
+ type VideoAspect = '16:9' | '4:3' | '1:1';
961
+ interface VideoEmbedProps {
962
+ /** A YouTube / Vimeo / Loom page URL, or a direct video file URL. */
963
+ url: string;
964
+ title?: string;
965
+ aspect?: VideoAspect;
966
+ rounded?: boolean;
967
+ testId?: string;
968
+ }
969
+ /**
970
+ * Resolve a shareable video URL to an embeddable iframe src. Supports YouTube,
971
+ * Vimeo and Loom; returns null for anything else (rendered as a `<video>`).
972
+ */
973
+ declare function toEmbedUrl(url: string): string | null;
974
+ /** Embed a video from a YouTube/Vimeo/Loom link or a direct file, in a set aspect. */
975
+ declare function VideoEmbed({ url, title, aspect, rounded, testId, }: VideoEmbedProps): react.JSX.Element;
976
+
977
+ interface ContactField {
978
+ name: string;
979
+ label: string;
980
+ type?: 'text' | 'email' | 'tel' | 'textarea';
981
+ required?: boolean;
982
+ }
983
+ interface ContactFormProps {
984
+ fields: ContactField[];
985
+ submitLabel?: string;
986
+ /** Optional POST endpoint. When set, the form submits natively to it. */
987
+ action?: string;
988
+ /** Message shown after a client-side (no-action) submit. */
989
+ successMessage?: string;
990
+ testId?: string;
991
+ }
992
+ /** A configurable lead/contact form. Posts to `action`, or confirms client-side. */
993
+ declare function ContactForm({ fields, submitLabel, action, successMessage, testId, }: ContactFormProps): react.JSX.Element;
994
+
995
+ type BannerTone = 'primary' | 'muted' | 'ink';
996
+ interface BannerProps {
997
+ text: string;
998
+ cta?: {
999
+ label?: string;
1000
+ href?: string;
1001
+ };
1002
+ tone?: BannerTone;
1003
+ testId?: string;
1004
+ }
1005
+ /** A slim full-width announcement strip with optional inline CTA. */
1006
+ declare function Banner({ text, cta, tone, testId }: BannerProps): react.JSX.Element;
1007
+
1008
+ interface MediaTextProps {
1009
+ eyebrow?: string;
1010
+ title: string;
1011
+ body?: string;
1012
+ imageUrl?: string;
1013
+ /** Which side the media sits on (desktop). */
1014
+ mediaSide?: 'left' | 'right';
1015
+ cta?: {
1016
+ label?: string;
1017
+ href?: string;
1018
+ };
1019
+ testId?: string;
1020
+ }
1021
+ /** A split media-and-copy row: an image on one side, prose + CTA on the other. */
1022
+ declare function MediaText({ eyebrow, title, body, imageUrl, mediaSide, cta, testId, }: MediaTextProps): react.JSX.Element;
1023
+
1024
+ interface TeamMember {
1025
+ name: string;
1026
+ role?: string;
1027
+ bio?: string;
1028
+ avatarUrl?: string;
1029
+ }
1030
+ interface TeamGridProps {
1031
+ members: TeamMember[];
1032
+ columns?: '2' | '3' | '4';
1033
+ testId?: string;
1034
+ }
1035
+ /** A grid of people cards: avatar, name, role and an optional short bio. */
1036
+ declare function TeamGrid({ members, columns, testId }: TeamGridProps): react.JSX.Element;
1037
+
1038
+ interface StepItem {
1039
+ title: string;
1040
+ description?: string;
1041
+ }
1042
+ interface StepsProps {
1043
+ steps: StepItem[];
1044
+ /** `timeline` draws a connected vertical rail; `numbered` is a horizontal grid. */
1045
+ variant?: 'numbered' | 'timeline';
1046
+ testId?: string;
1047
+ }
1048
+ /** A process / how-it-works sequence, as numbered cards or a vertical timeline. */
1049
+ declare function Steps({ steps, variant, testId }: StepsProps): react.JSX.Element;
1050
+
1051
+ interface TestimonialItem {
1052
+ quote: string;
1053
+ author?: string;
1054
+ role?: string;
1055
+ avatarUrl?: string;
1056
+ }
1057
+ interface TestimonialGridProps {
1058
+ items: TestimonialItem[];
1059
+ columns?: '2' | '3';
1060
+ testId?: string;
1061
+ }
1062
+ /** A grid of multiple pull-quote testimonials. */
1063
+ declare function TestimonialGrid({ items, columns, testId }: TestimonialGridProps): react.JSX.Element;
1064
+
880
1065
  /**
881
1066
  * Navigation shapes shared by firm app shells. The concrete nav manifest (which
882
1067
  * modules, in what order) is per-firm data the app supplies; these interfaces
@@ -918,8 +1103,16 @@ interface LoadResult<T> {
918
1103
  }
919
1104
  /** The save/load surface the studio + renderer consume. */
920
1105
  interface StudioPersistence {
1106
+ /** Persist the authoring layout for a slug (image values stay `asset:` refs). */
921
1107
  savePage: (arbi: Arbi | null, live: boolean, slug: string, data: unknown) => Promise<PersistVia>;
922
1108
  loadPage: <T>(arbi: Arbi | null, live: boolean, slug: string) => Promise<LoadResult<T>>;
1109
+ /**
1110
+ * Persist the **published** layout for a slug — a self-contained copy whose
1111
+ * asset refs have been materialized to `data:` URIs, so the unauthenticated
1112
+ * public renderer can paint it. The public renderer reads this, not savePage's.
1113
+ */
1114
+ savePublished: (arbi: Arbi | null, live: boolean, slug: string, data: unknown) => Promise<PersistVia>;
1115
+ loadPublished: <T>(arbi: Arbi | null, live: boolean, slug: string) => Promise<LoadResult<T>>;
923
1116
  saveTheme: (arbi: Arbi | null, live: boolean, theme: unknown) => Promise<PersistVia>;
924
1117
  loadTheme: <T>(arbi: Arbi | null, live: boolean) => Promise<LoadResult<T>>;
925
1118
  }
@@ -930,6 +1123,45 @@ type BuildPrompt = (a: {
930
1123
  current: string;
931
1124
  }) => string;
932
1125
 
1126
+ /**
1127
+ * Publish-time asset materialization.
1128
+ *
1129
+ * While authoring, an image is stored as a workspace **asset ref**
1130
+ * (`asset:<docId>`) — resolvable only inside the authenticated Studio. The
1131
+ * public marketing renderer has no auth token, so a published page must be
1132
+ * **self-contained**: every asset ref is replaced with a directly-renderable
1133
+ * source before the page is saved for the public.
1134
+ *
1135
+ * The default {@link createArbiMaterializer} downloads each asset once and
1136
+ * inlines it as a `data:` URI — the bytes travel *inside* the published JSON,
1137
+ * so nothing is fetched, served or auth-gated at render time (no backend). A
1138
+ * consumer that prefers a CDN/static host can pass a `publishAsset` hook that
1139
+ * uploads the bytes and returns a URL instead; that is purely a payload-size
1140
+ * optimization and keeps this package firm- and backend-agnostic.
1141
+ */
1142
+
1143
+ /** Resolve a workspace document ext_id to a public-renderable src, or null. */
1144
+ type AssetMaterializer = (docId: string) => Promise<string | null>;
1145
+ interface MaterializeOptions {
1146
+ /**
1147
+ * Optional sink: given a doc id + its bytes, store them somewhere public and
1148
+ * return the URL. When omitted, bytes are inlined as a `data:` URI (no backend).
1149
+ */
1150
+ publishAsset?: (docId: string, blob: Blob) => Promise<string>;
1151
+ }
1152
+ /**
1153
+ * A materializer backed by the authenticated Arbi client: download the asset,
1154
+ * then either hand it to `publishAsset` or inline it as a data URI. Any failure
1155
+ * resolves to `null` so a single broken asset never fails the whole publish.
1156
+ */
1157
+ declare function createArbiMaterializer(arbi: Arbi, opts?: MaterializeOptions): AssetMaterializer;
1158
+ /**
1159
+ * Return a copy of `data` with every `asset:<docId>` ref replaced by its
1160
+ * materialized source. Each distinct ref is resolved exactly once; a ref that
1161
+ * fails to resolve is left untouched (it simply won't paint for the public).
1162
+ */
1163
+ declare function materializePageData(data: Data, materialize: AssetMaterializer): Promise<Data>;
1164
+
933
1165
  interface StudioEditorProps {
934
1166
  config: Config;
935
1167
  pages: readonly StudioPageMeta[];
@@ -942,8 +1174,14 @@ interface StudioEditorProps {
942
1174
  live: boolean;
943
1175
  initialSlug?: string;
944
1176
  testIdPrefix?: string;
1177
+ /**
1178
+ * Optional sink for published image bytes. When omitted, publishing inlines
1179
+ * each asset as a `data:` URI (self-contained, no backend). Provide this to
1180
+ * upload bytes to a CDN/static host and return a URL instead.
1181
+ */
1182
+ publishAsset?: MaterializeOptions['publishAsset'];
945
1183
  }
946
- declare function StudioEditor({ config, pages, persistence, themeBundle, defaultTheme, brandLabel, backHref, backLabel, live, initialSlug, testIdPrefix, }: StudioEditorProps): react.JSX.Element;
1184
+ declare function StudioEditor({ config, pages, persistence, themeBundle, defaultTheme, brandLabel, backHref, backLabel, live, initialSlug, testIdPrefix, publishAsset, }: StudioEditorProps): react.JSX.Element;
947
1185
 
948
1186
  interface PageRendererProps {
949
1187
  config: Config;
@@ -964,7 +1202,7 @@ interface StudioPersistenceConfig {
964
1202
  workspaceId: string;
965
1203
  /** Folder inside the workspace where studio artefacts live. */
966
1204
  folder?: string;
967
- /** Prefix for the localStorage mirror keys (e.g. "clarum-studio-"). */
1205
+ /** Prefix for the localStorage mirror keys (e.g. "studio-"). */
968
1206
  storagePrefix: string;
969
1207
  /** localStorage key for the theme mirror (default `${storagePrefix}theme`). */
970
1208
  themeStorageKey?: string;
@@ -972,6 +1210,8 @@ interface StudioPersistenceConfig {
972
1210
  themeFileName?: string;
973
1211
  /** File name for a page's persisted document (default `${slug}.json`). */
974
1212
  pageFileName?: (slug: string) => string;
1213
+ /** File name for a page's published document (default `${slug}.published.json`). */
1214
+ publishedFileName?: (slug: string) => string;
975
1215
  }
976
1216
  declare function createStudioPersistence(cfg: StudioPersistenceConfig): StudioPersistence;
977
1217
 
@@ -991,12 +1231,68 @@ interface AiFields {
991
1231
  }
992
1232
  declare function createAiFields(cfg: AiFieldsConfig): AiFields;
993
1233
 
1234
+ interface ImageFieldConfig {
1235
+ /** The workspace uploads/generations are saved to, and assets are picked from. */
1236
+ workspaceId: string;
1237
+ /** Folder for uploaded/authored assets. Default "assets". */
1238
+ folder?: string;
1239
+ /** Testid namespace. Default "studio". */
1240
+ testIdPrefix?: string;
1241
+ }
1242
+ interface ImageFieldFactory {
1243
+ imageField: (label: string) => CustomField<string>;
1244
+ }
1245
+ /** Build the image field, closing over the firm's workspace + testid prefix. */
1246
+ declare function createImageField(cfg: ImageFieldConfig): ImageFieldFactory;
1247
+
1248
+ interface UseImageGen {
1249
+ /** ext_id of the most recently generated image document (null until one exists). */
1250
+ docExtId: string | null;
1251
+ /** Underlying task status: 'idle' | 'running' | 'done' | 'error'. */
1252
+ status: AiTaskStatus;
1253
+ /** Human-readable failure message, or null. */
1254
+ error: string | null;
1255
+ /** True while a generation is in flight. */
1256
+ isGenerating: boolean;
1257
+ /**
1258
+ * Generate an image from a prompt. Resolves with the new image document's
1259
+ * ext_id, or null when the prompt is empty or no image was produced.
1260
+ */
1261
+ generate: (prompt: string) => Promise<string | null>;
1262
+ /** Clear the current result and error. */
1263
+ reset: () => void;
1264
+ }
1265
+ declare function useImageGen(): UseImageGen;
1266
+
1267
+ /** Marks a stored image value as a workspace asset ref rather than a URL. */
1268
+ declare const ASSET_REF_PREFIX = "asset:";
1269
+ /** Wrap a workspace document ext_id as a storable asset ref. */
1270
+ declare function asAssetRef(docId: string): string;
1271
+ /** The workspace document ext_id behind an asset ref (`asset:doc-1` → `doc-1`). */
1272
+ declare function assetRefId(src: string): string;
1273
+ declare function AssetResolverProvider({ children }: {
1274
+ children: ReactNode;
1275
+ }): react.JSX.Element;
1276
+ declare function useAssetResolverActive(): boolean;
1277
+ /**
1278
+ * Is `src` a workspace asset ref (`asset:<docId>`) rather than an already-
1279
+ * renderable URL / `data:` URI? Only prefixed refs need resolution.
1280
+ */
1281
+ declare function isAssetRef(src: string | undefined): src is string;
1282
+
1283
+ type SectionTone = 'default' | 'muted' | 'ink';
1284
+ type SectionPadding = 'none' | 'sm' | 'md' | 'lg';
1285
+ type SectionWidth = 'narrow' | 'default' | 'wide' | 'full';
994
1286
  interface SectionProps {
995
1287
  children: ReactNode;
996
- tone?: 'default' | 'muted' | 'ink';
1288
+ tone?: SectionTone;
1289
+ padding?: SectionPadding;
1290
+ maxWidth?: SectionWidth;
1291
+ /** Subtle grain/texture overlay in the current text colour (editorial surfaces). */
1292
+ texture?: boolean;
997
1293
  className?: string;
998
1294
  }
999
- declare function Section({ children, tone, className }: SectionProps): react.JSX.Element;
1295
+ declare function Section({ children, tone, padding, maxWidth, texture, className, }: SectionProps): react.JSX.Element;
1000
1296
 
1001
1297
  /**
1002
1298
  * Shared field helpers for the block registry. Every block config — the built-ins
@@ -1013,6 +1309,8 @@ interface BlockKit {
1013
1309
  textField: (label: string, placeholder?: string) => Field;
1014
1310
  /** Multi-line copy: AI-authorable when a firm supplies aiFields, else plain textarea. */
1015
1311
  textareaField: (label: string, placeholder?: string, kind?: string) => Field;
1312
+ /** Image source: a workspace-asset picker when a firm supplies imageField, else a URL input. */
1313
+ imageField: (label: string) => Field;
1016
1314
  /** A Yes/No radio. */
1017
1315
  boolRadio: (label: string) => Field;
1018
1316
  /** A `select` over {@link iconMap} names. */
@@ -1021,9 +1319,15 @@ interface BlockKit {
1021
1319
  resolveIcon: (name?: string) => LucideIcon | undefined;
1022
1320
  /** Stable, e2e-locatable testid derived from a block's Puck id. */
1023
1321
  blockTestId: (id: string) => string;
1322
+ /**
1323
+ * Optional firm override for the eyebrow style on heading-bearing blocks
1324
+ * (Hero, Section heading). Lets a consumer render a brand accent (e.g. a brass
1325
+ * eyebrow) without forking the blocks. Undefined → the default token classes.
1326
+ */
1327
+ eyebrowClassName?: string;
1024
1328
  }
1025
- /** Build the shared field helpers, closing over the firm's optional AI fields. */
1026
- declare function createBlockKit(ai?: AiFields): BlockKit;
1329
+ /** Build the shared field helpers, closing over the firm's optional AI + image fields. */
1330
+ declare function createBlockKit(ai?: AiFields, image?: (label: string) => Field, eyebrowClassName?: string): BlockKit;
1027
1331
 
1028
1332
  interface ArbiBlocksConfigOptions {
1029
1333
  /**
@@ -1031,6 +1335,28 @@ interface ArbiBlocksConfigOptions {
1031
1335
  * prop becomes an AI-authorable field; when absent, plain Puck text inputs.
1032
1336
  */
1033
1337
  aiFields?: AiFields;
1338
+ /**
1339
+ * Firm image field from {@link createImageField}. When present, image props
1340
+ * become a workspace-asset picker (pick / upload / URL / generate); when absent,
1341
+ * a plain URL text input.
1342
+ */
1343
+ imageField?: (label: string) => Field;
1344
+ /**
1345
+ * Page canvas overrides. The builder paints every page inside this root; a
1346
+ * consumer sets e.g. a dark editorial canvas without forking the package.
1347
+ * Defaults to `bg-background text-foreground font-sans` on a neutral wrapper.
1348
+ */
1349
+ root?: {
1350
+ /** Extra classes appended to (and able to override) the default canvas classes. */
1351
+ className?: string;
1352
+ /** testid for the page root wrapper. Defaults to `arbi-blocks-page-root`. */
1353
+ testId?: string;
1354
+ };
1355
+ /**
1356
+ * Firm override for the eyebrow style on heading-bearing blocks (Hero, Section
1357
+ * heading) — e.g. a brand accent like a brass eyebrow. Undefined → token default.
1358
+ */
1359
+ eyebrowClassName?: string;
1034
1360
  }
1035
1361
 
1036
1362
  declare function createArbiBlocksConfig(opts?: ArbiBlocksConfigOptions): Config;
@@ -1038,6 +1364,20 @@ declare function createArbiBlocksConfig(opts?: ArbiBlocksConfigOptions): Config;
1038
1364
  /** Build every website block, closing over the shared field {@link BlockKit}. */
1039
1365
  declare function createWebsiteBlocks(kit: BlockKit): Record<string, ComponentConfig>;
1040
1366
 
1367
+ /**
1368
+ * The extended site-building block set — the richer vocabulary a builder needs to
1369
+ * assemble arbitrary sites beyond the marketing basics: pricing, tabs, accordion,
1370
+ * gallery, video, contact form, banner, split media, team, steps and a
1371
+ * multi-testimonial grid.
1372
+ *
1373
+ * Same contract as {@link createWebsiteBlocks}: serializable-only props, semantic
1374
+ * tokens (themes with the firm), a stable render-time `data-testid`, and sensible
1375
+ * defaults so each block looks right the moment it is dropped. Copy props route
1376
+ * through the shared {@link BlockKit} AI-or-plain fields.
1377
+ */
1378
+
1379
+ declare function createSiteBlocks(kit: BlockKit): Record<string, ComponentConfig>;
1380
+
1041
1381
  /**
1042
1382
  * Module registry types — a typed model of a firm's back-office modules,
1043
1383
  * derived from its canonical nav. The builder toggles/reorders these; the
@@ -1210,4 +1550,4 @@ interface AgentsPanelProps {
1210
1550
  }
1211
1551
  declare function AgentsPanel({ store, testIdPrefix }: AgentsPanelProps): react.JSX.Element;
1212
1552
 
1213
- export { type AgentSelectionStore, AgentsPanel, type AgentsPanelProps, type AiFields, type AiFieldsConfig, type AppNavItem, type AppNavSection, type ApplyThemeOptions, type ArbiBlocksConfigOptions, type ArbiMode, type ArbiUser, type AssistantCitation, type AssistantMessage, type AssistantStep, AvatarBlock, type AvatarBlockProps, BlockImage, type BlockImageProps, type BlockKit, type BuildPrompt, type BuilderModule, CTABanner, type CTABannerProps, Callout, type CalloutProps, type CalloutVariant, type ColorToken, type Column, Columns, type ColumnsProps, ConnectionProvider, type ConnectionStatus, Container, type ContainerProps, DataTable, DataTableBlock, type DataTableBlockColumn, type DataTableBlockProps, EmptyState, type ExportedModule, FAQ, type FAQProps, type FaqItem, FeatureGrid, type FeatureGridProps, type FeatureItem, type FirmArbiConfig, Footer, type FooterColumn, type FooterLink, type FooterProps, GridView, type GridViewEmptyState, type GridViewProps, type GridViewSelection, Hero, type HeroCta, type HeroProps, LegalArbiProvider, ListBlock, type ListBlockProps, type ListItem, type LoadResult, LogoCloud, type LogoCloudProps, type LogoItem, type MatterContext, MetricCard, type MetricCardProps, ModuleManager, type ModuleManagerProps, type ModuleRegistry, type ModuleStoreBundle, type NavLink, Navbar, type NavbarProps, PageHeader, PageRenderer, type PageRendererProps, type PersistVia, type PromptConfig, type PromptLibrary, type Prompts, type ResolvedModule, RichTextBlock, type RichTextBlockProps, Section, SectionHeading, type SectionProps, Spacer, type SpacerProps, StatGroup, type StatGroupProps, type StatItem, StudioEditor, type StudioEditorProps, type StudioPageMeta, type StudioPersistence, type StudioPersistenceConfig, THEME_STYLE_ID, Testimonial, type TestimonialProps, type ThemeBundle, ThemeEditor, type ThemeEditorProps, type ThemeEmitMode, type ThemeFonts, type ThemePreset, type ThemeState, type ThemeStoreConfig, type ThemeTokens, Toolbar, VerticalBuilder, type VerticalBuilderProps, type VerticalConfig, type VerticalExport, type VerticalExportConfig, applyStoredTheme, applyThemeVars, clearThemeVars, createAgentSelectionStore, createAiFields, createArbiBlocksConfig, createBlockKit, createModuleRegistry, createModuleStore, createPromptLibrary, createStudioPersistence, createThemeStore, createVerticalExport, createWebsiteBlocks, daysUntil, fmtDate, fmtDateTime, fromNow, gbp, hrs, iconMap, initials, isAuthenticated, matterToContext, pct, tid, toHslTriplet, useConnection, useFirmAiTask, useSemanticSearch, useWorkspaceDocs };
1553
+ export { ASSET_REF_PREFIX, Accordion, type AccordionItem, type AccordionProps, type AgentSelectionStore, AgentsPanel, type AgentsPanelProps, type AiFields, type AiFieldsConfig, type AppNavItem, type AppNavSection, type ApplyThemeOptions, type ArbiBlocksConfigOptions, type ArbiMode, type ArbiUser, type AssetMaterializer, AssetResolverProvider, type AssistantCitation, type AssistantMessage, type AssistantStep, AvatarBlock, type AvatarBlockProps, Banner, type BannerProps, type BannerTone, BlockImage, type BlockImageProps, type BlockKit, type BuildPrompt, type BuilderModule, CTABanner, type CTABannerProps, Callout, type CalloutProps, type CalloutVariant, type ColorToken, type Column, Columns, type ColumnsProps, ConnectionProvider, type ConnectionStatus, type ContactField, ContactForm, type ContactFormProps, Container, type ContainerProps, DataTable, DataTableBlock, type DataTableBlockColumn, type DataTableBlockProps, EmptyState, type ExportedModule, FAQ, type FAQProps, type FaqItem, FeatureGrid, type FeatureGridProps, type FeatureItem, type FirmArbiConfig, Footer, type FooterColumn, type FooterLink, type FooterProps, Gallery, type GalleryImage, type GalleryProps, GridView, type GridViewEmptyState, type GridViewProps, type GridViewSelection, Hero, type HeroCta, type HeroProps, type ImageFieldConfig, type ImageFieldFactory, LegalArbiProvider, ListBlock, type ListBlockProps, type ListItem, type LoadResult, LogoCloud, type LogoCloudProps, type LogoItem, type MaterializeOptions, type MatterContext, MediaText, type MediaTextProps, MetricCard, type MetricCardProps, ModuleManager, type ModuleManagerProps, type ModuleRegistry, type ModuleStoreBundle, type NavLink, Navbar, type NavbarProps, PageHeader, PageRenderer, type PageRendererProps, type PersistVia, type PricingPlan, PricingTable, type PricingTableProps, type PromptConfig, type PromptLibrary, type Prompts, type ResolvedModule, RichTextBlock, type RichTextBlockProps, Section, SectionHeading, type SectionProps, Spacer, type SpacerProps, StatGroup, type StatGroupProps, type StatItem, type StepItem, Steps, type StepsProps, StudioEditor, type StudioEditorProps, type StudioPageMeta, type StudioPersistence, type StudioPersistenceConfig, THEME_STYLE_ID, type TabItem, Tabs, type TabsProps, TeamGrid, type TeamGridProps, type TeamMember, Testimonial, TestimonialGrid, type TestimonialGridProps, type TestimonialItem, type TestimonialProps, type ThemeBundle, ThemeEditor, type ThemeEditorProps, type ThemeEmitMode, type ThemeFonts, type ThemePreset, type ThemeState, type ThemeStoreConfig, type ThemeTokens, Toolbar, type UseImageGen, VerticalBuilder, type VerticalBuilderProps, type VerticalConfig, type VerticalExport, type VerticalExportConfig, type VideoAspect, VideoEmbed, type VideoEmbedProps, applyStoredTheme, applyThemeVars, asAssetRef, assetRefId, clearThemeVars, createAgentSelectionStore, createAiFields, createArbiBlocksConfig, createArbiMaterializer, createBlockKit, createImageField, createModuleRegistry, createModuleStore, createPromptLibrary, createSiteBlocks, createStudioPersistence, createThemeStore, createVerticalExport, createWebsiteBlocks, daysUntil, fmtDate, fmtDateTime, fromNow, gbp, hrs, iconMap, initials, isAssetRef, isAuthenticated, materializePageData, matterToContext, pct, tid, toEmbedUrl, toHslTriplet, useAssetResolverActive, useConnection, useFirmAiTask, useImageGen, useSemanticSearch, useWorkspaceDocs };