@sonordev/contracts 2.12.0 → 2.15.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.
@@ -35,11 +35,11 @@ export declare const CASE_STUDY_STAGE_COPY: Record<CaseStudyStage, {
35
35
  question: string;
36
36
  }>;
37
37
  /**
38
- * An agency's own names for the four stages ("Heat", "Shape", "Temper",
39
- * "Finish"), set once in the dashboard and read everywhere a stage is named:
40
- * the editor, the public portfolio config, the agency's site. A stage left
41
- * unnamed falls back to its generic name. The ids never change; only what
42
- * people see does.
38
+ * A site's own names for the four stages ("Heat", "Shape", "Temper",
39
+ * "Finish"), set per project in the dashboard (branding is per project) and
40
+ * read everywhere a stage is named: the editor, the public portfolio config,
41
+ * the site itself. A stage left unnamed falls back to its generic name. The
42
+ * ids never change; only what people see does.
43
43
  */
44
44
  export type CaseStudyStageNames = Partial<Record<CaseStudyStage, string>>;
45
45
  /** The longest a stage name may run. It's a heading word, a rail label, a tab. */
@@ -49,7 +49,7 @@ export declare const STAGE_NAME_MAX_CHARS = 24;
49
49
  * (generic names); present must be an object of short text keyed by stage.
50
50
  */
51
51
  export declare function stageNamesProblems(names: unknown): string[];
52
- /** The name a stage is shown under: the agency's own when set, else the generic one. */
52
+ /** The name a stage is shown under: the site's own when set, else the generic one. */
53
53
  export declare function stageName(names: CaseStudyStageNames | null | undefined, stage: CaseStudyStage): string;
54
54
  /**
55
55
  * Every section type a case study can hold, in canonical reading order:
@@ -9,11 +9,12 @@ export type PublicationPlatform = (typeof PUBLICATION_PLATFORMS)[number];
9
9
  /** The sections of a profile and of each platform override, in the order they're read. */
10
10
  export declare const PUBLICATION_BRANDING_SECTIONS: readonly ['identity', 'colors', 'typography', 'editorial', 'newsletter'];
11
11
  export type PublicationBrandingSection = (typeof PUBLICATION_BRANDING_SECTIONS)[number];
12
- export declare const PUBLICATION_IDENTITY_FIELDS: readonly ['publicationName', 'wordmark', 'tagline', 'publisherName', 'publisherUrl', 'publisherLogoUrl', 'logos'];
12
+ export declare const PUBLICATION_IDENTITY_FIELDS: readonly ['publicationName', 'wordmark', 'tagline', 'publisherName', 'publisherUrl', 'publisherLogoUrl', 'logos', 'squareLogoUrl', 'fullLogoUrl'];
13
13
  export declare const PUBLICATION_LOGO_VARIANTS: readonly ['default', 'light', 'dark'];
14
14
  export declare const PUBLICATION_COLOR_FIELDS: readonly ['primary', 'secondary', 'accent', 'background', 'surface', 'text', 'muted', 'border'];
15
15
  export declare const PUBLICATION_TYPOGRAPHY_FIELDS: readonly ['heading', 'body', 'mono', 'emailHeadingFallback', 'emailBodyFallback'];
16
- export declare const PUBLICATION_EDITORIAL_FIELDS: readonly ['articleStyle', 'cardLayout', 'charter', 'siteCharters'];
16
+ export declare const PUBLICATION_EDITORIAL_FIELDS: readonly ['articleStyle', 'cardLayout', 'focusClosingBackground', 'charter', 'siteCharters'];
17
+ export declare const FOCUS_CLOSING_BACKGROUNDS: readonly ['planned_photo', 'article_atmosphere'];
17
18
  export declare const PUBLICATION_NEWSLETTER_FIELDS: readonly ['name', 'tagline', 'layout', 'maxWidth'];
18
19
  /** Fonts every email client has, the only families an email fallback may name. Lowercase. */
19
20
  export declare const EMAIL_SAFE_FONTS: ReadonlySet<string>;
