@odla-ai/chapter 0.61.0 → 0.63.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.
@@ -0,0 +1,370 @@
1
+ import * as preact from 'preact';
2
+ import { ComponentChildren } from 'preact';
3
+
4
+ type TextFields$2<Key extends string> = {
5
+ [Field in Key]: string;
6
+ };
7
+ /** User-visible language for sharing, delivery state, and leader rollups. */
8
+ type AdminNetworkCopy = TextFields$2<"title" | "allowlistDescription" | "sharing" | "shareWith" | "shared" | "shareFailed" | "deliveryFailed" | "loadingRollup" | "loadRollupFailed" | "overview" | "configuredFollowers" | "reachableFollowers" | "recordsAcrossFollowers" | "noFollowers" | "followers" | "available" | "unavailable" | "transportReachable" | "transportUnavailable" | "transportNotChecked" | "edgeUnpaired" | "edgeUnpairedHint" | "bindingTransport" | "urlTransport" | "activeConfiguration" | "noActiveConfiguration" | "publicSiteAvailable" | "publicSiteUnavailable" | "publicSiteNotChecked" | "recordTotals" | "noRecordTotals">;
9
+
10
+ type TextFields$1<Key extends string> = {
11
+ [Field in Key]: string;
12
+ };
13
+ /**
14
+ * Member portal language. Placeholders in braces are filled by
15
+ * `formatChapterCopy()`. Sites override any field through `copy.portal`.
16
+ */
17
+ interface PortalCopy {
18
+ shell: TextFields$1<"navLabel" | "welcomeBack" | "home" | "backHome" | "yourProfile" | "signedInAs" | "signOut" | "adminConsole" | "openMenu" | "closeMenu" | "locked" | "loading" | "loadFailed" | "notFound">;
19
+ pages: TextFields$1<"comingSoon" | "comingIn" | "includedWith" | "upgrade" | "comingToPortal" | "tagNew" | "tagSoon">;
20
+ profile: TextFields$1<"eyebrow" | "editProfile" | "saveProfile" | "saving" | "cancel" | "uploadPhoto" | "changePhoto" | "photoUploading" | "photoFailed" | "memberSince" | "promptsTitle" | "promptsNote" | "answerEmpty" | "addPrompt" | "howYouFoundUs" | "referredBy" | "referredByNote" | "introducedBy" | "introducedByPlaceholder" | "namePlaceholder" | "locationPlaceholder" | "saved" | "conflict" | "saveFailed">;
21
+ /** Invitations and referrals. Templates take {tierName}, {article}, {inviteUrl}, {firstName}, {location}, {credit}. */
22
+ share: TextFields$1<"eyebrow" | "intro" | "officialTitle" | "officialBody" | "showMeHow" | "stepsEyebrow" | "openLinkedIn" | "copyDescription" | "linkedinDescription" | "postTitle" | "postBody" | "shareOnLinkedIn" | "previewPost" | "linkedinPost" | "linkTitle" | "linkBody" | "linkCredit" | "referralsCredit" | "copyLink" | "copied" | "copyBlocked" | "emailInvite" | "textInvite" | "inviteNote" | "emailSubject" | "emailBody" | "textBody" | "fallbackEmail" | "fallbackText" | "copyMessage" | "close" | "referralsTitle" | "referralsBody" | "inviteFriend" | "joined" | "inProcess" | "offNextYear" | "joinedWith"> & {
23
+ steps: string[];
24
+ };
25
+ /** The cohort course page and Home panel. Templates take {left}, {capacity}, {position}, {count}. */
26
+ course: TextFields$1<"eyebrow" | "reserve" | "seeDetails" | "courseDetails" | "youreIn" | "invitesOnWay" | "openMeet" | "giveUp" | "confirmGiveUp" | "joinWaitlist" | "onWaitlist" | "leaveWaitlist" | "seatsOpen" | "full" | "closed" | "when" | "dates" | "where" | "seats" | "googleMeet" | "inviteEvery" | "guidesTitle" | "sessionsTitle" | "materialsOpen" | "materialsLocked" | "items" | "outcomesTitle" | "toolkitTitle" | "timeTitle" | "open" | "read" | "do" | "watch" | "extra" | "failed" | "reserveYourSeat">;
27
+ }
28
+
29
+ /** Copy for the person record panels: lifecycle actions, comms, scheduling, billing and meetings. */
30
+ type AdminRecordsCopy = {
31
+ [Field in AdminRecordsCopyKey]: string;
32
+ };
33
+ /** Every key a host may override under `admin.records`. */
34
+ type AdminRecordsCopyKey = "workflowMissing" | "invitation" | "comms" | "commsHistory" | "scheduling" | "billing" | "notes" | "access" | "sharing" | "lifecycle" | "role" | "superAdminHint" | "noAccount" | "approve" | "decline" | "refund" | "approved" | "declined" | "refunded" | "roleSet" | "messageSent" | "messageNotSent" | "loadingTemplates" | "template" | "chooseTemplate" | "sending" | "send" | "noMessages" | "message" | "newStartPrompt" | "parseFailed" | "cancelConfirm" | "callCancelled" | "callRescheduled" | "noApplication" | "loadingMeetings" | "noMeetings" | "joinMeeting" | "openCalendar" | "reschedule" | "cancel";
35
+
36
+ type TextFields<Key extends string> = {
37
+ [Field in Key]: string;
38
+ };
39
+
40
+ /** Complete serializable language for Chapter surfaces; use render slots for markup and `formatChapterCopy()` for placeholders. */
41
+ interface ChapterCopy {
42
+ common: TextFields<"loading" | "saved" | "unknown">;
43
+ join: {
44
+ /** Prepaid invitation attribution, consent and recoverable error copy. */
45
+ namedSeat?: TextFields<"title" | "from" | "prepaid" | "body" | "consent" | "accept" | "accepting" | "loading" | "unavailable" | "retry" | "failure">;
46
+ form: TextFields<"submit" | "submitting" | "submitFailed" | "unexpectedFailure">;
47
+ booking: TextFields<"unavailable" | "loadFailed" | "slotTaken" | "failed" | "loading" | "book" | "booking"> & {
48
+ title?: string;
49
+ intro?: string;
50
+ /** Shown under the booking button until a date is chosen. */
51
+ pickDate?: string;
52
+ /** Shown under the booking button once a date is chosen, until a time is. */
53
+ pickTime?: string;
54
+ };
55
+ /**
56
+ * `consent` is the affirmative statement a member agrees to before the card
57
+ * form appears, rendered beside the checkbox and beneath the policy text.
58
+ * It is what the member is shown at the moment of consent, so it says they
59
+ * agree rather than merely restating the policy. Set it to an empty string
60
+ * to render the checkbox with the policy as its only label.
61
+ */
62
+ payment: TextFields<"setupFailed" | "preparing" | "pending" | "processing" | "payAndContinue" | "incomplete" | "consent" | "foundingMember" | "foundingDiscount" | "standardRate" | "yourRate">;
63
+ done: TextFields<"label" | "calendarInvite" | "memberArea">;
64
+ accepted: TextFields<"label" | "body">;
65
+ gift: TextFields<"chooseSelf" | "optionsLabel" | "label" | "body" | "save" | "rotate" | "rotateFailed" | "claimTitle" | "claimBody" | "code" | "redeem" | "redeemed" | "redeemFailed">;
66
+ };
67
+ members: {
68
+ loadFailed: string;
69
+ account: TextFields<"signOut" | "adminConsole">;
70
+ provisional: TextFields<"cardLabel" | "applicationNeeded" | "applicationNeededBody" | "apply" | "refunded" | "refundedBody" | "declined" | "declinedBody" | "active" | "renews" | "introductionCall" | "calendarInvite" | "joinCall" | "bookCall" | "bookCallBody" | "chooseTime">;
71
+ full: TextFields<"welcome">;
72
+ gifts: TextFields<"title" | "body" | "noneAvailable" | "paid" | "saveCode" | "purchases" | "noPurchases" | "pending" | "redeemed" | "expired" | "revoked" | "rotate" | "rotated" | "rotateFailed" | "redeemTitle" | "code" | "redeem" | "redeemFailed">;
73
+ reschedule: TextFields<"changeTime" | "unavailable" | "loadFailed" | "slotGone" | "loading" | "noTimes" | "rescheduling" | "keepTime">;
74
+ };
75
+ /** Signed-in member portal: shell, pages, profile. */
76
+ portal: PortalCopy;
77
+ admin: {
78
+ auth: TextFields<"checking" | "notAuthorized" | "accountNotAuthorized" | "thisAccount" | "signOut" | "loading" | "signInNotConfigured" | "missingPublishableKey" | "noWorkspaces" | "signInTagline">;
79
+ shell: TextFields<"adminRole" | "adminConsole" | "adminName" | "navigationLabel">;
80
+ workspaces: TextFields<"dashboard" | "overview" | "billing" | "people" | "admission" | "network" | "portfolio" | "settings" | "calendar" | "email" | "chapters" | "formations" | "dealFlow" | "dashboardViewsLabel" | "settingsViewsLabel" | "collectionsLabel" | "portfolioViewsLabel">;
81
+ dashboard: TextFields<"loading" | "loadFailed" | "upcomingCalls" | "callsNeedAttention" | "noUpcomingCalls" | "drift" | "open" | "meet" | "applications" | "newMembers" | "newMembersUnavailable" | "revenueAdded" | "revenue" | "revenueUnavailable" | "pipeline" | "pipelineLabel" | "thisWeek" | "noChange" | "activeMemberships" | "annualRunRate" | "testMode">;
82
+ billing: TextFields<"loading" | "loadFailed" | "notConfigured" | "active" | "annualized" | "renewingSoon" | "pastDue" | "subscriptions" | "testMode" | "truncated" | "name" | "email" | "application" | "subscription" | "cancelling" | "amount" | "renews">;
83
+ availability: TextFields<"loading" | "loadFailed" | "saved" | "title" | "days" | "startHour" | "endHour" | "slotMinutes" | "minNoticeHours" | "windowDays" | "timezone" | "summaryTemplate" | "save"> & {
84
+ dayLabels: readonly string[];
85
+ };
86
+ email: TextFields<"loading" | "loadFailed" | "saved" | "sent" | "testFailed" | "delivery" | "notificationAddress" | "replyTo" | "fromName" | "fromNameHint" | "spamRisk" | "debugInbox" | "debugInboxHint" | "sendTest" | "enabled" | "subject" | "body" | "htmlBody" | "htmlBodyHint" | "save" | "sendLog" | "sentColumn" | "templateColumn" | "statusColumn" | "toColumn" | "failed" | "redirected" | "delivered">;
87
+ meetings: TextFields<"loading" | "loadFailed" | "cancelConfirm" | "newStartPrompt" | "parseFailed" | "agenda" | "empty" | "unknown" | "drift" | "meet" | "reschedule" | "cancel">;
88
+ admission: TextFields<"title" | "description" | "email" | "decision" | "expires" | "note" | "waive" | "require" | "add" | "ledger" | "loading" | "consumed" | "revoked" | "expired" | "active" | "local" | "parent" | "revoke">;
89
+ network: AdminNetworkCopy;
90
+ records: AdminRecordsCopy;
91
+ };
92
+ }
93
+ type DeepPartial<T> = T extends readonly (infer Item)[] ? readonly Item[] : T extends object ? {
94
+ [Key in keyof T]?: DeepPartial<T[Key]>;
95
+ } : T;
96
+ /** Recursively partial copy overrides accepted by `defineChapter({ copy })`. */
97
+ type ChapterCopyInput = DeepPartial<ChapterCopy>;
98
+
99
+ /** Brand identity and build-time tokens from the checked-in Chapter config. */
100
+ /** Typed semantic roles shared by the public site and application surfaces. */
101
+ interface ChapterBrandTokens {
102
+ background?: string;
103
+ surface?: string;
104
+ surface2?: string;
105
+ text?: string;
106
+ textMuted?: string;
107
+ textFaint?: string;
108
+ border?: string;
109
+ borderStrong?: string;
110
+ accent?: string;
111
+ accentStrong?: string;
112
+ accentSoft?: string;
113
+ onAccent?: string;
114
+ good?: string;
115
+ warn?: string;
116
+ danger?: string;
117
+ chart1?: string;
118
+ chart2?: string;
119
+ chart3?: string;
120
+ chart4?: string;
121
+ chart5?: string;
122
+ chart6?: string;
123
+ chartPositive?: string;
124
+ chartNegative?: string;
125
+ /** Admin/application content width, e.g. `"960px"`. */
126
+ contentWidth?: string;
127
+ panelRadius?: string;
128
+ panelShadow?: string;
129
+ masterDetailColumns?: string;
130
+ masterDetailMinHeight?: string;
131
+ /** Chapter-admin page padding shorthand. */
132
+ pagePadding?: string;
133
+ /** Chapter-admin workspace-tab padding shorthand. */
134
+ workspacePadding?: string;
135
+ }
136
+ /** Brand tokens that theme the site: theme, semantic roles, fonts, and logos. */
137
+ interface ChapterBrand {
138
+ /** Preloaded @odla-ai/ui theme name used by ThemeScope. */
139
+ theme?: string;
140
+ /** Named accent family supplied by the selected @odla-ai/ui theme. */
141
+ accent?: string;
142
+ /** Admin/application color mode. Explicit light is the safe default. */
143
+ colorScheme?: "light" | "dark" | "system";
144
+ tokens?: ChapterBrandTokens;
145
+ tokensDark?: ChapterBrandTokens;
146
+ /** Palette overrides written into styles.css :root (e.g. `{ moss: "#2F3E34" }`
147
+ * or `--ui-*` token names). Applies in BOTH light and dark unless overridden
148
+ * by {@link paletteDark}. */
149
+ palette?: Record<string, string>;
150
+ /** Dark-mode palette overrides. Same shape as {@link palette}; emitted under
151
+ * `:root[data-theme="dark"]` and `@media (prefers-color-scheme: dark)`, so a
152
+ * site brands both modes. */
153
+ paletteDark?: Record<string, string>;
154
+ /** Full token map for `.ui-invert` islands. A compiled custom theme normally
155
+ * uses its dark map here so inverted content never inherits stale composites. */
156
+ paletteInvert?: Record<string, string>;
157
+ fonts?: {
158
+ display?: string;
159
+ body?: string;
160
+ numeral?: string;
161
+ };
162
+ /** Short glyph used in compact admin chrome. Defaults to the first three
163
+ * letters of the chapter name. */
164
+ badge?: string;
165
+ wordmark?: string;
166
+ tagline?: string;
167
+ /** Header/footer nav sections for the web-component chrome: label → entries. */
168
+ nav?: Record<string, ReadonlyArray<{
169
+ label: string;
170
+ href: string;
171
+ }>>;
172
+ logos?: string;
173
+ }
174
+
175
+ /**
176
+ * Member catalog schema version 2: ordered navigation sections, page kinds,
177
+ * navigation tags and icons. Version 1 documents remain valid and keep their
178
+ * alphabetical section order; every field here requires `schemaVersion: 2`.
179
+ */
180
+ /** Packaged member features a catalog page can stand for. */
181
+ declare const MEMBER_PAGE_FEATURES: readonly ["course", "share"];
182
+ /** A packaged member feature: `course` (cohort course) or `share` (invite kit). */
183
+ type MemberPageFeatureName = typeof MEMBER_PAGE_FEATURES[number];
184
+ /** Fixed icon vocabulary. Content never carries SVG, URLs or markup. */
185
+ declare const MEMBER_PAGE_ICONS: readonly ["home", "course", "library", "deals", "training", "events", "members", "share", "profile", "document", "calendar", "chat", "star"];
186
+ /** One icon from {@link MEMBER_PAGE_ICONS}. */
187
+ type MemberPageIcon = typeof MEMBER_PAGE_ICONS[number];
188
+ /** Authored navigation tags. "Soon" and year tags are derived from placeholder pages. */
189
+ declare const MEMBER_PAGE_TAGS: readonly ["new"];
190
+ /** One tag from {@link MEMBER_PAGE_TAGS}. */
191
+ type MemberPageTag = typeof MEMBER_PAGE_TAGS[number];
192
+ /** How a page renders: authored Markdown, a not-yet-open placeholder, or a packaged feature. */
193
+ type MemberPageKind = "markdown" | "placeholder" | "feature";
194
+ /**
195
+ * A page that is announced but not open. Without `availableYear` it reads as
196
+ * "Coming soon"; with one, as "Coming in <year>".
197
+ */
198
+ interface MemberPagePlaceholder {
199
+ /** Calendar year the page is expected to open. */
200
+ availableYear?: number;
201
+ /** Replaces the derived "Coming soon" / "Coming in <year>" badge text. */
202
+ badge?: string;
203
+ /** Label of a disabled call to action, e.g. "Investor form opens in 2027". */
204
+ actionLabel?: string;
205
+ }
206
+ /** A catalog page backed by a packaged feature, gated by the page's audience. */
207
+ interface MemberPageFeature {
208
+ name: MemberPageFeatureName;
209
+ /** Feature-specific identity, e.g. the course id for `course`. */
210
+ ref?: string;
211
+ }
212
+ /**
213
+ * One navigation group. A section without a label renders without a heading.
214
+ * Section order is the order of the document's `sections` array.
215
+ */
216
+ interface MemberContentSection {
217
+ id: string;
218
+ label?: string;
219
+ }
220
+
221
+ /** Every member-content schema version this release validates. */
222
+ type MemberContentSchemaVersion = 1 | 2;
223
+ /** Authority that authored one independently stored member-content layer. */
224
+ type MemberContentSourceType = "parent" | "chapter";
225
+ /** Stable author identity attached to every member-content document and page. */
226
+ interface MemberContentSource {
227
+ type: MemberContentSourceType;
228
+ appId: string;
229
+ }
230
+ /** Chapter deployment that a parent member-content revision is intended for. */
231
+ interface MemberContentTarget {
232
+ chapterId: string;
233
+ environment: string;
234
+ }
235
+ /** Navigation is data, so agents do not have to coordinate route code. */
236
+ interface MemberPageNavigation {
237
+ /** A section id declared in `sections`, or (without `sections`) the section's display label. */
238
+ section: string;
239
+ order: number;
240
+ parentId?: string;
241
+ /** Schema version 2. */
242
+ tag?: MemberPageTag;
243
+ /** Schema version 2. */
244
+ icon?: MemberPageIcon;
245
+ }
246
+ /** Explicit sets avoid unsafe assumptions that commercial tiers form a ladder. */
247
+ type MemberPageAudience = {
248
+ kind: "all-members";
249
+ } | {
250
+ kind: "tiers";
251
+ tierIds: readonly string[];
252
+ };
253
+ /** Authored offer copy. Price and provider identity deliberately do not live here. */
254
+ interface MemberPageUpsellOffer {
255
+ tierId: string;
256
+ label?: string;
257
+ bodyMarkdown?: string;
258
+ ctaLabel?: string;
259
+ }
260
+ /** Parent offer authority is explicit; a Chapter can edit only a delegated offer. */
261
+ type MemberPageUpsell = {
262
+ owner: "parent";
263
+ offer: MemberPageUpsellOffer;
264
+ } | {
265
+ owner: "chapter";
266
+ offer?: MemberPageUpsellOffer;
267
+ };
268
+ /** Authored member page whose body is disclosed only after server-side projection. */
269
+ interface MemberContentPage {
270
+ id: string;
271
+ slug: string;
272
+ title: string;
273
+ summary?: string;
274
+ navigation: MemberPageNavigation;
275
+ audience: MemberPageAudience;
276
+ /** Safe Markdown shown while the body is withheld. */
277
+ teaserMarkdown?: string;
278
+ /** Never serialized to a viewer whose audience does not match. Required for Markdown pages. */
279
+ bodyMarkdown?: string;
280
+ upsell?: MemberPageUpsell;
281
+ /** Schema version 2; defaults to `markdown`. */
282
+ kind?: MemberPageKind;
283
+ /** Schema version 2; present exactly when `kind` is `placeholder`. */
284
+ placeholder?: MemberPagePlaceholder;
285
+ /** Schema version 2; present exactly when `kind` is `feature`. */
286
+ feature?: MemberPageFeature;
287
+ }
288
+ /** Chapter-owned offer attached to a Parent page that delegated offer authority. */
289
+ interface MemberPageUpsellOverride {
290
+ pageId: string;
291
+ offer: MemberPageUpsellOffer;
292
+ }
293
+ /** One complete source layer. Parent and Chapter layers are stored independently. */
294
+ interface MemberContentDocument {
295
+ schemaVersion: MemberContentSchemaVersion;
296
+ revision: number;
297
+ generatedAt: number;
298
+ source: MemberContentSource;
299
+ target?: MemberContentTarget;
300
+ pages: readonly MemberContentPage[];
301
+ upsellOverrides?: readonly MemberPageUpsellOverride[];
302
+ /** Schema version 2: navigation groups in display order. */
303
+ sections?: readonly MemberContentSection[];
304
+ }
305
+ /** Provider-neutral tier facts used to validate access and resolve safe offers. */
306
+ interface MemberContentTierAuthority {
307
+ id: string;
308
+ name?: string;
309
+ priceCents?: number;
310
+ active?: boolean;
311
+ }
312
+ /** Composed member page retaining the identity of its authoring layer. */
313
+ interface EffectiveMemberContentPage extends MemberContentPage {
314
+ source: MemberContentSource;
315
+ }
316
+ /** Deterministically ordered parent and chapter layers with their source revisions. */
317
+ interface EffectiveMemberContent {
318
+ pages: readonly EffectiveMemberContentPage[];
319
+ /** Navigation groups in display order; only groups that have pages. Always set by `composeMemberContent`. */
320
+ sections?: readonly MemberContentSection[];
321
+ parentRevision: number | null;
322
+ chapterRevision: number | null;
323
+ }
324
+ /** Authored upsell joined to active chapter tier name and price authority. */
325
+ interface ResolvedMemberPageUpsell extends MemberPageUpsellOffer {
326
+ tierName: string;
327
+ priceCents: number;
328
+ }
329
+ /** Viewer-safe page result; locked projections never carry bodyMarkdown. */
330
+ interface MemberContentPageProjection {
331
+ id: string;
332
+ slug: string;
333
+ title: string;
334
+ summary?: string;
335
+ navigation: MemberPageNavigation;
336
+ audience: MemberPageAudience;
337
+ source: MemberContentSource;
338
+ access: "allowed" | "locked";
339
+ /** Always sent by the server; a hand-built preview may omit it to mean `markdown`. */
340
+ kind?: MemberPageKind;
341
+ placeholder?: MemberPagePlaceholder;
342
+ feature?: MemberPageFeature;
343
+ teaserMarkdown?: string;
344
+ bodyMarkdown?: string;
345
+ upsell?: ResolvedMemberPageUpsell;
346
+ }
347
+ /** Complete viewer-safe member navigation and revision projection. */
348
+ interface MemberContentProjection {
349
+ pages: readonly MemberContentPageProjection[];
350
+ /** Always sent by the server; a hand-built preview may omit it. */
351
+ sections?: readonly MemberContentSection[];
352
+ viewer: {
353
+ tierId: string | null;
354
+ admin: boolean;
355
+ };
356
+ revisions: {
357
+ parent: number | null;
358
+ chapter: number | null;
359
+ };
360
+ }
361
+
362
+ /** Place a resolved or partial copy contract around any Chapter UI surface. */
363
+ declare function ChapterCopyProvider(props: {
364
+ copy?: ChapterCopy | ChapterCopyInput;
365
+ children: ComponentChildren;
366
+ }): preact.JSX.Element;
367
+ /** Read the nearest complete Chapter copy contract. */
368
+ declare function useChapterCopy(): ChapterCopy;
369
+
370
+ export { ChapterCopyProvider as C, type EffectiveMemberContent as E, type MemberContentDocument as M, type PortalCopy as P, type ChapterBrand as a, type ChapterCopyInput as b, type ChapterCopy as c, type MemberContentTierAuthority as d, type MemberContentProjection as e, type MemberContentPageProjection as f, type MemberPageFeatureName as g, type MemberPageIcon as h, useChapterCopy as u };