@forumone/throughline-design-system 0.0.0 → 1.0.0-next.2
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/CHANGELOG.md +182 -0
- package/LICENSE +21 -0
- package/README.md +23 -0
- package/bin/check-block-props.mjs +51 -0
- package/bin/stub-styles.mjs +28 -0
- package/dist/admin/BlockGuidance.d.ts +13 -0
- package/dist/admin/BlockGuidance.d.ts.map +1 -0
- package/dist/admin/BlockGuidance.js +13 -0
- package/dist/admin/BlockGuidance.js.map +1 -0
- package/dist/admin/BlockSummary.d.ts +10 -0
- package/dist/admin/BlockSummary.d.ts.map +1 -0
- package/dist/admin/BlockSummary.js +73 -0
- package/dist/admin/BlockSummary.js.map +1 -0
- package/dist/admin/RowSummary.d.ts +15 -0
- package/dist/admin/RowSummary.d.ts.map +1 -0
- package/dist/admin/RowSummary.js +16 -0
- package/dist/admin/RowSummary.js.map +1 -0
- package/dist/admin/summary.d.ts +18 -0
- package/dist/admin/summary.d.ts.map +1 -0
- package/dist/admin/summary.js +48 -0
- package/dist/admin/summary.js.map +1 -0
- package/dist/altText.d.ts +16 -0
- package/dist/altText.d.ts.map +1 -0
- package/dist/altText.js +54 -0
- package/dist/altText.js.map +1 -0
- package/dist/client.d.ts +15 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +12 -0
- package/dist/client.js.map +1 -0
- package/dist/contract/index.d.ts +5 -0
- package/dist/contract/index.d.ts.map +1 -0
- package/dist/contract/index.js +4 -0
- package/dist/contract/index.js.map +1 -0
- package/dist/contract/lint.d.ts +38 -0
- package/dist/contract/lint.d.ts.map +1 -0
- package/dist/contract/lint.js +110 -0
- package/dist/contract/lint.js.map +1 -0
- package/dist/contract/loader.d.ts +49 -0
- package/dist/contract/loader.d.ts.map +1 -0
- package/dist/contract/loader.js +95 -0
- package/dist/contract/loader.js.map +1 -0
- package/dist/contract/manifest.d.ts +454 -0
- package/dist/contract/manifest.d.ts.map +1 -0
- package/dist/contract/manifest.js +29 -0
- package/dist/contract/manifest.js.map +1 -0
- package/dist/contract/schema.d.ts +334 -0
- package/dist/contract/schema.d.ts.map +1 -0
- package/dist/contract/schema.js +224 -0
- package/dist/contract/schema.js.map +1 -0
- package/dist/generate/blocks.d.ts +79 -0
- package/dist/generate/blocks.d.ts.map +1 -0
- package/dist/generate/blocks.js +118 -0
- package/dist/generate/blocks.js.map +1 -0
- package/dist/generate/fields.d.ts +60 -0
- package/dist/generate/fields.d.ts.map +1 -0
- package/dist/generate/fields.js +478 -0
- package/dist/generate/fields.js.map +1 -0
- package/dist/generate/guidance.d.ts +5 -0
- package/dist/generate/guidance.d.ts.map +1 -0
- package/dist/generate/guidance.js +29 -0
- package/dist/generate/guidance.js.map +1 -0
- package/dist/generate/index.d.ts +13 -0
- package/dist/generate/index.d.ts.map +1 -0
- package/dist/generate/index.js +9 -0
- package/dist/generate/index.js.map +1 -0
- package/dist/generate/labels.d.ts +42 -0
- package/dist/generate/labels.d.ts.map +1 -0
- package/dist/generate/labels.js +226 -0
- package/dist/generate/labels.js.map +1 -0
- package/dist/generate/layout.d.ts +42 -0
- package/dist/generate/layout.d.ts.map +1 -0
- package/dist/generate/layout.js +252 -0
- package/dist/generate/layout.js.map +1 -0
- package/dist/generate/selectOptionSnapshot.d.ts +26 -0
- package/dist/generate/selectOptionSnapshot.d.ts.map +1 -0
- package/dist/generate/selectOptionSnapshot.js +47 -0
- package/dist/generate/selectOptionSnapshot.js.map +1 -0
- package/dist/generate/selectOptions.d.ts +64 -0
- package/dist/generate/selectOptions.d.ts.map +1 -0
- package/dist/generate/selectOptions.js +145 -0
- package/dist/generate/selectOptions.js.map +1 -0
- package/dist/overrides.d.ts +71 -0
- package/dist/overrides.d.ts.map +1 -0
- package/dist/overrides.js +16 -0
- package/dist/overrides.js.map +1 -0
- package/dist/render/RenderBlocks.d.ts +67 -0
- package/dist/render/RenderBlocks.d.ts.map +1 -0
- package/dist/render/RenderBlocks.js +31 -0
- package/dist/render/RenderBlocks.js.map +1 -0
- package/dist/render/coerce.d.ts +78 -0
- package/dist/render/coerce.d.ts.map +1 -0
- package/dist/render/coerce.js +243 -0
- package/dist/render/coerce.js.map +1 -0
- package/dist/render/index.d.ts +5 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +3 -0
- package/dist/render/index.js.map +1 -0
- package/dist/testing/checkBlockProps.d.ts +66 -0
- package/dist/testing/checkBlockProps.d.ts.map +1 -0
- package/dist/testing/checkBlockProps.js +241 -0
- package/dist/testing/checkBlockProps.js.map +1 -0
- package/dist/testing/checkBlockPropsCli.d.ts +12 -0
- package/dist/testing/checkBlockPropsCli.d.ts.map +1 -0
- package/dist/testing/checkBlockPropsCli.js +86 -0
- package/dist/testing/checkBlockPropsCli.js.map +1 -0
- package/dist/testing/contractDefaults.d.ts +21 -0
- package/dist/testing/contractDefaults.d.ts.map +1 -0
- package/dist/testing/contractDefaults.js +65 -0
- package/dist/testing/contractDefaults.js.map +1 -0
- package/dist/testing/describeBlockInvariants.d.ts +39 -0
- package/dist/testing/describeBlockInvariants.d.ts.map +1 -0
- package/dist/testing/describeBlockInvariants.js +71 -0
- package/dist/testing/describeBlockInvariants.js.map +1 -0
- package/dist/testing/index.d.ts +18 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +14 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/untouchedBlocks.d.ts +48 -0
- package/dist/testing/untouchedBlocks.d.ts.map +1 -0
- package/dist/testing/untouchedBlocks.js +155 -0
- package/dist/testing/untouchedBlocks.js.map +1 -0
- package/package.json +108 -1
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* The current version of the contract schema. Bump this when making a
|
|
4
|
+
* backwards-incompatible change to the shape. Manifests declare the
|
|
5
|
+
* version they satisfy so the loader can reject mismatches loudly.
|
|
6
|
+
*/
|
|
7
|
+
export declare const CONTRACT_VERSION = "1.0.0";
|
|
8
|
+
declare const FieldTypeSchema: z.ZodEnum<["text", "richtext", "link", "image", "video", "select", "group", "array", "boolean", "number"]>;
|
|
9
|
+
declare const PlacementSchema: z.ZodEnum<["page", "section", "inline"]>;
|
|
10
|
+
declare const CategorySchema: z.ZodEnum<["hero", "section", "card", "media", "cta", "navigation", "data", "form", "utility"]>;
|
|
11
|
+
/**
|
|
12
|
+
* Where an editor looks for a component, as distinct from what the component
|
|
13
|
+
* *is*.
|
|
14
|
+
*
|
|
15
|
+
* `category` answers the second question and several consumers reason about it
|
|
16
|
+
* as a kind. It is a poor answer to the first: a real design system files
|
|
17
|
+
* roughly half its library under `section`, so a picker grouped on `category`
|
|
18
|
+
* hands back the flat list the grouping was meant to avoid, while `card` and
|
|
19
|
+
* `navigation` hold one entry each. Redistributing within `category` to even
|
|
20
|
+
* the shelves out would file components under the wrong kind for every other
|
|
21
|
+
* consumer.
|
|
22
|
+
*
|
|
23
|
+
* So this is a second, optional field. The values are shelf labels, chosen to
|
|
24
|
+
* split the sections a `category` cannot:
|
|
25
|
+
*
|
|
26
|
+
* - `hero` — page openers
|
|
27
|
+
* - `narrative` — sections that explain, walk through, or tell
|
|
28
|
+
* - `proof` — sections that evidence a claim: testimony, clients, results
|
|
29
|
+
* - `listing` — collections of records, usually repeating
|
|
30
|
+
* - `media` — image, video, audio, and their captions
|
|
31
|
+
* - `form` — anything an editor thinks of as a form
|
|
32
|
+
* - `cta` — asks
|
|
33
|
+
* - `navigation` — wayfinding within or across pages
|
|
34
|
+
* - `utility` — structural or incidental
|
|
35
|
+
*
|
|
36
|
+
* There is deliberately no `section`: a shelf that holds half the library is
|
|
37
|
+
* the problem this field exists to solve. There is no `card` or `data` either
|
|
38
|
+
* — both name a kind rather than a place to look, and their contents belong on
|
|
39
|
+
* `listing` and `proof` respectively.
|
|
40
|
+
*/
|
|
41
|
+
declare const GroupSchema: z.ZodEnum<["hero", "narrative", "proof", "listing", "media", "form", "cta", "navigation", "utility"]>;
|
|
42
|
+
export type ContentField = {
|
|
43
|
+
name: string;
|
|
44
|
+
type: z.infer<typeof FieldTypeSchema>;
|
|
45
|
+
required: boolean;
|
|
46
|
+
maxLength?: number | undefined;
|
|
47
|
+
defaultValue?: boolean | undefined;
|
|
48
|
+
constraints?: string | undefined;
|
|
49
|
+
advanced?: boolean | undefined;
|
|
50
|
+
of?: ContentField[] | undefined;
|
|
51
|
+
};
|
|
52
|
+
/** Input shape for {@link ContentFieldSchema}: defaulted fields are optional. */
|
|
53
|
+
export type ContentFieldInput = {
|
|
54
|
+
name: string;
|
|
55
|
+
type: z.infer<typeof FieldTypeSchema>;
|
|
56
|
+
required?: boolean | undefined;
|
|
57
|
+
maxLength?: number | undefined;
|
|
58
|
+
defaultValue?: boolean | undefined;
|
|
59
|
+
constraints?: string | undefined;
|
|
60
|
+
advanced?: boolean | undefined;
|
|
61
|
+
of?: ContentFieldInput[] | undefined;
|
|
62
|
+
};
|
|
63
|
+
export declare const ComponentContractSchema: z.ZodObject<{
|
|
64
|
+
name: z.ZodString;
|
|
65
|
+
category: z.ZodEnum<["hero", "section", "card", "media", "cta", "navigation", "data", "form", "utility"]>;
|
|
66
|
+
/**
|
|
67
|
+
* The shelf an authoring UI files this component under. Optional: when it is
|
|
68
|
+
* absent, {@link groupOf} falls back to {@link category}, so a design system
|
|
69
|
+
* that sets none groups exactly as it did before this field existed.
|
|
70
|
+
*/
|
|
71
|
+
group: z.ZodOptional<z.ZodEnum<["hero", "narrative", "proof", "listing", "media", "form", "cta", "navigation", "utility"]>>;
|
|
72
|
+
description: z.ZodString;
|
|
73
|
+
intent: z.ZodString;
|
|
74
|
+
composition: z.ZodObject<{
|
|
75
|
+
placement: z.ZodArray<z.ZodEnum<["page", "section", "inline"]>, "atleastone">;
|
|
76
|
+
maxPerPage: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
|
|
77
|
+
requiredSiblings: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
78
|
+
forbiddenAdjacent: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
79
|
+
allowedSlots: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString, "many">>>;
|
|
80
|
+
}, "strip", z.ZodTypeAny, {
|
|
81
|
+
placement: ["inline" | "page" | "section", ...("inline" | "page" | "section")[]];
|
|
82
|
+
maxPerPage: number | null;
|
|
83
|
+
requiredSiblings: string[];
|
|
84
|
+
forbiddenAdjacent: string[];
|
|
85
|
+
allowedSlots?: Record<string, string[]> | undefined;
|
|
86
|
+
}, {
|
|
87
|
+
placement: ["inline" | "page" | "section", ...("inline" | "page" | "section")[]];
|
|
88
|
+
maxPerPage?: number | null | undefined;
|
|
89
|
+
requiredSiblings?: string[] | undefined;
|
|
90
|
+
forbiddenAdjacent?: string[] | undefined;
|
|
91
|
+
allowedSlots?: Record<string, string[]> | undefined;
|
|
92
|
+
}>;
|
|
93
|
+
content: z.ZodObject<{
|
|
94
|
+
fields: z.ZodArray<z.ZodType<ContentField, z.ZodTypeDef, ContentFieldInput>, "many">;
|
|
95
|
+
variants: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
96
|
+
name: z.ZodString;
|
|
97
|
+
description: z.ZodString;
|
|
98
|
+
whenToUse: z.ZodString;
|
|
99
|
+
}, "strip", z.ZodTypeAny, {
|
|
100
|
+
name: string;
|
|
101
|
+
description: string;
|
|
102
|
+
whenToUse: string;
|
|
103
|
+
}, {
|
|
104
|
+
name: string;
|
|
105
|
+
description: string;
|
|
106
|
+
whenToUse: string;
|
|
107
|
+
}>, "many">>;
|
|
108
|
+
}, "strip", z.ZodTypeAny, {
|
|
109
|
+
fields: ContentField[];
|
|
110
|
+
variants?: {
|
|
111
|
+
name: string;
|
|
112
|
+
description: string;
|
|
113
|
+
whenToUse: string;
|
|
114
|
+
}[] | undefined;
|
|
115
|
+
}, {
|
|
116
|
+
fields: ContentFieldInput[];
|
|
117
|
+
variants?: {
|
|
118
|
+
name: string;
|
|
119
|
+
description: string;
|
|
120
|
+
whenToUse: string;
|
|
121
|
+
}[] | undefined;
|
|
122
|
+
}>;
|
|
123
|
+
tokens: z.ZodObject<{
|
|
124
|
+
consumes: z.ZodArray<z.ZodString, "many">;
|
|
125
|
+
configurable: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
126
|
+
prop: z.ZodString;
|
|
127
|
+
tokenGroup: z.ZodString;
|
|
128
|
+
allowedValues: z.ZodArray<z.ZodString, "many">;
|
|
129
|
+
}, "strip", z.ZodTypeAny, {
|
|
130
|
+
prop: string;
|
|
131
|
+
tokenGroup: string;
|
|
132
|
+
allowedValues: string[];
|
|
133
|
+
}, {
|
|
134
|
+
prop: string;
|
|
135
|
+
tokenGroup: string;
|
|
136
|
+
allowedValues: string[];
|
|
137
|
+
}>, "many">>;
|
|
138
|
+
}, "strip", z.ZodTypeAny, {
|
|
139
|
+
consumes: string[];
|
|
140
|
+
configurable?: {
|
|
141
|
+
prop: string;
|
|
142
|
+
tokenGroup: string;
|
|
143
|
+
allowedValues: string[];
|
|
144
|
+
}[] | undefined;
|
|
145
|
+
}, {
|
|
146
|
+
consumes: string[];
|
|
147
|
+
configurable?: {
|
|
148
|
+
prop: string;
|
|
149
|
+
tokenGroup: string;
|
|
150
|
+
allowedValues: string[];
|
|
151
|
+
}[] | undefined;
|
|
152
|
+
}>;
|
|
153
|
+
accessibility: z.ZodObject<{
|
|
154
|
+
role: z.ZodOptional<z.ZodString>;
|
|
155
|
+
keyboardSupport: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
156
|
+
screenReaderBehavior: z.ZodString;
|
|
157
|
+
contentWarnings: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
158
|
+
}, "strip", z.ZodTypeAny, {
|
|
159
|
+
keyboardSupport: string[];
|
|
160
|
+
screenReaderBehavior: string;
|
|
161
|
+
contentWarnings: string[];
|
|
162
|
+
role?: string | undefined;
|
|
163
|
+
}, {
|
|
164
|
+
screenReaderBehavior: string;
|
|
165
|
+
role?: string | undefined;
|
|
166
|
+
keyboardSupport?: string[] | undefined;
|
|
167
|
+
contentWarnings?: string[] | undefined;
|
|
168
|
+
}>;
|
|
169
|
+
examples: z.ZodArray<z.ZodObject<{
|
|
170
|
+
label: z.ZodString;
|
|
171
|
+
intent: z.ZodString;
|
|
172
|
+
storyId: z.ZodString;
|
|
173
|
+
}, "strip", z.ZodTypeAny, {
|
|
174
|
+
label: string;
|
|
175
|
+
intent: string;
|
|
176
|
+
storyId: string;
|
|
177
|
+
}, {
|
|
178
|
+
label: string;
|
|
179
|
+
intent: string;
|
|
180
|
+
storyId: string;
|
|
181
|
+
}>, "many">;
|
|
182
|
+
antiExamples: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
183
|
+
label: z.ZodString;
|
|
184
|
+
why: z.ZodString;
|
|
185
|
+
useInstead: z.ZodOptional<z.ZodString>;
|
|
186
|
+
}, "strip", z.ZodTypeAny, {
|
|
187
|
+
label: string;
|
|
188
|
+
why: string;
|
|
189
|
+
useInstead?: string | undefined;
|
|
190
|
+
}, {
|
|
191
|
+
label: string;
|
|
192
|
+
why: string;
|
|
193
|
+
useInstead?: string | undefined;
|
|
194
|
+
}>, "many">>;
|
|
195
|
+
behavior: z.ZodDefault<z.ZodObject<{
|
|
196
|
+
fetchesData: z.ZodDefault<z.ZodBoolean>;
|
|
197
|
+
hasClientState: z.ZodDefault<z.ZodBoolean>;
|
|
198
|
+
animates: z.ZodDefault<z.ZodBoolean>;
|
|
199
|
+
requiresAnalytics: z.ZodDefault<z.ZodBoolean>;
|
|
200
|
+
}, "strip", z.ZodTypeAny, {
|
|
201
|
+
fetchesData: boolean;
|
|
202
|
+
hasClientState: boolean;
|
|
203
|
+
animates: boolean;
|
|
204
|
+
requiresAnalytics: boolean;
|
|
205
|
+
}, {
|
|
206
|
+
fetchesData?: boolean | undefined;
|
|
207
|
+
hasClientState?: boolean | undefined;
|
|
208
|
+
animates?: boolean | undefined;
|
|
209
|
+
requiresAnalytics?: boolean | undefined;
|
|
210
|
+
}>>;
|
|
211
|
+
}, "strip", z.ZodTypeAny, {
|
|
212
|
+
name: string;
|
|
213
|
+
description: string;
|
|
214
|
+
content: {
|
|
215
|
+
fields: ContentField[];
|
|
216
|
+
variants?: {
|
|
217
|
+
name: string;
|
|
218
|
+
description: string;
|
|
219
|
+
whenToUse: string;
|
|
220
|
+
}[] | undefined;
|
|
221
|
+
};
|
|
222
|
+
category: "cta" | "data" | "section" | "hero" | "card" | "media" | "navigation" | "form" | "utility";
|
|
223
|
+
intent: string;
|
|
224
|
+
composition: {
|
|
225
|
+
placement: ["inline" | "page" | "section", ...("inline" | "page" | "section")[]];
|
|
226
|
+
maxPerPage: number | null;
|
|
227
|
+
requiredSiblings: string[];
|
|
228
|
+
forbiddenAdjacent: string[];
|
|
229
|
+
allowedSlots?: Record<string, string[]> | undefined;
|
|
230
|
+
};
|
|
231
|
+
tokens: {
|
|
232
|
+
consumes: string[];
|
|
233
|
+
configurable?: {
|
|
234
|
+
prop: string;
|
|
235
|
+
tokenGroup: string;
|
|
236
|
+
allowedValues: string[];
|
|
237
|
+
}[] | undefined;
|
|
238
|
+
};
|
|
239
|
+
accessibility: {
|
|
240
|
+
keyboardSupport: string[];
|
|
241
|
+
screenReaderBehavior: string;
|
|
242
|
+
contentWarnings: string[];
|
|
243
|
+
role?: string | undefined;
|
|
244
|
+
};
|
|
245
|
+
examples: {
|
|
246
|
+
label: string;
|
|
247
|
+
intent: string;
|
|
248
|
+
storyId: string;
|
|
249
|
+
}[];
|
|
250
|
+
antiExamples: {
|
|
251
|
+
label: string;
|
|
252
|
+
why: string;
|
|
253
|
+
useInstead?: string | undefined;
|
|
254
|
+
}[];
|
|
255
|
+
behavior: {
|
|
256
|
+
fetchesData: boolean;
|
|
257
|
+
hasClientState: boolean;
|
|
258
|
+
animates: boolean;
|
|
259
|
+
requiresAnalytics: boolean;
|
|
260
|
+
};
|
|
261
|
+
group?: "cta" | "hero" | "media" | "navigation" | "form" | "utility" | "narrative" | "proof" | "listing" | undefined;
|
|
262
|
+
}, {
|
|
263
|
+
name: string;
|
|
264
|
+
description: string;
|
|
265
|
+
content: {
|
|
266
|
+
fields: ContentFieldInput[];
|
|
267
|
+
variants?: {
|
|
268
|
+
name: string;
|
|
269
|
+
description: string;
|
|
270
|
+
whenToUse: string;
|
|
271
|
+
}[] | undefined;
|
|
272
|
+
};
|
|
273
|
+
category: "cta" | "data" | "section" | "hero" | "card" | "media" | "navigation" | "form" | "utility";
|
|
274
|
+
intent: string;
|
|
275
|
+
composition: {
|
|
276
|
+
placement: ["inline" | "page" | "section", ...("inline" | "page" | "section")[]];
|
|
277
|
+
maxPerPage?: number | null | undefined;
|
|
278
|
+
requiredSiblings?: string[] | undefined;
|
|
279
|
+
forbiddenAdjacent?: string[] | undefined;
|
|
280
|
+
allowedSlots?: Record<string, string[]> | undefined;
|
|
281
|
+
};
|
|
282
|
+
tokens: {
|
|
283
|
+
consumes: string[];
|
|
284
|
+
configurable?: {
|
|
285
|
+
prop: string;
|
|
286
|
+
tokenGroup: string;
|
|
287
|
+
allowedValues: string[];
|
|
288
|
+
}[] | undefined;
|
|
289
|
+
};
|
|
290
|
+
accessibility: {
|
|
291
|
+
screenReaderBehavior: string;
|
|
292
|
+
role?: string | undefined;
|
|
293
|
+
keyboardSupport?: string[] | undefined;
|
|
294
|
+
contentWarnings?: string[] | undefined;
|
|
295
|
+
};
|
|
296
|
+
examples: {
|
|
297
|
+
label: string;
|
|
298
|
+
intent: string;
|
|
299
|
+
storyId: string;
|
|
300
|
+
}[];
|
|
301
|
+
group?: "cta" | "hero" | "media" | "navigation" | "form" | "utility" | "narrative" | "proof" | "listing" | undefined;
|
|
302
|
+
antiExamples?: {
|
|
303
|
+
label: string;
|
|
304
|
+
why: string;
|
|
305
|
+
useInstead?: string | undefined;
|
|
306
|
+
}[] | undefined;
|
|
307
|
+
behavior?: {
|
|
308
|
+
fetchesData?: boolean | undefined;
|
|
309
|
+
hasClientState?: boolean | undefined;
|
|
310
|
+
animates?: boolean | undefined;
|
|
311
|
+
requiresAnalytics?: boolean | undefined;
|
|
312
|
+
} | undefined;
|
|
313
|
+
}>;
|
|
314
|
+
export type ComponentContract = z.infer<typeof ComponentContractSchema>;
|
|
315
|
+
export type ComponentCategory = z.infer<typeof CategorySchema>;
|
|
316
|
+
export type ComponentGroup = z.infer<typeof GroupSchema>;
|
|
317
|
+
/**
|
|
318
|
+
* The shelf a component is filed under: its `group` when set, otherwise its
|
|
319
|
+
* `category`.
|
|
320
|
+
*
|
|
321
|
+
* Anything that groups components should call this rather than reading either
|
|
322
|
+
* field directly, so a design system part-way through adopting `group` groups
|
|
323
|
+
* consistently instead of half one way and half the other. It takes a
|
|
324
|
+
* structural type so it also accepts the looser component shapes consumers
|
|
325
|
+
* carry around, not only a fully parsed {@link ComponentContract}.
|
|
326
|
+
*/
|
|
327
|
+
export declare function groupOf(component: {
|
|
328
|
+
category: string;
|
|
329
|
+
group?: string | undefined;
|
|
330
|
+
}): string;
|
|
331
|
+
export type ComponentPlacement = z.infer<typeof PlacementSchema>;
|
|
332
|
+
export type ContentFieldType = z.infer<typeof FieldTypeSchema>;
|
|
333
|
+
export {};
|
|
334
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/contract/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,UAAU,CAAA;AAEvC,QAAA,MAAM,eAAe,4GAWnB,CAAA;AAEF,QAAA,MAAM,eAAe,0CAAwC,CAAA;AAE7D,QAAA,MAAM,cAAc,iGAUlB,CAAA;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,QAAA,MAAM,WAAW,uGAUf,CAAA;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;IACrC,QAAQ,EAAE,OAAO,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAClC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC9B,EAAE,CAAC,EAAE,YAAY,EAAE,GAAG,SAAS,CAAA;CAChC,CAAA;AAED,iFAAiF;AACjF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;IACrC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC9B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAClC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC9B,EAAE,CAAC,EAAE,iBAAiB,EAAE,GAAG,SAAS,CAAA;CACrC,CAAA;AAqED,eAAO,MAAM,uBAAuB;;;IAIlC;;;;OAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgFH,CAAA;AAEF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AACvE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAA;AAC9D,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAA;AAExD;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,SAAS,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAAG,MAAM,CAE3F;AACD,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AAChE,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* The current version of the contract schema. Bump this when making a
|
|
4
|
+
* backwards-incompatible change to the shape. Manifests declare the
|
|
5
|
+
* version they satisfy so the loader can reject mismatches loudly.
|
|
6
|
+
*/
|
|
7
|
+
export const CONTRACT_VERSION = '1.0.0';
|
|
8
|
+
const FieldTypeSchema = z.enum([
|
|
9
|
+
'text',
|
|
10
|
+
'richtext',
|
|
11
|
+
'link',
|
|
12
|
+
'image',
|
|
13
|
+
'video',
|
|
14
|
+
'select',
|
|
15
|
+
'group',
|
|
16
|
+
'array',
|
|
17
|
+
'boolean',
|
|
18
|
+
'number',
|
|
19
|
+
]);
|
|
20
|
+
const PlacementSchema = z.enum(['page', 'section', 'inline']);
|
|
21
|
+
const CategorySchema = z.enum([
|
|
22
|
+
'hero',
|
|
23
|
+
'section',
|
|
24
|
+
'card',
|
|
25
|
+
'media',
|
|
26
|
+
'cta',
|
|
27
|
+
'navigation',
|
|
28
|
+
'data',
|
|
29
|
+
'form',
|
|
30
|
+
'utility',
|
|
31
|
+
]);
|
|
32
|
+
/**
|
|
33
|
+
* Where an editor looks for a component, as distinct from what the component
|
|
34
|
+
* *is*.
|
|
35
|
+
*
|
|
36
|
+
* `category` answers the second question and several consumers reason about it
|
|
37
|
+
* as a kind. It is a poor answer to the first: a real design system files
|
|
38
|
+
* roughly half its library under `section`, so a picker grouped on `category`
|
|
39
|
+
* hands back the flat list the grouping was meant to avoid, while `card` and
|
|
40
|
+
* `navigation` hold one entry each. Redistributing within `category` to even
|
|
41
|
+
* the shelves out would file components under the wrong kind for every other
|
|
42
|
+
* consumer.
|
|
43
|
+
*
|
|
44
|
+
* So this is a second, optional field. The values are shelf labels, chosen to
|
|
45
|
+
* split the sections a `category` cannot:
|
|
46
|
+
*
|
|
47
|
+
* - `hero` — page openers
|
|
48
|
+
* - `narrative` — sections that explain, walk through, or tell
|
|
49
|
+
* - `proof` — sections that evidence a claim: testimony, clients, results
|
|
50
|
+
* - `listing` — collections of records, usually repeating
|
|
51
|
+
* - `media` — image, video, audio, and their captions
|
|
52
|
+
* - `form` — anything an editor thinks of as a form
|
|
53
|
+
* - `cta` — asks
|
|
54
|
+
* - `navigation` — wayfinding within or across pages
|
|
55
|
+
* - `utility` — structural or incidental
|
|
56
|
+
*
|
|
57
|
+
* There is deliberately no `section`: a shelf that holds half the library is
|
|
58
|
+
* the problem this field exists to solve. There is no `card` or `data` either
|
|
59
|
+
* — both name a kind rather than a place to look, and their contents belong on
|
|
60
|
+
* `listing` and `proof` respectively.
|
|
61
|
+
*/
|
|
62
|
+
const GroupSchema = z.enum([
|
|
63
|
+
'hero',
|
|
64
|
+
'narrative',
|
|
65
|
+
'proof',
|
|
66
|
+
'listing',
|
|
67
|
+
'media',
|
|
68
|
+
'form',
|
|
69
|
+
'cta',
|
|
70
|
+
'navigation',
|
|
71
|
+
'utility',
|
|
72
|
+
]);
|
|
73
|
+
const ContentFieldSchema = z.lazy(() => z.object({
|
|
74
|
+
name: z.string().min(1),
|
|
75
|
+
type: FieldTypeSchema,
|
|
76
|
+
required: z.boolean().default(false),
|
|
77
|
+
maxLength: z.number().int().positive().optional(),
|
|
78
|
+
/*
|
|
79
|
+
What the field holds before an author touches it, for `boolean` only.
|
|
80
|
+
|
|
81
|
+
A component's own default lives in its signature — `hasFacade = true` — and
|
|
82
|
+
is reachable only when the prop arrives as `undefined`. A generated CMS
|
|
83
|
+
field never leaves it undefined: a checkbox is stored ticked or unticked,
|
|
84
|
+
so the component is always handed an explicit value and its default can
|
|
85
|
+
never apply. Without somewhere to declare it, every boolean a contract
|
|
86
|
+
describes reaches the component as `false`, whatever the component says.
|
|
87
|
+
|
|
88
|
+
That inverted `VideoEmbed.hasFacade`, whose whole purpose is to keep a
|
|
89
|
+
provider's iframe and its third-party cookies off the page until a reader
|
|
90
|
+
presses play. The contract said "Leave on"; every embed an author added
|
|
91
|
+
shipped with it off.
|
|
92
|
+
|
|
93
|
+
Deliberately boolean-only. `text` and `number` defaults are a different
|
|
94
|
+
question — an empty string and a missing number are already meaningful, and
|
|
95
|
+
a default there competes with `required` rather than completing it. Widen
|
|
96
|
+
this when a component needs it, not before.
|
|
97
|
+
*/
|
|
98
|
+
defaultValue: z.boolean().optional(),
|
|
99
|
+
/** Human-readable constraint description the AI reasons about. */
|
|
100
|
+
constraints: z.string().optional(),
|
|
101
|
+
/*
|
|
102
|
+
An optional field that most authors, and most compositions, should leave
|
|
103
|
+
empty: an override of a default the component already chooses well, or
|
|
104
|
+
screen-reader and status copy it already supplies. `VideoHero.pauseLabel`
|
|
105
|
+
is the shape of it — the control is already called "Pause background
|
|
106
|
+
video", and a field an author meets on every hero asking them to rename it
|
|
107
|
+
is noise between them and the heading.
|
|
108
|
+
|
|
109
|
+
A hint about attention, not about validity. The CMS draws such a field in a
|
|
110
|
+
collapsed section; an agent composing a page can skip it. It never makes a
|
|
111
|
+
field required or forbidden, and it is refused on a required field, which by
|
|
112
|
+
definition cannot be left alone.
|
|
113
|
+
*/
|
|
114
|
+
advanced: z.boolean().optional(),
|
|
115
|
+
/** For array or group fields, the nested field shape. */
|
|
116
|
+
of: z.array(ContentFieldSchema).optional(),
|
|
117
|
+
}).superRefine((field, ctx) => {
|
|
118
|
+
// Only `boolean` reads `defaultValue`, so anywhere else it is a value the
|
|
119
|
+
// author expects to take effect and nothing ever will. Rejecting it is the
|
|
120
|
+
// difference between a contract that fails validation and a field that
|
|
121
|
+
// quietly ignores half of what it was told.
|
|
122
|
+
if (field.advanced && field.required) {
|
|
123
|
+
ctx.addIssue({
|
|
124
|
+
code: z.ZodIssueCode.custom,
|
|
125
|
+
path: ['advanced'],
|
|
126
|
+
message: `"${field.name}" is required, so it cannot be advanced: an author has to fill it in.`,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
if (field.defaultValue !== undefined && field.type !== 'boolean') {
|
|
130
|
+
ctx.addIssue({
|
|
131
|
+
code: z.ZodIssueCode.custom,
|
|
132
|
+
path: ['defaultValue'],
|
|
133
|
+
message: `defaultValue is only read for boolean fields; "${field.name}" is ${field.type}.`,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}));
|
|
137
|
+
export const ComponentContractSchema = z.object({
|
|
138
|
+
// Identity
|
|
139
|
+
name: z.string().min(1).regex(/^[A-Z][A-Za-z0-9]+$/, 'Component names must be PascalCase'),
|
|
140
|
+
category: CategorySchema,
|
|
141
|
+
/**
|
|
142
|
+
* The shelf an authoring UI files this component under. Optional: when it is
|
|
143
|
+
* absent, {@link groupOf} falls back to {@link category}, so a design system
|
|
144
|
+
* that sets none groups exactly as it did before this field existed.
|
|
145
|
+
*/
|
|
146
|
+
group: GroupSchema.optional(),
|
|
147
|
+
description: z.string().min(20).max(280),
|
|
148
|
+
intent: z.string().min(20).max(500),
|
|
149
|
+
// Composition
|
|
150
|
+
composition: z.object({
|
|
151
|
+
placement: z.array(PlacementSchema).nonempty(),
|
|
152
|
+
maxPerPage: z.number().int().positive().nullable().default(null),
|
|
153
|
+
requiredSiblings: z.array(z.string()).default([]),
|
|
154
|
+
forbiddenAdjacent: z.array(z.string()).default([]),
|
|
155
|
+
allowedSlots: z.record(z.string(), z.array(z.string())).optional(),
|
|
156
|
+
}),
|
|
157
|
+
// Content
|
|
158
|
+
content: z.object({
|
|
159
|
+
fields: z.array(ContentFieldSchema),
|
|
160
|
+
variants: z
|
|
161
|
+
.array(z.object({
|
|
162
|
+
name: z.string(),
|
|
163
|
+
description: z.string(),
|
|
164
|
+
whenToUse: z.string(),
|
|
165
|
+
}))
|
|
166
|
+
.optional(),
|
|
167
|
+
}),
|
|
168
|
+
// Tokens
|
|
169
|
+
tokens: z.object({
|
|
170
|
+
consumes: z.array(z.string()),
|
|
171
|
+
configurable: z
|
|
172
|
+
.array(z.object({
|
|
173
|
+
prop: z.string(),
|
|
174
|
+
tokenGroup: z.string(),
|
|
175
|
+
allowedValues: z.array(z.string()),
|
|
176
|
+
}))
|
|
177
|
+
.optional(),
|
|
178
|
+
}),
|
|
179
|
+
// Accessibility
|
|
180
|
+
accessibility: z.object({
|
|
181
|
+
role: z.string().optional(),
|
|
182
|
+
keyboardSupport: z.array(z.string()).default([]),
|
|
183
|
+
screenReaderBehavior: z.string().min(10),
|
|
184
|
+
contentWarnings: z.array(z.string()).default([]),
|
|
185
|
+
}),
|
|
186
|
+
// Examples
|
|
187
|
+
examples: z
|
|
188
|
+
.array(z.object({
|
|
189
|
+
label: z.string(),
|
|
190
|
+
intent: z.string(),
|
|
191
|
+
storyId: z.string(),
|
|
192
|
+
}))
|
|
193
|
+
.min(1, 'Each component must have at least one example'),
|
|
194
|
+
antiExamples: z
|
|
195
|
+
.array(z.object({
|
|
196
|
+
label: z.string(),
|
|
197
|
+
why: z.string(),
|
|
198
|
+
useInstead: z.string().optional(),
|
|
199
|
+
}))
|
|
200
|
+
.default([]),
|
|
201
|
+
// Behavioral
|
|
202
|
+
behavior: z
|
|
203
|
+
.object({
|
|
204
|
+
fetchesData: z.boolean().default(false),
|
|
205
|
+
hasClientState: z.boolean().default(false),
|
|
206
|
+
animates: z.boolean().default(false),
|
|
207
|
+
requiresAnalytics: z.boolean().default(false),
|
|
208
|
+
})
|
|
209
|
+
.default({}),
|
|
210
|
+
});
|
|
211
|
+
/**
|
|
212
|
+
* The shelf a component is filed under: its `group` when set, otherwise its
|
|
213
|
+
* `category`.
|
|
214
|
+
*
|
|
215
|
+
* Anything that groups components should call this rather than reading either
|
|
216
|
+
* field directly, so a design system part-way through adopting `group` groups
|
|
217
|
+
* consistently instead of half one way and half the other. It takes a
|
|
218
|
+
* structural type so it also accepts the looser component shapes consumers
|
|
219
|
+
* carry around, not only a fully parsed {@link ComponentContract}.
|
|
220
|
+
*/
|
|
221
|
+
export function groupOf(component) {
|
|
222
|
+
return component.group ?? component.category;
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/contract/schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { Block } from 'payload';
|
|
2
|
+
import type { Overrides } from '../overrides.js';
|
|
3
|
+
import { type ContentField } from './fields.js';
|
|
4
|
+
/** The slice of a manifest component entry the generator reads. */
|
|
5
|
+
export interface ManifestComponent {
|
|
6
|
+
name: string;
|
|
7
|
+
category: string;
|
|
8
|
+
group?: string;
|
|
9
|
+
description: string;
|
|
10
|
+
intent: string;
|
|
11
|
+
composition: {
|
|
12
|
+
placement: string[];
|
|
13
|
+
maxPerPage: number | null;
|
|
14
|
+
requiredSiblings: string[];
|
|
15
|
+
forbiddenAdjacent: string[];
|
|
16
|
+
allowedSlots?: Record<string, string[]>;
|
|
17
|
+
};
|
|
18
|
+
content: {
|
|
19
|
+
fields: ContentField[];
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export interface ManifestLike {
|
|
23
|
+
components: Record<string, ManifestComponent>;
|
|
24
|
+
}
|
|
25
|
+
export interface GenerateOptions {
|
|
26
|
+
manifest: ManifestLike;
|
|
27
|
+
overrides: Overrides;
|
|
28
|
+
mediaCollection: string;
|
|
29
|
+
linkCollections: string[];
|
|
30
|
+
resolveSelectOptions: (component: string, path: string) => readonly string[] | null;
|
|
31
|
+
resolveNamedOptions: (typeName: string) => readonly string[] | null;
|
|
32
|
+
/**
|
|
33
|
+
* The host's labels for option values whose meaning is particular to its
|
|
34
|
+
* design system — `{ 'text-image': 'Text and image' }`. Consulted before the
|
|
35
|
+
* generic words in `./labels.ts`, which cover heading levels, HTML elements
|
|
36
|
+
* and anything that reads well split into words.
|
|
37
|
+
*/
|
|
38
|
+
optionLabels?: Readonly<Record<string, string>>;
|
|
39
|
+
/**
|
|
40
|
+
* A thumbnail for the block picker, or null for none.
|
|
41
|
+
*
|
|
42
|
+
* Payload draws a generic placeholder when a block has no `imageURL`, so a
|
|
43
|
+
* palette this size renders as dozens of identical grey mountains — worse
|
|
44
|
+
* than nothing, because the uniformity implies the images carry information.
|
|
45
|
+
*/
|
|
46
|
+
resolvePreview?: (component: string) => {
|
|
47
|
+
url: string;
|
|
48
|
+
alt?: string;
|
|
49
|
+
} | null;
|
|
50
|
+
}
|
|
51
|
+
export interface GeneratedBlock {
|
|
52
|
+
block: Block;
|
|
53
|
+
component: ManifestComponent;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Which components are authorable as blocks.
|
|
57
|
+
*
|
|
58
|
+
* `inline` placement means the component is a building block used *inside*
|
|
59
|
+
* another one — a `Card` within a `CardGrid`, a `Button` within a CTA. It
|
|
60
|
+
* reaches the page through its parent's fields, so offering it in the palette
|
|
61
|
+
* would let an author drop a bare card onto a page with nothing around it.
|
|
62
|
+
*
|
|
63
|
+
* `page` and `section` are the two that stand on their own. `notABlock` in the
|
|
64
|
+
* overrides removes the handful that are page-level but not authored — the
|
|
65
|
+
* chrome a template renders rather than a block an author places.
|
|
66
|
+
*/
|
|
67
|
+
export declare function isBlockCandidate(component: ManifestComponent, overrides: Overrides): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* The block slug is the manifest component name, byte for byte.
|
|
70
|
+
*
|
|
71
|
+
* Not a stylistic choice. `@forumone/throughline/publishing`'s composition step maps
|
|
72
|
+
* `blockType` straight to `type` with no transformation and looks it up in the
|
|
73
|
+
* manifest; a miss is an `unknown-component` **error**, which blocks publish.
|
|
74
|
+
* Kebab-casing the slugs would make every block on every page unpublishable,
|
|
75
|
+
* and the error would point at the design system rather than at the naming.
|
|
76
|
+
*/
|
|
77
|
+
export declare function generateBlock(component: ManifestComponent, options: GenerateOptions): Block;
|
|
78
|
+
export declare function generateBlocks(options: GenerateOptions): GeneratedBlock[];
|
|
79
|
+
//# sourceMappingURL=blocks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../../src/generate/blocks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAS,MAAM,SAAS,CAAA;AAE3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAkB,KAAK,YAAY,EAAqB,MAAM,aAAa,CAAA;AAOlF,mEAAmE;AACnE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE;QACX,SAAS,EAAE,MAAM,EAAE,CAAA;QACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;QACzB,gBAAgB,EAAE,MAAM,EAAE,CAAA;QAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAA;QAC3B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;KACxC,CAAA;IACD,OAAO,EAAE;QAAE,MAAM,EAAE,YAAY,EAAE,CAAA;KAAE,CAAA;CACpC;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;CAC9C;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,YAAY,CAAA;IACtB,SAAS,EAAE,SAAS,CAAA;IACpB,eAAe,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,oBAAoB,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,SAAS,MAAM,EAAE,GAAG,IAAI,CAAA;IACnF,mBAAmB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,SAAS,MAAM,EAAE,GAAG,IAAI,CAAA;IACnE;;;;;OAKG;IACH,YAAY,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IAC/C;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;CAC7E;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,KAAK,CAAA;IACZ,SAAS,EAAE,iBAAiB,CAAA;CAC7B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAG5F;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,iBAAiB,EAAE,OAAO,EAAE,eAAe,GAAG,KAAK,CAwE3F;AAYD,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,cAAc,EAAE,CAKzE"}
|