@clipwright/core 0.33.0 → 0.35.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.
Files changed (236) hide show
  1. package/CHANGELOG.md +251 -0
  2. package/README.md +3 -1
  3. package/dist/account-actors.d.ts +173 -14
  4. package/dist/account-actors.js +142 -10
  5. package/dist/account-actors.js.map +1 -1
  6. package/dist/actor-bounds.d.ts +4 -0
  7. package/dist/actor-bounds.js +4 -0
  8. package/dist/actor-bounds.js.map +1 -1
  9. package/dist/actors.d.ts +31 -0
  10. package/dist/actors.js +26 -0
  11. package/dist/actors.js.map +1 -1
  12. package/dist/api-failure.js +2 -1
  13. package/dist/api-failure.js.map +1 -1
  14. package/dist/asset-identity.d.ts +6 -0
  15. package/dist/asset-identity.js +7 -0
  16. package/dist/asset-identity.js.map +1 -0
  17. package/dist/assets.d.ts +403 -8
  18. package/dist/assets.js +132 -22
  19. package/dist/assets.js.map +1 -1
  20. package/dist/billing-terms.d.ts +69 -0
  21. package/dist/billing-terms.js +8 -0
  22. package/dist/billing-terms.js.map +1 -1
  23. package/dist/caption-language.d.ts +2 -0
  24. package/dist/caption-language.js +17 -0
  25. package/dist/caption-language.js.map +1 -0
  26. package/dist/contract-dispositions.d.ts +1617 -8
  27. package/dist/contract-dispositions.js +75 -11
  28. package/dist/contract-dispositions.js.map +1 -1
  29. package/dist/contracts/v1/workflow-brief.d.ts +3166 -78
  30. package/dist/contracts/v1/workflow-brief.js +4 -0
  31. package/dist/contracts/v1/workflow-brief.js.map +1 -1
  32. package/dist/contracts/v1/workflow-catalog.d.ts +3712 -8
  33. package/dist/contracts/v1/workflow-catalog.js +4 -2
  34. package/dist/contracts/v1/workflow-catalog.js.map +1 -1
  35. package/dist/contracts/v1/workflow-client.d.ts +2466 -4
  36. package/dist/contracts/v1/workflow-client.js +6 -3
  37. package/dist/contracts/v1/workflow-client.js.map +1 -1
  38. package/dist/contracts/v1/workflow-execution.d.ts +163 -9
  39. package/dist/contracts/v1/workflow-execution.js +15 -7
  40. package/dist/contracts/v1/workflow-execution.js.map +1 -1
  41. package/dist/contracts/v1/workflow-plan.d.ts +6014 -487
  42. package/dist/contracts/v1/workflow-primitives.d.ts +3 -1
  43. package/dist/contracts/v1/workflow-primitives.js +1 -1
  44. package/dist/contracts/v1/workflow-primitives.js.map +1 -1
  45. package/dist/contracts/v1/workflow-run-read.d.ts +114 -1
  46. package/dist/edit-billing.d.ts +12 -0
  47. package/dist/edit-billing.js +8 -0
  48. package/dist/edit-billing.js.map +1 -1
  49. package/dist/edit-long-form.d.ts +1 -1
  50. package/dist/edit-long-form.js +12 -2
  51. package/dist/edit-long-form.js.map +1 -1
  52. package/dist/endpoint-notes.d.ts +3 -0
  53. package/dist/endpoint-notes.js +66 -0
  54. package/dist/endpoint-notes.js.map +1 -0
  55. package/dist/endpoints.d.ts +4 -0
  56. package/dist/endpoints.js +15 -0
  57. package/dist/endpoints.js.map +1 -1
  58. package/dist/errors.d.ts +1 -1
  59. package/dist/errors.js +7 -0
  60. package/dist/errors.js.map +1 -1
  61. package/dist/face-billing.d.ts +55 -0
  62. package/dist/face-billing.js +22 -0
  63. package/dist/face-billing.js.map +1 -1
  64. package/dist/faceless-price.d.ts +26 -2
  65. package/dist/faceless-price.js +33 -6
  66. package/dist/faceless-price.js.map +1 -1
  67. package/dist/faceless-public.d.ts +6 -1
  68. package/dist/faceless-public.js +2 -2
  69. package/dist/faceless-public.js.map +1 -1
  70. package/dist/generations.d.ts +32 -6
  71. package/dist/generations.js +82 -27
  72. package/dist/generations.js.map +1 -1
  73. package/dist/idempotency.d.ts +2 -0
  74. package/dist/idempotency.js +7 -4
  75. package/dist/idempotency.js.map +1 -1
  76. package/dist/index.d.ts +15 -0
  77. package/dist/index.js +17 -0
  78. package/dist/index.js.map +1 -1
  79. package/dist/long-form-pricing.d.ts +7 -4
  80. package/dist/long-form-pricing.js +13 -10
  81. package/dist/long-form-pricing.js.map +1 -1
  82. package/dist/long-form-revision.js +1 -1
  83. package/dist/long-form-revision.js.map +1 -1
  84. package/dist/openapi.d.ts +154 -0
  85. package/dist/openapi.js +334 -0
  86. package/dist/openapi.js.map +1 -0
  87. package/dist/pacing.d.ts +15 -0
  88. package/dist/pacing.js +30 -0
  89. package/dist/pacing.js.map +1 -1
  90. package/dist/parts-pricing.d.ts +84 -0
  91. package/dist/parts-pricing.js +105 -0
  92. package/dist/parts-pricing.js.map +1 -0
  93. package/dist/presenter-beats.d.ts +45 -0
  94. package/dist/presenter-beats.js +144 -0
  95. package/dist/presenter-beats.js.map +1 -0
  96. package/dist/prices.d.ts +98 -0
  97. package/dist/prices.js +189 -0
  98. package/dist/prices.js.map +1 -0
  99. package/dist/public-endpoints.d.ts +2 -0
  100. package/dist/public-endpoints.js +2 -0
  101. package/dist/public-endpoints.js.map +1 -1
  102. package/dist/public-responses.d.ts +23 -0
  103. package/dist/public-responses.js +11 -0
  104. package/dist/public-responses.js.map +1 -0
  105. package/dist/reference-analysis.d.ts +683 -0
  106. package/dist/reference-analysis.js +91 -0
  107. package/dist/reference-analysis.js.map +1 -0
  108. package/dist/reference-kinds.d.ts +6 -0
  109. package/dist/reference-kinds.js +8 -0
  110. package/dist/reference-kinds.js.map +1 -0
  111. package/dist/reference-profile.d.ts +633 -0
  112. package/dist/reference-profile.js +151 -0
  113. package/dist/reference-profile.js.map +1 -0
  114. package/dist/reference-staging.d.ts +571 -0
  115. package/dist/reference-staging.js +151 -0
  116. package/dist/reference-staging.js.map +1 -0
  117. package/dist/reference-voice.d.ts +305 -0
  118. package/dist/reference-voice.js +108 -0
  119. package/dist/reference-voice.js.map +1 -0
  120. package/dist/resolved-timeline.d.ts +206 -1
  121. package/dist/resolved-timeline.js +96 -4
  122. package/dist/resolved-timeline.js.map +1 -1
  123. package/dist/run-static-warnings.js +19 -7
  124. package/dist/run-static-warnings.js.map +1 -1
  125. package/dist/runs.d.ts +75 -3
  126. package/dist/runs.js +6 -1
  127. package/dist/runs.js.map +1 -1
  128. package/dist/semantic-inserts.d.ts +7 -0
  129. package/dist/semantic-inserts.js +19 -9
  130. package/dist/semantic-inserts.js.map +1 -1
  131. package/dist/skills.d.ts +5838 -22
  132. package/dist/skills.js +380 -25
  133. package/dist/skills.js.map +1 -1
  134. package/dist/templates/callout.d.ts +34 -0
  135. package/dist/templates/callout.js +51 -0
  136. package/dist/templates/callout.js.map +1 -0
  137. package/dist/templates/checklist.d.ts +42 -0
  138. package/dist/templates/checklist.js +47 -0
  139. package/dist/templates/checklist.js.map +1 -0
  140. package/dist/templates/compare.d.ts +26 -0
  141. package/dist/templates/compare.js +35 -0
  142. package/dist/templates/compare.js.map +1 -0
  143. package/dist/templates/end-card.d.ts +16 -0
  144. package/dist/templates/end-card.js +25 -0
  145. package/dist/templates/end-card.js.map +1 -0
  146. package/dist/templates/index.d.ts +171 -0
  147. package/dist/templates/index.js +394 -0
  148. package/dist/templates/index.js.map +1 -0
  149. package/dist/templates/lower-third.d.ts +18 -0
  150. package/dist/templates/lower-third.js +26 -0
  151. package/dist/templates/lower-third.js.map +1 -0
  152. package/dist/templates/notification.d.ts +30 -0
  153. package/dist/templates/notification.js +32 -0
  154. package/dist/templates/notification.js.map +1 -0
  155. package/dist/templates/phone-call.d.ts +27 -0
  156. package/dist/templates/phone-call.js +43 -0
  157. package/dist/templates/phone-call.js.map +1 -0
  158. package/dist/templates/progress.d.ts +22 -0
  159. package/dist/templates/progress.js +42 -0
  160. package/dist/templates/progress.js.map +1 -0
  161. package/dist/templates/quote.d.ts +21 -0
  162. package/dist/templates/quote.js +29 -0
  163. package/dist/templates/quote.js.map +1 -0
  164. package/dist/templates/rating.d.ts +22 -0
  165. package/dist/templates/rating.js +29 -0
  166. package/dist/templates/rating.js.map +1 -0
  167. package/dist/templates/size.d.ts +13 -0
  168. package/dist/templates/size.js +10 -0
  169. package/dist/templates/size.js.map +1 -0
  170. package/dist/templates/slot.d.ts +10 -0
  171. package/dist/templates/slot.js +5 -0
  172. package/dist/templates/slot.js.map +1 -0
  173. package/dist/templates/sounds.d.ts +701 -0
  174. package/dist/templates/sounds.js +89 -0
  175. package/dist/templates/sounds.js.map +1 -0
  176. package/dist/templates/stat.d.ts +20 -0
  177. package/dist/templates/stat.js +33 -0
  178. package/dist/templates/stat.js.map +1 -0
  179. package/dist/templates/tag.d.ts +23 -0
  180. package/dist/templates/tag.js +31 -0
  181. package/dist/templates/tag.js.map +1 -0
  182. package/dist/templates/theme.d.ts +29 -0
  183. package/dist/templates/theme.js +47 -0
  184. package/dist/templates/theme.js.map +1 -0
  185. package/dist/templates/title-card.d.ts +21 -0
  186. package/dist/templates/title-card.js +30 -0
  187. package/dist/templates/title-card.js.map +1 -0
  188. package/dist/tts-backend.d.ts +9 -0
  189. package/dist/tts-backend.js +21 -0
  190. package/dist/tts-backend.js.map +1 -1
  191. package/dist/ugc-call.d.ts +89 -0
  192. package/dist/ugc-call.js +111 -0
  193. package/dist/ugc-call.js.map +1 -0
  194. package/dist/ugc-framing.d.ts +26 -0
  195. package/dist/ugc-framing.js +64 -0
  196. package/dist/ugc-framing.js.map +1 -0
  197. package/dist/ugc-layers.d.ts +88 -0
  198. package/dist/ugc-layers.js +142 -0
  199. package/dist/ugc-layers.js.map +1 -0
  200. package/dist/ugc-video-media.d.ts +12 -0
  201. package/dist/ugc-video-media.js +39 -0
  202. package/dist/ugc-video-media.js.map +1 -0
  203. package/dist/vendor-response.d.ts +4 -0
  204. package/dist/vendor-response.js +12 -0
  205. package/dist/vendor-response.js.map +1 -1
  206. package/dist/voice-admission.d.ts +1244 -1
  207. package/dist/voice-listing.js +7 -1
  208. package/dist/voice-listing.js.map +1 -1
  209. package/dist/voice-pace.d.ts +34 -0
  210. package/dist/voice-pace.generated.json +72 -0
  211. package/dist/voice-pace.js +34 -0
  212. package/dist/voice-pace.js.map +1 -0
  213. package/dist/voices.d.ts +21 -8
  214. package/dist/voices.js +44 -19
  215. package/dist/voices.js.map +1 -1
  216. package/dist/workflows/catalog.js +2 -1
  217. package/dist/workflows/catalog.js.map +1 -1
  218. package/dist/workflows/index.d.ts +2 -0
  219. package/dist/workflows/index.js +2 -0
  220. package/dist/workflows/index.js.map +1 -1
  221. package/dist/workflows/methods/faceless-explainer.d.ts +697 -3
  222. package/dist/workflows/methods/kinetic-launch.d.ts +697 -3
  223. package/dist/workflows/methods/product-image-story.d.ts +697 -3
  224. package/dist/workflows/methods/reference-remake.d.ts +870 -0
  225. package/dist/workflows/methods/reference-remake.js +26 -0
  226. package/dist/workflows/methods/reference-remake.js.map +1 -0
  227. package/dist/workflows/methods/shared.d.ts +697 -3
  228. package/dist/workflows/methods/ugc-faq-answer.d.ts +697 -3
  229. package/dist/workflows/methods/ugc-product-intro.d.ts +697 -3
  230. package/dist/workflows/methods/website-proof-demo.d.ts +697 -3
  231. package/dist/workflows/reference-remake.d.ts +663 -0
  232. package/dist/workflows/reference-remake.js +598 -0
  233. package/dist/workflows/reference-remake.js.map +1 -0
  234. package/dist/workflows/validate.js +19 -11
  235. package/dist/workflows/validate.js.map +1 -1
  236. package/package.json +9 -3
