@zhama/a2ui-core 0.1.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 ADDED
@@ -0,0 +1,161 @@
1
+ # @zhama/a2ui-core
2
+
3
+ A2UI Protocol Core Library - Framework-agnostic TypeScript types and builders for A2UI protocol.
4
+
5
+ ## Overview
6
+
7
+ A2UI (Agent to UI) is a JSON-based streaming UI protocol for dynamically rendering user interfaces. This library provides:
8
+
9
+ - **Types**: Complete TypeScript type definitions for A2UI v0.8 and v0.9
10
+ - **Builders**: Convenient functions to build messages and components
11
+ - **Validators**: Message validation utilities
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @zhama/a2ui-core
17
+ # or
18
+ pnpm add @zhama/a2ui-core
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ ```typescript
24
+ import {
25
+ // Builders
26
+ text, column, button, card,
27
+ createSurface, updateComponents, updateDataModel,
28
+ createV09Messages,
29
+
30
+ // Validators
31
+ validateMessage,
32
+
33
+ // Utils
34
+ path, generateId,
35
+
36
+ // Types
37
+ type ComponentInstance,
38
+ type ServerToClientMessage,
39
+ } from '@zhama/a2ui-core';
40
+
41
+ // Create components
42
+ const title = text('Hello World', { id: 'title', usageHint: 'h1' });
43
+ const greeting = text({ path: '/user/name' }, { id: 'greeting' });
44
+ const root = column(['title', 'greeting'], { id: 'root' });
45
+
46
+ // Create messages
47
+ const messages = createV09Messages({
48
+ surfaceId: 'my-surface',
49
+ components: [title, greeting, root],
50
+ dataModel: { user: { name: 'John' } },
51
+ });
52
+
53
+ // Validate messages
54
+ const result = validateMessage(messages[0]);
55
+ console.log(result.valid); // true
56
+ ```
57
+
58
+ ## API Reference
59
+
60
+ ### Types
61
+
62
+ #### Primitives
63
+ - `StringOrPath` - String literal or data path binding
64
+ - `NumberOrPath` - Number literal or data path binding
65
+ - `BooleanOrPath` - Boolean literal or data path binding
66
+
67
+ #### Components
68
+ - `TextComponent`, `ImageComponent`, `IconComponent`, `VideoComponent`, `AudioPlayerComponent`
69
+ - `RowComponent`, `ColumnComponent`, `ListComponent`, `CardComponent`
70
+ - `TabsComponent`, `DividerComponent`, `ModalComponent`
71
+ - `ButtonComponent`, `CheckBoxComponent`, `TextFieldComponent`
72
+ - `DateTimeInputComponent`, `ChoicePickerComponent`, `SliderComponent`
73
+
74
+ #### Messages
75
+ - `CreateSurfaceMessage`, `UpdateComponentsMessage`, `UpdateDataModelMessage`, `DeleteSurfaceMessage` (v0.9)
76
+ - `BeginRenderingMessage`, `SurfaceUpdateMessage`, `DataModelUpdateMessage` (v0.8)
77
+
78
+ ### Builders
79
+
80
+ #### Component Builders
81
+ ```typescript
82
+ // Content components
83
+ text(content: StringOrPath, options?: TextOptions): ComponentInstance
84
+ image(url: StringOrPath, options?: ImageOptions): ComponentInstance
85
+ icon(name: StringOrPath, options?: IconOptions): ComponentInstance
86
+
87
+ // Layout components
88
+ row(children: ChildrenProperty, options?: LayoutOptions): ComponentInstance
89
+ column(children: ChildrenProperty, options?: LayoutOptions): ComponentInstance
90
+ card(childId: string, options?: CardOptions): ComponentInstance
91
+
92
+ // Interactive components
93
+ button(childId: string, action: Action, options?: ButtonOptions): ComponentInstance
94
+ textField(label: StringOrPath, text?: StringOrPath, options?: TextFieldOptions): ComponentInstance
95
+
96
+ // Convenience
97
+ textButton(buttonText: string, action: Action, options?: ButtonOptions): [ComponentInstance, ComponentInstance]
98
+ h1(content: StringOrPath, options?: TextOptions): ComponentInstance
99
+ ```
100
+
101
+ #### Message Builders
102
+ ```typescript
103
+ // v0.9
104
+ createSurface(surfaceId: string, catalogId?: string): CreateSurfaceMessage
105
+ updateComponents(surfaceId: string, components: ComponentInstance[]): UpdateComponentsMessage
106
+ updateDataModel(surfaceId: string, value: unknown, path?: string): UpdateDataModelMessage
107
+ deleteSurface(surfaceId: string): DeleteSurfaceMessage
108
+ createV09Messages(options: CreateV09Options): ServerToClientMessageV09[]
109
+
110
+ // v0.8
111
+ beginRendering(rootId: string, surfaceId?: string, styles?: Record<string, string>): BeginRenderingMessage
112
+ surfaceUpdate(components: ComponentInstanceV08[], surfaceId?: string): SurfaceUpdateMessage
113
+ dataModelUpdate(contents: ValueMap[], surfaceId?: string): DataModelUpdateMessage
114
+ createV08Messages(options: CreateV08Options): ServerToClientMessageV08[]
115
+
116
+ // Utilities
117
+ messagesToJsonl(messages: ServerToClientMessage[]): string
118
+ jsonlToMessages(jsonl: string): ServerToClientMessage[]
119
+ ```
120
+
121
+ #### Data Model Builders
122
+ ```typescript
123
+ objectToValueMap(obj: DataObject): ValueMap[]
124
+ valueToValueMap(key: string, value: DataValue): ValueMap
125
+ valueMapToObject(valueMaps: ValueMap[]): DataObject
126
+ ```
127
+
128
+ ### Validators
129
+
130
+ ```typescript
131
+ validateMessage(message: ServerToClientMessage, options?: ValidationOptions): ValidationResult
132
+ validateMessages(messages: ServerToClientMessage[], options?: ValidationOptions): ValidationResult
133
+ ```
134
+
135
+ ### Utils
136
+
137
+ ```typescript
138
+ path(dataPath: string): { path: string } // Create data binding
139
+ isPathBinding(value): boolean // Check if value is a path binding
140
+ generateId(prefix?: string): string // Generate unique ID
141
+ uuid(): string // Generate UUID v4
142
+ ```
143
+
144
+ ## Protocol Versions
145
+
146
+ ### v0.9 (Prompt-first)
147
+ - `createSurface` - Create a new surface
148
+ - `updateComponents` - Update components with flat component list
149
+ - `updateDataModel` - Update data model
150
+ - `deleteSurface` - Delete surface
151
+
152
+ ### v0.8 (Structured output)
153
+ - `beginRendering` - Signal to begin rendering
154
+ - `surfaceUpdate` - Update components
155
+ - `dataModelUpdate` - Update data model using ValueMap format
156
+ - `deleteSurface` - Delete surface
157
+
158
+ ## License
159
+
160
+ MIT
161
+
@@ -0,0 +1,496 @@
1
+ 'use strict';
2
+
3
+ // src/builders/id-generator.ts
4
+ var componentIdCounter = 0;
5
+ function generateId(prefix = "comp") {
6
+ return `${prefix}_${Date.now()}_${componentIdCounter++}`;
7
+ }
8
+ function resetIdCounter() {
9
+ componentIdCounter = 0;
10
+ }
11
+ function getIdCounter() {
12
+ return componentIdCounter;
13
+ }
14
+
15
+ // src/builders/component-builder.ts
16
+ function text(content, options = {}) {
17
+ const { id = generateId("text"), weight, usageHint } = options;
18
+ return {
19
+ id,
20
+ component: "Text",
21
+ text: content,
22
+ ...weight !== void 0 && { weight },
23
+ ...usageHint && { usageHint }
24
+ };
25
+ }
26
+ function image(url, options = {}) {
27
+ const { id = generateId("image"), weight, fit, usageHint } = options;
28
+ return {
29
+ id,
30
+ component: "Image",
31
+ url,
32
+ ...weight !== void 0 && { weight },
33
+ ...fit && { fit },
34
+ ...usageHint && { usageHint }
35
+ };
36
+ }
37
+ function icon(name, options = {}) {
38
+ const { id = generateId("icon"), weight } = options;
39
+ return {
40
+ id,
41
+ component: "Icon",
42
+ name,
43
+ ...weight !== void 0 && { weight }
44
+ };
45
+ }
46
+ function video(url, options = {}) {
47
+ const { id = generateId("video"), weight } = options;
48
+ return {
49
+ id,
50
+ component: "Video",
51
+ url,
52
+ ...weight !== void 0 && { weight }
53
+ };
54
+ }
55
+ function audioPlayer(url, options = {}) {
56
+ const { id = generateId("audio"), weight, description } = options;
57
+ return {
58
+ id,
59
+ component: "AudioPlayer",
60
+ url,
61
+ ...weight !== void 0 && { weight },
62
+ ...description && { description }
63
+ };
64
+ }
65
+ function row(children, options = {}) {
66
+ const { id = generateId("row"), weight, alignment, distribution } = options;
67
+ return {
68
+ id,
69
+ component: "Row",
70
+ children,
71
+ ...weight !== void 0 && { weight },
72
+ ...alignment && { alignment },
73
+ ...distribution && { distribution }
74
+ };
75
+ }
76
+ function column(children, options = {}) {
77
+ const { id = generateId("column"), weight, alignment, distribution } = options;
78
+ return {
79
+ id,
80
+ component: "Column",
81
+ children,
82
+ ...weight !== void 0 && { weight },
83
+ ...alignment && { alignment },
84
+ ...distribution && { distribution }
85
+ };
86
+ }
87
+ function list(children, options = {}) {
88
+ const { id = generateId("list"), weight, direction, alignment } = options;
89
+ return {
90
+ id,
91
+ component: "List",
92
+ children,
93
+ ...weight !== void 0 && { weight },
94
+ ...direction && { direction },
95
+ ...alignment && { alignment }
96
+ };
97
+ }
98
+ function card(childId, options = {}) {
99
+ const { id = generateId("card"), weight } = options;
100
+ return {
101
+ id,
102
+ component: "Card",
103
+ child: childId,
104
+ ...weight !== void 0 && { weight }
105
+ };
106
+ }
107
+ function tabs(items, options = {}) {
108
+ const { id = generateId("tabs"), weight } = options;
109
+ return {
110
+ id,
111
+ component: "Tabs",
112
+ tabItems: items.map((item) => ({
113
+ title: item.title,
114
+ child: item.childId
115
+ })),
116
+ ...weight !== void 0 && { weight }
117
+ };
118
+ }
119
+ function divider(options = {}) {
120
+ const { id = generateId("divider"), weight, axis } = options;
121
+ return {
122
+ id,
123
+ component: "Divider",
124
+ ...weight !== void 0 && { weight },
125
+ ...axis && { axis }
126
+ };
127
+ }
128
+ function modal(entryPointChildId, contentChildId, options = {}) {
129
+ const { id = generateId("modal"), weight } = options;
130
+ return {
131
+ id,
132
+ component: "Modal",
133
+ entryPointChild: entryPointChildId,
134
+ contentChild: contentChildId,
135
+ ...weight !== void 0 && { weight }
136
+ };
137
+ }
138
+ function button(childId, action, options = {}) {
139
+ const { id = generateId("button"), weight, primary } = options;
140
+ return {
141
+ id,
142
+ component: "Button",
143
+ child: childId,
144
+ action,
145
+ ...weight !== void 0 && { weight },
146
+ ...primary !== void 0 && { primary }
147
+ };
148
+ }
149
+ function checkbox(label, value, options = {}) {
150
+ const { id = generateId("checkbox"), weight } = options;
151
+ return {
152
+ id,
153
+ component: "CheckBox",
154
+ label,
155
+ value,
156
+ ...weight !== void 0 && { weight }
157
+ };
158
+ }
159
+ function textField(label, textValue, options = {}) {
160
+ const { id = generateId("textfield"), weight, usageHint, validationRegexp } = options;
161
+ return {
162
+ id,
163
+ component: "TextField",
164
+ label,
165
+ ...textValue !== void 0 && { text: textValue },
166
+ ...weight !== void 0 && { weight },
167
+ ...usageHint && { usageHint },
168
+ ...validationRegexp && { validationRegexp }
169
+ };
170
+ }
171
+ function dateTimeInput(value, options = {}) {
172
+ const { id = generateId("datetime"), weight, enableDate, enableTime, outputFormat, label } = options;
173
+ return {
174
+ id,
175
+ component: "DateTimeInput",
176
+ value,
177
+ ...weight !== void 0 && { weight },
178
+ ...enableDate !== void 0 && { enableDate },
179
+ ...enableTime !== void 0 && { enableTime },
180
+ ...outputFormat && { outputFormat },
181
+ ...label && { label }
182
+ };
183
+ }
184
+ function choicePicker(optionsList, value, usageHint, options = {}) {
185
+ const { id = generateId("choice"), weight, label } = options;
186
+ return {
187
+ id,
188
+ component: "ChoicePicker",
189
+ options: optionsList,
190
+ value,
191
+ usageHint,
192
+ ...weight !== void 0 && { weight },
193
+ ...label && { label }
194
+ };
195
+ }
196
+ function slider(value, options = {}) {
197
+ const { id = generateId("slider"), weight, label, min, max } = options;
198
+ return {
199
+ id,
200
+ component: "Slider",
201
+ value,
202
+ ...weight !== void 0 && { weight },
203
+ ...label && { label },
204
+ ...min !== void 0 && { min },
205
+ ...max !== void 0 && { max }
206
+ };
207
+ }
208
+ function textButton(buttonText, action, options = {}) {
209
+ const textId = options.textId ?? generateId("btn_text");
210
+ const textComp = text(buttonText, { id: textId });
211
+ const buttonComp = button(textId, action, options);
212
+ return [textComp, buttonComp];
213
+ }
214
+ function h1(content, options = {}) {
215
+ return text(content, { ...options, usageHint: "h1" });
216
+ }
217
+ function h2(content, options = {}) {
218
+ return text(content, { ...options, usageHint: "h2" });
219
+ }
220
+ function h3(content, options = {}) {
221
+ return text(content, { ...options, usageHint: "h3" });
222
+ }
223
+ function h4(content, options = {}) {
224
+ return text(content, { ...options, usageHint: "h4" });
225
+ }
226
+ function h5(content, options = {}) {
227
+ return text(content, { ...options, usageHint: "h5" });
228
+ }
229
+ function caption(content, options = {}) {
230
+ return text(content, { ...options, usageHint: "caption" });
231
+ }
232
+ function body(content, options = {}) {
233
+ return text(content, { ...options, usageHint: "body" });
234
+ }
235
+
236
+ // src/types/messages.ts
237
+ var STANDARD_CATALOG_ID = "https://a2ui.dev/specification/0.9/standard_catalog_definition.json";
238
+
239
+ // src/builders/data-model-builder.ts
240
+ var DEFAULT_PATH_MAPPINGS = {};
241
+ function objectToValueMap(obj, prefix = "") {
242
+ const entries = [];
243
+ for (const [key, value] of Object.entries(obj)) {
244
+ const fullKey = prefix ? `${prefix}/${key}` : `/${key}`;
245
+ entries.push(valueToValueMap(fullKey, value));
246
+ }
247
+ return entries;
248
+ }
249
+ function valueToValueMap(key, value) {
250
+ if (value === null || value === void 0) {
251
+ return { key, valueString: "" };
252
+ }
253
+ if (typeof value === "string") {
254
+ return { key, valueString: value };
255
+ }
256
+ if (typeof value === "number") {
257
+ return { key, valueNumber: value };
258
+ }
259
+ if (typeof value === "boolean") {
260
+ return { key, valueBoolean: value };
261
+ }
262
+ if (Array.isArray(value)) {
263
+ return {
264
+ key,
265
+ valueMap: value.map((item, index) => valueToValueMap(String(index), item))
266
+ };
267
+ }
268
+ if (typeof value === "object") {
269
+ const nestedMaps = [];
270
+ for (const [k, v] of Object.entries(value)) {
271
+ nestedMaps.push(valueToValueMap(k, v));
272
+ }
273
+ return { key, valueMap: nestedMaps };
274
+ }
275
+ return { key, valueString: String(value) };
276
+ }
277
+ function normalizePath(path, pathMappings = {}) {
278
+ let normalizedPath = path.replace(/\./g, "/");
279
+ if (!normalizedPath.startsWith("/")) {
280
+ normalizedPath = `/${normalizedPath}`;
281
+ }
282
+ for (const [from, to] of Object.entries(pathMappings)) {
283
+ const fromPattern = new RegExp(`^/${from}(/|$)`);
284
+ if (fromPattern.test(normalizedPath)) {
285
+ normalizedPath = normalizedPath.replace(fromPattern, `/${to}$1`);
286
+ }
287
+ }
288
+ return normalizedPath;
289
+ }
290
+ function updatesToValueMap(updates, basePath = "", pathMappings = DEFAULT_PATH_MAPPINGS) {
291
+ const entries = [];
292
+ for (const update of updates) {
293
+ const rawPath = update.path.startsWith("/") ? update.path : `${basePath}/${update.path}`;
294
+ const normalizedPath = normalizePath(rawPath, pathMappings);
295
+ if (update.value !== null && typeof update.value === "object" && !Array.isArray(update.value)) {
296
+ const flattenedEntries = flattenObjectToValueMap(
297
+ update.value,
298
+ normalizedPath
299
+ );
300
+ entries.push(...flattenedEntries);
301
+ } else {
302
+ entries.push(valueToValueMap(normalizedPath, update.value));
303
+ }
304
+ }
305
+ return entries;
306
+ }
307
+ function flattenObjectToValueMap(obj, basePath) {
308
+ const entries = [];
309
+ for (const [key, value] of Object.entries(obj)) {
310
+ const fullPath = `${basePath}/${key}`;
311
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
312
+ const nestedEntries = flattenObjectToValueMap(value, fullPath);
313
+ entries.push(...nestedEntries);
314
+ } else {
315
+ entries.push(valueToValueMap(fullPath, value));
316
+ }
317
+ }
318
+ return entries;
319
+ }
320
+ function valueMapToObject(valueMaps) {
321
+ const result = {};
322
+ for (const valueMap of valueMaps) {
323
+ const key = valueMap.key.startsWith("/") ? valueMap.key.slice(1) : valueMap.key;
324
+ if (valueMap.valueString !== void 0) {
325
+ result[key] = valueMap.valueString;
326
+ } else if (valueMap.valueNumber !== void 0) {
327
+ result[key] = valueMap.valueNumber;
328
+ } else if (valueMap.valueBoolean !== void 0) {
329
+ result[key] = valueMap.valueBoolean;
330
+ } else if (valueMap.valueMap !== void 0) {
331
+ result[key] = valueMapToObject(valueMap.valueMap);
332
+ }
333
+ }
334
+ return result;
335
+ }
336
+
337
+ // src/builders/message-builder.ts
338
+ function createSurface(surfaceId, catalogId = STANDARD_CATALOG_ID) {
339
+ return {
340
+ createSurface: {
341
+ surfaceId,
342
+ catalogId
343
+ }
344
+ };
345
+ }
346
+ function updateComponents(surfaceId, components) {
347
+ return {
348
+ updateComponents: {
349
+ surfaceId,
350
+ components
351
+ }
352
+ };
353
+ }
354
+ function updateDataModel(surfaceId, value, path, op = "replace") {
355
+ return {
356
+ updateDataModel: {
357
+ surfaceId,
358
+ ...path && { path },
359
+ op,
360
+ ...op !== "remove" && { value }
361
+ }
362
+ };
363
+ }
364
+ function deleteSurface(surfaceId) {
365
+ return {
366
+ deleteSurface: {
367
+ surfaceId
368
+ }
369
+ };
370
+ }
371
+ function createV09Messages(options) {
372
+ const { surfaceId, catalogId = STANDARD_CATALOG_ID, components, dataModel } = options;
373
+ const messages = [
374
+ createSurface(surfaceId, catalogId),
375
+ updateComponents(surfaceId, components)
376
+ ];
377
+ if (dataModel) {
378
+ messages.push(updateDataModel(surfaceId, dataModel));
379
+ }
380
+ return messages;
381
+ }
382
+ function beginRendering(rootId, surfaceId = "@default", styles) {
383
+ return {
384
+ beginRendering: {
385
+ surfaceId,
386
+ root: rootId,
387
+ ...styles && { styles }
388
+ }
389
+ };
390
+ }
391
+ function surfaceUpdate(components, surfaceId = "@default") {
392
+ return {
393
+ surfaceUpdate: {
394
+ surfaceId,
395
+ components
396
+ }
397
+ };
398
+ }
399
+ function dataModelUpdate(contents, surfaceId = "@default", path) {
400
+ return {
401
+ dataModelUpdate: {
402
+ surfaceId,
403
+ contents,
404
+ ...path && { path }
405
+ }
406
+ };
407
+ }
408
+ function dataModelInit(data, surfaceId = "@default") {
409
+ return dataModelUpdate(objectToValueMap(data), surfaceId);
410
+ }
411
+ function pathUpdate(path, value, surfaceId = "@default") {
412
+ return {
413
+ dataModelUpdate: {
414
+ surfaceId,
415
+ path,
416
+ contents: [valueToValueMap("", value)]
417
+ }
418
+ };
419
+ }
420
+ function deleteSurfaceV08(surfaceId) {
421
+ return {
422
+ deleteSurface: {
423
+ surfaceId
424
+ }
425
+ };
426
+ }
427
+ function createV08Messages(options) {
428
+ const { rootId, components, dataModel, surfaceId = "@default", styles } = options;
429
+ const messages = [
430
+ surfaceUpdate(components, surfaceId)
431
+ ];
432
+ if (dataModel) {
433
+ messages.push(dataModelInit(dataModel, surfaceId));
434
+ }
435
+ messages.push(beginRendering(rootId, surfaceId, styles));
436
+ return messages;
437
+ }
438
+ function messagesToJsonl(messages) {
439
+ return messages.map((msg) => JSON.stringify(msg)).join("\n");
440
+ }
441
+ function jsonlToMessages(jsonl) {
442
+ return jsonl.split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
443
+ }
444
+
445
+ exports.DEFAULT_PATH_MAPPINGS = DEFAULT_PATH_MAPPINGS;
446
+ exports.audioPlayer = audioPlayer;
447
+ exports.beginRendering = beginRendering;
448
+ exports.body = body;
449
+ exports.button = button;
450
+ exports.caption = caption;
451
+ exports.card = card;
452
+ exports.checkbox = checkbox;
453
+ exports.choicePicker = choicePicker;
454
+ exports.column = column;
455
+ exports.createSurface = createSurface;
456
+ exports.createV08Messages = createV08Messages;
457
+ exports.createV09Messages = createV09Messages;
458
+ exports.dataModelInit = dataModelInit;
459
+ exports.dataModelUpdate = dataModelUpdate;
460
+ exports.dateTimeInput = dateTimeInput;
461
+ exports.deleteSurface = deleteSurface;
462
+ exports.deleteSurfaceV08 = deleteSurfaceV08;
463
+ exports.divider = divider;
464
+ exports.flattenObjectToValueMap = flattenObjectToValueMap;
465
+ exports.generateId = generateId;
466
+ exports.getIdCounter = getIdCounter;
467
+ exports.h1 = h1;
468
+ exports.h2 = h2;
469
+ exports.h3 = h3;
470
+ exports.h4 = h4;
471
+ exports.h5 = h5;
472
+ exports.icon = icon;
473
+ exports.image = image;
474
+ exports.jsonlToMessages = jsonlToMessages;
475
+ exports.list = list;
476
+ exports.messagesToJsonl = messagesToJsonl;
477
+ exports.modal = modal;
478
+ exports.normalizePath = normalizePath;
479
+ exports.objectToValueMap = objectToValueMap;
480
+ exports.pathUpdate = pathUpdate;
481
+ exports.resetIdCounter = resetIdCounter;
482
+ exports.row = row;
483
+ exports.slider = slider;
484
+ exports.surfaceUpdate = surfaceUpdate;
485
+ exports.tabs = tabs;
486
+ exports.text = text;
487
+ exports.textButton = textButton;
488
+ exports.textField = textField;
489
+ exports.updateComponents = updateComponents;
490
+ exports.updateDataModel = updateDataModel;
491
+ exports.updatesToValueMap = updatesToValueMap;
492
+ exports.valueMapToObject = valueMapToObject;
493
+ exports.valueToValueMap = valueToValueMap;
494
+ exports.video = video;
495
+ //# sourceMappingURL=index.cjs.map
496
+ //# sourceMappingURL=index.cjs.map