@odla-ai/chapter 0.8.0 → 0.10.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.
- package/README.md +55 -17
- package/dist/chunk-YO6DY5DL.js +281 -0
- package/dist/chunk-YO6DY5DL.js.map +1 -0
- package/dist/chunk-ZCZK6QLC.js +537 -0
- package/dist/chunk-ZCZK6QLC.js.map +1 -0
- package/dist/index.cjs +61 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +60 -14
- package/dist/index.d.ts +60 -14
- package/dist/index.js +61 -16
- package/dist/index.js.map +1 -1
- package/dist/ui/admin/index.d.ts +71 -0
- package/dist/ui/admin/index.js +9 -0
- package/dist/ui/admin/index.js.map +1 -0
- package/dist/ui/index.d.ts +4 -219
- package/dist/ui/index.js +20 -795
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/member/index.d.ts +152 -0
- package/dist/ui/member/index.js +33 -0
- package/dist/ui/member/index.js.map +1 -0
- package/dist/worker/index.cjs +105 -30
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.d.cts +17 -0
- package/dist/worker/index.d.ts +17 -0
- package/dist/worker/index.js +105 -30
- package/dist/worker/index.js.map +1 -1
- package/package.json +9 -5
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { CrmClient, Crm } from '@odla-ai/crm';
|
|
4
|
+
|
|
5
|
+
/** What each admin section receives. `client` is a CrmClient bound to the
|
|
6
|
+
* signed-in admin's bearer token; `navigate` switches sections. */
|
|
7
|
+
interface AdminSectionContext {
|
|
8
|
+
client: CrmClient;
|
|
9
|
+
getToken: () => Promise<string | null>;
|
|
10
|
+
/** Switch to another section by id (e.g. Overview "jump in" buttons). */
|
|
11
|
+
navigate: (sectionId: string) => void;
|
|
12
|
+
}
|
|
13
|
+
/** One admin-console section: a nav label and a body renderer. */
|
|
14
|
+
interface AdminSection {
|
|
15
|
+
id: string;
|
|
16
|
+
label: string;
|
|
17
|
+
render: (ctx: AdminSectionContext) => ReactNode;
|
|
18
|
+
}
|
|
19
|
+
/** Wordmark shown in the gate and top bar. `name` is the plain-text identity (and
|
|
20
|
+
* the badge fallback); `wordmark` is an optional rich display node for brands
|
|
21
|
+
* whose typography can't be a plain string (e.g. an ampersand wrapped to render
|
|
22
|
+
* upright), and `badge` overrides the glyph. */
|
|
23
|
+
type Brand = {
|
|
24
|
+
name: string;
|
|
25
|
+
badge?: string;
|
|
26
|
+
wordmark?: ReactNode;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/** Props for {@link ChapterAdmin}. */
|
|
30
|
+
interface ChapterAdminProps {
|
|
31
|
+
/** The admin sections to render (nav label + body). */
|
|
32
|
+
sections: AdminSection[];
|
|
33
|
+
/** Admin mount path. The sign-in redirect + section routing derive from it,
|
|
34
|
+
* so the "bounce to home after sign-in" bug is impossible. Default "/admin". */
|
|
35
|
+
basePath?: string;
|
|
36
|
+
/** Wordmark shown in the gate + top bar. */
|
|
37
|
+
brand?: Brand;
|
|
38
|
+
/** CRM route mount. Default "/api/crm". */
|
|
39
|
+
crmBasePath?: string;
|
|
40
|
+
/** Origin for /api/config and /api/me. Default same origin. */
|
|
41
|
+
apiBase?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The whole admin console for a chapter/hub: fetches the Clerk publishable key
|
|
45
|
+
* (/api/config), gates on sign-in with the post-sign-in redirect derived from
|
|
46
|
+
* `basePath`, checks the odla-db admins allowlist (/api/me), and renders a
|
|
47
|
+
* TopBar shell over the caller's `sections`. The gate/shell/redirect are owned
|
|
48
|
+
* here so no site re-wires (or re-bugs) them.
|
|
49
|
+
*/
|
|
50
|
+
declare function ChapterAdmin(props: ChapterAdminProps): react.JSX.Element;
|
|
51
|
+
|
|
52
|
+
/** Options for {@link peopleSection}. */
|
|
53
|
+
interface PeopleSectionOptions {
|
|
54
|
+
/** The chapter's resolved CRM engine — `chapter.crm` from defineChapter. */
|
|
55
|
+
crm: Crm;
|
|
56
|
+
/** Section id / route segment. Default "people". */
|
|
57
|
+
id?: string;
|
|
58
|
+
/** Nav label. Default "People". */
|
|
59
|
+
label?: string;
|
|
60
|
+
/** The record type to list. Default "person". */
|
|
61
|
+
type?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Build the People/CRM admin section: a server-driven records table plus a
|
|
65
|
+
* facet-composed detail drawer (fields, pipeline stage, tags) over the
|
|
66
|
+
* token-bound CrmClient. Drop the result into `ChapterAdmin`'s `sections`.
|
|
67
|
+
* (Notes/activity feed and saved-view navigation are noted follow-ups.)
|
|
68
|
+
*/
|
|
69
|
+
declare function peopleSection(options: PeopleSectionOptions): AdminSection;
|
|
70
|
+
|
|
71
|
+
export { type AdminSection, type AdminSectionContext, ChapterAdmin, type ChapterAdminProps, type PeopleSectionOptions, peopleSection };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -1,219 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
/** What each admin section receives. `client` is a CrmClient bound to the
|
|
6
|
-
* signed-in admin's bearer token; `navigate` switches sections. */
|
|
7
|
-
interface AdminSectionContext {
|
|
8
|
-
client: CrmClient;
|
|
9
|
-
getToken: () => Promise<string | null>;
|
|
10
|
-
/** Switch to another section by id (e.g. Overview "jump in" buttons). */
|
|
11
|
-
navigate: (sectionId: string) => void;
|
|
12
|
-
}
|
|
13
|
-
/** One admin-console section: a nav label and a body renderer. */
|
|
14
|
-
interface AdminSection {
|
|
15
|
-
id: string;
|
|
16
|
-
label: string;
|
|
17
|
-
render: (ctx: AdminSectionContext) => ReactNode;
|
|
18
|
-
}
|
|
19
|
-
/** Wordmark shown in the gate and top bar. `name` is the plain-text identity (and
|
|
20
|
-
* the badge fallback); `wordmark` is an optional rich display node for brands
|
|
21
|
-
* whose typography can't be a plain string (e.g. an ampersand wrapped to render
|
|
22
|
-
* upright), and `badge` overrides the glyph. */
|
|
23
|
-
type Brand = {
|
|
24
|
-
name: string;
|
|
25
|
-
badge?: string;
|
|
26
|
-
wordmark?: ReactNode;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/** Props for {@link ChapterAdmin}. */
|
|
30
|
-
interface ChapterAdminProps {
|
|
31
|
-
/** The admin sections to render (nav label + body). */
|
|
32
|
-
sections: AdminSection[];
|
|
33
|
-
/** Admin mount path. The sign-in redirect + section routing derive from it,
|
|
34
|
-
* so the "bounce to home after sign-in" bug is impossible. Default "/admin". */
|
|
35
|
-
basePath?: string;
|
|
36
|
-
/** Wordmark shown in the gate + top bar. */
|
|
37
|
-
brand?: Brand;
|
|
38
|
-
/** CRM route mount. Default "/api/crm". */
|
|
39
|
-
crmBasePath?: string;
|
|
40
|
-
/** Origin for /api/config and /api/me. Default same origin. */
|
|
41
|
-
apiBase?: string;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* The whole admin console for a chapter/hub: fetches the Clerk publishable key
|
|
45
|
-
* (/api/config), gates on sign-in with the post-sign-in redirect derived from
|
|
46
|
-
* `basePath`, checks the odla-db admins allowlist (/api/me), and renders a
|
|
47
|
-
* TopBar shell over the caller's `sections`. The gate/shell/redirect are owned
|
|
48
|
-
* here so no site re-wires (or re-bugs) them.
|
|
49
|
-
*/
|
|
50
|
-
declare function ChapterAdmin(props: ChapterAdminProps): react.JSX.Element;
|
|
51
|
-
|
|
52
|
-
/** Options for {@link peopleSection}. */
|
|
53
|
-
interface PeopleSectionOptions {
|
|
54
|
-
/** The chapter's resolved CRM engine — `chapter.crm` from defineChapter. */
|
|
55
|
-
crm: Crm;
|
|
56
|
-
/** Section id / route segment. Default "people". */
|
|
57
|
-
id?: string;
|
|
58
|
-
/** Nav label. Default "People". */
|
|
59
|
-
label?: string;
|
|
60
|
-
/** The record type to list. Default "person". */
|
|
61
|
-
type?: string;
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Build the People/CRM admin section: a server-driven records table plus a
|
|
65
|
-
* facet-composed detail drawer (fields, pipeline stage, tags) over the
|
|
66
|
-
* token-bound CrmClient. Drop the result into `ChapterAdmin`'s `sections`.
|
|
67
|
-
* (Notes/activity feed and saved-view navigation are noted follow-ups.)
|
|
68
|
-
*/
|
|
69
|
-
declare function peopleSection(options: PeopleSectionOptions): AdminSection;
|
|
70
|
-
|
|
71
|
-
/** A bookable slot: a start instant in epoch milliseconds. */
|
|
72
|
-
interface Slot {
|
|
73
|
-
startAt: number;
|
|
74
|
-
}
|
|
75
|
-
/** The timezone's short abbreviation (e.g. "PST"); falls back to the id if the
|
|
76
|
-
* runtime can't resolve it. */
|
|
77
|
-
declare function tzShort(tz: string): string;
|
|
78
|
-
/** DST-safe day bucket key (ISO date in the target zone). Groups slots by the
|
|
79
|
-
* calendar day a viewer in `tz` would see, not by UTC midnight. */
|
|
80
|
-
declare function dayKey(ms: number, tz: string): string;
|
|
81
|
-
/** Short day label for a day chip, e.g. "Mon, Jun 3". */
|
|
82
|
-
declare function dayLabel(ms: number, tz: string): string;
|
|
83
|
-
/** Time-of-day label for a slot button, e.g. "2:30 PM". */
|
|
84
|
-
declare function timeLabel(ms: number, tz: string): string;
|
|
85
|
-
/** Full, human confirmation label, e.g. "Monday, June 3, 2:30 PM PST". */
|
|
86
|
-
declare function fullLabel(ms: number, tz: string): string;
|
|
87
|
-
/** Currency label from integer cents, e.g. 100000 → "$1,000". */
|
|
88
|
-
declare function fmtMoney(cents: number): string;
|
|
89
|
-
/** Short date label, e.g. "Jun 3, 2026" (used for renewal/refund copy). */
|
|
90
|
-
declare function fmtDate(ms: number): string;
|
|
91
|
-
/** Bucket slots into an insertion-ordered `Map<dayKey, Slot[]>` for the picker.
|
|
92
|
-
* Input order is preserved within each day, so a server that returns slots
|
|
93
|
-
* chronologically yields chronological chips + times. */
|
|
94
|
-
declare function groupSlotsByDay<T extends Slot>(slots: readonly T[], tz: string): Map<string, T[]>;
|
|
95
|
-
|
|
96
|
-
/** CSS class names for the four picker parts — overridable so one component
|
|
97
|
-
* serves several differently-styled surfaces. */
|
|
98
|
-
interface SlotPickerClasses {
|
|
99
|
-
days: string;
|
|
100
|
-
day: string;
|
|
101
|
-
times: string;
|
|
102
|
-
time: string;
|
|
103
|
-
}
|
|
104
|
-
/** Props for {@link SlotPicker}. Generic over the slot type so a caller's richer
|
|
105
|
-
* slot object survives through `onPick`. */
|
|
106
|
-
interface SlotPickerProps<T extends Slot = Slot> {
|
|
107
|
-
/** Bookable slots, ideally already chronological. */
|
|
108
|
-
slots: readonly T[];
|
|
109
|
-
/** The group's scheduling timezone; all labels render in it. */
|
|
110
|
-
timezone: string;
|
|
111
|
-
/** The currently-selected slot's start, for the pressed state. */
|
|
112
|
-
selectedStartAt?: number;
|
|
113
|
-
/** Called with the full slot object when a time is chosen. */
|
|
114
|
-
onPick: (slot: T) => void;
|
|
115
|
-
/** Called when the active day changes (callers clear their selection). */
|
|
116
|
-
onDayChange?: () => void;
|
|
117
|
-
classes?: SlotPickerClasses;
|
|
118
|
-
}
|
|
119
|
-
/** A day-chips + time-grid slot picker. Presentational and `onPick`-driven: it
|
|
120
|
-
* owns only the active-day selection; the caller owns slot data, the chosen
|
|
121
|
-
* slot, and booking. Shared by the join booking step and the member reschedule. */
|
|
122
|
-
declare function SlotPicker<T extends Slot = Slot>(props: SlotPickerProps<T>): react.JSX.Element;
|
|
123
|
-
|
|
124
|
-
/** Issue an authenticated request and parse the JSON response. Throws on a
|
|
125
|
-
* non-2xx status (the islands catch and surface a friendly message). */
|
|
126
|
-
type ApiFn = <T = unknown>(path: string, opts?: RequestInit) => Promise<T>;
|
|
127
|
-
|
|
128
|
-
/** Props for {@link MembersArea}. */
|
|
129
|
-
interface MembersAreaProps {
|
|
130
|
-
api: ApiFn;
|
|
131
|
-
/** Sign the member out (the host owns Clerk's signOut). */
|
|
132
|
-
signOut: () => void;
|
|
133
|
-
/** Where the "Admin console" link points for admins. Default "/admin/". */
|
|
134
|
-
adminHref?: string;
|
|
135
|
-
/** Where an accountless member goes to apply. Default "/join.html". */
|
|
136
|
-
applyHref?: string;
|
|
137
|
-
/** What a full (non-provisional) member sees below the account header. */
|
|
138
|
-
memberContent?: ReactNode;
|
|
139
|
-
}
|
|
140
|
-
/** The signed-in member area. Loads /api/me on mount and renders the account
|
|
141
|
-
* header plus the provisional application card or the full-member content. */
|
|
142
|
-
declare function MembersArea(props: MembersAreaProps): react.JSX.Element;
|
|
143
|
-
|
|
144
|
-
/** Props for {@link Rescheduler}. */
|
|
145
|
-
interface RescheduleProps {
|
|
146
|
-
api: ApiFn;
|
|
147
|
-
applicationId: string;
|
|
148
|
-
timezone: string;
|
|
149
|
-
/** Called after a successful (re)booking so the caller can refresh /api/me. */
|
|
150
|
-
onRescheduled: () => void | Promise<void>;
|
|
151
|
-
/** Link text to open the picker (e.g. "Choose a time" for a first booking). */
|
|
152
|
-
label?: string;
|
|
153
|
-
}
|
|
154
|
-
/** A collapsed "change your time" link that expands into a {@link SlotPicker} and
|
|
155
|
-
* rebooks on pick. Degrades to a message when scheduling is unavailable. */
|
|
156
|
-
declare function Rescheduler(props: RescheduleProps): react.JSX.Element;
|
|
157
|
-
|
|
158
|
-
/** The public join config (the shape `GET /api/join-config` returns). */
|
|
159
|
-
interface JoinConfig {
|
|
160
|
-
id: string;
|
|
161
|
-
name: string;
|
|
162
|
-
paymentsReady: boolean;
|
|
163
|
-
refundPolicyText?: string;
|
|
164
|
-
}
|
|
165
|
-
/** Props for {@link JoinIsland}. */
|
|
166
|
-
interface JoinIslandProps {
|
|
167
|
-
config: JoinConfig;
|
|
168
|
-
/** The site's application form fields — inputs with `name` attributes; their
|
|
169
|
-
* values are collected via FormData and posted to /api/applications. */
|
|
170
|
-
children: ReactNode;
|
|
171
|
-
/** Where the confirmation links after booking. Default "/members/". */
|
|
172
|
-
membersHref?: string;
|
|
173
|
-
}
|
|
174
|
-
/** The signup island. Renders the site's form, then drives payment (when the
|
|
175
|
-
* chapter charges) and booking (when a calendar is connected) to confirmation. */
|
|
176
|
-
declare function JoinIsland(props: JoinIslandProps): react.JSX.Element;
|
|
177
|
-
|
|
178
|
-
/** Props for {@link PaymentStep}. */
|
|
179
|
-
interface PaymentStepProps {
|
|
180
|
-
/** The application to attach the subscription to (the capability). */
|
|
181
|
-
applicationId: string;
|
|
182
|
-
/** Refund-policy copy the applicant must acknowledge to start payment. */
|
|
183
|
-
refundPolicyText: string;
|
|
184
|
-
/** Called once the payment succeeds (or is processing) — advance to booking. */
|
|
185
|
-
onPaid: () => void;
|
|
186
|
-
}
|
|
187
|
-
/** The card-entry step: acknowledge the refund policy → create the subscription
|
|
188
|
-
* → mount Stripe Elements → confirm. */
|
|
189
|
-
declare function PaymentStep(props: PaymentStepProps): react.JSX.Element;
|
|
190
|
-
|
|
191
|
-
/** Brand tokens that theme the site: palette, fonts, wordmark, nav, logos. */
|
|
192
|
-
interface ChapterBrand {
|
|
193
|
-
/** Palette overrides written into styles.css :root (e.g. `{ moss: "#2F3E34" }`
|
|
194
|
-
* or `--ui-*` token names). */
|
|
195
|
-
palette?: Record<string, string>;
|
|
196
|
-
fonts?: {
|
|
197
|
-
display?: string;
|
|
198
|
-
body?: string;
|
|
199
|
-
numeral?: string;
|
|
200
|
-
};
|
|
201
|
-
wordmark?: string;
|
|
202
|
-
tagline?: string;
|
|
203
|
-
/** Header/footer nav sections for the web-component chrome: label → entries. */
|
|
204
|
-
nav?: Record<string, ReadonlyArray<{
|
|
205
|
-
label: string;
|
|
206
|
-
href: string;
|
|
207
|
-
}>>;
|
|
208
|
-
logos?: string;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/** Props for {@link BrandStyle}. */
|
|
212
|
-
interface BrandStyleProps {
|
|
213
|
-
brand: ChapterBrand | undefined;
|
|
214
|
-
}
|
|
215
|
-
/** Render a chapter's brand tokens as an inline <style> block (or nothing when
|
|
216
|
-
* there is no brand to theme). */
|
|
217
|
-
declare function BrandStyle(props: BrandStyleProps): react.JSX.Element | null;
|
|
218
|
-
|
|
219
|
-
export { type AdminSection, type AdminSectionContext, type ApiFn, BrandStyle, type BrandStyleProps, ChapterAdmin, type ChapterAdminProps, type JoinConfig, JoinIsland, type JoinIslandProps, MembersArea, type MembersAreaProps, PaymentStep, type PaymentStepProps, type PeopleSectionOptions, type RescheduleProps, Rescheduler, type Slot, SlotPicker, type SlotPickerClasses, type SlotPickerProps, dayKey, dayLabel, fmtDate, fmtMoney, fullLabel, groupSlotsByDay, peopleSection, timeLabel, tzShort };
|
|
1
|
+
export { AdminSection, AdminSectionContext, ChapterAdmin, ChapterAdminProps, PeopleSectionOptions, peopleSection } from './admin/index.js';
|
|
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 'react';
|
|
4
|
+
import '@odla-ai/crm';
|