@@ -0,0 +1,89 @@
1
+ import { z } from "zod";
2
+ // Template sounds (#778 S3c): the owner's library of 23.10, refreshed and extended on 25.10, one list of names per beat, with his default first in each.
3
+ export const TEMPLATE_SOUND_BEATS = ["click", "toggle", "ring", "answer", "notify", "step", "whoosh", "flash", "pop", "hangup", "money", "edit"];
4
+ /** Each beat's names, its default and where it plays; the composition bundles `<beat>__<name>.mp3` for each, and a test keeps the two equal. */
5
+ export const TEMPLATE_SOUNDS = {
6
+ click: { default: "click_mouse", names: ["click_mouse", "click_soft", "click_crisp", "click_light"],
7
+ plays: "a checklist's cursor clicks a row, on each click" },
8
+ toggle: { default: "switch_flip", names: ["switch_flip", "toggle_snap", "switch_heavy", "switch_light"],
9
+ plays: "a checklist row's switch or check box lands, just after each click" },
10
+ ring: { default: "ring_classic", names: ["ring_classic", "ring_marimba", "ring_digital", "ring_double"],
11
+ plays: "a phone_call rings from its pop, repeating, until it is answered; over a call it rings ring_double once, before the first line" },
12
+ answer: { default: "answer_confirm", names: ["answer_confirm", "answer_open", "answer_pop", "answer_select", "pickup"],
13
+ plays: "a phone_call is answered, on answer_at" },
14
+ notify: { default: "chime", names: ["chime", "glass_ping", "glass_soft", "bong", "question_ping"], plays: "a notification drops in" },
15
+ step: { default: "drop", names: ["drop", "drop_high", "tick", "pluck", "pluck_bright"], plays: "a progress step fills, and each rating star" },
16
+ whoosh: { default: "whoosh", names: ["whoosh", "whip", "paper_swipe", "sweep", "slide_quick"],
17
+ plays: "a full-frame template's wipe or zoom, in and out, and a compare's reveal" },
18
+ flash: { default: "shutter", names: ["shutter", "glitch", "swish"], plays: "a full-frame template's flash, on each of its cuts" },
19
+ pop: { default: "plop", names: ["plop"], plays: "a tag or a callout pops in" },
20
+ hangup: { default: "phone", names: ["phone"], plays: "an answered phone_call hangs up, just before it leaves" },
21
+ money: { default: "cash_register", names: ["cash_register", "coins"], plays: "a stat with a currency sign in its prefix or suffix counts up" },
22
+ edit: { default: "swell_hit", names: ["swell_hit", "whoosh_deep", "whoosh_low", "boom_low", "sub_drop", "riser_boom", "riser_hit"],
23
+ plays: "with edit_sounds, each cut: to or from an insert, a full-frame template's cut without its own whoosh or flash, a layout window's in and out; " +
24
+ "its peak lands on the cut" },
25
+ };
26
+ /** The beats each kind plays over the presenter; a full-frame template adds its transition's beat (see `templateSoundBeats`). */
27
+ export const TEMPLATE_KIND_SOUNDS = {
28
+ checklist: ["click", "toggle"], phone_call: ["ring", "answer", "hangup"], notification: ["notify"], progress: ["step"], rating: ["step"], compare: ["whoosh"],
29
+ tag: ["pop"], callout: ["pop"], stat: ["money"],
30
+ };
31
+ export const DEFAULT_TEMPLATE_SOUNDS = Object.freeze(Object.fromEntries(TEMPLATE_SOUND_BEATS.map(beat => [beat, TEMPLATE_SOUNDS[beat].default])));
32
+ const name = (beat) => z.enum(TEMPLATE_SOUNDS[beat].names, {
33
+ error: issue => `${JSON.stringify(issue.input)} is not ${/^[aeiou]/.test(beat) ? "an" : "a"} ${beat} sound: use ${TEMPLATE_SOUNDS[beat].names.join(", ")}`,
34
+ }).optional();
35
+ const overrides = z.strictObject({ click: name("click"), toggle: name("toggle"), ring: name("ring"), answer: name("answer"), notify: name("notify"),
36
+ step: name("step"), whoosh: name("whoosh"), flash: name("flash"), pop: name("pop"), hangup: name("hangup"), money: name("money"), edit: name("edit") }, {
37
+ error: issue => (issue.code === "unrecognized_keys" ? `template_sounds has no beat ${issue.keys.join(", ")}: the beats are ${TEMPLATE_SOUND_BEATS.join(", ")}` : undefined),
38
+ });
39
+ /** Why a value cannot be the field, with the beat's path; a union names no branch on its own, so the message does. */
40
+ function soundsRefusal(input) {
41
+ if (input === null || typeof input !== "object" || Array.isArray(input))
42
+ return "template_sounds is false (no sounds) or { beat: name }";
43
+ const issue = overrides.safeParse(input).error?.issues[0];
44
+ // zod 4.6 may surface the unknown-beat issue past the union, so that message carries its own path.
45
+ if (issue?.code === "unrecognized_keys")
46
+ return issue.message;
47
+ return `${["template_sounds", ...(issue?.path ?? []).map(String)].join(".")} ${issue?.message ?? "is invalid"}`;
48
+ }
49
+ export const templateSounds = z.union([z.literal(false), overrides], { error: issue => soundsRefusal(issue.input) })
50
+ .describe("Template sounds: false for none, or { beat: name } over the defaults; list_template_sounds names them.");
51
+ /** The slim MCP field, which keeps tools/list small: any beat and name pass here, and the server checks them strictly (S3 D3). */
52
+ export const mcpTemplateSounds = z.union([z.literal(false), z.record(z.string(), z.string())]).describe(templateSounds.description);
53
+ /** Opt-in, so a run that never asked keeps its silent cuts (rule 3); no default in the schema. */
54
+ export const editSounds = z.boolean().describe("A low sound on every cut (insert, full-frame template, layout window, framing), its peak on the cut. " +
55
+ "Needs inserts, layout_windows or framing; template_sounds.edit picks it (list_template_sounds). Price unchanged.");
56
+ /** Refusals of `edit_sounds` and `template_sounds.edit` that would otherwise be ignored: nothing to cut, a name without the switch, both on and muted. */
57
+ export function editSoundRefusals(input) {
58
+ const sounds = input.template_sounds;
59
+ if (input.edit_sounds !== true) {
60
+ return sounds !== null && typeof sounds === "object" && "edit" in sounds
61
+ ? [{ path: ["template_sounds", "edit"], message: "template_sounds.edit picks the edit sound: add edit_sounds: true or drop it" }] : [];
62
+ }
63
+ return [...(input.inserts === undefined && input.layout_windows === undefined && input.framing === undefined ? [{ path: ["edit_sounds"],
64
+ message: "edit_sounds sounds the cuts of inserts, layout windows and framing: add inserts, layout_windows or framing, or drop it" }] : []),
65
+ ...(sounds === false ? [{ path: ["edit_sounds"], message: "edit_sounds plays a sound on each cut and template_sounds: false mutes every sound: drop one" }] : [])];
66
+ }
67
+ /** A run's sounds: the defaults with its overrides, or none for `false` (S3c C2, C4). */
68
+ export function templateSoundMap(sounds) {
69
+ return sounds === false ? undefined : { ...DEFAULT_TEMPLATE_SOUNDS, ...sounds };
70
+ }
71
+ /** The beats one template plays: its kind's, and on a full frame its wipe or zoom (whoosh) or flash; money only with a currency sign around a stat. */
72
+ export function templateSoundBeats(item) {
73
+ const transition = item.placement !== "full" ? [] : item.transition === "wipe" || item.transition === "zoom" ? ["whoosh"]
74
+ : item.transition === "flash" ? ["flash"] : [];
75
+ const currency = [item.data?.prefix, item.data?.suffix].some(text => typeof text === "string" && /\p{Sc}/u.test(text));
76
+ return [...new Set([...(TEMPLATE_KIND_SOUNDS[item.kind] ?? []).filter(beat => beat !== "money" || currency), ...transition])];
77
+ }
78
+ export const TEMPLATE_SOUNDS_PATH = "/v1/template-sounds";
79
+ /** The catalog `GET /v1/template-sounds` and `list_template_sounds` return. */
80
+ export const templateSoundsList = z.strictObject({
81
+ beats: z.array(z.strictObject({ beat: z.enum(TEMPLATE_SOUND_BEATS), default: z.string().min(1), names: z.array(z.string().min(1)).min(1),
82
+ plays: z.string().min(1) })),
83
+ contract_version: z.string().min(1),
84
+ });
85
+ export function listTemplateSounds() {
86
+ return TEMPLATE_SOUND_BEATS.map(beat => ({ beat, default: TEMPLATE_SOUNDS[beat].default, names: [...TEMPLATE_SOUNDS[beat].names],
87
+ plays: TEMPLATE_SOUNDS[beat].plays }));
88
+ }
89
+ //# sourceMappingURL=sounds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sounds.js","sourceRoot":"","sources":["../../src/templates/sounds.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ import type { TemplateKind } from "./index.js";
3
+ /** The number at medium on a 1080 short side over the presenter; on a full frame it draws 1.6 times larger. */
4
+ export declare const STAT_FONT_PX = 120;
5
+ /** The drawn area is this many number sizes high: the number and its label; the composition reads the size back. */
6
+ export declare const STAT_RECT_EMS = 1.9;
7
+ declare const data: z.ZodObject<{
8
+ value: z.ZodNumber;
9
+ prefix: z.ZodOptional<z.ZodString>;
10
+ suffix: z.ZodOptional<z.ZodString>;
11
+ label: z.ZodOptional<z.ZodString>;
12
+ size: z.ZodOptional<z.ZodEnum<{
13
+ large: "large";
14
+ medium: "medium";
15
+ small: "small";
16
+ }>>;
17
+ }, z.core.$strict>;
18
+ /** A number that counts up from zero to `value`, with an optional prefix, suffix and label under it. */
19
+ export declare const stat: TemplateKind<typeof data>;
20
+ export {};
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ import { frameCanvasOf } from "../ugc-layers.js";
3
+ import { sizedScale, templateSize } from "./size.js";
4
+ /** The number at medium on a 1080 short side over the presenter; on a full frame it draws 1.6 times larger. */
5
+ export const STAT_FONT_PX = 120;
6
+ const FULL_SCALE = 1.6;
7
+ /** The drawn area is this many number sizes high: the number and its label; the composition reads the size back. */
8
+ export const STAT_RECT_EMS = 1.9;
9
+ const data = z.object({ value: z.number().min(0).max(999_999_999).multipleOf(0.01), prefix: z.string().min(1).max(6).optional(),
10
+ suffix: z.string().min(1).max(6).optional(), label: z.string().min(1).max(32).optional(), size: templateSize }).strict();
11
+ /** A number that counts up from zero to `value`, with an optional prefix, suffix and label under it. */
12
+ export const stat = {
13
+ kind: "stat",
14
+ kindVersion: 1,
15
+ description: "a number counting up from 0 to value (up to 2 decimals), with prefix and suffix around it and a label under it; " +
16
+ "full fills the frame, over sits at chest level on a card",
17
+ placements: ["full", "over"],
18
+ data,
19
+ text: { prefix: 6, suffix: 6, label: 32 },
20
+ slots: {},
21
+ hidesCaptions: () => false,
22
+ onInserts: false,
23
+ rect: (value, aspectRatio, placement) => {
24
+ const canvas = frameCanvasOf(aspectRatio), { width: w, height: h } = canvas, short = Math.min(w, h);
25
+ const scale = sizedScale(value.size, canvas) * (placement === "full" ? FULL_SCALE : 1);
26
+ const width = Math.round(Math.min(0.9 * w, 1.1 * short * Math.min(scale, 1))), height = Math.round(STAT_RECT_EMS * STAT_FONT_PX * scale);
27
+ // Over the presenter it sits at chest level, as the reference's toggle card (62–80% of the height), off the face.
28
+ const centre = placement === "full" ? 0.5 : 0.71;
29
+ return { left: Math.round((w - width) / 2) / w, top: Math.round(centre * h - height / 2) / h, width: width / w, height: height / h };
30
+ },
31
+ sample: { value: 17, prefix: "$", suffix: "M", label: "raised this year" },
32
+ };
33
+ //# sourceMappingURL=stat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stat.js","sourceRoot":"","sources":["../../src/templates/stat.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { z } from "zod";
2
+ import type { TemplateKind } from "./index.js";
3
+ export declare const TAG_POSITIONS: readonly ["top", "center", "bottom"];
4
+ /** The pill's text at medium on a 1080 short side: the reference pill's cap height, about 3.5% of a 9:16 frame. */
5
+ export declare const TAG_FONT_PX = 92;
6
+ /** The footprint is this many font sizes high: the pill and its glow; the composition reads the font back from it. */
7
+ export declare const TAG_RECT_EMS = 1.6;
8
+ declare const data: z.ZodObject<{
9
+ text: z.ZodString;
10
+ position: z.ZodOptional<z.ZodEnum<{
11
+ bottom: "bottom";
12
+ center: "center";
13
+ top: "top";
14
+ }>>;
15
+ size: z.ZodOptional<z.ZodEnum<{
16
+ large: "large";
17
+ medium: "medium";
18
+ small: "small";
19
+ }>>;
20
+ }, z.core.$strict>;
21
+ /** A short gradient pill over the presenter, centred on a caption line or in the caption spot; it may sit on insert frames. */
22
+ export declare const tag: TemplateKind<typeof data>;
23
+ export {};
@@ -0,0 +1,31 @@
1
+ import { z } from "zod";
2
+ import { frameCanvasOf } from "../ugc-layers.js";
3
+ import { sizedScale, templateSize } from "./size.js";
4
+ export const TAG_POSITIONS = ["top", "center", "bottom"];
5
+ /** Absent position is the reference's: two thirds down, at chest level, in the caption spot. */
6
+ const CENTRES = { top: 0.22, center: 0.5, bottom: 0.78, caption: 0.66 };
7
+ /** The pill's text at medium on a 1080 short side: the reference pill's cap height, about 3.5% of a 9:16 frame. */
8
+ export const TAG_FONT_PX = 92;
9
+ /** The footprint is this many font sizes high: the pill and its glow; the composition reads the font back from it. */
10
+ export const TAG_RECT_EMS = 1.6;
11
+ const data = z.object({ text: z.string().min(1).max(32), position: z.enum(TAG_POSITIONS).optional(), size: templateSize }).strict();
12
+ /** A short gradient pill over the presenter, centred on a caption line or in the caption spot; it may sit on insert frames. */
13
+ export const tag = {
14
+ kind: "tag",
15
+ kindVersion: 1,
16
+ description: "a short gradient pill over the presenter or an insert; without position it sits in the caption spot and hides captions while it shows",
17
+ placements: ["over"],
18
+ data,
19
+ text: { text: 32 },
20
+ slots: {},
21
+ hidesCaptions: value => value.position === undefined,
22
+ onInserts: true,
23
+ rect: (value, aspectRatio) => {
24
+ const canvas = frameCanvasOf(aspectRatio), { width: w, height: h } = canvas, short = Math.min(w, h), scale = sizedScale(value.size, canvas);
25
+ const width = Math.round(Math.min(0.9 * w, 1.25 * short * scale)), height = Math.round(TAG_RECT_EMS * TAG_FONT_PX * scale);
26
+ return { left: Math.round((w - width) / 2) / w, top: Math.round(CENTRES[value.position ?? "caption"] * h - height / 2) / h, width: width / w,
27
+ height: height / h };
28
+ },
29
+ sample: { text: "sounds natural", position: "center" },
30
+ };
31
+ //# sourceMappingURL=tag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tag.js","sourceRoot":"","sources":["../../src/templates/tag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAErD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAU,CAAC;AAClE,gGAAgG;AAChG,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAW,CAAC;AACjF,mHAAmH;AACnH,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAC9B,sHAAsH;AACtH,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC;AAChC,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;AAEpI,+HAA+H;AAC/H,MAAM,CAAC,MAAM,GAAG,GAA8B;IAC5C,IAAI,EAAE,KAAK;IACX,WAAW,EAAE,CAAC;IACd,WAAW,EAAE,uIAAuI;IACpJ,UAAU,EAAE,CAAC,MAAM,CAAC;IACpB,IAAI;IACJ,IAAI,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;IAClB,KAAK,EAAE,EAAE;IACT,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS;IACpD,SAAS,EAAE,IAAI;IACf,IAAI,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;QAC3B,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC5I,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,EAAE,IAAI,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,WAAW,GAAG,KAAK,CAAC,CAAC;QAC3H,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC;YAC1I,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;IACzB,CAAC;IACD,MAAM,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,QAAQ,EAAE;CACvD,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+ /** Looks the composition draws templates in (#778 S3, D8); presets are judged by eye on sheets, only a customer's colour is checked. */
3
+ export declare const TEMPLATE_PRESETS: readonly ["clean_light", "bold_dark", "neon", "paper", "mono"];
4
+ export type TemplatePreset = (typeof TEMPLATE_PRESETS)[number];
5
+ /** The look of a run whose `template_theme` names none; the schema has no default (A8). */
6
+ export declare const DEFAULT_TEMPLATE_PRESET: TemplatePreset;
7
+ /** The colours an accent meets in each look: the text drawn on it, and the grounds it is drawn on as ink. The composition's themes
8
+ * hold the same values; a test keeps them equal. */
9
+ export declare const TEMPLATE_PRESET_SURFACES: Readonly<Record<TemplatePreset, {
10
+ onAccent: string;
11
+ grounds: readonly string[];
12
+ }>>;
13
+ /** Large text needs 3:1 (WCAG 1.4.3); every template text is large. */
14
+ export declare const TEMPLATE_MIN_CONTRAST = 3;
15
+ export declare const templateTheme: z.ZodObject<{
16
+ preset: z.ZodOptional<z.ZodEnum<{
17
+ bold_dark: "bold_dark";
18
+ clean_light: "clean_light";
19
+ mono: "mono";
20
+ neon: "neon";
21
+ paper: "paper";
22
+ }>>;
23
+ accent: z.ZodOptional<z.ZodString>;
24
+ }, z.core.$strict>;
25
+ export type TemplateTheme = z.infer<typeof templateTheme>;
26
+ /** The WCAG contrast ratio of two `#RRGGBB` colours. */
27
+ export declare function contrastRatio(a: string, b: string): number;
28
+ /** Why a customer accent cannot be drawn in a look, or nothing: it is refused, never shifted (D8). */
29
+ export declare function templateAccentRefusal(preset: TemplatePreset, accent: string): string | undefined;
@@ -0,0 +1,47 @@
1
+ import { z } from "zod";
2
+ /** Looks the composition draws templates in (#778 S3, D8); presets are judged by eye on sheets, only a customer's colour is checked. */
3
+ export const TEMPLATE_PRESETS = ["clean_light", "bold_dark", "neon", "paper", "mono"];
4
+ /** The look of a run whose `template_theme` names none; the schema has no default (A8). */
5
+ export const DEFAULT_TEMPLATE_PRESET = "clean_light";
6
+ /** The colours an accent meets in each look: the text drawn on it, and the grounds it is drawn on as ink. The composition's themes
7
+ * hold the same values; a test keeps them equal. */
8
+ export const TEMPLATE_PRESET_SURFACES = {
9
+ clean_light: { onAccent: "#FFFFFF", grounds: ["#FFFFFF", "#EAF1FC", "#D9E7FB"] },
10
+ bold_dark: { onAccent: "#0B0F19", grounds: ["#1F2937", "#0B0F17", "#1C222C"] },
11
+ neon: { onAccent: "#FFFFFF", grounds: ["#0A0E16", "#05070D", "#0A1428"] },
12
+ paper: { onAccent: "#FFFFFF", grounds: ["#FDF8EF", "#F6EFE3", "#EADCC8"] },
13
+ mono: { onAccent: "#FFFFFF", grounds: ["#FFFFFF", "#F4F4F4", "#E2E2E2"] },
14
+ };
15
+ /** Large text needs 3:1 (WCAG 1.4.3); every template text is large. */
16
+ export const TEMPLATE_MIN_CONTRAST = 3;
17
+ export const templateTheme = z.object({
18
+ preset: z.enum(TEMPLATE_PRESETS).optional().describe("clean_light (light cards on our blue gradient), bold_dark (dark cards, a yellow accent), neon (black, " +
19
+ "cyan to blue), paper (warm cream, terracotta) or mono (black and white); omitted is clean_light."),
20
+ accent: z.string().regex(/^#[0-9A-Fa-f]{6}$/, "must be a #RRGGBB hex colour").optional()
21
+ .describe("#RRGGBB in place of the preset's accent: the pills' fill and the accent text. Refused below 3:1 against the colours it meets."),
22
+ }).strict();
23
+ const luminance = (hex) => {
24
+ const [r, g, b] = [1, 3, 5].map(at => Number.parseInt(hex.slice(at, at + 2), 16) / 255)
25
+ .map(channel => (channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4));
26
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
27
+ };
28
+ /** The WCAG contrast ratio of two `#RRGGBB` colours. */
29
+ export function contrastRatio(a, b) {
30
+ const [light, dark] = [luminance(a), luminance(b)].sort((x, y) => y - x);
31
+ return (light + 0.05) / (dark + 0.05);
32
+ }
33
+ /** Why a customer accent cannot be drawn in a look, or nothing: it is refused, never shifted (D8). */
34
+ export function templateAccentRefusal(preset, accent) {
35
+ const { onAccent, grounds } = TEMPLATE_PRESET_SURFACES[preset];
36
+ const worst = [{ against: onAccent, role: `the ${onAccent} text drawn on it` },
37
+ ...grounds.map(ground => ({ against: ground, role: `the ${ground} card or ground it is drawn on` }))]
38
+ .map(entry => ({ ...entry, ratio: contrastRatio(accent, entry.against) })).sort((a, b) => a.ratio - b.ratio)[0];
39
+ if (worst.ratio >= TEMPLATE_MIN_CONTRAST)
40
+ return undefined;
41
+ // Towards the nearest luminance that clears them all: in neon the white text and the dark grounds sit on opposite sides of it.
42
+ const own = luminance(accent), levels = [onAccent, ...grounds].map(luminance);
43
+ const nearest = Array.from({ length: 1001 }, (_, step) => step / 1000).filter(level => levels.every(other => (Math.max(level, other) + 0.05) / (Math.min(level, other) + 0.05) >= TEMPLATE_MIN_CONTRAST)).sort((a, b) => Math.abs(a - own) - Math.abs(b - own))[0];
44
+ return `${accent} reaches ${worst.ratio.toFixed(2)}:1 against ${worst.role} in ${preset}, under the ${TEMPLATE_MIN_CONTRAST}:1 large text needs: ` +
45
+ (nearest === undefined ? "pick another preset" : `pick a ${nearest < own ? "darker" : "lighter"} accent or another preset`);
46
+ }
47
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/templates/theme.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,wIAAwI;AACxI,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAU,CAAC;AAE/F,2FAA2F;AAC3F,MAAM,CAAC,MAAM,uBAAuB,GAAmB,aAAa,CAAC;AACrE;oDACoD;AACpD,MAAM,CAAC,MAAM,wBAAwB,GAAuF;IAC1H,WAAW,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE;IAChF,SAAS,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE;IAC9E,IAAI,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE;IACzE,KAAK,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE;IAC1E,IAAI,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE;CAC1E,CAAC;AACF,uEAAuE;AACvE,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEvC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wGAAwG;QAC3J,kGAAkG,CAAC;IACrG,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,mBAAmB,EAAE,8BAA8B,CAAC,CAAC,QAAQ,EAAE;SACrF,QAAQ,CAAC,+HAA+H,CAAC;CAC7I,CAAC,CAAC,MAAM,EAAE,CAAC;AAGZ,MAAM,SAAS,GAAG,CAAC,GAAW,EAAU,EAAE;IACxC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC;SACpF,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,GAAG,CAAC,CAA6B,CAAC;IAC3H,OAAO,MAAM,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;AAC9C,CAAC,CAAC;AACF,wDAAwD;AACxD,MAAM,UAAU,aAAa,CAAC,CAAS,EAAE,CAAS;IAChD,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAqB,CAAC;IAC7F,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,qBAAqB,CAAC,MAAsB,EAAE,MAAc;IAC1E,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAG,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,QAAQ,mBAAmB,EAAE;QAC5E,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,MAAM,gCAAgC,EAAE,CAAC,CAAC,CAAC;SACpG,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,CAAC;IACnH,IAAI,KAAK,CAAC,KAAK,IAAI,qBAAqB;QAAE,OAAO,SAAS,CAAC;IAC3D,+HAA+H;IAC/H,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,QAAQ,EAAE,GAAG,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC9E,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAC1G,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxJ,OAAO,GAAG,MAAM,YAAY,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,KAAK,CAAC,IAAI,OAAO,MAAM,eAAe,qBAAqB,uBAAuB;QAChJ,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,UAAU,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,2BAA2B,CAAC,CAAC;AAChI,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { z } from "zod";
2
+ import type { TemplateKind } from "./index.js";
3
+ /** The title at medium on a 1080 short side, as reference frames 1–2 draw the brand on the card. */
4
+ export declare const TITLE_CARD_FONT_PX = 96;
5
+ /** The drawn area is this many title sizes high: the card with two title lines, the gap and the chip; the composition reads the size back. */
6
+ export declare const TITLE_CARD_RECT_EMS = 5;
7
+ declare const data: z.ZodObject<{
8
+ title: z.ZodString;
9
+ chip: z.ZodOptional<z.ZodString>;
10
+ logo: z.ZodOptional<z.ZodObject<{
11
+ asset_id: z.ZodString;
12
+ }, z.core.$strict>>;
13
+ size: z.ZodOptional<z.ZodEnum<{
14
+ large: "large";
15
+ medium: "medium";
16
+ small: "small";
17
+ }>>;
18
+ }, z.core.$strict>;
19
+ /** The hook card of reference frames 1–2: the title on a white card beside an optional logo, a gradient chip under it, on a full frame. */
20
+ export declare const titleCard: TemplateKind<typeof data>;
21
+ export {};
@@ -0,0 +1,30 @@
1
+ import { z } from "zod";
2
+ import { frameCanvasOf } from "../ugc-layers.js";
3
+ import { sizedScale, templateSize } from "./size.js";
4
+ import { templateMedia } from "./slot.js";
5
+ /** The title at medium on a 1080 short side, as reference frames 1–2 draw the brand on the card. */
6
+ export const TITLE_CARD_FONT_PX = 96;
7
+ /** The drawn area is this many title sizes high: the card with two title lines, the gap and the chip; the composition reads the size back. */
8
+ export const TITLE_CARD_RECT_EMS = 5;
9
+ const data = z.object({ title: z.string().min(1).max(48), chip: z.string().min(1).max(32).optional(), logo: templateMedia.optional(),
10
+ size: templateSize }).strict();
11
+ /** The hook card of reference frames 1–2: the title on a white card beside an optional logo, a gradient chip under it, on a full frame. */
12
+ export const titleCard = {
13
+ kind: "title_card",
14
+ kindVersion: 1,
15
+ description: "a full-frame hook card: the title (up to two lines) on a white card beside an optional logo image, and an optional chip under it",
16
+ placements: ["full"],
17
+ data,
18
+ text: { title: 48, chip: 32 },
19
+ slots: { logo: { type: "image" } },
20
+ hidesCaptions: () => true,
21
+ onInserts: false,
22
+ rect: (value, aspectRatio) => {
23
+ const canvas = frameCanvasOf(aspectRatio), { width: w, height: h } = canvas, scale = sizedScale(value.size, canvas);
24
+ // The reference card is 89% of a 1080 width; the drawn area adds a 3% margin on each side.
25
+ const width = Math.round(Math.min(0.95 * w, 1022 * scale)), height = Math.round(TITLE_CARD_RECT_EMS * TITLE_CARD_FONT_PX * scale);
26
+ return { left: Math.round((w - width) / 2) / w, top: Math.round((h > w ? 0.38 : 0.5) * h - height / 2) / h, width: width / w, height: height / h };
27
+ },
28
+ sample: { title: "fonio.ai", chip: "raised $17 million" },
29
+ };
30
+ //# sourceMappingURL=title-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"title-card.js","sourceRoot":"","sources":["../../src/templates/title-card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,oGAAoG;AACpG,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AACrC,8IAA8I;AAC9I,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AACrC,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,aAAa,CAAC,QAAQ,EAAE;IAClI,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;AAEjC,2IAA2I;AAC3I,MAAM,CAAC,MAAM,SAAS,GAA8B;IAClD,IAAI,EAAE,YAAY;IAClB,WAAW,EAAE,CAAC;IACd,WAAW,EAAE,kIAAkI;IAC/I,UAAU,EAAE,CAAC,MAAM,CAAC;IACpB,IAAI;IACJ,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;IAC7B,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;IAClC,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI;IACzB,SAAS,EAAE,KAAK;IAChB,IAAI,EAAE,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;QAC3B,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACpH,2FAA2F;QAC3F,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,mBAAmB,GAAG,kBAAkB,GAAG,KAAK,CAAC,CAAC;QAClI,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;IACrJ,CAAC;IACD,MAAM,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,oBAAoB,EAAE;CAC1D,CAAC"}
@@ -45,3 +45,12 @@ export interface TtsBackend {
45
45
  /** Joins per-character timings into words, shared by vendors with that format. Whitespace */
46
46
  /** ends a word without joining it; empty words are never produced. */
47
47
  export declare function charTimingsToWords(characters: readonly string[], startTimes: readonly number[], endTimes: readonly number[]): WordTiming[];
48
+ /** One speech model's alignment ends 80 ms past its decoded audio on every measured take (#779), */
49
+ /** fresh and recovered alike; a tail up to this long is the model's, not a timing error. */
50
+ export declare const ALIGNMENT_TAIL_TOLERANCE_SEC = 0.1;
51
+ /** Word ends past the decoded audio pulled back to its end, or null when a word starts at */
52
+ /** or after it or overshoots by more than the tolerance. `clippedSec` is the largest pull. */
53
+ export declare function clampAlignmentTail(words: readonly WordTiming[], durationSec: number): {
54
+ words: WordTiming[];
55
+ clippedSec: number;
56
+ } | null;
@@ -30,4 +30,25 @@ export function charTimingsToWords(characters, startTimes, endTimes) {
30
30
  flush();
31
31
  return words;
32
32
  }
33
+ /** One speech model's alignment ends 80 ms past its decoded audio on every measured take (#779), */
34
+ /** fresh and recovered alike; a tail up to this long is the model's, not a timing error. */
35
+ export const ALIGNMENT_TAIL_TOLERANCE_SEC = 0.1;
36
+ /** Word ends past the decoded audio pulled back to its end, or null when a word starts at */
37
+ /** or after it or overshoots by more than the tolerance. `clippedSec` is the largest pull. */
38
+ export function clampAlignmentTail(words, durationSec) {
39
+ let clippedSec = 0;
40
+ const clamped = [];
41
+ for (const word of words) {
42
+ if (word.endSec <= durationSec) {
43
+ clamped.push({ ...word });
44
+ continue;
45
+ }
46
+ const overshoot = word.endSec - durationSec;
47
+ if (!(word.startSec < durationSec) || overshoot > ALIGNMENT_TAIL_TOLERANCE_SEC + 1e-9)
48
+ return null;
49
+ clippedSec = Math.max(clippedSec, overshoot);
50
+ clamped.push({ ...word, endSec: durationSec });
51
+ }
52
+ return { words: clamped, clippedSec };
53
+ }
33
54
  //# sourceMappingURL=tts-backend.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tts-backend.js","sourceRoot":"","sources":["../src/tts-backend.ts"],"names":[],"mappings":"AAsDA,6FAA6F;AAC7F,sEAAsE;AACtE,MAAM,UAAU,kBAAkB,CAChC,UAA6B,EAC7B,UAA6B,EAC7B,QAA2B;IAE3B,IAAI,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrF,MAAM,IAAI,KAAK,CACb,qCAAqC,UAAU,CAAC,MAAM,UAAU;YAC9D,GAAG,UAAU,CAAC,MAAM,YAAY,QAAQ,CAAC,MAAM,OAAO,CACzD,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,GAAG,GAAG,CAAC,CAAC;IAEZ,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YACxD,GAAG,GAAG,EAAE,CAAC;QACX,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9C,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAW,CAAC;QACnC,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAClB,KAAK,EAAE,CAAC;YACR,SAAS;QACX,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,KAAK,GAAG,UAAU,CAAC,CAAC,CAAW,CAAC;QAClC,CAAC;QACD,GAAG,IAAI,EAAE,CAAC;QACV,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAW,CAAC;IAC9B,CAAC;IACD,KAAK,EAAE,CAAC;IAER,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"tts-backend.js","sourceRoot":"","sources":["../src/tts-backend.ts"],"names":[],"mappings":"AAsDA,6FAA6F;AAC7F,sEAAsE;AACtE,MAAM,UAAU,kBAAkB,CAChC,UAA6B,EAC7B,UAA6B,EAC7B,QAA2B;IAE3B,IAAI,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,EAAE,CAAC;QACrF,MAAM,IAAI,KAAK,CACb,qCAAqC,UAAU,CAAC,MAAM,UAAU;YAC9D,GAAG,UAAU,CAAC,MAAM,YAAY,QAAQ,CAAC,MAAM,OAAO,CACzD,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,GAAG,GAAG,CAAC,CAAC;IAEZ,MAAM,KAAK,GAAG,GAAS,EAAE;QACvB,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YACxD,GAAG,GAAG,EAAE,CAAC;QACX,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9C,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAW,CAAC;QACnC,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAClB,KAAK,EAAE,CAAC;YACR,SAAS;QACX,CAAC;QACD,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrB,KAAK,GAAG,UAAU,CAAC,CAAC,CAAW,CAAC;QAClC,CAAC;QACD,GAAG,IAAI,EAAE,CAAC;QACV,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAW,CAAC;IAC9B,CAAC;IACD,KAAK,EAAE,CAAC;IAER,OAAO,KAAK,CAAC;AACf,CAAC;AAED,oGAAoG;AACpG,4FAA4F;AAC5F,MAAM,CAAC,MAAM,4BAA4B,GAAG,GAAG,CAAC;AAEhD,6FAA6F;AAC7F,8FAA8F;AAC9F,MAAM,UAAU,kBAAkB,CAAC,KAA4B,EAAE,WAAmB;IAElF,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,IAAI,WAAW,EAAE,CAAC;YAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;YAAC,SAAS;QAAC,CAAC;QACxE,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,WAAW,CAAC;QAC5C,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,IAAI,SAAS,GAAG,4BAA4B,GAAG,IAAI;YAAE,OAAO,IAAI,CAAC;QACnG,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;AACxC,CAAC"}
@@ -0,0 +1,89 @@
1
+ import { type AnchoredItem, type LayerRefusal } from "./ugc-layers.js";
2
+ export declare const CALL_SPEAKERS: readonly ["agent", "caller"];
3
+ export type CallSpeaker = (typeof CALL_SPEAKERS)[number];
4
+ export declare const MAX_CALL_LINES = 12;
5
+ export declare const MAX_CALL_LINE_CHARS = 400;
6
+ export declare const MAX_CALL_CHARS = 1500;
7
+ /** A call's length before synthesis, at the reference's 19 characters a second (D10). */
8
+ export declare const CALL_CHARS_PER_SEC = 19;
9
+ export declare const MAX_CALL_SEC = 45;
10
+ /** Past this the presenter holds still long enough to name it (D1). */
11
+ export declare const CALL_WARN_SEC = 20;
12
+ /** The bake-off's pair (S5-0): agent Cassidy, caller Mark; the agent is never the narration's voice. */
13
+ export declare const DEFAULT_CALL_VOICES: Readonly<Record<CallSpeaker, string>>;
14
+ export declare const SECOND_CALL_AGENT = "sarah";
15
+ /** The reference's in-call screen (D8): a US number shown only to its area code and the hold banner, generic phone UI. */
16
+ export declare const CALL_PHONE_DEFAULTS: Readonly<{
17
+ caller: "+1 (305) 555-0147";
18
+ banner: "Hold This Call?";
19
+ banner_note: "You'll be notified to pick up.";
20
+ mask_number: true;
21
+ }>;
22
+ /** The phone the worker draws over a call: an id no client template can spell, so it never meets one. */
23
+ export declare const CALL_PHONE_ID = "call.phone";
24
+ /** The ring starts this long after the phone enters, rings for CALL_RING_SEC (the `ring_double` file) and the first word follows it. */
25
+ export declare const CALL_RING_LEAD_SEC = 0.07;
26
+ export declare const CALL_RING_SEC = 1.35;
27
+ export declare const CALL_RING_TO_VOICE_SEC = 0.1;
28
+ /** From the call's last word to the end of the freeze. */
29
+ export declare const CALL_TAIL_SEC = 0.4;
30
+ /** The presenter's live listening before the freeze (S4d), and how far before the freeze the phone enters behind it. */
31
+ export declare const CALL_LIVE_SEC = 3.58;
32
+ export declare const CALL_PHONE_LEAD_SEC = 3.96;
33
+ /** A staged phone (#914 D1e) rises from one of these sides, within these bounds; the composition draws no other entry for it. */
34
+ export declare const CALL_STAGE_SIDES: readonly ["bottom", "lower_left", "lower_right"];
35
+ export declare const CALL_STAGE_MAX_ENTER_SEC = 5;
36
+ export declare const CALL_STAGE_MAX_LEAD_SEC = 10;
37
+ export interface CallLine {
38
+ speaker: CallSpeaker;
39
+ text: string;
40
+ }
41
+ export interface CallInput {
42
+ after: AnchoredItem["anchor"];
43
+ lines: readonly CallLine[];
44
+ voices?: {
45
+ agent?: string | undefined;
46
+ caller?: string | undefined;
47
+ } | undefined;
48
+ phone?: {
49
+ caller?: string | undefined;
50
+ banner?: string | undefined;
51
+ banner_note?: string | undefined;
52
+ mask_number?: boolean | undefined;
53
+ } | undefined;
54
+ }
55
+ export declare const callChars: (call: Pick<CallInput, "lines">) => number;
56
+ export declare const callEstimateSec: (call: Pick<CallInput, "lines">) => number;
57
+ /** The seconds a call adds to the video: its lines, the ring before them and the tail after (D10). */
58
+ export declare const callGapEstimateSec: (call: Pick<CallInput, "lines">) => number;
59
+ /** The lexical word the presenter resumes on: the one after the quote's last word, or why there is none. */
60
+ export declare function callResumeWord(script: string, after: CallInput["after"]): number | string;
61
+ /** The agent and caller voices: the named ones, else the defaults, the agent kept off the narration's voice. */
62
+ export declare function callVoices(call: Pick<CallInput, "voices">, narrationVoice: string | undefined): Record<CallSpeaker, string>;
63
+ export interface CallCheckInput {
64
+ script?: string | undefined;
65
+ segments?: unknown;
66
+ aspect_ratio?: string | undefined;
67
+ voice?: string | undefined;
68
+ inserts?: readonly AnchoredItem[] | undefined;
69
+ call?: CallInput | undefined;
70
+ }
71
+ /** Every refusal of `call` before money, named by path (C1); the schema already bounds each line and the count. */
72
+ export declare function callRefusals(input: CallCheckInput): LayerRefusal[];
73
+ /** A long call is delivered, and named (rule 3). */
74
+ export declare function callWarnings(input: {
75
+ call?: unknown;
76
+ }): string[];
77
+ /** Where a call sits in its gap, in frames from the presenter's last word before it (D2): the phone enters, the ring starts, the first word,
78
+ * and the gap and hold lengths. Gap = ring lead + ring + call + tail after the phone; hold = gap − live. */
79
+ export declare function callGapFrames(args: {
80
+ callFrames: number;
81
+ liveFrames: number;
82
+ fps: number;
83
+ }): {
84
+ phoneEntry: number;
85
+ ringFrom: number;
86
+ voiceFrom: number;
87
+ gapFrames: number;
88
+ holdFrames: number;
89
+ };