@@ -27,6 +28,11 @@ export interface PublicationIdentity {
27
28
  publisherUrl?: string;
28
29
  /** The publisher's attribution mark, separate from the publication masthead. */
29
30
  publisherLogoUrl?: string;
31
+ /** The publication's square mark; independent of theme variants and publisher attribution. */
32
+ squareLogoUrl?: string;
33
+ /** The publication's full/display logo; wordmark remains a text fallback. */
34
+ fullLogoUrl?: string;
35
+ /** Legacy theme variants, not square/full logo roles. */
30
36
  logos?: {
31
37
  default?: string;
32
38
  light?: string;
@@ -56,6 +62,8 @@ export interface PublicationEditorial {
56
62
  /** Shared Broadcast style for articles, reviews and generated posts; portfolio is excluded. Legacy wire name. */
57
63
  articleStyle?: BroadcastStyleId;
58
64
  cardLayout?: PublicationCardLayout;
65
+ /** Focus closing frames may reuse the article's saved atmosphere and real author portrait. */
66
+ focusClosingBackground?: (typeof FOCUS_CLOSING_BACKGROUNDS)[number];
59
67
  }
60
68
  export interface PublicationNewsletter {
61
69
  name?: string;
@@ -134,11 +134,12 @@ function publicationCharterContext(charter) {
134
134
  var PUBLICATION_BRANDING_VERSION = 1;
135
135
  var PUBLICATION_PLATFORMS = ["publication", "email", "social", "instagram", "facebook", "linkedin", "gbp"];
136
136
  var PUBLICATION_BRANDING_SECTIONS = ["identity", "colors", "typography", "editorial", "newsletter"];
137
- var PUBLICATION_IDENTITY_FIELDS = ["publicationName", "wordmark", "tagline", "publisherName", "publisherUrl", "publisherLogoUrl", "logos"];
137
+ var PUBLICATION_IDENTITY_FIELDS = ["publicationName", "wordmark", "tagline", "publisherName", "publisherUrl", "publisherLogoUrl", "logos", "squareLogoUrl", "fullLogoUrl"];
138
138
  var PUBLICATION_LOGO_VARIANTS = ["default", "light", "dark"];
139
139
  var PUBLICATION_COLOR_FIELDS = ["primary", "secondary", "accent", "background", "surface", "text", "muted", "border"];
140
140
  var PUBLICATION_TYPOGRAPHY_FIELDS = ["heading", "body", "mono", "emailHeadingFallback", "emailBodyFallback"];
141
- var PUBLICATION_EDITORIAL_FIELDS = ["articleStyle", "cardLayout", "charter", "siteCharters"];
141
+ var PUBLICATION_EDITORIAL_FIELDS = ["articleStyle", "cardLayout", "focusClosingBackground", "charter", "siteCharters"];
142
+ var FOCUS_CLOSING_BACKGROUNDS = ["planned_photo", "article_atmosphere"];
142
143
  var PUBLICATION_NEWSLETTER_FIELDS = ["name", "tagline", "layout", "maxWidth"];
143
144
  var EMAIL_SAFE_FONTS = /* @__PURE__ */ new Set([
144
145
  "arial",
@@ -279,7 +280,7 @@ function createPublicationBrandingValidator(options) {
279
280
  throw new PublicationBrandingValidationError(`${prefix}.${key}`, error.message);
280
281
  }
281
282
  }
282
- const allowed = key === "articleStyle" ? BROADCAST_STYLES : patch ? PUBLICATION_CARD_LAYOUTS : SAVED_PUBLICATION_CARD_LAYOUTS;
283
+ const allowed = key === "articleStyle" ? BROADCAST_STYLES : key === "focusClosingBackground" ? FOCUS_CLOSING_BACKGROUNDS : patch ? PUBLICATION_CARD_LAYOUTS : SAVED_PUBLICATION_CARD_LAYOUTS;
283
284
  if (typeof v !== "string" || !allowed.includes(v)) throw new PublicationBrandingValidationError(`${prefix}.${key}`, `choose ${allowed.join(", ")}`);
284
285
  return v;
285
286
  });
@@ -328,6 +329,7 @@ function createPublicationBrandingValidator(options) {
328
329
  }
329
330
 
330
331
  exports.EMAIL_SAFE_FONTS = EMAIL_SAFE_FONTS;
332
+ exports.FOCUS_CLOSING_BACKGROUNDS = FOCUS_CLOSING_BACKGROUNDS;
331
333
  exports.GENERIC_FONT_FAMILIES = GENERIC_FONT_FAMILIES;
332
334
  exports.PUBLICATION_BRANDING_SECTIONS = PUBLICATION_BRANDING_SECTIONS;
333
335
  exports.PUBLICATION_BRANDING_VERSION = PUBLICATION_BRANDING_VERSION;
@@ -132,11 +132,12 @@ function publicationCharterContext(charter) {
132
132
  var PUBLICATION_BRANDING_VERSION = 1;
133
133
  var PUBLICATION_PLATFORMS = ["publication", "email", "social", "instagram", "facebook", "linkedin", "gbp"];
134
134
  var PUBLICATION_BRANDING_SECTIONS = ["identity", "colors", "typography", "editorial", "newsletter"];
135
- var PUBLICATION_IDENTITY_FIELDS = ["publicationName", "wordmark", "tagline", "publisherName", "publisherUrl", "publisherLogoUrl", "logos"];
135
+ var PUBLICATION_IDENTITY_FIELDS = ["publicationName", "wordmark", "tagline", "publisherName", "publisherUrl", "publisherLogoUrl", "logos", "squareLogoUrl", "fullLogoUrl"];
136
136
  var PUBLICATION_LOGO_VARIANTS = ["default", "light", "dark"];
137
137
  var PUBLICATION_COLOR_FIELDS = ["primary", "secondary", "accent", "background", "surface", "text", "muted", "border"];
138
138
  var PUBLICATION_TYPOGRAPHY_FIELDS = ["heading", "body", "mono", "emailHeadingFallback", "emailBodyFallback"];
139
- var PUBLICATION_EDITORIAL_FIELDS = ["articleStyle", "cardLayout", "charter", "siteCharters"];
139
+ var PUBLICATION_EDITORIAL_FIELDS = ["articleStyle", "cardLayout", "focusClosingBackground", "charter", "siteCharters"];
140
+ var FOCUS_CLOSING_BACKGROUNDS = ["planned_photo", "article_atmosphere"];
140
141
  var PUBLICATION_NEWSLETTER_FIELDS = ["name", "tagline", "layout", "maxWidth"];
141
142
  var EMAIL_SAFE_FONTS = /* @__PURE__ */ new Set([
142
143
  "arial",
@@ -277,7 +278,7 @@ function createPublicationBrandingValidator(options) {
277
278
  throw new PublicationBrandingValidationError(`${prefix}.${key}`, error.message);
278
279
  }
279
280
  }
280
- const allowed = key === "articleStyle" ? BROADCAST_STYLES : patch ? PUBLICATION_CARD_LAYOUTS : SAVED_PUBLICATION_CARD_LAYOUTS;
281
+ const allowed = key === "articleStyle" ? BROADCAST_STYLES : key === "focusClosingBackground" ? FOCUS_CLOSING_BACKGROUNDS : patch ? PUBLICATION_CARD_LAYOUTS : SAVED_PUBLICATION_CARD_LAYOUTS;
281
282
  if (typeof v !== "string" || !allowed.includes(v)) throw new PublicationBrandingValidationError(`${prefix}.${key}`, `choose ${allowed.join(", ")}`);
282
283
  return v;
283
284
  });
@@ -325,4 +326,4 @@ function createPublicationBrandingValidator(options) {
325
326
  };
326
327
  }
327
328
 
328
- export { EMAIL_SAFE_FONTS, GENERIC_FONT_FAMILIES, PUBLICATION_BRANDING_SECTIONS, PUBLICATION_BRANDING_VERSION, PUBLICATION_CHARTER_FIELDS, PUBLICATION_COLOR_FIELDS, PUBLICATION_EDITORIAL_FIELDS, PUBLICATION_IDENTITY_FIELDS, PUBLICATION_LOGO_VARIANTS, PUBLICATION_NEWSLETTER_FIELDS, PUBLICATION_PLATFORMS, PUBLICATION_TYPOGRAPHY_FIELDS, PublicationBrandingValidationError, containsControlCharacters, createPublicationBrandingValidator, mergePublicationBrandingLayers, parsePublicationCharter, parseSiteCharters, publicationCharterContext, publicationCharterFor, safeFontStack };
329
+ export { EMAIL_SAFE_FONTS, FOCUS_CLOSING_BACKGROUNDS, GENERIC_FONT_FAMILIES, PUBLICATION_BRANDING_SECTIONS, PUBLICATION_BRANDING_VERSION, PUBLICATION_CHARTER_FIELDS, PUBLICATION_COLOR_FIELDS, PUBLICATION_EDITORIAL_FIELDS, PUBLICATION_IDENTITY_FIELDS, PUBLICATION_LOGO_VARIANTS, PUBLICATION_NEWSLETTER_FIELDS, PUBLICATION_PLATFORMS, PUBLICATION_TYPOGRAPHY_FIELDS, PublicationBrandingValidationError, containsControlCharacters, createPublicationBrandingValidator, mergePublicationBrandingLayers, parsePublicationCharter, parseSiteCharters, publicationCharterContext, publicationCharterFor, safeFontStack };
@@ -29,6 +29,8 @@ export declare const SITE_CACHE_TAGS: {
29
29
  readonly portfolio: 'portfolio';
30
30
  /** Products, services, events and membership plans (commerce-kit). */
31
31
  readonly commerce: 'commerce';
32
+ /** Published managed landing pages. Draft previews never enter this cache. */
33
+ readonly funnels: 'sonor-funnels';
32
34
  };
33
35
  export type SiteCacheTag = (typeof SITE_CACHE_TAGS)[keyof typeof SITE_CACHE_TAGS];
34
36
  /** The body Sonor POSTs to the revalidation route. */
@@ -14,7 +14,9 @@ var SITE_CACHE_TAGS = {
14
14
  /** Portfolio items (agency-site-kit). */
15
15
  portfolio: "portfolio",
16
16
  /** Products, services, events and membership plans (commerce-kit). */
17
- commerce: "commerce"
17
+ commerce: "commerce",
18
+ /** Published managed landing pages. Draft previews never enter this cache. */
19
+ funnels: "sonor-funnels"
18
20
  };
19
21
  function isSiteRevalidatePong(body) {
20
22
  return typeof body === "object" && body !== null && body.ok === true && body.ping === true;
@@ -12,7 +12,9 @@ var SITE_CACHE_TAGS = {
12
12
  /** Portfolio items (agency-site-kit). */
13
13
  portfolio: "portfolio",
14
14
  /** Products, services, events and membership plans (commerce-kit). */
15
- commerce: "commerce"
15
+ commerce: "commerce",
16
+ /** Published managed landing pages. Draft previews never enter this cache. */
17
+ funnels: "sonor-funnels"
16
18
  };
17
19
  function isSiteRevalidatePong(body) {
18
20
  return typeof body === "object" && body !== null && body.ok === true && body.ping === true;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sonordev/contracts",
3
- "version": "2.12.0",
4
- "description": "The rules Sonor's sites, APIs and dashboard share: popup blocks and site design tokens, site hosts, SEO page identity, title quality, llms.txt sanitizers, the forms honeypot, fleet heartbeats, slot content and signing, site cache tags, portfolio metrics, the house voice's contraction rule, how a proposal's site plan counts its pages, what separates an error page from a page's content, which stored JSON-LD is a template's unfilled placeholder, where prose splits into sentences, which Sonor records Signal reads into a project's knowledge and the address each one is stored under, what outbound email and text may claim about a business and whether a sent email arrived intact, what a segment of outreach is and who may turn one on, a page's own name taken from its title or its slug, which Broadcast card layouts and review compositions are drawn and what a retired one draws as, what a publication's branding may hold, and which literal hosts are refused as public fetch destinations. Pure functions, no dependencies.",
3
+ "version": "2.15.0",
4
+ "description": "The rules Sonor's sites, APIs and dashboard share: popup blocks and site design tokens, site hosts, SEO page identity, title quality, llms.txt sanitizers, the forms honeypot, fleet heartbeats, slot content and signing, site cache tags, portfolio metrics, the house voice's contraction rule, how a proposal's site plan counts its pages, what separates an error page from a page's content, which stored JSON-LD is a template's unfilled placeholder, where prose splits into sentences, which Sonor records Signal reads into a project's knowledge and the address each one is stored under, what outbound email and text may claim about a business and whether a sent email arrived intact, what a segment of outreach is and who may turn one on, a page's own name taken from its title or its slug, which Broadcast card layouts and review compositions are drawn and what a retired one draws as, what a publication's branding may hold, which literal hosts are refused as public fetch destinations, and which inbox cards are decisions a bulk action leaves alone. Pure functions, no dependencies.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -130,8 +130,7 @@
130
130
  "types": "./dist/page-titles.d.ts",
131
131
  "import": "./dist/page-titles.mjs",
132
132
  "require": "./dist/page-titles.js"
133
- }
134
- ,
133
+ },
135
134
  "./broadcast-layouts": {
136
135
  "types": "./dist/broadcast-layouts.d.ts",
137
136
  "import": "./dist/broadcast-layouts.mjs",
@@ -146,6 +145,16 @@
146
145
  "types": "./dist/public-url-host.d.ts",
147
146
  "import": "./dist/public-url-host.mjs",
148
147
  "require": "./dist/public-url-host.js"
148
+ },
149
+ "./inbox": {
150
+ "types": "./dist/inbox.d.ts",
151
+ "import": "./dist/inbox.mjs",
152
+ "require": "./dist/inbox.js"
153
+ },
154
+ "./funnels": {
155
+ "types": "./dist/funnels.d.ts",
156
+ "import": "./dist/funnels.mjs",
157
+ "require": "./dist/funnels.js"
149
158
  }
150
159
  },
151
160
  "typesVersions": {