svedit 0.3.0 → 0.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Svedit
2
2
 
3
- Svedit (think Svelte Edit) is a tiny library for building **rich content editors** with Svelte 5. You can model your content in JSON, render it with custom Svelte components, and edit it directly in the layout.
3
+ Svedit (think Svelte Edit) is a a tiny library for building editable websites in Svelte. You can model your content in JSON, render it with custom Svelte components, and edit it directly in the layout.
4
4
 
5
5
  Try the [demo](https://svedit.vercel.app).
6
6
 
@@ -39,7 +39,7 @@ Now make it your own. The next thing you probably want to do is define your own
39
39
 
40
40
  **Chromeless canvas:** We keep the canvas chromeless, meaning there's no UI elements like toolbars or menus mingled with the content. You can interact with text directly, but everything else happens via tools are shown in separate overlays or in the fixed toolbar.
41
41
 
42
- **Convention over configuration:** We use conventions and assumptions to reduce configuration code and limit the number of ways something can go wrong. For instance, we assume that a node with a property named `content` of type `string` or `annotated_string` is considered kind `text`, while all other nodes are considered kind `node`. Text nodes have special behavior in the system for editing (e.g. they can be splitted and joined).
42
+ **Convention over configuration:** We use conventions and assumptions to reduce configuration code and limit the number of ways something can go wrong. For instance, we assume that a node with a property named `content` of type `annotated_text` is considered kind `text`, while all other nodes are considered kind `node`. Text nodes have special behavior in the system for editing (e.g. they can be splitted and joined).
43
43
 
44
44
  **White-box library:** We expose the internals of the library to allow you to customize and extend it to your needs. That means a little bit more work upfront, but in return lets you control "everything" — the toolbar, the overlays, or how fast the node cursor blinks.
45
45
 
@@ -63,7 +63,7 @@ Properties of nodes can hold values:
63
63
  - `string_array`: An array of good old JavaScript strings
64
64
  - `integer_array`: An array of integers
65
65
  - `number_array`: An array of numbers
66
- - `annotated_string`: a plain text string, but with annotations (bold, italic, link etc.)
66
+ - `annotated_text`: a plain text string, but with annotations (bold, italic, link etc.)
67
67
 
68
68
  Or references:
69
69
  - `node`: References a single node (e.g. an image node can reference a global asset node)
@@ -73,35 +73,53 @@ Or references:
73
73
  ```js
74
74
  const document_schema = {
75
75
  page: {
76
- body: {
77
- type: 'node_array',
78
- node_types: ['nav', 'paragraph', 'list'],
79
- default_node_type: 'paragraph',
76
+ kind: 'document',
77
+ properties: {
78
+ body: {
79
+ type: 'node_array',
80
+ node_types: ['nav', 'paragraph', 'list'],
81
+ default_node_type: 'paragraph',
82
+ }
80
83
  }
81
84
  },
82
85
  paragraph: {
83
- content: { type: 'annotated_string' }
86
+ kind: 'text',
87
+ properties: {
88
+ content: { type: 'annotated_text', allow_newlines: true }
89
+ }
84
90
  },
85
91
  list_item: {
86
- content: { type: 'annotated_string' },
92
+ kind: 'text',
93
+ properties: {
94
+ content: { type: 'annotated_text', allow_newlines: true },
95
+ }
87
96
  },
88
97
  list: {
89
- list_items: {
90
- type: 'node_array',
91
- node_types: ['list_item'],
92
- default_node_type: 'list_item',
98
+ kind: 'block',
99
+ properties: {
100
+ list_items: {
101
+ type: 'node_array',
102
+ node_types: ['list_item'],
103
+ default_node_type: 'list_item',
104
+ }
93
105
  }
94
106
  },
95
107
  nav: {
96
- nav_items: {
97
- type: 'node_array',
98
- node_types: ['nav_item'],
99
- default_node_type: 'nav_item',
108
+ kind: 'block',
109
+ properties: {
110
+ nav_items: {
111
+ type: 'node_array',
112
+ node_types: ['nav_item'],
113
+ default_node_type: 'nav_item',
114
+ }
100
115
  }
101
116
  },
102
117
  nav_item: {
103
- url: { type: 'string' },
104
- label: { type: 'string' },
118
+ kind: 'block',
119
+ properties: {
120
+ url: { type: 'string' },
121
+ label: { type: 'string' },
122
+ }
105
123
  }
106
124
  };
107
125
  ```
@@ -192,14 +210,15 @@ const document_config = {
192
210
  // Custom functions to insert new "blank" nodes and setting the selection
193
211
  // depending on the intended behavior.
194
212
  inserters: {
195
- text: function(tr, content = ['', []], layout = 1) {
213
+ text: function(tr, content = {text: '', annotations: []}, layout = 1) {
196
214
  const new_text = {
197
215
  id: nanoid(),
198
216
  type: 'text',
199
217
  layout,
200
218
  content
201
219
  };
202
- tr.insert_nodes([new_text]);
220
+ tr.create(new_text);
221
+ tr.insert_nodes([new_text.id]);
203
222
  },
204
223
  }
205
224
  };
@@ -276,7 +295,7 @@ Selections are at the heart of Svedit. There are just three types of selections:
276
295
  }
277
296
  ```
278
297
 
279
- You can access the current selection through `doc.selection` anytime. And you can programmatically set the selection using `doc.set_selection(new_selection)`.
298
+ You can access the current selection through `doc.selection` anytime. And you can programmatically set the selection using `doc.selection = new_selection`.
280
299
 
281
300
  ## Rendering
282
301
 
@@ -320,7 +339,7 @@ a simplified version of the markup of `<NodeCursorTrap>` and why it is implement
320
339
  Further things to consider:
321
340
 
322
341
  - If you make a sub-tree `contenteditable="false"`, be aware that you can't create a `contenteditable="true"` segment somewhere inside it. Svedit can only work reliably when there's one contenteditable="true" at root (it's set by `<Svedit`>)
323
- - `<AnnotatedString>` and `<CustomProperty>` must not be wrapped in `contenteditable="false"` to work properly.
342
+ - `<AnnotatedTextProperty>` and `<CustomProperty>` must not be wrapped in `contenteditable="false"` to work properly.
324
343
  - Never apply `position: relative` to the direct parent of `<AnnotatedTextProperty>`, it will cause a [weird Safari bug](https://bsky.app/profile/michaelaufreiter.com/post/3lxvdqyxc622s) to destroy the DOM.
325
344
  - Never use an `<a>` tag inside a `contenteditable="true"` element, as it will cause unexpected behavior. Make it a `<div>` while editing, and an `<a>` in read-only mode.
326
345
 
@@ -358,4 +377,4 @@ It's early. Expect bugs. Expect missing features. Expect the need for more work
358
377
 
359
378
  ## Credits
360
379
 
361
- Svedit led by [Michael Aufreiter](https://michaelaufreiter.com) with guidance and support from [Johannes Mutter](https://mutter.co).
380
+ Svedit is led by [Michael Aufreiter](https://michaelaufreiter.com) with guidance and support from [Johannes Mutter](https://mutter.co).
@@ -1,12 +1,12 @@
1
1
  <script>
2
2
  import { getContext } from 'svelte';
3
- import { char_slice, get_char_length } from './util.js';
3
+ import { char_slice, get_char_length, snake_to_pascal } from './util.js';
4
4
 
5
- /** @import { AnnotatedStringPropertyProps, Annotation, AnnotationFragment } from './types.d.ts'; */
5
+ /** @import { AnnotatedTextPropertyProps, Annotation, AnnotationFragment } from './types.d.ts'; */
6
6
 
7
7
  const svedit = getContext('svedit');
8
8
 
9
- /** @type {AnnotatedStringPropertyProps} */
9
+ /** @type {AnnotatedTextPropertyProps} */
10
10
  let {
11
11
  path,
12
12
  class: css_class,
@@ -20,32 +20,36 @@
20
20
  /**
21
21
  * Converts text with annotations into renderable fragments for display.
22
22
  * @param {string} text - The plain text content
23
- * @param {Array<Annotation>} annotations - Array of annotations where each is [start_offset, end_offset, type, options?] (minimum 3 elements)
23
+ * @param {Array<Annotation>} annotations - Array of annotations where each is {start_offset, end_offset, node_id}
24
24
  * @returns {Array<string|AnnotationFragment>} Array of fragments - strings for plain text, AnnotationFragment objects for annotated content
25
25
  */
26
- function render_annotated_string(text, annotations) {
26
+ function get_fragments(text, annotations) {
27
27
  let fragments = [];
28
28
  let last_index = 0;
29
29
 
30
30
  // Sort annotations by start_offset
31
- const sorted_annotations = [...annotations].sort((a, b) => a[0] - b[0]);
31
+ const sorted_annotations = [...annotations].sort((a, b) => a.start_offset - b.start_offset);
32
32
 
33
- for (let [index, annotation] of sorted_annotations.entries()) {
33
+ for (let [, annotation] of sorted_annotations.entries()) {
34
34
  // Add text before the annotation using character-aware slicing
35
- if (annotation[0] > last_index) {
36
- fragments.push(char_slice(text, last_index, annotation[0]));
35
+ if (annotation.start_offset > last_index) {
36
+ fragments.push(char_slice(text, last_index, annotation.start_offset));
37
37
  }
38
38
 
39
39
  // Add the annotated string using character-aware slicing
40
- const annotated_content = char_slice(text, annotation[0], annotation[1]);
40
+ const annotated_content = char_slice(text, annotation.start_offset, annotation.end_offset);
41
+ const node = svedit.doc.get(annotation.node_id);
42
+ if (!node) throw new Error(`Node not found for annotation ${annotation.node_id}`);
43
+
41
44
  fragments.push({
42
- type: annotation[2],
45
+ node,
43
46
  content: annotated_content,
44
- annotation_index: index,
45
- data: annotation[3]
47
+ // NOTE: We need to provide the original index here, because the source data
48
+ // is the address space.
49
+ annotation_index: annotations.indexOf(annotation),
46
50
  });
47
51
 
48
- last_index = annotation[1];
52
+ last_index = annotation.end_offset;
49
53
  }
50
54
 
51
55
  // Add any remaining text after the last annotation using character-aware slicing
@@ -56,15 +60,9 @@
56
60
  return fragments;
57
61
  }
58
62
 
59
- let fragments = $derived(render_annotated_string(svedit.doc.get(path)[0], svedit.doc.get(path)[1]));
60
- let plain_text = $derived(svedit.doc.get(path)[0]);
63
+ let fragments = $derived(get_fragments(svedit.doc.get(path).text, svedit.doc.get(path).annotations));
64
+ let plain_text = $derived(svedit.doc.get(path).text);
61
65
 
62
- /**
63
- * @param {MouseEvent} e - The click event
64
- */
65
- function handle_link_click(e) {
66
- e.preventDefault();
67
- }
68
66
  </script>
69
67
 
70
68
  {#key plain_text}
@@ -79,21 +77,10 @@
79
77
  placeholder={placeholder}
80
78
  >
81
79
  {#each fragments as fragment, index (index)}
82
- {#if typeof fragment === 'string'}<!--
83
- -->{fragment}<!--
84
- -->{:else if fragment.type === 'emphasis'}<!--
85
- --><em>{fragment.content}</em><!--
86
- -->{:else if fragment.type === 'strong'}<!--
87
- --><strong>{fragment.content}</strong><!--
88
- -->{:else if fragment.type === 'link'}<!--
89
- --><a
90
- onclick={handle_link_click}
91
- style="anchor-name: --{path.join('-') + '-' + fragment.annotation_index};"
92
- href={fragment.data.href}
93
- target={fragment.data.target || '_self'}>{fragment.content}</a><!--
94
- -->{:else}<!--
95
- -->{fragment.content}<!--
96
- -->{/if}
80
+ {#if typeof fragment === 'string'}{fragment}{:else}
81
+ {@const AnnotationComponent = svedit.doc.config.node_components[snake_to_pascal(fragment.node.type)]}
82
+ <AnnotationComponent path={[...path, 'annotations', fragment.annotation_index, 'node_id']} content={fragment.content} />
83
+ {/if}
97
84
  {/each}<!--
98
85
  --><br>
99
86
  </div>
@@ -118,12 +105,13 @@
118
105
 
119
106
  /* We can safely hide the <br> element when the placeholder is empty and focused. */
120
107
  /* No longer the cursor will be rendered after the placeholder when focused. */
108
+ /* ATTENTION: This hack has the side effect that in Safari Desktop the cursor sometimes disappears. */
121
109
  [placeholder].empty.focused br {
122
110
  display:none;
123
111
  }
124
112
 
125
- .text.focused {
113
+ /*.text.focused {
126
114
  background: none;
127
- outline: 1px dashed var(--editing-stroke-color);
128
- }
115
+ outline: 1px solid var(--editing-stroke-color);
116
+ }*/
129
117
  </style>
@@ -0,0 +1,7 @@
1
+ export default AnnotatedTextProperty;
2
+ type AnnotatedTextProperty = {
3
+ $on?(type: string, callback: (e: any) => void): () => void;
4
+ $set?(props: Partial<AnnotatedTextPropertyProps>): void;
5
+ };
6
+ declare const AnnotatedTextProperty: import("svelte").Component<import("./types.d.ts").AnnotatedTextPropertyProps, {}, "">;
7
+ //# sourceMappingURL=AnnotatedTextProperty.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnnotatedTextProperty.svelte.d.ts","sourceRoot":"","sources":["../src/lib/AnnotatedTextProperty.svelte.js"],"names":[],"mappings":";;;;;AAyFA,2HAAoE"}
@@ -5,9 +5,10 @@
5
5
  * Selection,
6
6
  * Annotation,
7
7
  * PrimitiveType,
8
- * DocumentSchemaPrimitive,
9
8
  * NodeProperty,
10
9
  * NodeArrayProperty,
10
+ * NodeKind,
11
+ * NodeSchema,
11
12
  * DocumentSchema,
12
13
  * SerializedDocument
13
14
  * } from './types.d.ts';
@@ -16,13 +17,11 @@
16
17
  * Identity function — keeps schema at runtime & makes IDE infer types.
17
18
  * Similar to your define_schema pattern but for document schemas.
18
19
  *
19
- * @template {Record<string, Record<string, {type: DocumentSchemaPrimitive}>>} S
20
+ * @template {Record<string, NodeSchema>} S
20
21
  * @param {S} schema - The document schema to validate
21
22
  * @returns {S} The same schema, but with type information preserved
22
23
  */
23
- export function define_document_schema<S extends Record<string, Record<string, {
24
- type: DocumentSchemaPrimitive;
25
- }>>>(schema: S): S;
24
+ export function define_document_schema<S extends Record<string, NodeSchema>>(schema: S): S;
26
25
  /**
27
26
  * Check if a string represents a valid primitive type.
28
27
  * @param {string} type - The type string to check
@@ -53,8 +52,6 @@ export default class Document {
53
52
  selection?: Selection;
54
53
  config?: any;
55
54
  });
56
- /** @type {Selection | undefined} */
57
- selection: Selection | undefined;
58
55
  config: any;
59
56
  document_id: any;
60
57
  nodes: any;
@@ -63,9 +60,32 @@ export default class Document {
63
60
  can_undo: boolean;
64
61
  can_redo: boolean;
65
62
  selected_node: any;
63
+ layout_node: any;
64
+ available_annotation_types: any;
65
+ /**
66
+ * Sets the selection with validation
67
+ * @param {Selection | undefined} value - The new selection
68
+ * @throws {Error} Throws if the selection is invalid
69
+ */
70
+ set selection(value: Selection | undefined);
71
+ /**
72
+ * Gets the current selection
73
+ * @returns {Selection | undefined}
74
+ */
75
+ get selection(): Selection | undefined;
76
+ /**
77
+ * Validates that a selection is within bounds and refers to valid paths.
78
+ *
79
+ * @param {Selection} selection - The selection to validate
80
+ * @throws {Error} Throws if the selection is invalid
81
+ * @private
82
+ */
83
+ private _validate_selection;
66
84
  schema: DocumentSchema;
67
85
  generate_id(): any;
86
+ get_available_annotation_types(): any;
68
87
  get_selected_node(): any;
88
+ get_layout_node(): any;
69
89
  _apply_op(op: any): void;
70
90
  /**
71
91
  * Validate a node against the document schema.
@@ -104,8 +124,8 @@ export default class Document {
104
124
  * doc.get(['page_1', 'body', 3, 'list_items', 0]) // => { type: 'list_item', id: 'list_item_1', ... }
105
125
  *
106
126
  * @example
107
- * // Get an annotated string property
108
- * doc.get(['page_1', 'cover', 'title']) // => ['Hello world', []]
127
+ * // Get an annotated text property
128
+ * doc.get(['page_1', 'cover', 'title']) // => {text: 'Hello world', annotations: []}
109
129
  */
110
130
  get(path: DocumentPath | string): any;
111
131
  /**
@@ -139,12 +159,26 @@ export default class Document {
139
159
  [key: string]: any;
140
160
  };
141
161
  /**
142
- * Determines the kind of a node ('text' for pure text nodes or 'node' for anything else)
143
- * NOTE: currently we assume a 'content' property for pure text nodes
162
+ * Determines the kind of a node ('block' for structured blocks, 'text' for pure
163
+ * text nodes or 'annotation' for annotation nodes.
144
164
  * @param {any} node
145
- * @returns {'text'|'node'}
165
+ * @returns {NodeKind}
146
166
  */
147
- kind(node: any): "text" | "node";
167
+ kind(node: any): NodeKind;
168
+ /**
169
+ * Determines whether a node type can be inserted at a given selection.
170
+ * @param {string} node_type - The type of node to insert.
171
+ * @param {Selection} [selection] - The selection at which to insert the node.
172
+ * @returns {boolean} True if the node type can be inserted, false otherwise.
173
+ */
174
+ can_insert(node_type: string, selection?: Selection): boolean;
175
+ /**
176
+ * Compute next possible insert position from a given selection
177
+ *
178
+ * @param {Selection} [selection] - Reference selection
179
+ * @returns {Selection} True if the paste operation was successful, false otherwise
180
+ */
181
+ get_next_node_insert_cursor(selection?: Selection): Selection;
148
182
  /**
149
183
  * Returns the annotation object that is currently "under the cursor".
150
184
  * NOTE: Annotations in Svedit are exclusive, so there can only be one active_annotation
@@ -153,10 +187,13 @@ export default class Document {
153
187
  * @returns {Annotation|null}
154
188
  */
155
189
  active_annotation(annotation_type: string): Annotation | null;
190
+ get_selected_annotated_text(): {
191
+ text: string;
192
+ annotations: any;
193
+ nodes: {};
194
+ };
156
195
  get_selected_plain_text(): string;
157
196
  get_selected_nodes(): any;
158
- move_node_cursor(direction: any): void;
159
- expand_node_selection(direction: any): void;
160
197
  select_parent(): void;
161
198
  get_selection_range(): {
162
199
  start: number;
@@ -169,15 +206,16 @@ export default class Document {
169
206
  * @returns {SerializedDocument} The serialized document array
170
207
  */
171
208
  to_json(): SerializedDocument;
172
- property_type(type: any, property: any): "string" | "number" | "boolean" | "node" | "node_array" | "integer" | "datetime" | "string_array" | "number_array" | "boolean_array" | "integer_array" | "annotated_string";
209
+ property_type(type: any, property: any): "string" | "number" | "boolean" | "node_array" | "node" | "annotated_text" | "integer" | "integer_array" | "number_array" | "string_array" | "datetime" | "boolean_array";
173
210
  count_references(node_id: any): number;
174
211
  /**
175
212
  * @param {NodeId} node_id
176
213
  * @returns {NodeId[]}
177
214
  */
178
215
  get_referenced_nodes(node_id: NodeId): NodeId[];
216
+ #private;
179
217
  }
180
- import type { DocumentSchemaPrimitive } from './types.d.ts';
218
+ import type { NodeSchema } from './types.d.ts';
181
219
  import type { PrimitiveType } from './types.d.ts';
182
220
  import type { NodeProperty } from './types.d.ts';
183
221
  import type { NodeArrayProperty } from './types.d.ts';
@@ -185,6 +223,7 @@ import type { DocumentSchema } from './types.d.ts';
185
223
  import type { Selection } from './types.d.ts';
186
224
  import Transaction from './Transaction.svelte.js';
187
225
  import type { DocumentPath } from './types.d.ts';
226
+ import type { NodeKind } from './types.d.ts';
188
227
  import type { Annotation } from './types.d.ts';
189
228
  import type { SerializedDocument } from './types.d.ts';
190
229
  import type { NodeId } from './types.d.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"Document.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Document.svelte.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;GAaG;AAEH;;;;;;;GAOG;AACH,uCAJ+E,CAAC,SAAlE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;IAAC,IAAI,EAAE,uBAAuB,CAAA;CAAC,CAAC,CAAE,UACnE,CAAC,GACC,CAAC,CAIb;AAED;;;;GAIG;AACH,wCAHW,MAAM,GACJ,IAAI,IAAI,aAAa,CAQjC;AAED;;;;GAIG;AACH,2DAHW,YAAY,GAAG,iBAAiB,GAC9B,MAAM,GAAG,IAAI,CASzB;AAED;;;;GAIG;AACH,0DAHW,cAAc,QAexB;AAuGD;IAgBE;;;;;;OAMG;IACH,oBANW,cAAc,kBACd,kBAAkB,0BAE1B;QAA4B,SAAS,GAA7B,SAAS;QACK,MAAM,GAApB,GAAG;KACb,EAmBA;IAxCD,oCAAoC;IACpC,WADW,SAAS,GAAG,SAAS,CACX;IACrB,YAAkB;IAClB,iBAAuB;IACvB,WAAiB;IACjB,eAAqB;IACrB,sBAA2B;IAG3B,kBAA6C;IAC7C,kBAAkE;IAGnE,mBAAmD;IAahD,uBAAoB;IAgBtB,mBAMC;IAGF,yBAkBC;IAGA,yBAWC;IAED;;;;OAIG;IACH,oBAHW,GAAG,QAKb;IAED;;;;OAIG;IACH,UAFa,WAAW,CASvB;IAED;;;;OAIG;IACH,mBAFW,WAAW,QAkBrB;IAED,aAWC;IAED,aAaC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,UAlBW,YAAY,GAAC,MAAM,GACjB,GAAG,CAuDf;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,cAHW,YAAY,GACV;QAAC,IAAI,EAAE,UAAU,GAAC,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC,CAuBzD;IAED;;;;;OAKG;IACH,WAHW,GAAG,GACD,MAAM,GAAC,MAAM,CAQzB;IAED;;;;;;OAMG;IACH,mCAHW,MAAM,GACJ,UAAU,GAAC,IAAI,CAoB3B;IAGD,kCAOC;IAED,0BAOC;IAED,uCAsBC;IAED,4CASC;IAED,sBAmCC;IAED;;;;MAaC;IAKD,8BA4BC;IAED;;;OAGG;IACH,WAFa,kBAAkB,CAI9B;IAID,qNAWC;IAGD,uCAkBC;IAGD;;;OAGG;IACH,8BAHW,MAAM,GACJ,MAAM,EAAE,CASpB;CACF;6CA5pBS,cAAc;mCAAd,cAAc;kCAAd,cAAc;uCAAd,cAAc;oCAAd,cAAc;+BAAd,cAAc;wBAfA,yBAAyB;kCAevC,cAAc;gCAAd,cAAc;wCAAd,cAAc;4BAAd,cAAc"}
1
+ {"version":3,"file":"Document.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Document.svelte.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;GAOG;AACH,uCAJ0C,CAAC,SAA7B,MAAM,CAAC,MAAM,EAAE,UAAU,CAAE,UAC9B,CAAC,GACC,CAAC,CAIb;AAED;;;;GAIG;AACH,wCAHW,MAAM,GACJ,IAAI,IAAI,aAAa,CAQjC;AAED;;;;GAIG;AACH,2DAHW,YAAY,GAAG,iBAAiB,GAC9B,MAAM,GAAG,IAAI,CASzB;AAED;;;;GAIG;AACH,0DAHW,cAAc,QAexB;AAuGD;IAgGE;;;;;;OAMG;IACH,oBANW,cAAc,kBACd,kBAAkB,0BAE1B;QAA4B,SAAS,GAA7B,SAAS;QACK,MAAM,GAApB,GAAG;KACb,EAqBA;IAxHD,YAAkB;IAClB,iBAAuB;IACvB,WAAiB;IACjB,eAAqB;IACrB,sBAA2B;IAG3B,kBAA6C;IAC7C,kBAAkE;IAGnE,mBAAmD;IACnD,iBAA+C;IAC/C,gCAA6E;IAU5E;;;;OAIG;IACH,qBAHW,SAAS,GAAG,SAAS,EAQ/B;IAlBD;;;OAGG;IACH,iBAFa,SAAS,GAAG,SAAS,CAIjC;IAcD;;;;;;OAMG;IACH,4BAiDC;IAaC,uBAAoB;IAkBtB,mBAMC;IAED,sCAKA;IAGD,yBAkBC;IAID,uBAoBC;IAGA,yBAWC;IAED;;;;OAIG;IACH,oBAHW,GAAG,QAKb;IAED;;;;OAIG;IACH,UAFa,WAAW,CASvB;IAED;;;;OAIG;IACH,mBAFW,WAAW,QAkBrB;IAED,aAWC;IAED,aAaC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,UAlBW,YAAY,GAAC,MAAM,GACjB,GAAG,CAoFf;IAED;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,cAHW,YAAY,GACV;QAAC,IAAI,EAAE,UAAU,GAAC,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC,CAuBzD;IAED;;;;;OAKG;IACH,WAHW,GAAG,GACD,QAAQ,CAIpB;IAED;;;;;OAKG;IACH,sBAJW,MAAM,cACN,SAAS,GACP,OAAO,CAcnB;IAED;;;;;OAKG;IACH,wCAHW,SAAS,GACP,SAAS,CAerB;IAED;;;;;;OAMG;IACH,mCAHW,MAAM,GACJ,UAAU,GAAC,IAAI,CAqB3B;IAED;;;;MA2BC;IAGD,kCAOC;IAED,0BAOC;IAED,sBAmCC;IAED;;;;MAaC;IAKD,8BAEC;IAED;;;OAGG;IACH,WAFa,kBAAkB,CAI9B;IAID,mNAWC;IAGD,uCAkBC;IAGD;;;OAGG;IACH,8BAHW,MAAM,GACJ,MAAM,EAAE,CASpB;;CACF;gCAhzBS,cAAc;mCAAd,cAAc;kCAAd,cAAc;uCAAd,cAAc;oCAAd,cAAc;+BAAd,cAAc;wBAhBA,yBAAyB;kCAgBvC,cAAc;8BAAd,cAAc;gCAAd,cAAc;wCAAd,cAAc;4BAAd,cAAc"}