uhuu-components 0.4.5 → 0.4.7

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
@@ -721,6 +721,50 @@ export interface FrameBlockProps extends FrameDeclaration, Omit<ImageBlockProps,
721
721
  */
722
722
  export const FrameBlock: ComponentType<FrameBlockProps>;
723
723
 
724
+ /**
725
+ * A neutral, brand-free empty image (outline and icon in Text mixed into Paper) for `ImageBlock`'s
726
+ * `placeholder`, so templates never borrow placeholder photos from a client folder.
727
+ */
728
+ export const ImagePlaceholder: ComponentType<{ label?: string; className?: string; style?: CSSProperties }>;
729
+
730
+ /** A position on the sheet in mm: `left` or `right`, and `top` or `bottom`. */
731
+ export interface FurniturePosition { left?: number; right?: number; top?: number; bottom?: number }
732
+
733
+ /**
734
+ * The printed page number of sheet `pageNo` (1-based, deck order), or `null` when it is not numbered.
735
+ * Counting starts at the first numbered sheet and skips unnumbered sheets after it; `offset` is subtracted.
736
+ */
737
+ export function folioNumber(input: {
738
+ pageNo: number;
739
+ sheetKeys: readonly string[];
740
+ numbered: readonly string[] | ((key: string) => boolean);
741
+ offset?: number;
742
+ }): number | null;
743
+
744
+ /** The page number in the brand's body font and muted colour, at the verso (even) or recto (odd) position. */
745
+ export const PageFolio: ComponentType<{
746
+ number: number | null | undefined;
747
+ pageNo: number;
748
+ verso: FurniturePosition;
749
+ recto: FurniturePosition;
750
+ /** pt, default 9. */
751
+ size?: number;
752
+ className?: string;
753
+ style?: CSSProperties;
754
+ }>;
755
+
756
+ /** A running header: title, the brand's logo (default the mark on Paper) and a `border` or `accent` rule. */
757
+ export const RunningHeader: ComponentType<{
758
+ position: FurniturePosition;
759
+ children?: ReactNode;
760
+ logo?: false | { kind?: "primary" | "mark" | "wordmark"; background?: "light" | "dark"; name?: string; locale?: string };
761
+ /** mm, default 6. */
762
+ logoHeight?: number;
763
+ rule?: "border" | "accent" | false;
764
+ className?: string;
765
+ style?: CSSProperties;
766
+ }>;
767
+
724
768
  // --- Brand-kit runtime (src/uhuu/brand-kit/). See docs/brand-kit-runtime.md. ---
725
769
 
726
770
  export interface BrandKitFontFile {
@@ -768,30 +812,57 @@ export interface BrandKitJson {
768
812
  [token: string]: unknown;
769
813
  };
770
814
  colorMode?: "light" | "manual" | "shade";
771
- /** Template variables Brand Kit precomputed at publish. Applied as is when `version` is 2. */
815
+ /** Template variables Brand Kit precomputed at publish for current public 3.x documents. */
772
816
  runtime?: BrandKitRuntimeBlock;
817
+ /** What wrote the document; a published version names itself in `release`. */
818
+ generator?: { name?: string; release?: BrandKitRelease; [key: string]: unknown };
773
819
  [key: string]: unknown;
774
820
  }
775
821
 
776
822
  /**
777
- * `brandkit.json.runtime` (brandkit.json "2.0"): shadcn role variables (`--primary`, `--color-primary`),
778
- * `--color-kit-*` / `--font-*` / `--font-kit-*` values, ready to apply, and the fonts to load.
823
+ * `generator.release` of a published version's document (older documents have none): it lets
824
+ * `?brand=v9` and `uhuu-components brand status | activate v9` name another version of the brand a
825
+ * template's `src/brand/brandkit.json` holds.
826
+ */
827
+ export interface BrandKitRelease {
828
+ teamId: string;
829
+ kitId: string;
830
+ /** `v1`, `v2`… */
831
+ version: string;
832
+ /** This version's immutable `…/versions/vN/brandkit.json`. */
833
+ url: string;
834
+ /** The Brand Kit app's origin, which says which version is newest. */
835
+ appUrl?: string;
836
+ }
837
+
838
+ /**
839
+ * `brandkit.json.runtime` (public 3.x): canonical semantic and font-role variables, ready to
840
+ * apply, and the fonts to load. It cannot carry template layout or decoration tokens.
779
841
  */
