@odla-ai/chapter 0.21.0 → 0.22.1
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/README.md +92 -25
- package/dist/{chunk-3JG5X2LT.js → chunk-3QKGKUTX.js} +14 -3
- package/dist/chunk-3QKGKUTX.js.map +1 -0
- package/dist/{chunk-ILGUJXSB.js → chunk-4COPR4SY.js} +11 -11
- package/dist/chunk-4COPR4SY.js.map +1 -0
- package/dist/{chunk-AOTWFOH4.js → chunk-C4XQSRW7.js} +308 -123
- package/dist/chunk-C4XQSRW7.js.map +1 -0
- package/dist/index.cjs +12 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +12 -1
- package/dist/index.js.map +1 -1
- package/dist/{types-CXDiDj_s.d.ts → types-CgWUQ2MH.d.ts} +14 -0
- package/dist/ui/admin/index.d.ts +94 -28
- package/dist/ui/admin/index.js +8 -2
- package/dist/ui/index.d.ts +3 -3
- package/dist/ui/index.js +9 -3
- package/dist/ui/member/index.d.ts +11 -11
- package/dist/ui/member/index.js +2 -2
- package/dist/worker/index.d.cts +14 -0
- package/dist/worker/index.d.ts +14 -0
- package/package.json +11 -11
- package/runbooks/adopt-existing.md +13 -4
- package/runbooks/greenfield.md +13 -14
- package/dist/chunk-3JG5X2LT.js.map +0 -1
- package/dist/chunk-AOTWFOH4.js.map +0 -1
- package/dist/chunk-ILGUJXSB.js.map +0 -1
|
@@ -50,8 +50,22 @@ interface ChapterBrandTokens {
|
|
|
50
50
|
danger?: string;
|
|
51
51
|
chart1?: string;
|
|
52
52
|
chart2?: string;
|
|
53
|
+
chart3?: string;
|
|
54
|
+
chart4?: string;
|
|
55
|
+
chart5?: string;
|
|
56
|
+
chart6?: string;
|
|
53
57
|
chartPositive?: string;
|
|
54
58
|
chartNegative?: string;
|
|
59
|
+
/** Admin/application content width, e.g. `"960px"`. */
|
|
60
|
+
contentWidth?: string;
|
|
61
|
+
panelRadius?: string;
|
|
62
|
+
panelShadow?: string;
|
|
63
|
+
masterDetailColumns?: string;
|
|
64
|
+
masterDetailMinHeight?: string;
|
|
65
|
+
/** Chapter-admin page padding shorthand. */
|
|
66
|
+
pagePadding?: string;
|
|
67
|
+
/** Chapter-admin workspace-tab padding shorthand. */
|
|
68
|
+
workspacePadding?: string;
|
|
55
69
|
}
|
|
56
70
|
/** Brand tokens that theme the site: theme, semantic roles, fonts, and logos. */
|
|
57
71
|
interface ChapterBrand {
|
package/dist/ui/admin/index.d.ts
CHANGED
|
@@ -1,13 +1,42 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import {
|
|
1
|
+
import * as preact from 'preact';
|
|
2
|
+
import { ComponentChildren, JSX } from 'preact';
|
|
3
3
|
import { CrmClient, Crm, CrmRecord } from '@odla-ai/crm';
|
|
4
|
-
import { C as Chapter } from '../../types-
|
|
5
|
-
import {
|
|
4
|
+
import { C as Chapter } from '../../types-CgWUQ2MH.js';
|
|
5
|
+
import { CrmLifecycleAdapter, CrmWorkspaceMasterContext, CrmWorkspaceRecordContext, RecordPanelTab } from '@odla-ai/crm/ui';
|
|
6
|
+
|
|
7
|
+
/** Normalized public auth configuration consumed by the Clerk gate. */
|
|
8
|
+
interface ChapterAdminAuthConfig {
|
|
9
|
+
publishableKey: string | null;
|
|
10
|
+
}
|
|
11
|
+
/** Normalized current-user data retained for workspace visibility decisions. */
|
|
12
|
+
interface ChapterAdminUser extends Record<string, unknown> {
|
|
13
|
+
authorized?: boolean;
|
|
14
|
+
email?: string | null;
|
|
15
|
+
}
|
|
16
|
+
/** Inputs supplied to custom admin configuration and current-user loaders. */
|
|
17
|
+
interface ChapterAdminAuthLoadContext {
|
|
18
|
+
apiBase: string;
|
|
19
|
+
getToken?: () => Promise<string | null>;
|
|
20
|
+
}
|
|
21
|
+
/** Existing-site adapter for auth endpoint names and response shapes. */
|
|
22
|
+
interface ChapterAdminAuthAdapter {
|
|
23
|
+
configPath?: string;
|
|
24
|
+
currentUserPath?: string;
|
|
25
|
+
loadConfig?: (context: ChapterAdminAuthLoadContext) => Promise<ChapterAdminAuthConfig>;
|
|
26
|
+
loadCurrentUser?: (context: Required<ChapterAdminAuthLoadContext>) => Promise<ChapterAdminUser>;
|
|
27
|
+
mapConfig?: (body: Record<string, unknown>) => ChapterAdminAuthConfig;
|
|
28
|
+
mapCurrentUser?: (body: Record<string, unknown>) => ChapterAdminUser;
|
|
29
|
+
isAuthorized?: (user: ChapterAdminUser) => boolean;
|
|
30
|
+
}
|
|
31
|
+
/** Load and normalize the public authentication configuration. */
|
|
32
|
+
declare function loadChapterAdminConfig(adapter: ChapterAdminAuthAdapter, apiBase: string): Promise<ChapterAdminAuthConfig>;
|
|
33
|
+
/** Load and normalize the authenticated user used by admin workspaces. */
|
|
34
|
+
declare function loadChapterAdminUser(adapter: ChapterAdminAuthAdapter, apiBase: string, getToken: () => Promise<string | null>): Promise<ChapterAdminUser>;
|
|
6
35
|
|
|
7
36
|
type Brand = {
|
|
8
37
|
name: string;
|
|
9
38
|
badge?: string;
|
|
10
|
-
wordmark?:
|
|
39
|
+
wordmark?: ComponentChildren;
|
|
11
40
|
};
|
|
12
41
|
|
|
13
42
|
/** Typed URL state for the admin's nested in-page workspaces. */
|
|
@@ -40,6 +69,7 @@ type AdminRouteTarget = string | {
|
|
|
40
69
|
interface AdminSectionContext {
|
|
41
70
|
client: CrmClient;
|
|
42
71
|
getToken: () => Promise<string | null>;
|
|
72
|
+
currentUser?: Record<string, unknown>;
|
|
43
73
|
route: AdminRouteState;
|
|
44
74
|
navigate: (target: AdminRouteTarget) => void;
|
|
45
75
|
href: (target: AdminRouteTarget) => string;
|
|
@@ -48,12 +78,28 @@ interface AdminSectionContext {
|
|
|
48
78
|
interface AdminWorkspace {
|
|
49
79
|
id: string;
|
|
50
80
|
label: string;
|
|
51
|
-
|
|
81
|
+
/** Canonical nested view used when a workspace is opened without one. */
|
|
82
|
+
defaultViewId?: string;
|
|
83
|
+
render: (ctx: AdminSectionContext) => ComponentChildren;
|
|
52
84
|
}
|
|
53
85
|
/** Legacy name for a top-level workspace. @deprecated Use AdminWorkspace. */
|
|
54
86
|
type AdminSection = AdminWorkspace;
|
|
55
|
-
/** Built-in shell presentation
|
|
56
|
-
type AdminChrome = "editorial" | "topbar" | "none";
|
|
87
|
+
/** Built-in shell presentation; embedded preserves site-owned chrome. */
|
|
88
|
+
type AdminChrome = "embedded" | "standalone" | "editorial" | "topbar" | "none";
|
|
89
|
+
/** Identity and sign-out services supplied to host-owned account controls. */
|
|
90
|
+
interface AdminAccountMenuProps {
|
|
91
|
+
brand: Brand;
|
|
92
|
+
email: string | null;
|
|
93
|
+
currentUser?: Record<string, unknown>;
|
|
94
|
+
signOut: () => void;
|
|
95
|
+
}
|
|
96
|
+
/** Workspace route and navigation services supplied to host-owned navigation. */
|
|
97
|
+
interface AdminWorkspaceNavProps {
|
|
98
|
+
workspaces: readonly AdminWorkspace[];
|
|
99
|
+
route: AdminRouteState;
|
|
100
|
+
navigate: (target: AdminRouteTarget) => void;
|
|
101
|
+
href: (target: AdminRouteTarget) => string;
|
|
102
|
+
}
|
|
57
103
|
interface AdminShellProps {
|
|
58
104
|
workspaces: AdminWorkspace[];
|
|
59
105
|
basePath: string;
|
|
@@ -62,13 +108,12 @@ interface AdminShellProps {
|
|
|
62
108
|
getToken: () => Promise<string | null>;
|
|
63
109
|
signOut: () => void;
|
|
64
110
|
email: string | null;
|
|
111
|
+
currentUser?: Record<string, unknown>;
|
|
65
112
|
routing?: AdminRouting;
|
|
66
113
|
chrome?: AdminChrome;
|
|
67
|
-
renderHeader?: (props:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
signOut: () => void;
|
|
71
|
-
}) => ReactNode;
|
|
114
|
+
renderHeader?: (props: AdminAccountMenuProps) => ComponentChildren;
|
|
115
|
+
renderAccountMenu?: (props: AdminAccountMenuProps) => ComponentChildren;
|
|
116
|
+
renderWorkspaceNav?: (props: AdminWorkspaceNavProps) => ComponentChildren;
|
|
72
117
|
}
|
|
73
118
|
|
|
74
119
|
/** Configuration for the Clerk-gated, brand-scoped Chapter admin console. */
|
|
@@ -84,12 +129,16 @@ interface ChapterAdminProps {
|
|
|
84
129
|
apiBase?: string;
|
|
85
130
|
/** Default fragment: `/admin/#people/person/record-id/profile`. */
|
|
86
131
|
routing?: AdminRouting;
|
|
87
|
-
/** Default
|
|
132
|
+
/** Default embedded. Standalone adds packaged global chrome. */
|
|
88
133
|
chrome?: AdminChrome;
|
|
89
134
|
renderHeader?: AdminShellProps["renderHeader"];
|
|
135
|
+
renderAccountMenu?: (props: AdminAccountMenuProps) => ComponentChildren;
|
|
136
|
+
renderWorkspaceNav?: (props: AdminWorkspaceNavProps) => ComponentChildren;
|
|
137
|
+
/** Adapt existing config/current-user endpoints without rewriting auth. */
|
|
138
|
+
auth?: ChapterAdminAuthAdapter;
|
|
90
139
|
}
|
|
91
140
|
/** Render the complete authenticated admin application from one Chapter config. */
|
|
92
|
-
declare function ChapterAdmin(props: ChapterAdminProps):
|
|
141
|
+
declare function ChapterAdmin(props: ChapterAdminProps): preact.JSX.Element;
|
|
93
142
|
|
|
94
143
|
/** Default follower grammar: three workspaces with nested operational views. */
|
|
95
144
|
declare function defaultAdminWorkspaces(chapter: Chapter): AdminWorkspace[];
|
|
@@ -97,6 +146,9 @@ declare function defaultAdminWorkspaces(chapter: Chapter): AdminWorkspace[];
|
|
|
97
146
|
/** Legacy default catalog. @deprecated Use defaultAdminWorkspaces. */
|
|
98
147
|
declare function defaultAdminSections(chapter: Chapter): AdminSection[];
|
|
99
148
|
|
|
149
|
+
/** Application-authoritative stage transitions used by Chapter collections. */
|
|
150
|
+
declare function applicationLifecycleAdapter(ctx: Pick<AdminSectionContext, "getToken">): CrmLifecycleAdapter;
|
|
151
|
+
|
|
100
152
|
/** Configuration for the person-collection compatibility preset. */
|
|
101
153
|
interface PeopleSectionOptions {
|
|
102
154
|
crm: Crm;
|
|
@@ -113,6 +165,13 @@ interface CollectionSectionOptions {
|
|
|
113
165
|
lifecycle?: boolean;
|
|
114
166
|
roles?: readonly string[];
|
|
115
167
|
networkSharing?: boolean;
|
|
168
|
+
lifecycleAdapter?: (CrmLifecycleAdapter | ((ctx: AdminSectionContext) => CrmLifecycleAdapter));
|
|
169
|
+
requireLifecycleAdapter?: boolean;
|
|
170
|
+
renderSummary?: (context: CrmWorkspaceMasterContext, ctx: AdminSectionContext) => ComponentChildren;
|
|
171
|
+
renderMaster?: (context: CrmWorkspaceMasterContext, ctx: AdminSectionContext) => ComponentChildren;
|
|
172
|
+
renderDetailHeader?: (context: CrmWorkspaceRecordContext, ctx: AdminSectionContext) => ComponentChildren;
|
|
173
|
+
renderEmptyDetail?: (context: CrmWorkspaceMasterContext, ctx: AdminSectionContext) => ComponentChildren;
|
|
174
|
+
hrefForRecord?: (record: CrmRecord, ctx: AdminSectionContext) => string;
|
|
116
175
|
extendRecordTabs?: (tabs: readonly RecordPanelTab[], context: CrmWorkspaceRecordContext) => readonly RecordPanelTab[];
|
|
117
176
|
}
|
|
118
177
|
/** Build one CRM collection as an admin workspace. */
|
|
@@ -121,6 +180,13 @@ declare function collectionSection(options: CollectionSectionOptions): AdminSect
|
|
|
121
180
|
declare function peopleSection(options: PeopleSectionOptions & {
|
|
122
181
|
roles?: readonly string[];
|
|
123
182
|
networkSharing?: boolean;
|
|
183
|
+
lifecycleAdapter?: CollectionSectionOptions["lifecycleAdapter"];
|
|
184
|
+
requireLifecycleAdapter?: boolean;
|
|
185
|
+
renderSummary?: CollectionSectionOptions["renderSummary"];
|
|
186
|
+
renderMaster?: CollectionSectionOptions["renderMaster"];
|
|
187
|
+
renderDetailHeader?: CollectionSectionOptions["renderDetailHeader"];
|
|
188
|
+
renderEmptyDetail?: CollectionSectionOptions["renderEmptyDetail"];
|
|
189
|
+
hrefForRecord?: CollectionSectionOptions["hrefForRecord"];
|
|
124
190
|
extendRecordTabs?: CollectionSectionOptions["extendRecordTabs"];
|
|
125
191
|
}): AdminSection;
|
|
126
192
|
|
|
@@ -179,7 +245,7 @@ interface RecordActionsProps {
|
|
|
179
245
|
}
|
|
180
246
|
/** The role/approve/refund controls for one person record. Renders only the
|
|
181
247
|
* actions the record supports. */
|
|
182
|
-
declare function RecordActions({ getToken, record, roles, onChanged }: RecordActionsProps):
|
|
248
|
+
declare function RecordActions({ getToken, record, roles, onChanged }: RecordActionsProps): preact.JSX.Element | null;
|
|
183
249
|
|
|
184
250
|
/** Props for {@link NetworkShareActions}. */
|
|
185
251
|
interface NetworkShareActionsProps {
|
|
@@ -189,7 +255,7 @@ interface NetworkShareActionsProps {
|
|
|
189
255
|
}
|
|
190
256
|
/** Render follower delivery buttons when this chapter configured network
|
|
191
257
|
* targets. Targets with an explicit type allowlist hide incompatible records. */
|
|
192
|
-
declare function NetworkShareActions(props: NetworkShareActionsProps):
|
|
258
|
+
declare function NetworkShareActions(props: NetworkShareActionsProps): preact.JSX.Element | null;
|
|
193
259
|
|
|
194
260
|
/** Fetch a JSON `/api/admin/*` route with the admin bearer token. Throws on a
|
|
195
261
|
* non-2xx (the body's `error`, else the status). */
|
|
@@ -202,25 +268,25 @@ interface AdminResource<T> {
|
|
|
202
268
|
/** Re-fetch (e.g. after a mutation). */
|
|
203
269
|
refresh: () => void;
|
|
204
270
|
}
|
|
205
|
-
/** Load a `/api/admin/*` GET route into
|
|
271
|
+
/** Load a `/api/admin/*` GET route into Preact state, re-fetching on `refresh()`
|
|
206
272
|
* or when `path` changes. */
|
|
207
273
|
declare function useAdminResource<T = unknown>(getToken: () => Promise<string | null>, path: string): AdminResource<T>;
|
|
208
274
|
|
|
209
275
|
/** The centered content column every admin section renders into. */
|
|
210
276
|
declare function AdminPage({ children }: {
|
|
211
|
-
children:
|
|
212
|
-
}):
|
|
277
|
+
children: ComponentChildren;
|
|
278
|
+
}): JSX.Element;
|
|
213
279
|
/** An odla-ui `.panel` card with an optional heading + trailing actions. */
|
|
214
280
|
declare function Panel({ title, actions, children }: {
|
|
215
|
-
title?:
|
|
216
|
-
actions?:
|
|
217
|
-
children:
|
|
218
|
-
}):
|
|
281
|
+
title?: ComponentChildren;
|
|
282
|
+
actions?: ComponentChildren;
|
|
283
|
+
children: ComponentChildren;
|
|
284
|
+
}): JSX.Element;
|
|
219
285
|
/** A loud banner when the odla-ui theme token layer is missing. */
|
|
220
|
-
declare function ThemeWarning():
|
|
286
|
+
declare function ThemeWarning(): JSX.Element | null;
|
|
221
287
|
/** A centered status line for loading / empty / error states. */
|
|
222
288
|
declare function AdminNote({ children }: {
|
|
223
|
-
children:
|
|
224
|
-
}):
|
|
289
|
+
children: ComponentChildren;
|
|
290
|
+
}): JSX.Element;
|
|
225
291
|
|
|
226
|
-
export { type AdminChrome, AdminNote, AdminPage, type AdminResource, type AdminRouteState, type AdminRouteTarget, type AdminRouting, type AdminSection, type AdminSectionContext, type AdminWorkspace, type AvailabilitySectionOptions, type BillingSectionOptions, ChapterAdmin, type ChapterAdminProps, type CollectionSectionOptions, type DashboardSectionOptions, type EmailSectionOptions, type MeetingsSectionOptions, NetworkShareActions, type NetworkShareActionsProps, Panel, type PeopleSectionOptions, RecordActions, type RecordActionsProps, ThemeWarning, adminFetch, adminRouteFromUrl, adminRouteHref, adminSectionFromUrl, adminSectionHref, availabilitySection, billingSection, collectionSection, dashboardSection, defaultAdminSections, defaultAdminWorkspaces, emailSection, meetingsSection, peopleSection, useAdminResource };
|
|
292
|
+
export { type AdminAccountMenuProps, type AdminChrome, AdminNote, AdminPage, type AdminResource, type AdminRouteState, type AdminRouteTarget, type AdminRouting, type AdminSection, type AdminSectionContext, type AdminWorkspace, type AdminWorkspaceNavProps, type AvailabilitySectionOptions, type BillingSectionOptions, ChapterAdmin, type ChapterAdminAuthAdapter, type ChapterAdminAuthConfig, type ChapterAdminAuthLoadContext, type ChapterAdminProps, type ChapterAdminUser, type CollectionSectionOptions, type DashboardSectionOptions, type EmailSectionOptions, type MeetingsSectionOptions, NetworkShareActions, type NetworkShareActionsProps, Panel, type PeopleSectionOptions, RecordActions, type RecordActionsProps, ThemeWarning, adminFetch, adminRouteFromUrl, adminRouteHref, adminSectionFromUrl, adminSectionHref, applicationLifecycleAdapter, availabilitySection, billingSection, collectionSection, dashboardSection, defaultAdminSections, defaultAdminWorkspaces, emailSection, loadChapterAdminConfig, loadChapterAdminUser, meetingsSection, peopleSection, useAdminResource };
|
package/dist/ui/admin/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
adminRouteHref,
|
|
12
12
|
adminSectionFromUrl,
|
|
13
13
|
adminSectionHref,
|
|
14
|
+
applicationLifecycleAdapter,
|
|
14
15
|
availabilitySection,
|
|
15
16
|
billingSection,
|
|
16
17
|
collectionSection,
|
|
@@ -18,11 +19,13 @@ import {
|
|
|
18
19
|
defaultAdminSections,
|
|
19
20
|
defaultAdminWorkspaces,
|
|
20
21
|
emailSection,
|
|
22
|
+
loadChapterAdminConfig,
|
|
23
|
+
loadChapterAdminUser,
|
|
21
24
|
meetingsSection,
|
|
22
25
|
peopleSection,
|
|
23
26
|
useAdminResource
|
|
24
|
-
} from "../../chunk-
|
|
25
|
-
import "../../chunk-
|
|
27
|
+
} from "../../chunk-C4XQSRW7.js";
|
|
28
|
+
import "../../chunk-3QKGKUTX.js";
|
|
26
29
|
export {
|
|
27
30
|
AdminNote,
|
|
28
31
|
AdminPage,
|
|
@@ -36,6 +39,7 @@ export {
|
|
|
36
39
|
adminRouteHref,
|
|
37
40
|
adminSectionFromUrl,
|
|
38
41
|
adminSectionHref,
|
|
42
|
+
applicationLifecycleAdapter,
|
|
39
43
|
availabilitySection,
|
|
40
44
|
billingSection,
|
|
41
45
|
collectionSection,
|
|
@@ -43,6 +47,8 @@ export {
|
|
|
43
47
|
defaultAdminSections,
|
|
44
48
|
defaultAdminWorkspaces,
|
|
45
49
|
emailSection,
|
|
50
|
+
loadChapterAdminConfig,
|
|
51
|
+
loadChapterAdminUser,
|
|
46
52
|
meetingsSection,
|
|
47
53
|
peopleSection,
|
|
48
54
|
useAdminResource
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { AdminChrome, AdminNote, AdminPage, AdminResource, AdminRouteState, AdminRouteTarget, AdminRouting, AdminSection, AdminSectionContext, AdminWorkspace, AvailabilitySectionOptions, BillingSectionOptions, ChapterAdmin, ChapterAdminProps, CollectionSectionOptions, DashboardSectionOptions, EmailSectionOptions, MeetingsSectionOptions, NetworkShareActions, NetworkShareActionsProps, Panel, PeopleSectionOptions, RecordActions, RecordActionsProps, ThemeWarning, adminFetch, adminRouteFromUrl, adminRouteHref, adminSectionFromUrl, adminSectionHref, availabilitySection, billingSection, collectionSection, dashboardSection, defaultAdminSections, defaultAdminWorkspaces, emailSection, meetingsSection, peopleSection, useAdminResource } from './admin/index.js';
|
|
1
|
+
export { AdminAccountMenuProps, AdminChrome, AdminNote, AdminPage, AdminResource, AdminRouteState, AdminRouteTarget, AdminRouting, AdminSection, AdminSectionContext, AdminWorkspace, AdminWorkspaceNavProps, AvailabilitySectionOptions, BillingSectionOptions, ChapterAdmin, ChapterAdminAuthAdapter, ChapterAdminAuthConfig, ChapterAdminAuthLoadContext, ChapterAdminProps, ChapterAdminUser, CollectionSectionOptions, DashboardSectionOptions, EmailSectionOptions, MeetingsSectionOptions, NetworkShareActions, NetworkShareActionsProps, Panel, PeopleSectionOptions, RecordActions, RecordActionsProps, ThemeWarning, adminFetch, adminRouteFromUrl, adminRouteHref, adminSectionFromUrl, adminSectionHref, applicationLifecycleAdapter, availabilitySection, billingSection, collectionSection, dashboardSection, defaultAdminSections, defaultAdminWorkspaces, emailSection, loadChapterAdminConfig, loadChapterAdminUser, meetingsSection, peopleSection, useAdminResource } from './admin/index.js';
|
|
2
2
|
export { ApiFn, BrandStyle, BrandStyleProps, JoinConfig, JoinIsland, JoinIslandProps, MembersArea, MembersAreaProps, PaymentStep, PaymentStepProps, RescheduleProps, Rescheduler, Slot, SlotPicker, SlotPickerClasses, SlotPickerProps, dayKey, dayLabel, fmtDate, fmtMoney, fullLabel, groupSlotsByDay, timeLabel, tzShort } from './member/index.js';
|
|
3
|
-
import '
|
|
3
|
+
import 'preact';
|
|
4
4
|
import '@odla-ai/crm';
|
|
5
|
-
import '../types-
|
|
5
|
+
import '../types-CgWUQ2MH.js';
|
|
6
6
|
import '@odla-ai/crm/ui';
|
package/dist/ui/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
groupSlotsByDay,
|
|
13
13
|
timeLabel,
|
|
14
14
|
tzShort
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-4COPR4SY.js";
|
|
16
16
|
import {
|
|
17
17
|
AdminNote,
|
|
18
18
|
AdminPage,
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
adminRouteHref,
|
|
27
27
|
adminSectionFromUrl,
|
|
28
28
|
adminSectionHref,
|
|
29
|
+
applicationLifecycleAdapter,
|
|
29
30
|
availabilitySection,
|
|
30
31
|
billingSection,
|
|
31
32
|
collectionSection,
|
|
@@ -33,13 +34,15 @@ import {
|
|
|
33
34
|
defaultAdminSections,
|
|
34
35
|
defaultAdminWorkspaces,
|
|
35
36
|
emailSection,
|
|
37
|
+
loadChapterAdminConfig,
|
|
38
|
+
loadChapterAdminUser,
|
|
36
39
|
meetingsSection,
|
|
37
40
|
peopleSection,
|
|
38
41
|
useAdminResource
|
|
39
|
-
} from "../chunk-
|
|
42
|
+
} from "../chunk-C4XQSRW7.js";
|
|
40
43
|
import {
|
|
41
44
|
BrandStyle
|
|
42
|
-
} from "../chunk-
|
|
45
|
+
} from "../chunk-3QKGKUTX.js";
|
|
43
46
|
export {
|
|
44
47
|
AdminNote,
|
|
45
48
|
AdminPage,
|
|
@@ -59,6 +62,7 @@ export {
|
|
|
59
62
|
adminRouteHref,
|
|
60
63
|
adminSectionFromUrl,
|
|
61
64
|
adminSectionHref,
|
|
65
|
+
applicationLifecycleAdapter,
|
|
62
66
|
availabilitySection,
|
|
63
67
|
billingSection,
|
|
64
68
|
collectionSection,
|
|
@@ -72,6 +76,8 @@ export {
|
|
|
72
76
|
fmtMoney,
|
|
73
77
|
fullLabel,
|
|
74
78
|
groupSlotsByDay,
|
|
79
|
+
loadChapterAdminConfig,
|
|
80
|
+
loadChapterAdminUser,
|
|
75
81
|
meetingsSection,
|
|
76
82
|
peopleSection,
|
|
77
83
|
timeLabel,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import {
|
|
3
|
-
import { a as ChapterBrand } from '../../types-
|
|
1
|
+
import * as preact from 'preact';
|
|
2
|
+
import { ComponentChildren, JSX } from 'preact';
|
|
3
|
+
import { a as ChapterBrand } from '../../types-CgWUQ2MH.js';
|
|
4
4
|
import '@odla-ai/crm';
|
|
5
5
|
|
|
6
6
|
/** A bookable slot: a start instant in epoch milliseconds. */
|
|
@@ -54,7 +54,7 @@ interface SlotPickerProps<T extends Slot = Slot> {
|
|
|
54
54
|
/** A day-chips + time-grid slot picker. Presentational and `onPick`-driven: it
|
|
55
55
|
* owns only the active-day selection; the caller owns slot data, the chosen
|
|
56
56
|
* slot, and booking. Shared by the join booking step and the member reschedule. */
|
|
57
|
-
declare function SlotPicker<T extends Slot = Slot>(props: SlotPickerProps<T>):
|
|
57
|
+
declare function SlotPicker<T extends Slot = Slot>(props: SlotPickerProps<T>): preact.JSX.Element;
|
|
58
58
|
|
|
59
59
|
/** Issue an authenticated request and parse the JSON response. Throws on a
|
|
60
60
|
* non-2xx status (the islands catch and surface a friendly message). */
|
|
@@ -70,11 +70,11 @@ interface MembersAreaProps {
|
|
|
70
70
|
/** Where an accountless member goes to apply. Default "/join.html". */
|
|
71
71
|
applyHref?: string;
|
|
72
72
|
/** What a full (non-provisional) member sees below the account header. */
|
|
73
|
-
memberContent?:
|
|
73
|
+
memberContent?: ComponentChildren;
|
|
74
74
|
}
|
|
75
75
|
/** The signed-in member area. Loads /api/me on mount and renders the account
|
|
76
76
|
* header plus the provisional application card or the full-member content. */
|
|
77
|
-
declare function MembersArea(props: MembersAreaProps):
|
|
77
|
+
declare function MembersArea(props: MembersAreaProps): preact.JSX.Element;
|
|
78
78
|
|
|
79
79
|
/** Props for {@link Rescheduler}. */
|
|
80
80
|
interface RescheduleProps {
|
|
@@ -88,7 +88,7 @@ interface RescheduleProps {
|
|
|
88
88
|
}
|
|
89
89
|
/** A collapsed "change your time" link that expands into a {@link SlotPicker} and
|
|
90
90
|
* rebooks on pick. Degrades to a message when scheduling is unavailable. */
|
|
91
|
-
declare function Rescheduler(props: RescheduleProps):
|
|
91
|
+
declare function Rescheduler(props: RescheduleProps): preact.JSX.Element;
|
|
92
92
|
|
|
93
93
|
/** The public join config (the shape `GET /api/join-config` returns). */
|
|
94
94
|
interface JoinConfig {
|
|
@@ -102,13 +102,13 @@ interface JoinIslandProps {
|
|
|
102
102
|
config: JoinConfig;
|
|
103
103
|
/** The site's application form fields — inputs with `name` attributes; their
|
|
104
104
|
* values are collected via FormData and posted to /api/applications. */
|
|
105
|
-
children:
|
|
105
|
+
children: ComponentChildren;
|
|
106
106
|
/** Where the confirmation links after booking. Default "/members/". */
|
|
107
107
|
membersHref?: string;
|
|
108
108
|
}
|
|
109
109
|
/** The signup island. Renders the site's form, then drives payment (when the
|
|
110
110
|
* chapter charges) and booking (when a calendar is connected) to confirmation. */
|
|
111
|
-
declare function JoinIsland(props: JoinIslandProps):
|
|
111
|
+
declare function JoinIsland(props: JoinIslandProps): JSX.Element;
|
|
112
112
|
|
|
113
113
|
/** Props for {@link PaymentStep}. */
|
|
114
114
|
interface PaymentStepProps {
|
|
@@ -121,7 +121,7 @@ interface PaymentStepProps {
|
|
|
121
121
|
}
|
|
122
122
|
/** The card-entry step: acknowledge the refund policy → create the subscription
|
|
123
123
|
* → mount Stripe Elements → confirm. */
|
|
124
|
-
declare function PaymentStep(props: PaymentStepProps):
|
|
124
|
+
declare function PaymentStep(props: PaymentStepProps): preact.JSX.Element;
|
|
125
125
|
|
|
126
126
|
/** Props for {@link BrandStyle}. */
|
|
127
127
|
interface BrandStyleProps {
|
|
@@ -131,6 +131,6 @@ interface BrandStyleProps {
|
|
|
131
131
|
}
|
|
132
132
|
/** Render a chapter's brand tokens as an inline <style> block (or nothing when
|
|
133
133
|
* there is no brand to theme). */
|
|
134
|
-
declare function BrandStyle(props: BrandStyleProps):
|
|
134
|
+
declare function BrandStyle(props: BrandStyleProps): preact.JSX.Element | null;
|
|
135
135
|
|
|
136
136
|
export { type ApiFn, BrandStyle, type BrandStyleProps, type JoinConfig, JoinIsland, type JoinIslandProps, MembersArea, type MembersAreaProps, PaymentStep, type PaymentStepProps, type RescheduleProps, Rescheduler, type Slot, SlotPicker, type SlotPickerClasses, type SlotPickerProps, dayKey, dayLabel, fmtDate, fmtMoney, fullLabel, groupSlotsByDay, timeLabel, tzShort };
|
package/dist/ui/member/index.js
CHANGED
|
@@ -12,10 +12,10 @@ import {
|
|
|
12
12
|
groupSlotsByDay,
|
|
13
13
|
timeLabel,
|
|
14
14
|
tzShort
|
|
15
|
-
} from "../../chunk-
|
|
15
|
+
} from "../../chunk-4COPR4SY.js";
|
|
16
16
|
import {
|
|
17
17
|
BrandStyle
|
|
18
|
-
} from "../../chunk-
|
|
18
|
+
} from "../../chunk-3QKGKUTX.js";
|
|
19
19
|
export {
|
|
20
20
|
BrandStyle,
|
|
21
21
|
JoinIsland,
|
package/dist/worker/index.d.cts
CHANGED
|
@@ -51,8 +51,22 @@ interface ChapterBrandTokens {
|
|
|
51
51
|
danger?: string;
|
|
52
52
|
chart1?: string;
|
|
53
53
|
chart2?: string;
|
|
54
|
+
chart3?: string;
|
|
55
|
+
chart4?: string;
|
|
56
|
+
chart5?: string;
|
|
57
|
+
chart6?: string;
|
|
54
58
|
chartPositive?: string;
|
|
55
59
|
chartNegative?: string;
|
|
60
|
+
/** Admin/application content width, e.g. `"960px"`. */
|
|
61
|
+
contentWidth?: string;
|
|
62
|
+
panelRadius?: string;
|
|
63
|
+
panelShadow?: string;
|
|
64
|
+
masterDetailColumns?: string;
|
|
65
|
+
masterDetailMinHeight?: string;
|
|
66
|
+
/** Chapter-admin page padding shorthand. */
|
|
67
|
+
pagePadding?: string;
|
|
68
|
+
/** Chapter-admin workspace-tab padding shorthand. */
|
|
69
|
+
workspacePadding?: string;
|
|
56
70
|
}
|
|
57
71
|
/** Brand tokens that theme the site: theme, semantic roles, fonts, and logos. */
|
|
58
72
|
interface ChapterBrand {
|
package/dist/worker/index.d.ts
CHANGED
|
@@ -51,8 +51,22 @@ interface ChapterBrandTokens {
|
|
|
51
51
|
danger?: string;
|
|
52
52
|
chart1?: string;
|
|
53
53
|
chart2?: string;
|
|
54
|
+
chart3?: string;
|
|
55
|
+
chart4?: string;
|
|
56
|
+
chart5?: string;
|
|
57
|
+
chart6?: string;
|
|
54
58
|
chartPositive?: string;
|
|
55
59
|
chartNegative?: string;
|
|
60
|
+
/** Admin/application content width, e.g. `"960px"`. */
|
|
61
|
+
contentWidth?: string;
|
|
62
|
+
panelRadius?: string;
|
|
63
|
+
panelShadow?: string;
|
|
64
|
+
masterDetailColumns?: string;
|
|
65
|
+
masterDetailMinHeight?: string;
|
|
66
|
+
/** Chapter-admin page padding shorthand. */
|
|
67
|
+
pagePadding?: string;
|
|
68
|
+
/** Chapter-admin workspace-tab padding shorthand. */
|
|
69
|
+
workspacePadding?: string;
|
|
56
70
|
}
|
|
57
71
|
/** Brand tokens that theme the site: theme, semantic roles, fonts, and logos. */
|
|
58
72
|
interface ChapterBrand {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@odla-ai/chapter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.1",
|
|
4
4
|
"description": "A leader/follower foundation for branded membership sites: shared CRM, admin, auth, payments, booking, and explicit record delivery from one defineChapter config.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://odla.ai/docs/packages/chapter",
|
|
@@ -70,16 +70,20 @@
|
|
|
70
70
|
"prepublishOnly": "npm run build && npm test"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@odla-ai/crm": "^0.
|
|
73
|
+
"@odla-ai/crm": "^0.3.1",
|
|
74
74
|
"jose": "^6.2.3"
|
|
75
75
|
},
|
|
76
76
|
"peerDependencies": {
|
|
77
|
+
"@odla-ai/auth-clerk": ">=0.4.1 <1.0.0",
|
|
77
78
|
"@odla-ai/calendar": ">=0.2.0 <1.0.0",
|
|
78
|
-
"@odla-ai/db": ">=0.6.
|
|
79
|
-
"@odla-ai/ui": ">=0.
|
|
80
|
-
"
|
|
79
|
+
"@odla-ai/db": ">=0.6.7 <1.0.0",
|
|
80
|
+
"@odla-ai/ui": ">=0.12.1 <1.0.0",
|
|
81
|
+
"preact": ">=10.29.7 <11"
|
|
81
82
|
},
|
|
82
83
|
"peerDependenciesMeta": {
|
|
84
|
+
"@odla-ai/auth-clerk": {
|
|
85
|
+
"optional": true
|
|
86
|
+
},
|
|
83
87
|
"@odla-ai/calendar": {
|
|
84
88
|
"optional": true
|
|
85
89
|
},
|
|
@@ -88,9 +92,6 @@
|
|
|
88
92
|
},
|
|
89
93
|
"@odla-ai/ui": {
|
|
90
94
|
"optional": true
|
|
91
|
-
},
|
|
92
|
-
"react": {
|
|
93
|
-
"optional": true
|
|
94
95
|
}
|
|
95
96
|
},
|
|
96
97
|
"devDependencies": {
|
|
@@ -99,10 +100,9 @@
|
|
|
99
100
|
"@odla-ai/db": "*",
|
|
100
101
|
"@odla-ai/ui": "*",
|
|
101
102
|
"@types/node": "^26.1.0",
|
|
102
|
-
"@types/react": "^19.2.7",
|
|
103
103
|
"@vitest/coverage-v8": "^4.1.9",
|
|
104
|
-
"
|
|
105
|
-
"
|
|
104
|
+
"preact": "10.29.7",
|
|
105
|
+
"preact-render-to-string": "6.7.0",
|
|
106
106
|
"tsup": "^8.3.0",
|
|
107
107
|
"typescript": "^6.0.3",
|
|
108
108
|
"vitest": "^4.1.9"
|
|
@@ -118,7 +118,7 @@ npx @odla-ai/cli@0.17.1 capabilities --json
|
|
|
118
118
|
|
|
119
119
|
Pin the exact known-good package matrix from the installed Chapter README.
|
|
120
120
|
For this runbook, first require
|
|
121
|
-
`npm view @odla-ai/chapter@0.
|
|
121
|
+
`npm view @odla-ai/chapter@0.22.0 version` to succeed. Install every runtime,
|
|
122
122
|
toolchain, CLI, and security package with the exact versions in that README;
|
|
123
123
|
never use `latest`, a range, or `--legacy-peer-deps`.
|
|
124
124
|
|
|
@@ -356,9 +356,18 @@ fixture. Compare markup/behavior and the Phase 0 screenshots before deletion.
|
|
|
356
356
|
- Replace join orchestration with `JoinIsland`, member behavior with
|
|
357
357
|
`MembersArea`, and admin with `<ChapterAdmin chapter={chapter}/>` only after
|
|
358
358
|
field/auth/action parity.
|
|
359
|
-
- Preserve the site's global header with `chrome="
|
|
360
|
-
|
|
361
|
-
|
|
359
|
+
- Preserve the site's global header with the default `chrome="embedded"`;
|
|
360
|
+
use `chrome="standalone"` only when Chapter should supply the masthead, or
|
|
361
|
+
`renderHeader` when the header belongs inside the Chapter scope. Chapter mode
|
|
362
|
+
defaults to Dashboard, People, and Settings; move former global Billing,
|
|
363
|
+
Calendar, Email, and per-record operations into nested tabs.
|
|
364
|
+
- Preserve a distinctive People summary, rail, and record heading with
|
|
365
|
+
`collectionSection`'s `renderSummary`, `renderMaster`, and
|
|
366
|
+
`renderDetailHeader` slots. Replace specialized record tabs rather than
|
|
367
|
+
flattening them into global navigation.
|
|
368
|
+
- Application-backed pipeline changes must use a lifecycle adapter that invokes
|
|
369
|
+
the authoritative application endpoints. Prove approve/refund/manual
|
|
370
|
+
transition side effects; a raw CRM `setStage` is not parity.
|
|
362
371
|
- Accept old query/path admin links as inbound compatibility URLs, but generate
|
|
363
372
|
canonical fragment links such as
|
|
364
373
|
`/admin/#people/person/record-id/profile`. Prove refresh, back/forward, and
|
package/runbooks/greenfield.md
CHANGED
|
@@ -18,12 +18,12 @@ Chapter supplies:
|
|
|
18
18
|
- the validated `defineChapter()` engine and generated schema/rules/seed;
|
|
19
19
|
- the Cloudflare Worker API through `chapterWorker()`;
|
|
20
20
|
- the join, payment, booking, member, admin, CRM, and network behavior;
|
|
21
|
-
- member-facing
|
|
21
|
+
- member-facing Preact components and the complete Clerk-gated admin console;
|
|
22
22
|
- the provisioning descriptor consumed by `@odla-ai/cli`.
|
|
23
23
|
|
|
24
24
|
Chapter does **not** generate a website. The host still owns:
|
|
25
25
|
|
|
26
|
-
- `package.json`, Vite/
|
|
26
|
+
- `package.json`, Vite/Preact, HTML entries, routing, and CSS;
|
|
27
27
|
- public pages, navigation, copy, imagery, SEO, legal text, and the join form;
|
|
28
28
|
- the member auth wrapper that gives `MembersArea` an authenticated `api`;
|
|
29
29
|
- Wrangler configuration, observability wrapping, provider setup, and tests.
|
|
@@ -115,31 +115,30 @@ npm init -y
|
|
|
115
115
|
npx @odla-ai/cli@0.17.1 setup
|
|
116
116
|
```
|
|
117
117
|
|
|
118
|
-
Verify every release target exists, then install the exact known-good
|
|
118
|
+
Verify every release target exists, then install the exact known-good Preact
|
|
119
119
|
host matrix. Do not copy these commands into a pre-release branch where
|
|
120
|
-
`@odla-ai/chapter@0.
|
|
120
|
+
`@odla-ai/chapter@0.22.1` is not yet on npm.
|
|
121
121
|
|
|
122
122
|
```sh
|
|
123
|
-
npm view @odla-ai/chapter@0.
|
|
123
|
+
npm view @odla-ai/chapter@0.22.1 version
|
|
124
124
|
npm install --save-exact \
|
|
125
|
-
@odla-ai/chapter@0.
|
|
126
|
-
@odla-ai/crm@0.
|
|
125
|
+
@odla-ai/chapter@0.22.1 @odla-ai/ui@0.12.1 \
|
|
126
|
+
@odla-ai/crm@0.3.1 @odla-ai/db@0.6.7 \
|
|
127
127
|
@odla-ai/calendar@0.2.0 @odla-ai/email@0.3.1 \
|
|
128
|
-
@odla-ai/auth-clerk@0.4.
|
|
129
|
-
jose@6.2.3
|
|
128
|
+
@odla-ai/auth-clerk@0.4.1 @odla-ai/o11y@2.2.2 \
|
|
129
|
+
jose@6.2.3 preact@10.29.7
|
|
130
130
|
npm install --save-dev --save-exact \
|
|
131
131
|
@odla-ai/cli@0.17.1 @odla-ai/security@0.3.1 \
|
|
132
132
|
@cloudflare/workers-types@4.20260702.1 \
|
|
133
|
-
@
|
|
134
|
-
@vitejs/plugin-react@6.0.3 typescript@6.0.3 \
|
|
133
|
+
typescript@6.0.3 \
|
|
135
134
|
vite@8.1.4 vitest@4.1.10 wrangler@4.107.0
|
|
136
135
|
npx odla-ai capabilities --json
|
|
137
136
|
```
|
|
138
137
|
|
|
139
138
|
The parent `README.md` repeats this version matrix. This runbook standardizes on
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
Preact. Install auth-clerk explicitly when adopting the admin entry; it is an
|
|
140
|
+
optional Chapter peer because worker-only and member-only consumers do not need
|
|
141
|
+
it.
|
|
143
142
|
|
|
144
143
|
Required host scripts:
|
|
145
144
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/brand.ts","../src/ui/brand-style.tsx"],"sourcesContent":["// Brand tokens (H4). defineChapter accepts a `brand` block; this turns it into a\n// `:root { --…: … }` CSS block, so a chapter re-skins the WHOLE UI — the\n// @odla-ai/ui components, the admin shell, and the member islands, which all read\n// --ui-* design tokens — from one config instead of hand-writing inline CSS.\n//\n// Pure string generation, so it is unit-testable and can be emitted at\n// build/SSR time into the page <head> (no flash of unstyled content), or via the\n// <BrandStyle> component from @odla-ai/chapter/ui.\nimport type { ChapterBrand, ChapterBrandTokens } from \"./types\";\n\n// A palette entry is either a direct custom property (already `--…`, e.g.\n// `--ui-accent` to retheme components) or a bare name we expose as `--<name>`\n// (e.g. `moss` → `--moss`, for a site to reference in its own CSS).\nfunction paletteVar(key: string): string {\n return key.startsWith(\"--\") ? key : `--${key}`;\n}\n\n// Strip characters that could break out of a `--var: value;` declaration or the\n// surrounding <style>. Brand config is trusted author input, so this is a\n// belt-and-suspenders guard, not a security boundary.\nfunction cleanValue(value: string): string {\n return value.replace(/[<>{};]/g, \"\").trim();\n}\n\nfunction paletteDecls(palette: Record<string, string> | undefined): string[] {\n const decls: string[] = [];\n for (const [key, value] of Object.entries(palette ?? {})) {\n if (typeof value === \"string\" && value.trim()) decls.push(`${paletteVar(key)}: ${cleanValue(value)};`);\n }\n return decls;\n}\n\nconst TOKEN_VARS: Record<keyof ChapterBrandTokens, string> = {\n background: \"--ui-bg\",\n surface: \"--ui-surface\",\n surface2: \"--ui-surface-2\",\n text: \"--ui-text\",\n textMuted: \"--ui-text-muted\",\n textFaint: \"--ui-text-faint\",\n border: \"--ui-border\",\n borderStrong: \"--ui-border-strong\",\n accent: \"--ui-accent\",\n accentStrong: \"--ui-accent-strong\",\n accentSoft: \"--ui-accent-soft\",\n onAccent: \"--ui-on-accent\",\n good: \"--ui-good\",\n warn: \"--ui-warn\",\n danger: \"--ui-danger\",\n chart1: \"--ui-chart-1\",\n chart2: \"--ui-chart-2\",\n chartPositive: \"--ui-chart-pos\",\n chartNegative: \"--ui-chart-neg\",\n};\n\nfunction semanticDecls(tokens: ChapterBrandTokens | undefined): string[] {\n return Object.entries(tokens ?? {}).flatMap(([key, value]) =>\n typeof value === \"string\" && value.trim()\n ? [`${TOKEN_VARS[key as keyof ChapterBrandTokens]}: ${cleanValue(value)};`]\n : [],\n );\n}\n\n/**\n * Build the CSS that maps a chapter's brand onto the design tokens the UI reads:\n * each `palette` entry becomes a custom property (light, and dark unless\n * `paletteDark` overrides), and `fonts` (display/body/numeral) map to\n * `--ui-font-display` / `--ui-font-sans` / `--ui-font-numeral`. The dark block is\n * emitted under both `:root[data-theme=\"dark\"]` (the odla-ui theme toggle) and\n * `@media (prefers-color-scheme: dark)`. Returns \"\" when there is nothing to\n * theme. These are brand OVERRIDES on top of a base theme — they do not replace\n * the theme layer the components need (see {@link brandTokens} usage in the docs).\n */\nexport function brandTokens(\n brand: ChapterBrand | undefined,\n options: { selector?: string } = {},\n): string {\n if (!brand) return \"\";\n const light = [...paletteDecls(brand.palette), ...semanticDecls(brand.tokens)];\n const fonts = brand.fonts;\n if (fonts?.display) light.push(`--ui-font-display: ${cleanValue(fonts.display)};`);\n if (fonts?.body) light.push(`--ui-font-sans: ${cleanValue(fonts.body)};`);\n if (fonts?.numeral) light.push(`--ui-font-numeral: ${cleanValue(fonts.numeral)};`);\n const dark = [...paletteDecls(brand.paletteDark), ...semanticDecls(brand.tokensDark)];\n const selector = options.selector ?? \":root\";\n const darkSelector = selector === \":root\" ? ':root[data-theme=\"dark\"]' : `${selector}[data-theme=\"dark\"]`;\n const systemSelector = selector === \":root\"\n ? ':root:not([data-theme=\"light\"])'\n : `${selector}:not([data-theme=\"light\"])`;\n\n let css = light.length ? `${selector} {\\n ${light.join(\"\\n \")}\\n}\\n` : \"\";\n if (dark.length) {\n const block = `{\\n ${dark.join(\"\\n \")}\\n}`;\n css += `${darkSelector} ${block}\\n@media (prefers-color-scheme: dark) {\\n ${systemSelector} ${block}\\n}\\n`;\n }\n return css;\n}\n","// Client-side convenience for brand tokens: render the chapter's brand as a\n// <style> tag. Prefer emitting brandTokens() into the page <head> at build/SSR\n// time (no flash); use this when that isn't available (e.g. a pure SPA mount).\nimport { brandTokens } from \"../brand.js\";\nimport type { ChapterBrand } from \"../types\";\n\n/** Props for {@link BrandStyle}. */\nexport interface BrandStyleProps {\n brand: ChapterBrand | undefined;\n /** CSS selector receiving the variables. Default `:root`. */\n selector?: string;\n}\n\n/** Render a chapter's brand tokens as an inline <style> block (or nothing when\n * there is no brand to theme). */\nexport function BrandStyle(props: BrandStyleProps) {\n const css = brandTokens(props.brand, { selector: props.selector });\n if (!css) return null;\n return <style>{css}</style>;\n}\n"],"mappings":";AAaA,SAAS,WAAW,KAAqB;AACvC,SAAO,IAAI,WAAW,IAAI,IAAI,MAAM,KAAK,GAAG;AAC9C;AAKA,SAAS,WAAW,OAAuB;AACzC,SAAO,MAAM,QAAQ,YAAY,EAAE,EAAE,KAAK;AAC5C;AAEA,SAAS,aAAa,SAAuD;AAC3E,QAAM,QAAkB,CAAC;AACzB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,WAAW,CAAC,CAAC,GAAG;AACxD,QAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAG,OAAM,KAAK,GAAG,WAAW,GAAG,CAAC,KAAK,WAAW,KAAK,CAAC,GAAG;AAAA,EACvG;AACA,SAAO;AACT;AAEA,IAAM,aAAuD;AAAA,EAC3D,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,UAAU;AAAA,EACV,MAAM;AAAA,EACN,WAAW;AAAA,EACX,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,eAAe;AACjB;AAEA,SAAS,cAAc,QAAkD;AACvE,SAAO,OAAO,QAAQ,UAAU,CAAC,CAAC,EAAE;AAAA,IAAQ,CAAC,CAAC,KAAK,KAAK,MACtD,OAAO,UAAU,YAAY,MAAM,KAAK,IACpC,CAAC,GAAG,WAAW,GAA+B,CAAC,KAAK,WAAW,KAAK,CAAC,GAAG,IACxE,CAAC;AAAA,EACP;AACF;AAYO,SAAS,YACd,OACA,UAAiC,CAAC,GAC1B;AACR,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,QAAQ,CAAC,GAAG,aAAa,MAAM,OAAO,GAAG,GAAG,cAAc,MAAM,MAAM,CAAC;AAC7E,QAAM,QAAQ,MAAM;AACpB,MAAI,OAAO,QAAS,OAAM,KAAK,sBAAsB,WAAW,MAAM,OAAO,CAAC,GAAG;AACjF,MAAI,OAAO,KAAM,OAAM,KAAK,mBAAmB,WAAW,MAAM,IAAI,CAAC,GAAG;AACxE,MAAI,OAAO,QAAS,OAAM,KAAK,sBAAsB,WAAW,MAAM,OAAO,CAAC,GAAG;AACjF,QAAM,OAAO,CAAC,GAAG,aAAa,MAAM,WAAW,GAAG,GAAG,cAAc,MAAM,UAAU,CAAC;AACpF,QAAM,WAAW,QAAQ,YAAY;AACrC,QAAM,eAAe,aAAa,UAAU,6BAA6B,GAAG,QAAQ;AACpF,QAAM,iBAAiB,aAAa,UAChC,oCACA,GAAG,QAAQ;AAEf,MAAI,MAAM,MAAM,SAAS,GAAG,QAAQ;AAAA,IAAS,MAAM,KAAK,MAAM,CAAC;AAAA;AAAA,IAAU;AACzE,MAAI,KAAK,QAAQ;AACf,UAAM,QAAQ;AAAA,IAAQ,KAAK,KAAK,MAAM,CAAC;AAAA;AACvC,WAAO,GAAG,YAAY,IAAI,KAAK;AAAA;AAAA,IAA8C,cAAc,IAAI,KAAK;AAAA;AAAA;AAAA,EACtG;AACA,SAAO;AACT;;;AC7ES;AAHF,SAAS,WAAW,OAAwB;AACjD,QAAM,MAAM,YAAY,MAAM,OAAO,EAAE,UAAU,MAAM,SAAS,CAAC;AACjE,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,oBAAC,WAAO,eAAI;AACrB;","names":[]}
|