@bettercms-ai/types 1.5.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 +18 -0
- package/dist/index.d.ts +652 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/package.json +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @bettercms-ai/types
|
|
2
|
+
|
|
3
|
+
Pure TypeScript type definitions for BetterCMS.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @bettercms-ai/types --registry=https://npm.pkg.github.com/
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import type { Workspace, Page, ContentBlock } from "@bettercms-ai/types"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## License
|
|
18
|
+
Private - bettercms.ai
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,652 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace — a top-level container for a CMS project/tenant.
|
|
3
|
+
* Each workspace has its own content, pages, and API keys.
|
|
4
|
+
*/
|
|
5
|
+
interface Workspace {
|
|
6
|
+
id: string;
|
|
7
|
+
slug: string;
|
|
8
|
+
name: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
domain?: string;
|
|
11
|
+
isActive: boolean;
|
|
12
|
+
createdAt: string;
|
|
13
|
+
updatedAt: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Page — a published content page within a workspace.
|
|
18
|
+
*/
|
|
19
|
+
interface Page {
|
|
20
|
+
id: string;
|
|
21
|
+
workspaceId: string;
|
|
22
|
+
slug: string;
|
|
23
|
+
title: string;
|
|
24
|
+
metaTitle?: string;
|
|
25
|
+
metaDescription?: string;
|
|
26
|
+
isPublished: boolean;
|
|
27
|
+
publishedAt?: string;
|
|
28
|
+
createdAt: string;
|
|
29
|
+
updatedAt: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* ContentBlock — a discriminated union of all CMS block types.
|
|
34
|
+
* Each block has a `type` discriminator and a `props` object
|
|
35
|
+
* whose shape matches the block type.
|
|
36
|
+
*/
|
|
37
|
+
type SpaceToken = "none" | "xs" | "sm" | "md" | "lg" | "xl";
|
|
38
|
+
type ColorToken = "none" | "white" | "black" | "muted" | "mutedBg" | "primary" | "accent";
|
|
39
|
+
type AlignToken = "left" | "center" | "right";
|
|
40
|
+
type FontSizeToken = "sm" | "base" | "lg" | "xl" | "2xl";
|
|
41
|
+
type WeightToken = "normal" | "medium" | "semibold" | "bold";
|
|
42
|
+
type RadiusToken = "none" | "sm" | "md" | "lg" | "full";
|
|
43
|
+
interface BlockStyle {
|
|
44
|
+
paddingY?: SpaceToken;
|
|
45
|
+
paddingX?: SpaceToken;
|
|
46
|
+
marginTop?: SpaceToken;
|
|
47
|
+
marginBottom?: SpaceToken;
|
|
48
|
+
background?: ColorToken;
|
|
49
|
+
textColor?: ColorToken;
|
|
50
|
+
align?: AlignToken;
|
|
51
|
+
fontSize?: FontSizeToken;
|
|
52
|
+
weight?: WeightToken;
|
|
53
|
+
radius?: RadiusToken;
|
|
54
|
+
}
|
|
55
|
+
interface HeadingProps {
|
|
56
|
+
text: string;
|
|
57
|
+
level?: 1 | 2 | 3;
|
|
58
|
+
}
|
|
59
|
+
interface HeadingBlock {
|
|
60
|
+
type: "heading";
|
|
61
|
+
id: string;
|
|
62
|
+
style?: BlockStyle;
|
|
63
|
+
props: HeadingProps;
|
|
64
|
+
}
|
|
65
|
+
interface TextProps {
|
|
66
|
+
html: string;
|
|
67
|
+
}
|
|
68
|
+
interface TextBlock {
|
|
69
|
+
type: "text";
|
|
70
|
+
id: string;
|
|
71
|
+
style?: BlockStyle;
|
|
72
|
+
props: TextProps;
|
|
73
|
+
}
|
|
74
|
+
interface ImageProps {
|
|
75
|
+
src: string;
|
|
76
|
+
alt: string;
|
|
77
|
+
width?: number;
|
|
78
|
+
height?: number;
|
|
79
|
+
caption?: string;
|
|
80
|
+
}
|
|
81
|
+
interface ImageBlock {
|
|
82
|
+
type: "image";
|
|
83
|
+
id: string;
|
|
84
|
+
style?: BlockStyle;
|
|
85
|
+
props: ImageProps;
|
|
86
|
+
}
|
|
87
|
+
interface ButtonProps {
|
|
88
|
+
text: string;
|
|
89
|
+
href: string;
|
|
90
|
+
variant?: "primary" | "secondary";
|
|
91
|
+
}
|
|
92
|
+
interface ButtonBlock {
|
|
93
|
+
type: "button";
|
|
94
|
+
id: string;
|
|
95
|
+
style?: BlockStyle;
|
|
96
|
+
props: ButtonProps;
|
|
97
|
+
}
|
|
98
|
+
interface SpacerProps {
|
|
99
|
+
height: number;
|
|
100
|
+
}
|
|
101
|
+
interface SpacerBlock {
|
|
102
|
+
type: "spacer";
|
|
103
|
+
id: string;
|
|
104
|
+
style?: BlockStyle;
|
|
105
|
+
props: SpacerProps;
|
|
106
|
+
}
|
|
107
|
+
interface ColumnsProps {
|
|
108
|
+
columns: ContentBlock[][];
|
|
109
|
+
gap?: number;
|
|
110
|
+
}
|
|
111
|
+
interface ColumnsBlock {
|
|
112
|
+
type: "columns";
|
|
113
|
+
id: string;
|
|
114
|
+
style?: BlockStyle;
|
|
115
|
+
props: ColumnsProps;
|
|
116
|
+
}
|
|
117
|
+
interface VideoProps {
|
|
118
|
+
url: string;
|
|
119
|
+
poster?: string;
|
|
120
|
+
autoplay?: boolean;
|
|
121
|
+
loop?: boolean;
|
|
122
|
+
}
|
|
123
|
+
interface VideoBlock {
|
|
124
|
+
type: "video";
|
|
125
|
+
id: string;
|
|
126
|
+
style?: BlockStyle;
|
|
127
|
+
props: VideoProps;
|
|
128
|
+
}
|
|
129
|
+
interface FormProps {
|
|
130
|
+
formId: string;
|
|
131
|
+
}
|
|
132
|
+
interface FormBlock {
|
|
133
|
+
type: "form";
|
|
134
|
+
id: string;
|
|
135
|
+
style?: BlockStyle;
|
|
136
|
+
props: FormProps;
|
|
137
|
+
}
|
|
138
|
+
interface SectionProps {
|
|
139
|
+
children: ContentBlock[];
|
|
140
|
+
background?: string;
|
|
141
|
+
paddingY?: number;
|
|
142
|
+
maxWidth?: number;
|
|
143
|
+
}
|
|
144
|
+
interface SectionBlock {
|
|
145
|
+
type: "section";
|
|
146
|
+
id: string;
|
|
147
|
+
style?: BlockStyle;
|
|
148
|
+
props: SectionProps;
|
|
149
|
+
}
|
|
150
|
+
interface NavLink {
|
|
151
|
+
label: string;
|
|
152
|
+
href: string;
|
|
153
|
+
}
|
|
154
|
+
interface NavbarProps {
|
|
155
|
+
logo?: {
|
|
156
|
+
src: string;
|
|
157
|
+
alt: string;
|
|
158
|
+
href?: string;
|
|
159
|
+
};
|
|
160
|
+
links: NavLink[];
|
|
161
|
+
cta?: {
|
|
162
|
+
text: string;
|
|
163
|
+
href: string;
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
interface NavbarBlock {
|
|
167
|
+
type: "navbar";
|
|
168
|
+
id: string;
|
|
169
|
+
style?: BlockStyle;
|
|
170
|
+
props: NavbarProps;
|
|
171
|
+
}
|
|
172
|
+
interface FooterColumn {
|
|
173
|
+
heading?: string;
|
|
174
|
+
links: NavLink[];
|
|
175
|
+
}
|
|
176
|
+
interface FooterProps {
|
|
177
|
+
columns: FooterColumn[];
|
|
178
|
+
copyright?: string;
|
|
179
|
+
}
|
|
180
|
+
interface FooterBlock {
|
|
181
|
+
type: "footer";
|
|
182
|
+
id: string;
|
|
183
|
+
style?: BlockStyle;
|
|
184
|
+
props: FooterProps;
|
|
185
|
+
}
|
|
186
|
+
interface SlideItem {
|
|
187
|
+
id: string;
|
|
188
|
+
children: ContentBlock[];
|
|
189
|
+
}
|
|
190
|
+
interface SliderProps {
|
|
191
|
+
slides: SlideItem[];
|
|
192
|
+
autoplay?: boolean;
|
|
193
|
+
interval?: number;
|
|
194
|
+
loop?: boolean;
|
|
195
|
+
}
|
|
196
|
+
interface SliderBlock {
|
|
197
|
+
type: "slider";
|
|
198
|
+
id: string;
|
|
199
|
+
style?: BlockStyle;
|
|
200
|
+
props: SliderProps;
|
|
201
|
+
}
|
|
202
|
+
interface TabItem {
|
|
203
|
+
id: string;
|
|
204
|
+
label: string;
|
|
205
|
+
children: ContentBlock[];
|
|
206
|
+
}
|
|
207
|
+
interface TabsProps {
|
|
208
|
+
tabs: TabItem[];
|
|
209
|
+
}
|
|
210
|
+
interface TabsBlock {
|
|
211
|
+
type: "tabs";
|
|
212
|
+
id: string;
|
|
213
|
+
style?: BlockStyle;
|
|
214
|
+
props: TabsProps;
|
|
215
|
+
}
|
|
216
|
+
interface ComponentProps {
|
|
217
|
+
componentId: string;
|
|
218
|
+
overrides?: Record<string, unknown>;
|
|
219
|
+
}
|
|
220
|
+
interface ComponentBlock {
|
|
221
|
+
type: "component";
|
|
222
|
+
id: string;
|
|
223
|
+
style?: BlockStyle;
|
|
224
|
+
props: ComponentProps;
|
|
225
|
+
}
|
|
226
|
+
type ContentBlock = HeadingBlock | TextBlock | ImageBlock | ButtonBlock | SpacerBlock | ColumnsBlock | VideoBlock | FormBlock | SectionBlock | NavbarBlock | FooterBlock | SliderBlock | TabsBlock | ComponentBlock;
|
|
227
|
+
/** Literal union of all block type discriminators. */
|
|
228
|
+
type BlockType = ContentBlock["type"];
|
|
229
|
+
/**
|
|
230
|
+
* Type guard — narrows an unknown block to `ContentBlock`.
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* const block = maybeBlock as unknown;
|
|
234
|
+
* if (isBlock(block)) {
|
|
235
|
+
* // block is ContentBlock here
|
|
236
|
+
* }
|
|
237
|
+
*/
|
|
238
|
+
declare function isBlock(value: unknown): value is ContentBlock;
|
|
239
|
+
/**
|
|
240
|
+
* Extract the `type` discriminator from a block, or `null` if not a block.
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* const block = { type: "heading", id: "1", props: { text: "Hi" } };
|
|
244
|
+
* getBlockType(block); // "heading"
|
|
245
|
+
* getBlockType({ not: "a block" }); // null
|
|
246
|
+
*/
|
|
247
|
+
declare function getBlockType(value: unknown): BlockType | null;
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* FLO-264 — bounded block-style tokens → CSS. Framework-agnostic (returns a plain
|
|
251
|
+
* declaration object, no React types) so every renderer shares ONE mapping: the
|
|
252
|
+
* headless @betttercms/next adapter, @betttercms/ui, and (string form) the hosted
|
|
253
|
+
* render-page.ts. Unknown tokens are dropped — closed set, no arbitrary CSS.
|
|
254
|
+
*/
|
|
255
|
+
|
|
256
|
+
/** A CSS declaration object (key → value) usable as a React `style` prop, or undefined when empty. */
|
|
257
|
+
declare function blockStyleToCss(style: BlockStyle | undefined): Record<string, string | number> | undefined;
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Component — a reusable, Webflow-style block tree (a "symbol").
|
|
261
|
+
*
|
|
262
|
+
* A component is authored once and placed across pages via `component` blocks
|
|
263
|
+
* (see `ComponentBlock` in `./block.ts`). Its definition lives in `blockJson`;
|
|
264
|
+
* `props` declares a flat allowlist of values an instance may override.
|
|
265
|
+
*/
|
|
266
|
+
|
|
267
|
+
/** The category a component belongs to (drives library grouping + icons). */
|
|
268
|
+
type ComponentCategory = "navbar" | "footer" | "button" | "section" | "slider" | "tabs" | "form" | "custom";
|
|
269
|
+
/**
|
|
270
|
+
* A single overridable field on a component. `target` points at the block + JSON
|
|
271
|
+
* path inside `blockJson` the override writes to (e.g. blockId "cta", path
|
|
272
|
+
* "props.text"). Keeping overrides a declared allowlist (not arbitrary nested
|
|
273
|
+
* rewrites) keeps instance data small and the contract explicit.
|
|
274
|
+
*/
|
|
275
|
+
interface ComponentPropDef {
|
|
276
|
+
key: string;
|
|
277
|
+
label: string;
|
|
278
|
+
target: {
|
|
279
|
+
blockId: string;
|
|
280
|
+
path: string;
|
|
281
|
+
};
|
|
282
|
+
type: "text" | "richtext" | "image" | "url" | "boolean";
|
|
283
|
+
defaultValue?: unknown;
|
|
284
|
+
}
|
|
285
|
+
interface Component {
|
|
286
|
+
id: string;
|
|
287
|
+
workspaceId: string;
|
|
288
|
+
projectId?: string | null;
|
|
289
|
+
name: string;
|
|
290
|
+
slug: string;
|
|
291
|
+
category: ComponentCategory;
|
|
292
|
+
description?: string | null;
|
|
293
|
+
blockJson: ContentBlock[];
|
|
294
|
+
props: ComponentPropDef[];
|
|
295
|
+
thumbnail?: string | null;
|
|
296
|
+
createdAt: string;
|
|
297
|
+
updatedAt: string;
|
|
298
|
+
}
|
|
299
|
+
/** Public/delivery projection — the fields a renderer needs to resolve instances. */
|
|
300
|
+
interface DeliveryComponent {
|
|
301
|
+
id: string;
|
|
302
|
+
name: string;
|
|
303
|
+
slug: string;
|
|
304
|
+
category: ComponentCategory;
|
|
305
|
+
blockJson: ContentBlock[];
|
|
306
|
+
props: ComponentPropDef[];
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* ContentEntry — a single unit of content, representing the
|
|
311
|
+
* published layout of a page: a collection of ordered blocks
|
|
312
|
+
* with their resolved props.
|
|
313
|
+
*/
|
|
314
|
+
|
|
315
|
+
interface ContentEntry {
|
|
316
|
+
slug: string;
|
|
317
|
+
title: string;
|
|
318
|
+
blocks: ContentBlock[];
|
|
319
|
+
updatedAt: string;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* ContentModel — the structured content model (schema) for a workspace.
|
|
324
|
+
* Defines which content fields are available for authors to fill in.
|
|
325
|
+
*/
|
|
326
|
+
interface ContentModel {
|
|
327
|
+
id: string;
|
|
328
|
+
workspaceId: string;
|
|
329
|
+
name: string;
|
|
330
|
+
description?: string;
|
|
331
|
+
fields: ContentModelField[];
|
|
332
|
+
createdAt: string;
|
|
333
|
+
updatedAt: string;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Canonical field types. Nesting lives on `array` via `config.zones`
|
|
337
|
+
* (see {@link ArrayZoneConfig}): `group`/`repeater` are accepted as legacy input
|
|
338
|
+
* by the API but normalized to `array` + zones on write, so stored/delivered
|
|
339
|
+
* content never contains them.
|
|
340
|
+
*/
|
|
341
|
+
type ContentModelFieldType = "text" | "richtext" | "image" | "boolean" | "number" | "select" | "reference" | "multi-reference" | "array" | "date" | "datetime";
|
|
342
|
+
/**
|
|
343
|
+
* Nested-content config for an `array` field. A zone holds ordinary fields, and a
|
|
344
|
+
* zone field may itself be an `array` with its own zones, so nesting is recursive
|
|
345
|
+
* to any depth.
|
|
346
|
+
* - `nonRepeatable` — a single fixed block of fields (former `group`).
|
|
347
|
+
* - `repeatable` — a repeating list of field-objects (former `repeater`).
|
|
348
|
+
* Mutually exclusive with the primitive form (`config.itemType`).
|
|
349
|
+
*/
|
|
350
|
+
interface ArrayZoneConfig {
|
|
351
|
+
nonRepeatable?: ContentModelField[];
|
|
352
|
+
repeatable?: {
|
|
353
|
+
fields: ContentModelField[];
|
|
354
|
+
minItems?: number;
|
|
355
|
+
maxItems?: number;
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
/** Per-type config for a field (the typed shape behind the loose `config` bag). */
|
|
359
|
+
interface FieldConfig {
|
|
360
|
+
/** primitive array: list of scalars */
|
|
361
|
+
itemType?: "text" | "number" | "date";
|
|
362
|
+
/** nested array: zoned fields (recursive) */
|
|
363
|
+
zones?: ArrayZoneConfig;
|
|
364
|
+
/** reference / multi-reference */
|
|
365
|
+
contentModelId?: string;
|
|
366
|
+
min?: number;
|
|
367
|
+
max?: number;
|
|
368
|
+
/** date / datetime */
|
|
369
|
+
includeTime?: boolean;
|
|
370
|
+
[key: string]: unknown;
|
|
371
|
+
}
|
|
372
|
+
interface ContentModelField {
|
|
373
|
+
key: string;
|
|
374
|
+
label: string;
|
|
375
|
+
type: ContentModelFieldType;
|
|
376
|
+
required?: boolean;
|
|
377
|
+
defaultValue?: unknown;
|
|
378
|
+
options?: string[];
|
|
379
|
+
/** Per-type config. For `array`: either `itemType` (primitive) or `zones` (nested). */
|
|
380
|
+
config?: FieldConfig | null;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* A field inside an array zone — identical to a top-level {@link ContentModelField}.
|
|
384
|
+
* Kept as a named alias so consumers can express "zone field" intent; recursion
|
|
385
|
+
* (an array zone field with its own `config.zones`) is supported.
|
|
386
|
+
*/
|
|
387
|
+
type ZoneField = ContentModelField;
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* MediaAsset — a file uploaded to the CMS media library.
|
|
391
|
+
*/
|
|
392
|
+
interface MediaAsset {
|
|
393
|
+
id: string;
|
|
394
|
+
workspaceId: string;
|
|
395
|
+
filename: string;
|
|
396
|
+
originalFilename: string;
|
|
397
|
+
mimeType: string;
|
|
398
|
+
size: number;
|
|
399
|
+
url: string;
|
|
400
|
+
thumbnailUrl?: string;
|
|
401
|
+
width?: number;
|
|
402
|
+
height?: number;
|
|
403
|
+
altText?: string;
|
|
404
|
+
isActive: boolean;
|
|
405
|
+
createdAt: string;
|
|
406
|
+
updatedAt: string;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Delivery API response shapes — the read surface consumed by framework
|
|
411
|
+
* SDKs (@bettercms-ai/sdk core client, @bettercms-ai/astro, @bettercms-ai/next).
|
|
412
|
+
*/
|
|
413
|
+
|
|
414
|
+
/** Which content lane to read from. */
|
|
415
|
+
type Perspective = "published" | "drafts";
|
|
416
|
+
/** A single content entry as returned by the Delivery API. */
|
|
417
|
+
interface DeliveryEntry<T = Record<string, unknown>> {
|
|
418
|
+
id: string;
|
|
419
|
+
slug: string;
|
|
420
|
+
status: "draft" | "published";
|
|
421
|
+
publishedAt: string | null;
|
|
422
|
+
updatedAt: string | null;
|
|
423
|
+
data: T;
|
|
424
|
+
/** Hydrated reference fields, present when `depth >= 1`. */
|
|
425
|
+
_hydration?: Record<string, DeliveryEntry | DeliveryEntry[]>;
|
|
426
|
+
_meta?: {
|
|
427
|
+
modelSlug: string;
|
|
428
|
+
depth: number;
|
|
429
|
+
cached?: boolean;
|
|
430
|
+
preview?: boolean;
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Per-page rich SEO blob (OG / Twitter / canonical / JSON-LD), stored on the page
|
|
435
|
+
* row and surfaced verbatim by the Delivery API. Merged page-over-site by
|
|
436
|
+
* `resolveSeo` (`@bettercms-ai/sdk`). `schema` is raw JSON-LD (one node or a @graph array).
|
|
437
|
+
*/
|
|
438
|
+
interface PageMetaJson {
|
|
439
|
+
canonical?: string;
|
|
440
|
+
og?: {
|
|
441
|
+
title?: string;
|
|
442
|
+
description?: string;
|
|
443
|
+
image?: string;
|
|
444
|
+
type?: string;
|
|
445
|
+
};
|
|
446
|
+
twitter?: {
|
|
447
|
+
card?: string;
|
|
448
|
+
title?: string;
|
|
449
|
+
description?: string;
|
|
450
|
+
image?: string;
|
|
451
|
+
};
|
|
452
|
+
schema?: Record<string, unknown> | Array<Record<string, unknown>>;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Site-level SEO defaults a headless consumer passes to `resolveSeo`/`buildMetadata`
|
|
456
|
+
* so per-page meta layers over project-wide fallbacks (mirrors the server renderer's
|
|
457
|
+
* `mergeSeoMeta`). All fields optional — supply whatever your project configures.
|
|
458
|
+
*/
|
|
459
|
+
interface SiteSeoDefaults {
|
|
460
|
+
metaTitle?: string;
|
|
461
|
+
metaDescription?: string;
|
|
462
|
+
ogImage?: string | null;
|
|
463
|
+
twitterHandle?: string | null;
|
|
464
|
+
og?: {
|
|
465
|
+
image?: string;
|
|
466
|
+
type?: string;
|
|
467
|
+
};
|
|
468
|
+
twitter?: {
|
|
469
|
+
card?: string;
|
|
470
|
+
};
|
|
471
|
+
/** Site-wide JSON-LD emitted alongside the page's own `schema`. */
|
|
472
|
+
siteSchema?: Record<string, unknown> | Array<Record<string, unknown>>;
|
|
473
|
+
}
|
|
474
|
+
/** A published page with its rendered block tree. */
|
|
475
|
+
interface DeliveryPage {
|
|
476
|
+
slug: string;
|
|
477
|
+
title: string;
|
|
478
|
+
metaTitle: string | null;
|
|
479
|
+
metaDescription: string | null;
|
|
480
|
+
/** Rich SEO (OG / Twitter / canonical / JSON-LD). Always present; `null` when unset. */
|
|
481
|
+
metaJson: PageMetaJson | null;
|
|
482
|
+
blocks: ContentBlock[];
|
|
483
|
+
updatedAt: string | null;
|
|
484
|
+
publishedAt: string | null;
|
|
485
|
+
}
|
|
486
|
+
/** Generic paginated list envelope (the `data` of a list response). */
|
|
487
|
+
interface DeliveryList<T> {
|
|
488
|
+
items: T[];
|
|
489
|
+
page: number;
|
|
490
|
+
perPage: number;
|
|
491
|
+
totalItems: number;
|
|
492
|
+
totalPages: number;
|
|
493
|
+
hasNextPage: boolean;
|
|
494
|
+
hasPreviousPage: boolean;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Form — a CMS form that renders on a page and accepts submissions.
|
|
499
|
+
*/
|
|
500
|
+
interface Form {
|
|
501
|
+
id: string;
|
|
502
|
+
workspaceId: string;
|
|
503
|
+
name: string;
|
|
504
|
+
fields: FormField[];
|
|
505
|
+
submitLabel?: string;
|
|
506
|
+
successMessage?: string;
|
|
507
|
+
redirectUrl?: string;
|
|
508
|
+
createdAt: string;
|
|
509
|
+
updatedAt: string;
|
|
510
|
+
}
|
|
511
|
+
interface FormField {
|
|
512
|
+
key: string;
|
|
513
|
+
label: string;
|
|
514
|
+
type: "text" | "email" | "textarea" | "select" | "checkbox";
|
|
515
|
+
placeholder?: string;
|
|
516
|
+
required?: boolean;
|
|
517
|
+
options?: string[];
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* FormSubmission — a single form submission submitted by a visitor.
|
|
521
|
+
*/
|
|
522
|
+
interface FormSubmission {
|
|
523
|
+
id: string;
|
|
524
|
+
formId: string;
|
|
525
|
+
workspaceId: string;
|
|
526
|
+
data: Record<string, string | boolean | string[]>;
|
|
527
|
+
submittedAt: string;
|
|
528
|
+
ipAddress?: string;
|
|
529
|
+
userAgent?: string;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Redirect — a server-side redirect managed in the CMS.
|
|
534
|
+
*/
|
|
535
|
+
interface Redirect {
|
|
536
|
+
id: string;
|
|
537
|
+
workspaceId: string;
|
|
538
|
+
source: string;
|
|
539
|
+
destination: string;
|
|
540
|
+
type: 301 | 302 | 307 | 308;
|
|
541
|
+
isActive: boolean;
|
|
542
|
+
createdAt: string;
|
|
543
|
+
updatedAt: string;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* ApiKey — an API key scoped to a workspace, used for
|
|
548
|
+
* authenticating against the Delivery API.
|
|
549
|
+
*/
|
|
550
|
+
interface ApiKey {
|
|
551
|
+
id: string;
|
|
552
|
+
workspaceId: string;
|
|
553
|
+
projectId?: string;
|
|
554
|
+
name: string;
|
|
555
|
+
keyPrefix: string;
|
|
556
|
+
permissions: ApiKeyPermission[];
|
|
557
|
+
tokenType: ApiKeyTokenType;
|
|
558
|
+
description?: string;
|
|
559
|
+
expiresAt?: string;
|
|
560
|
+
rateLimit?: number;
|
|
561
|
+
isActive: boolean;
|
|
562
|
+
lastUsedAt?: string;
|
|
563
|
+
createdAt: string;
|
|
564
|
+
}
|
|
565
|
+
type ApiKeyPermission = "content:read" | "content:read:draft" | "content:write" | "form:read" | "form:submit" | "artifact:write";
|
|
566
|
+
type ApiKeyTokenType = "full_access" | "read_only" | "preview";
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Auth types for BetterCMS SDK.
|
|
570
|
+
*/
|
|
571
|
+
/** User returned by BetterAuth. */
|
|
572
|
+
interface AuthUser {
|
|
573
|
+
id: string;
|
|
574
|
+
email: string;
|
|
575
|
+
name: string;
|
|
576
|
+
emailVerified: boolean | null;
|
|
577
|
+
createdAt: string;
|
|
578
|
+
updatedAt: string;
|
|
579
|
+
}
|
|
580
|
+
/** Session returned by BetterAuth. */
|
|
581
|
+
interface AuthSession {
|
|
582
|
+
id: string;
|
|
583
|
+
userId: string;
|
|
584
|
+
token: string;
|
|
585
|
+
expiresAt: string;
|
|
586
|
+
ipAddress: string | null;
|
|
587
|
+
userAgent: string | null;
|
|
588
|
+
createdAt: string;
|
|
589
|
+
updatedAt: string;
|
|
590
|
+
}
|
|
591
|
+
/** Sign-up request payload. */
|
|
592
|
+
interface SignUpInput {
|
|
593
|
+
email: string;
|
|
594
|
+
password: string;
|
|
595
|
+
name: string;
|
|
596
|
+
}
|
|
597
|
+
/** Sign-in request payload. */
|
|
598
|
+
interface SignInInput {
|
|
599
|
+
email: string;
|
|
600
|
+
password: string;
|
|
601
|
+
}
|
|
602
|
+
/** Auth response from sign-up / sign-in endpoints. */
|
|
603
|
+
interface AuthResponse {
|
|
604
|
+
user: AuthUser;
|
|
605
|
+
session: AuthSession;
|
|
606
|
+
token: string;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Common API response types shared across the Delivery and Admin APIs.
|
|
611
|
+
*/
|
|
612
|
+
|
|
613
|
+
type BetterCMSErrorCode = "CONTENT_NOT_FOUND" | "UNAUTHORIZED" | "FORBIDDEN" | "RATE_LIMITED" | "INTERNAL_ERROR" | "VALIDATION_ERROR" | "NETWORK_ERROR" | "ADMIN_NOT_IMPLEMENTED" | "AUTH_ERROR" | "EMAIL_IN_USE";
|
|
614
|
+
interface ApiError {
|
|
615
|
+
message: string;
|
|
616
|
+
code: BetterCMSErrorCode;
|
|
617
|
+
details?: unknown;
|
|
618
|
+
}
|
|
619
|
+
interface PaginatedResult<T> {
|
|
620
|
+
items: T[];
|
|
621
|
+
page: number;
|
|
622
|
+
perPage: number;
|
|
623
|
+
totalItems: number;
|
|
624
|
+
totalPages: number;
|
|
625
|
+
hasNextPage: boolean;
|
|
626
|
+
hasPreviousPage: boolean;
|
|
627
|
+
}
|
|
628
|
+
interface Content {
|
|
629
|
+
slug: string;
|
|
630
|
+
entry: ContentEntry;
|
|
631
|
+
publishedAt: string;
|
|
632
|
+
}
|
|
633
|
+
interface ContentResponse {
|
|
634
|
+
data: Content;
|
|
635
|
+
}
|
|
636
|
+
interface ContentPageResult {
|
|
637
|
+
data: PaginatedResult<Content>;
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Recursively applies `readonly` to all nested properties of T.
|
|
641
|
+
* API responses that should never be mutated can use this.
|
|
642
|
+
*/
|
|
643
|
+
type DeepReadonly<T> = T extends Function ? T : T extends object ? {
|
|
644
|
+
readonly [K in keyof T]: DeepReadonly<T[K]>;
|
|
645
|
+
} : T;
|
|
646
|
+
/**
|
|
647
|
+
* Compile-time type equality assertion.
|
|
648
|
+
* Use in type tests: `type _ = AssertEqual<A, B>` — compiler errors if they differ.
|
|
649
|
+
*/
|
|
650
|
+
type AssertEqual<L, R> = [L] extends [R] ? ([R] extends [L] ? true : false) : false;
|
|
651
|
+
|
|
652
|
+
export { type AlignToken, type ApiError, type ApiKey, type ApiKeyPermission, type ApiKeyTokenType, type ArrayZoneConfig, type AssertEqual, type AuthResponse, type AuthSession, type AuthUser, type BetterCMSErrorCode, type BlockStyle, type BlockType, type ButtonBlock, type ButtonProps, type ColorToken, type ColumnsBlock, type ColumnsProps, type Component, type ComponentBlock, type ComponentCategory, type ComponentPropDef, type ComponentProps, type Content, type ContentBlock, type ContentEntry, type ContentModel, type ContentModelField, type ContentModelFieldType, type ContentPageResult, type ContentResponse, type DeepReadonly, type DeliveryComponent, type DeliveryEntry, type DeliveryList, type DeliveryPage, type FieldConfig, type FontSizeToken, type FooterBlock, type FooterColumn, type FooterProps, type Form, type FormBlock, type FormField, type FormProps, type FormSubmission, type HeadingBlock, type HeadingProps, type ImageBlock, type ImageProps, type MediaAsset, type NavLink, type NavbarBlock, type NavbarProps, type Page, type PageMetaJson, type PaginatedResult, type Perspective, type RadiusToken, type Redirect, type SectionBlock, type SectionProps, type SignInInput, type SignUpInput, type SiteSeoDefaults, type SlideItem, type SliderBlock, type SliderProps, type SpaceToken, type SpacerBlock, type SpacerProps, type TabItem, type TabsBlock, type TabsProps, type TextBlock, type TextProps, type VideoBlock, type VideoProps, type WeightToken, type Workspace, type ZoneField, blockStyleToCss, getBlockType, isBlock };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// src/block.ts
|
|
2
|
+
function isBlock(value) {
|
|
3
|
+
return typeof value === "object" && value !== null && "type" in value && typeof value["type"] === "string";
|
|
4
|
+
}
|
|
5
|
+
function getBlockType(value) {
|
|
6
|
+
if (isBlock(value)) return value.type;
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// src/blockStyle.ts
|
|
11
|
+
var SPACE_PX = { none: "0", xs: "4px", sm: "8px", md: "16px", lg: "32px", xl: "64px" };
|
|
12
|
+
var FONT_SIZE_REM = { sm: "0.875rem", base: "1rem", lg: "1.25rem", xl: "1.5rem", "2xl": "2rem" };
|
|
13
|
+
var WEIGHT = { normal: 400, medium: 500, semibold: 600, bold: 700 };
|
|
14
|
+
var RADIUS_PX = { none: "0", sm: "4px", md: "8px", lg: "16px", full: "9999px" };
|
|
15
|
+
var COLOR_HEX = { white: "#ffffff", black: "#111111", muted: "#6b7280", mutedBg: "#f3f4f6", primary: "#111111", accent: "#4f46e5" };
|
|
16
|
+
function blockStyleToCss(style) {
|
|
17
|
+
if (!style || typeof style !== "object") return void 0;
|
|
18
|
+
const s = style;
|
|
19
|
+
const css = {};
|
|
20
|
+
if (s.paddingY && SPACE_PX[s.paddingY] != null) {
|
|
21
|
+
css.paddingTop = SPACE_PX[s.paddingY];
|
|
22
|
+
css.paddingBottom = SPACE_PX[s.paddingY];
|
|
23
|
+
}
|
|
24
|
+
if (s.paddingX && SPACE_PX[s.paddingX] != null) {
|
|
25
|
+
css.paddingLeft = SPACE_PX[s.paddingX];
|
|
26
|
+
css.paddingRight = SPACE_PX[s.paddingX];
|
|
27
|
+
}
|
|
28
|
+
if (s.marginTop && SPACE_PX[s.marginTop] != null) css.marginTop = SPACE_PX[s.marginTop];
|
|
29
|
+
if (s.marginBottom && SPACE_PX[s.marginBottom] != null) css.marginBottom = SPACE_PX[s.marginBottom];
|
|
30
|
+
if (s.background && COLOR_HEX[s.background]) css.background = COLOR_HEX[s.background];
|
|
31
|
+
if (s.textColor && COLOR_HEX[s.textColor]) css.color = COLOR_HEX[s.textColor];
|
|
32
|
+
if (s.align === "left" || s.align === "center" || s.align === "right") css.textAlign = s.align;
|
|
33
|
+
if (s.fontSize && FONT_SIZE_REM[s.fontSize]) css.fontSize = FONT_SIZE_REM[s.fontSize];
|
|
34
|
+
if (s.weight && WEIGHT[s.weight] != null) css.fontWeight = WEIGHT[s.weight];
|
|
35
|
+
if (s.radius && RADIUS_PX[s.radius] != null) css.borderRadius = RADIUS_PX[s.radius];
|
|
36
|
+
return Object.keys(css).length ? css : void 0;
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
blockStyleToCss,
|
|
40
|
+
getBlockType,
|
|
41
|
+
isBlock
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/block.ts","../src/blockStyle.ts"],"sourcesContent":["/**\n * ContentBlock — a discriminated union of all CMS block types.\n * Each block has a `type` discriminator and a `props` object\n * whose shape matches the block type.\n */\n\n// ── Block style (FLO-264) ──────────────────────────────────────────────────────\n// A uniform, BOUNDED set of design tokens any block may carry (sibling to `props`).\n// Tokens map to fixed CSS values in the renderer (`styleTokensToCss`) so styling\n// reaches the live site WITHOUT arbitrary CSS. Additive + fully optional.\n\nexport type SpaceToken = \"none\" | \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\nexport type ColorToken = \"none\" | \"white\" | \"black\" | \"muted\" | \"mutedBg\" | \"primary\" | \"accent\";\nexport type AlignToken = \"left\" | \"center\" | \"right\";\nexport type FontSizeToken = \"sm\" | \"base\" | \"lg\" | \"xl\" | \"2xl\";\nexport type WeightToken = \"normal\" | \"medium\" | \"semibold\" | \"bold\";\nexport type RadiusToken = \"none\" | \"sm\" | \"md\" | \"lg\" | \"full\";\n\nexport interface BlockStyle {\n paddingY?: SpaceToken;\n paddingX?: SpaceToken;\n marginTop?: SpaceToken;\n marginBottom?: SpaceToken;\n background?: ColorToken;\n textColor?: ColorToken;\n align?: AlignToken;\n fontSize?: FontSizeToken;\n weight?: WeightToken;\n radius?: RadiusToken;\n}\n\n// ── Heading ──────────────────────────────────────────────────────────────────\n\nexport interface HeadingProps {\n text: string;\n level?: 1 | 2 | 3;\n}\n\nexport interface HeadingBlock {\n type: \"heading\";\n id: string;\n style?: BlockStyle;\n props: HeadingProps;\n}\n\n// ── Text ─────────────────────────────────────────────────────────────────────\n\nexport interface TextProps {\n html: string;\n}\n\nexport interface TextBlock {\n type: \"text\";\n id: string;\n style?: BlockStyle;\n props: TextProps;\n}\n\n// ── Image ────────────────────────────────────────────────────────────────────\n\nexport interface ImageProps {\n src: string;\n alt: string;\n width?: number;\n height?: number;\n caption?: string;\n}\n\nexport interface ImageBlock {\n type: \"image\";\n id: string;\n style?: BlockStyle;\n props: ImageProps;\n}\n\n// ── Button ───────────────────────────────────────────────────────────────────\n\nexport interface ButtonProps {\n text: string;\n href: string;\n variant?: \"primary\" | \"secondary\";\n}\n\nexport interface ButtonBlock {\n type: \"button\";\n id: string;\n style?: BlockStyle;\n props: ButtonProps;\n}\n\n// ── Spacer ───────────────────────────────────────────────────────────────────\n\nexport interface SpacerProps {\n height: number; // in px\n}\n\nexport interface SpacerBlock {\n type: \"spacer\";\n id: string;\n style?: BlockStyle;\n props: SpacerProps;\n}\n\n// ── Columns ───────────────────────────────────────────────────────────────────\n\nexport interface ColumnsProps {\n columns: ContentBlock[][]; // array of column slots, each slot is an array of blocks\n gap?: number; // in px\n}\n\nexport interface ColumnsBlock {\n type: \"columns\";\n id: string;\n style?: BlockStyle;\n props: ColumnsProps;\n}\n\n// ── Video ────────────────────────────────────────────────────────────────────\n\nexport interface VideoProps {\n url: string;\n poster?: string;\n autoplay?: boolean;\n loop?: boolean;\n}\n\nexport interface VideoBlock {\n type: \"video\";\n id: string;\n style?: BlockStyle;\n props: VideoProps;\n}\n\n// ── Form ─────────────────────────────────────────────────────────────────────\n\nexport interface FormProps {\n formId: string; // references forms.id (a nanoid). Resolved against delivered forms at render time.\n}\n\nexport interface FormBlock {\n type: \"form\";\n id: string;\n style?: BlockStyle;\n props: FormProps;\n}\n\n// ── Section (recursive container) ──────────────────────────────────────────────\n\nexport interface SectionProps {\n children: ContentBlock[];\n background?: string;\n paddingY?: number; // in px\n maxWidth?: number; // in px\n}\n\nexport interface SectionBlock {\n type: \"section\";\n id: string;\n style?: BlockStyle;\n props: SectionProps;\n}\n\n// ── Navbar ─────────────────────────────────────────────────────────────────────\n\nexport interface NavLink {\n label: string;\n href: string;\n}\n\nexport interface NavbarProps {\n logo?: { src: string; alt: string; href?: string };\n links: NavLink[];\n cta?: { text: string; href: string };\n}\n\nexport interface NavbarBlock {\n type: \"navbar\";\n id: string;\n style?: BlockStyle;\n props: NavbarProps;\n}\n\n// ── Footer ─────────────────────────────────────────────────────────────────────\n\nexport interface FooterColumn {\n heading?: string;\n links: NavLink[];\n}\n\nexport interface FooterProps {\n columns: FooterColumn[];\n copyright?: string;\n}\n\nexport interface FooterBlock {\n type: \"footer\";\n id: string;\n style?: BlockStyle;\n props: FooterProps;\n}\n\n// ── Slider / Carousel (recursive container, client-hydrated) ────────────────────\n\nexport interface SlideItem {\n id: string;\n children: ContentBlock[];\n}\n\nexport interface SliderProps {\n slides: SlideItem[];\n autoplay?: boolean;\n interval?: number; // in ms\n loop?: boolean;\n}\n\nexport interface SliderBlock {\n type: \"slider\";\n id: string;\n style?: BlockStyle;\n props: SliderProps;\n}\n\n// ── Tabs (recursive container, client-hydrated) ─────────────────────────────────\n\nexport interface TabItem {\n id: string;\n label: string;\n children: ContentBlock[];\n}\n\nexport interface TabsProps {\n tabs: TabItem[];\n}\n\nexport interface TabsBlock {\n type: \"tabs\";\n id: string;\n style?: BlockStyle;\n props: TabsProps;\n}\n\n// ── Component instance (Webflow-style reusable symbol) ──────────────────────────\n// References a reusable component by id. `overrides` maps a component prop key\n// (declared in the component's `props[]` allowlist) to a value, applied to the\n// component's block tree at render time. Resolved against delivered components.\n\nexport interface ComponentProps {\n componentId: string;\n overrides?: Record<string, unknown>;\n}\n\nexport interface ComponentBlock {\n type: \"component\";\n id: string;\n style?: BlockStyle;\n props: ComponentProps;\n}\n\n// ── Union ─────────────────────────────────────────────────────────────────────\n\nexport type ContentBlock =\n | HeadingBlock\n | TextBlock\n | ImageBlock\n | ButtonBlock\n | SpacerBlock\n | ColumnsBlock\n | VideoBlock\n | FormBlock\n | SectionBlock\n | NavbarBlock\n | FooterBlock\n | SliderBlock\n | TabsBlock\n | ComponentBlock;\n\n/** Literal union of all block type discriminators. */\nexport type BlockType = ContentBlock[\"type\"];\n\n/**\n * Type guard — narrows an unknown block to `ContentBlock`.\n *\n * @example\n * const block = maybeBlock as unknown;\n * if (isBlock(block)) {\n * // block is ContentBlock here\n * }\n */\nexport function isBlock(value: unknown): value is ContentBlock {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"type\" in value &&\n typeof (value as Record<string, unknown>)[\"type\"] === \"string\"\n );\n}\n\n/**\n * Extract the `type` discriminator from a block, or `null` if not a block.\n *\n * @example\n * const block = { type: \"heading\", id: \"1\", props: { text: \"Hi\" } };\n * getBlockType(block); // \"heading\"\n * getBlockType({ not: \"a block\" }); // null\n */\nexport function getBlockType(value: unknown): BlockType | null {\n if (isBlock(value)) return value.type;\n return null;\n}\n","/**\n * FLO-264 — bounded block-style tokens → CSS. Framework-agnostic (returns a plain\n * declaration object, no React types) so every renderer shares ONE mapping: the\n * headless @betttercms/next adapter, @betttercms/ui, and (string form) the hosted\n * render-page.ts. Unknown tokens are dropped — closed set, no arbitrary CSS.\n */\nimport type { BlockStyle } from \"./block.js\";\n\nconst SPACE_PX: Record<string, string> = { none: \"0\", xs: \"4px\", sm: \"8px\", md: \"16px\", lg: \"32px\", xl: \"64px\" };\nconst FONT_SIZE_REM: Record<string, string> = { sm: \"0.875rem\", base: \"1rem\", lg: \"1.25rem\", xl: \"1.5rem\", \"2xl\": \"2rem\" };\nconst WEIGHT: Record<string, number> = { normal: 400, medium: 500, semibold: 600, bold: 700 };\nconst RADIUS_PX: Record<string, string> = { none: \"0\", sm: \"4px\", md: \"8px\", lg: \"16px\", full: \"9999px\" };\nconst COLOR_HEX: Record<string, string> = { white: \"#ffffff\", black: \"#111111\", muted: \"#6b7280\", mutedBg: \"#f3f4f6\", primary: \"#111111\", accent: \"#4f46e5\" };\n\n/** A CSS declaration object (key → value) usable as a React `style` prop, or undefined when empty. */\nexport function blockStyleToCss(style: BlockStyle | undefined): Record<string, string | number> | undefined {\n if (!style || typeof style !== \"object\") return undefined;\n const s = style as Record<string, string>;\n const css: Record<string, string | number> = {};\n if (s.paddingY && SPACE_PX[s.paddingY] != null) { css.paddingTop = SPACE_PX[s.paddingY]!; css.paddingBottom = SPACE_PX[s.paddingY]!; }\n if (s.paddingX && SPACE_PX[s.paddingX] != null) { css.paddingLeft = SPACE_PX[s.paddingX]!; css.paddingRight = SPACE_PX[s.paddingX]!; }\n if (s.marginTop && SPACE_PX[s.marginTop] != null) css.marginTop = SPACE_PX[s.marginTop]!;\n if (s.marginBottom && SPACE_PX[s.marginBottom] != null) css.marginBottom = SPACE_PX[s.marginBottom]!;\n if (s.background && COLOR_HEX[s.background]) css.background = COLOR_HEX[s.background]!;\n if (s.textColor && COLOR_HEX[s.textColor]) css.color = COLOR_HEX[s.textColor]!;\n if (s.align === \"left\" || s.align === \"center\" || s.align === \"right\") css.textAlign = s.align;\n if (s.fontSize && FONT_SIZE_REM[s.fontSize]) css.fontSize = FONT_SIZE_REM[s.fontSize]!;\n if (s.weight && WEIGHT[s.weight] != null) css.fontWeight = WEIGHT[s.weight]!;\n if (s.radius && RADIUS_PX[s.radius] != null) css.borderRadius = RADIUS_PX[s.radius]!;\n return Object.keys(css).length ? css : undefined;\n}\n"],"mappings":";AAgSO,SAAS,QAAQ,OAAuC;AAC7D,SACE,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,OAAQ,MAAkC,MAAM,MAAM;AAE1D;AAUO,SAAS,aAAa,OAAkC;AAC7D,MAAI,QAAQ,KAAK,EAAG,QAAO,MAAM;AACjC,SAAO;AACT;;;AC5SA,IAAM,WAAmC,EAAE,MAAM,KAAK,IAAI,OAAO,IAAI,OAAO,IAAI,QAAQ,IAAI,QAAQ,IAAI,OAAO;AAC/G,IAAM,gBAAwC,EAAE,IAAI,YAAY,MAAM,QAAQ,IAAI,WAAW,IAAI,UAAU,OAAO,OAAO;AACzH,IAAM,SAAiC,EAAE,QAAQ,KAAK,QAAQ,KAAK,UAAU,KAAK,MAAM,IAAI;AAC5F,IAAM,YAAoC,EAAE,MAAM,KAAK,IAAI,OAAO,IAAI,OAAO,IAAI,QAAQ,MAAM,SAAS;AACxG,IAAM,YAAoC,EAAE,OAAO,WAAW,OAAO,WAAW,OAAO,WAAW,SAAS,WAAW,SAAS,WAAW,QAAQ,UAAU;AAGrJ,SAAS,gBAAgB,OAA4E;AAC1G,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,IAAI;AACV,QAAM,MAAuC,CAAC;AAC9C,MAAI,EAAE,YAAY,SAAS,EAAE,QAAQ,KAAK,MAAM;AAAE,QAAI,aAAa,SAAS,EAAE,QAAQ;AAAI,QAAI,gBAAgB,SAAS,EAAE,QAAQ;AAAA,EAAI;AACrI,MAAI,EAAE,YAAY,SAAS,EAAE,QAAQ,KAAK,MAAM;AAAE,QAAI,cAAc,SAAS,EAAE,QAAQ;AAAI,QAAI,eAAe,SAAS,EAAE,QAAQ;AAAA,EAAI;AACrI,MAAI,EAAE,aAAa,SAAS,EAAE,SAAS,KAAK,KAAM,KAAI,YAAY,SAAS,EAAE,SAAS;AACtF,MAAI,EAAE,gBAAgB,SAAS,EAAE,YAAY,KAAK,KAAM,KAAI,eAAe,SAAS,EAAE,YAAY;AAClG,MAAI,EAAE,cAAc,UAAU,EAAE,UAAU,EAAG,KAAI,aAAa,UAAU,EAAE,UAAU;AACpF,MAAI,EAAE,aAAa,UAAU,EAAE,SAAS,EAAG,KAAI,QAAQ,UAAU,EAAE,SAAS;AAC5E,MAAI,EAAE,UAAU,UAAU,EAAE,UAAU,YAAY,EAAE,UAAU,QAAS,KAAI,YAAY,EAAE;AACzF,MAAI,EAAE,YAAY,cAAc,EAAE,QAAQ,EAAG,KAAI,WAAW,cAAc,EAAE,QAAQ;AACpF,MAAI,EAAE,UAAU,OAAO,EAAE,MAAM,KAAK,KAAM,KAAI,aAAa,OAAO,EAAE,MAAM;AAC1E,MAAI,EAAE,UAAU,UAAU,EAAE,MAAM,KAAK,KAAM,KAAI,eAAe,UAAU,EAAE,MAAM;AAClF,SAAO,OAAO,KAAK,GAAG,EAAE,SAAS,MAAM;AACzC;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bettercms-ai/types",
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"sideEffects": false,
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"scripts": {
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"build": "tsup",
|
|
22
|
+
"prepack": "tsup"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"tsup": "^8.5.1"
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public",
|
|
29
|
+
"registry": "https://registry.npmjs.org/"
|
|
30
|
+
}
|
|
31
|
+
}
|