780
842
  export interface BrandKitRuntimeBlock {
781
- version: 2;
843
+ version: 3;
782
844
  light: Record<string, string>;
783
845
  fontStylesheets?: string[];
784
- fontFaces?: Array<{ family: string; src: string; weight?: number; style?: "normal" | "italic"; format?: string }>;
846
+ fontFaces?: Array<{
847
+ family: string;
848
+ src: string;
849
+ weight?: number;
850
+ style?: "normal" | "italic";
851
+ format?: string;
852
+ ascentOverride?: number;
853
+ descentOverride?: number;
854
+ lineGapOverride?: number;
855
+ }>;
785
856
  }
786
857
 
787
858
  export interface BrandKitLogo {
788
- /** Absolute URL (SVG preferred, else PNG). */
859
+ /** Absolute SVG URL. */
789
860
  src: string;
790
861
  alt?: string;
791
862
  kind: "primary" | "mark" | "wordmark";
792
863
  background?: "light" | "dark" | "any";
793
- minWidth?: { value: number; unit: "px" | "mm" };
794
- clearSpace?: { value: number; unit: "px" | "mm" | "mark" };
864
+ /** The language a named or language version is for. */
865
+ locale?: string;
795
866
  }
796
867
 
797
868
  export interface BrandKitCollectionItem {
@@ -817,7 +888,7 @@ export interface BrandKitCollection {
817
888
  export interface BrandKitMapStyle {
818
889
  url: string;
819
890
  name?: string;
820
- source: "config.maps" | "config.env";
891
+ source: "extensions.maps" | "extensions.env";
821
892
  }
822
893
 
823
894
  export type BrandKitLogoKind = "primary" | "logo" | "lockup" | "mark" | "icon" | "symbol" | "wordmark";
@@ -827,34 +898,47 @@ export type BrandKitMediaKind = "photos" | "icons" | "graphics" | "backgrounds"
827
898
  export interface BrandKitRuntime {
828
899
  /** The kit being rendered: the fetched one, else the `brandKit` prop. */
829
900
  brandKit: BrandKitJson | null;
830
- /** `--<role>`, `--color-<role>`, `--color-kit-*`, `--font-*` and `--font-kit-*`, as the provider's scope element carries them. */
901
+ /** Canonical semantic, extension-colour and font-role variables as the provider's scope element carries them. */
831
902
  cssVars: Record<string, string>;
832
903
  /** Where the rendered kit came from (`src` once fetched, else the `sourceUrl` prop). */
833
904
  sourceUrl?: string;
834
- /** `idle` without `src`; `loading` until it arrives; `ready`; `error` (the `brandKit` prop renders). */
905
+ /** `idle` without `src` (the `brandKit` prop renders); `loading` until it arrives; `ready`; `error`. */
835
906
  status: "idle" | "loading" | "ready" | "error";
836
- /** A logo, resolved: `logoSystem` first, then `logos`. Default `{ kind: "primary", background: "light" }`. */
837
- logo(options?: { kind?: BrandKitLogoKind; background?: "light" | "dark" }): BrandKitLogo | null;
838
- /** The assigned media collection's promoted version, items resolved. */
839
- collection(kind: BrandKitMediaKind | string, options?: { versionId?: string }): BrandKitCollection | null;
907
+ /**
908
+ * A logo resolved from `logoSystem`. Default `{ kind: "primary", background: "light" }`.
909
+ * `name` and `locale` pick a named or language version, falling back to the standard logo.
910
+ */
911
+ logo(options?: { kind?: BrandKitLogoKind; background?: "light" | "dark"; name?: string; locale?: string }): BrandKitLogo | null;
912
+ /** The brand's chart colors as hex when it set them, else `fallback` (the template's). */
913
+ chartPalette(options?: { fallback?: string[]; count?: number }): BrandChartPalette;
914
+ /** The brand's default locale and currency (`extensions.locale`); `payload.locale` wins over it. */
915
+ locale: { locale?: string; currency?: string };
916
+ /** Public 3.x: canonical kind/id and active-version selection. */
917
+ collection(kindOrId: BrandKitMediaKind | string, options?: { versionId?: string }): BrandKitCollection | null;
840
918
  mapStyle(mode: "micro" | "macro"): BrandKitMapStyle | null;
841
- /** A `config.env` value; keys compare case- and punctuation-insensitively, first present wins. */
919
+ /** An `extensions.env.strings` value; keys compare case- and punctuation-insensitively. */
842
920
  env(keys: string | string[]): string | undefined;
843
921
  /** A kit-relative asset path made absolute. */
844
922
  resolveUrl(path: unknown): string | undefined;
845
923
  }
846
924
 
847
925
  export interface BrandKitProviderProps {
848
- /** The kit to render; with `src`, the fallback until the fetched kit arrives or when the fetch fails. */
926
+ /**
927
+ * The kit to render, usually the template's own `src/brand/brandkit.json`; with `src`, the fallback
928
+ * until the fetched kit arrives or when the fetch fails.
929
+ */
849
930
  brandKit?: BrandKitJson | null;
850
- /** A brandkit.json URL to fetch, usually `brandKitSourceUrl(payload)`. */
931
+ /** A brandkit.json URL to fetch, usually `brandKitSelection(payload).src`. */
851
932
  src?: string | null;
933
+ /** Brand values the template opts into beyond colours and fonts: `{ radius: true }` adds `--radius*`. Stable object. */
934
+ adopt?: { radius?: boolean };
852
935
  /** Custom properties for whatever the kit leaves out; the kit wins. Pass a stable object. */
853
936
  defaults?: Record<string, string>;
854
937
  /** Where a `brandKit` passed in came from; its directory resolves relative URLs when the kit has no `baseUrl`. */
855
938
  sourceUrl?: string;
939
+ /** Called with each kit fetched from `src`; never for a development preview (`?brand=`). */
856
940
  onLoad?: (brandKit: BrandKitJson) => void;
857
- /** Default: `console.error`. */
941
+ /** Called when `src` fails to load; never for a development preview. Default: `console.error`. */
858
942
  onError?: (error: unknown) => void;
859
943
  /** For the scope element. `style` is applied last, so `{ display: "block" }` gives it a box. */
860
944
  className?: string;
@@ -867,6 +951,10 @@ export interface BrandKitProviderProps {
867
951
  * element (`data-uhuu-brand-kit-status` tells a print step when a fetched kit has arrived), and
868
952
  * loads the fonts the kit declares. Colours are hex, `rgb()`/`rgba()`, `oklch()`/`oklab()` or
869
953
  * keywords: HSL is converted, anything else is skipped as if absent.
954
+ *
955
+ * On a development host, and never when `$uhuu_renderer` is set, `?brand=` on the page URL (`v9`, a
956
+ * `…/versions/vN/brandkit.json` link, or a same-origin path) renders that candidate instead, under a
957
+ * bar with what changed and Stop. It is written nowhere and never printed.
870
958
  */
871
959
  export const BrandKitProvider: ComponentType<BrandKitProviderProps>;
872
960
 
@@ -877,20 +965,60 @@ export function useBrandKit(): BrandKitRuntime | null;
877
965
  export const BRAND_KIT_PUBLIC_BASE_URL: string;
878
966
 
879
967
  /**
880
- * The brandkit.json URL a payload points at: `brandKitUrl` (URL or `kit-…` id), `brandKitId`, or
881
- * `brandKit.storage.publicUrl`. Ids need `brandKitTeamId` (or `teamId`) and resolve under `publicBaseUrl`.
968
+ * Which brand a document renders: a pinned `payload.brand` (unpinned warns), then none: the
969
+ * template's own current `brandkit.json` (`brandKit` prop) renders.
970
+ * `pinned` is true when `src` is an immutable `…/versions/vN/brandkit.json` (and for a preset, which
971
+ * fetches nothing). A `version: "vN"` beside a kit's root `…/kits/<kit>/brandkit.json` selects that
972
+ * version's URL; a version alone pins nothing.
882
973
  */
883
- export function brandKitSourceUrl(
974
+ export function brandKitSelection(
884
975
  payload: Record<string, unknown> | null | undefined,
885
- options?: { publicBaseUrl?: string; teamId?: string | number },
886
- ): string | null;
976
+ ): { source: "payload" | "none"; src: string | null; pinned: boolean; presetId?: string };
977
+
978
+ export interface BrandChartPalette {
979
+ colors: string[];
980
+ source: "brand" | "template";
981
+ }
982
+
983
+ /** Chart colors as `#rrggbb`: the brand's when it set them (Brand Kit publishes them only then), else `fallback`. */
984
+ export function brandChartPalette(brandKit: BrandKitJson | null | undefined, options?: { fallback?: string[]; count?: number }): BrandChartPalette;
985
+
986
+ /**
987
+ * The chart dialog's `config.brand` (`ChartDialogBrand`): the series palette from `brandChartPalette`
988
+ * and ink, line, muted and surface, all `#rrggbb`. Missing roles are left for the dialog's defaults.
989
+ */
990
+ export function brandChartDialogBrand(
991
+ brandKit: BrandKitJson | null | undefined,
992
+ options?: { fallback?: string[]; count?: number },
993
+ ): { palette?: string[]; ink?: string; line?: string; muted?: string; surface?: string };
994
+
995
+ /** `#rrggbb` for hex, `rgb()`, HSL, `oklch()` or `oklab()`; `undefined` otherwise. */
996
+ export function colorToHex(value: unknown): string | undefined;
997
+
998
+ /** The brand's default locale and currency (`extensions.locale.strings`). */
999
+ export function brandKitLocale(brandKit: BrandKitJson | null | undefined): { locale?: string; currency?: string };
1000
+
1001
+ /** A number in the locale (`payload.locale`, else the brand's); Swiss locales group with `'`. */
1002
+ export function formatNumber(
1003
+ value: number,
1004
+ options?: { locale?: string; brandKit?: BrandKitJson | null; apostrophe?: "straight" | "typographic" } & Intl.NumberFormatOptions,
1005
+ ): string;
1006
+
1007
+ /** Money; Swiss locales print `CHF 3'600'000.–` (whole) and `CHF 1'250.50`. Currency: option, brand, `CHF`. */
1008
+ export function formatMoney(
1009
+ value: number,
1010
+ options?: { locale?: string; currency?: string; brandKit?: BrandKitJson | null; wholeDash?: boolean; apostrophe?: "straight" | "typographic" },
1011
+ ): string;
1012
+
1013
+ /** A date in the locale; `dateStyle: "long"` unless date fields are given. */
1014
+ export function formatDate(value: Date | string | number, options?: { locale?: string; brandKit?: BrandKitJson | null } & Intl.DateTimeFormatOptions): string;
887
1015
 
888
1016
  /** Fetches a brandkit.json; rejects on network errors, non-2xx and non-object bodies. */
889
1017
  export function loadBrandKit(url: string, options?: { fetch?: typeof fetch; signal?: AbortSignal }): Promise<BrandKitJson>;
890
1018
 
891
1019
  export function brandKitLogo(
892
1020
  brandKit: BrandKitJson | null | undefined,
893
- options?: { kind?: BrandKitLogoKind; background?: "light" | "dark"; sourceUrl?: string },
1021
+ options?: { kind?: BrandKitLogoKind; background?: "light" | "dark"; name?: string; locale?: string; sourceUrl?: string },
894
1022
  ): BrandKitLogo | null;
895
1023
 
896
1024
  export function brandKitCollection(
@@ -1293,6 +1421,8 @@ export interface PageEditorProps {
1293
1421
  /**
1294
1422
  * Development only: the brand-kit switcher in the dev tools menu (dev tools on). It lists
1295
1423
  * `brandKits` and calls back; it does not load a kit: wire the choice to `BrandKitProvider`.
1424
+ * Inside a `BrandKitProvider` on a development host the Brand Kit submenu also offers
1425
+ * *Preview a version…* (`?brand=`), with or without `brandKits`.
1296
1426
  */
1297
1427
  brandKits?: BrandKitOption[];
1298
1428
  /** Development only: the kit the dev switcher marks as active. */
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.4.5",
2
+ "version": "0.4.7",
3
3
  "name": "uhuu-components",
4
4
  "main": "uhuu-components.umd.cjs",
5
5
  "module": "uhuu-components.es.js",
@@ -15,6 +15,9 @@
15
15
  }
16
16
  },
17
17
  "license": "https://uhuu.io/license",
18
+ "bin": {
19
+ "uhuu-components": "cli.js"
20
+ },
18
21
  "scripts": {
19
22
  "prepublishOnly": "node verify-release.cjs"
20
23
  },
@@ -23,7 +26,8 @@
23
26
  "uhuu-components.es.js.map",
24
27
  "uhuu-components.umd.cjs",
25
28
  "uhuu-components.umd.cjs.map",
26
- "index.d.ts"
29
+ "index.d.ts",
30
+ "cli.js"
27
31
  ],
28
32
  "peerDependencies": {
29
33
  "react": "^18.0.0 || ^19.0.0",