@loro-extended/change 0.6.0 → 0.8.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
@@ -32,7 +32,7 @@ import { TypedDoc, Shape } from "@loro-extended/change";
32
32
 
33
33
  // Define your document schema
34
34
  const schema = Shape.doc({
35
- title: Shape.text(),
35
+ title: Shape.text().placeholder("My Todo List"),
36
36
  todos: Shape.list(
37
37
  Shape.plain.object({
38
38
  id: Shape.plain.string(),
@@ -42,14 +42,8 @@ const schema = Shape.doc({
42
42
  ),
43
43
  });
44
44
 
45
- // Define empty state (default values)
46
- const emptyState = {
47
- title: "My Todo List",
48
- todos: [],
49
- };
50
-
51
45
  // Create a typed document
52
- const doc = new TypedDoc(schema, emptyState);
46
+ const doc = new TypedDoc(schema);
53
47
 
54
48
  // Make changes with natural syntax
55
49
  const result = doc.change((draft) => {
@@ -109,19 +103,26 @@ const blogSchema = Shape.doc({
109
103
  Empty state provides default values that are merged when CRDT containers are empty, keeping the whole document typesafe:
110
104
 
111
105
  ```typescript
112
- const emptyState = {
113
- title: "Untitled Document", // unusual empty state, but technically ok
114
- viewCount: 0,
115
- tags: [],
116
- metadata: {
117
- author: "Anonymous",
118
- publishedAt: "",
119
- featured: false,
120
- },
121
- sections: [],
122
- };
106
+ // Use .placeholder() to set default values
107
+ const blogSchemaWithDefaults = Shape.doc({
108
+ title: Shape.text().placeholder("Untitled Document"),
109
+ viewCount: Shape.counter(), // defaults to 0
110
+ tags: Shape.list(Shape.plain.string()), // defaults to []
111
+ metadata: Shape.map({
112
+ author: Shape.plain.string().placeholder("Anonymous"),
113
+ publishedAt: Shape.plain.string(), // defaults to ""
114
+ featured: Shape.plain.boolean(), // defaults to false
115
+ }),
116
+ sections: Shape.movableList(
117
+ Shape.map({
118
+ heading: Shape.text(),
119
+ content: Shape.text(),
120
+ order: Shape.plain.number(),
121
+ })
122
+ ),
123
+ });
123
124
 
124
- const doc = new TypedDoc(blogSchema, emptyState);
125
+ const doc = new TypedDoc(blogSchemaWithDefaults);
125
126
 
126
127
  // Initially returns empty state
127
128
  console.log(doc.value);
@@ -351,13 +352,13 @@ doc.change((draft) => {
351
352
 
352
353
  ### Core Functions
353
354
 
354
- #### `new TypedDoc<T>(schema, emptyState, existingDoc?)`
355
+ #### `new TypedDoc<T>(schema, existingDoc?)`
355
356
 
356
357
  Creates a new typed Loro document.
357
358
 
358
359
  ```typescript
359
- const doc = new TypedDoc(schema, emptyState);
360
- const docFromExisting = new TypedDoc(schema, emptyState, existingLoroDoc);
360
+ const doc = new TypedDoc(schema);
361
+ const docFromExisting = new TypedDoc(schema, existingLoroDoc);
361
362
  ```
362
363
 
363
364
  #### `doc.change(mutator)`
@@ -571,14 +572,8 @@ const todoSchema = Shape.doc({
571
572
  ),
572
573
  });
573
574
 
574
- // Define empty state that matches your interface
575
- const emptyState: TodoDoc = {
576
- title: "My Todos",
577
- todos: [],
578
- };
579
-
580
575
  // TypeScript will ensure the schema produces the correct type
581
- const doc = new TypedDoc(todoSchema, emptyState);
576
+ const doc = new TypedDoc(todoSchema);
582
577
 
583
578
  // The result will be properly typed as TodoDoc
584
579
  const result: TodoDoc = doc.change((draft) => {
@@ -610,7 +605,7 @@ import { LoroDoc } from "loro-crdt";
610
605
 
611
606
  // Wrap existing LoroDoc
612
607
  const existingDoc = new LoroDoc();
613
- const typedDoc = new TypedDoc(schema, emptyState, existingDoc);
608
+ const typedDoc = new TypedDoc(schema, existingDoc);
614
609
 
615
610
  // Access underlying LoroDoc
616
611
  const loroDoc = typedDoc.loroDoc;
package/dist/index.d.ts CHANGED
@@ -1,20 +1,53 @@
1
1
  import { LoroList, LoroMovableList, Container, LoroMap, Value, LoroText, LoroCounter, LoroTree, LoroDoc } from 'loro-crdt';
2
2
 
3
- type InferPlainType<T> = T extends Shape<infer P, any, any> ? P : never;
3
+ /**
4
+ * Infers the plain (JSON-serializable) type from any Shape.
5
+ *
6
+ * This is the recommended way to extract types from shapes.
7
+ * Works with DocShape, ContainerShape, and ValueShape.
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const ChatSchema = Shape.doc({
12
+ * messages: Shape.list(Shape.map({
13
+ * id: Shape.plain.string(),
14
+ * content: Shape.text(),
15
+ * })),
16
+ * })
17
+ *
18
+ * // Extract the document type
19
+ * type ChatDoc = Infer<typeof ChatSchema>
20
+ * // Result: { messages: { id: string; content: string }[] }
21
+ *
22
+ * const PresenceSchema = Shape.plain.object({
23
+ * name: Shape.plain.string(),
24
+ * cursor: Shape.plain.object({ x: Shape.plain.number(), y: Shape.plain.number() }),
25
+ * })
26
+ *
27
+ * // Extract the presence type
28
+ * type Presence = Infer<typeof PresenceSchema>
29
+ * // Result: { name: string; cursor: { x: number; y: number } }
30
+ * ```
31
+ */
32
+ type Infer<T> = T extends Shape<infer P, any, any> ? P : never;
4
33
  type InferDraftType<T> = T extends Shape<any, infer D, any> ? D : never;
5
34
  /**
6
- * Extracts the valid empty state type from a shape.
35
+ * Extracts the valid placeholder type from a shape.
7
36
  *
8
37
  * For dynamic containers (list, record, etc.), this will be constrained to
9
38
  * empty values ([] or {}) to prevent users from expecting per-entry merging.
10
39
  */
11
- type InferEmptyStateType<T> = T extends Shape<any, any, infer E> ? E : never;
40
+ type InferPlaceholderType<T> = T extends Shape<any, any, infer P> ? P : never;
12
41
  type Draft<T extends DocShape<Record<string, ContainerShape>>> = InferDraftType<T>;
42
+ type DeepReadonly<T> = {
43
+ readonly [P in keyof T]: DeepReadonly<T[P]>;
44
+ };
13
45
 
14
46
  type DraftNodeParams<Shape extends DocShape | ContainerShape> = {
15
47
  shape: Shape;
16
- emptyState?: InferPlainType<Shape>;
48
+ placeholder?: Infer<Shape>;
17
49
  getContainer: () => ShapeToContainer<Shape>;
50
+ readonly?: boolean;
18
51
  };
19
52
  declare abstract class DraftNode<Shape extends DocShape | ContainerShape> {
20
53
  protected _params: DraftNodeParams<Shape>;
@@ -22,7 +55,8 @@ declare abstract class DraftNode<Shape extends DocShape | ContainerShape> {
22
55
  constructor(_params: DraftNodeParams<Shape>);
23
56
  abstract absorbPlainValues(): void;
24
57
  protected get shape(): Shape;
25
- protected get emptyState(): InferPlainType<Shape> | undefined;
58
+ protected get placeholder(): Infer<Shape> | undefined;
59
+ protected get readonly(): boolean;
26
60
  protected get container(): ShapeToContainer<Shape>;
27
61
  }
28
62
 
@@ -43,7 +77,7 @@ declare abstract class ListDraftNodeBase<NestedShape extends ContainerOrValueSha
43
77
  protected pushWithConversion(item: Item): void;
44
78
  getDraftNodeParams(index: number, shape: ContainerShape): DraftNodeParams<ContainerShape>;
45
79
  protected getPredicateItem(index: number): Item;
46
- protected getDraftItem(index: number): DraftItem;
80
+ protected getDraftItem(index: number): any;
47
81
  find(predicate: (item: Item, index: number) => boolean): DraftItem | undefined;
48
82
  findIndex(predicate: (item: Item, index: number) => boolean): number;
49
83
  map<ReturnType>(callback: (item: Item, index: number) => ReturnType): ReturnType[];
@@ -64,6 +98,7 @@ declare abstract class ListDraftNodeBase<NestedShape extends ContainerOrValueSha
64
98
  }
65
99
 
66
100
  declare class ListDraftNode<NestedShape extends ContainerOrValueShape> extends ListDraftNodeBase<NestedShape> {
101
+ [index: number]: Infer<NestedShape>;
67
102
  protected get container(): LoroList;
68
103
  protected absorbValueAtIndex(index: number, value: any): void;
69
104
  }
@@ -75,7 +110,7 @@ declare class MapDraftNode<NestedShapes extends Record<string, ContainerOrValueS
75
110
  protected get container(): LoroMap;
76
111
  absorbPlainValues(): void;
77
112
  getDraftNodeParams<S extends ContainerShape>(key: string, shape: S): DraftNodeParams<ContainerShape>;
78
- getOrCreateNode<Shape extends ContainerShape | ValueShape>(key: string, shape: Shape): Shape extends ContainerShape ? DraftNode<Shape> : Value;
113
+ getOrCreateNode<Shape extends ContainerShape | ValueShape>(key: string, shape: Shape): any;
79
114
  private createLazyProperties;
80
115
  get(key: string): any;
81
116
  set(key: string, value: Value): void;
@@ -88,6 +123,7 @@ declare class MapDraftNode<NestedShapes extends Record<string, ContainerOrValueS
88
123
  }
89
124
 
90
125
  declare class MovableListDraftNode<NestedShape extends ContainerOrValueShape, Item = NestedShape["_plain"]> extends ListDraftNodeBase<NestedShape> {
126
+ [index: number]: Infer<NestedShape>;
91
127
  protected get container(): LoroMovableList;
92
128
  protected absorbValueAtIndex(index: number, value: any): void;
93
129
  move(from: number, to: number): void;
@@ -95,13 +131,13 @@ declare class MovableListDraftNode<NestedShape extends ContainerOrValueShape, It
95
131
  }
96
132
 
97
133
  declare class RecordDraftNode<NestedShape extends ContainerOrValueShape> extends DraftNode<any> {
134
+ [key: string]: Infer<NestedShape> | any;
98
135
  private nodeCache;
99
- constructor(params: DraftNodeParams<RecordContainerShape<NestedShape>>);
100
136
  protected get shape(): RecordContainerShape<NestedShape>;
101
137
  protected get container(): LoroMap;
102
138
  absorbPlainValues(): void;
103
139
  getDraftNodeParams<S extends ContainerShape>(key: string, shape: S): DraftNodeParams<ContainerShape>;
104
- getOrCreateNode(key: string): InferDraftType<NestedShape>;
140
+ getOrCreateNode(key: string): any;
105
141
  get(key: string): InferDraftType<NestedShape>;
106
142
  set(key: string, value: any): void;
107
143
  setContainer<C extends Container>(key: string, container: C): C;
@@ -131,12 +167,15 @@ declare class TextDraftNode extends DraftNode<TextContainerShape> {
131
167
  get length(): number;
132
168
  }
133
169
 
170
+ type WithPlaceholder<S extends Shape<any, any, any>> = S & {
171
+ placeholder(value: S["_placeholder"]): S;
172
+ };
134
173
  interface DocShape<NestedShapes extends Record<string, ContainerShape> = Record<string, ContainerShape>> extends Shape<{
135
174
  [K in keyof NestedShapes]: NestedShapes[K]["_plain"];
136
175
  }, {
137
176
  [K in keyof NestedShapes]: NestedShapes[K]["_draft"];
138
177
  }, {
139
- [K in keyof NestedShapes]: NestedShapes[K]["_emptyState"];
178
+ [K in keyof NestedShapes]: NestedShapes[K]["_placeholder"];
140
179
  }> {
141
180
  readonly _type: "doc";
142
181
  readonly shapes: NestedShapes;
@@ -164,7 +203,7 @@ interface MapContainerShape<NestedShapes extends Record<string, ContainerOrValue
164
203
  }, MapDraftNode<NestedShapes> & {
165
204
  [K in keyof NestedShapes]: NestedShapes[K]["_draft"];
166
205
  }, {
167
- [K in keyof NestedShapes]: NestedShapes[K]["_emptyState"];
206
+ [K in keyof NestedShapes]: NestedShapes[K]["_placeholder"];
168
207
  }> {
169
208
  readonly _type: "map";
170
209
  readonly shapes: NestedShapes;
@@ -205,7 +244,7 @@ interface ObjectValueShape<T extends Record<string, ValueShape> = Record<string,
205
244
  }, {
206
245
  [K in keyof T]: T[K]["_draft"];
207
246
  }, {
208
- [K in keyof T]: T[K]["_emptyState"];
247
+ [K in keyof T]: T[K]["_placeholder"];
209
248
  }> {
210
249
  readonly _type: "value";
211
250
  readonly valueType: "object";
@@ -221,7 +260,7 @@ interface ArrayValueShape<T extends ValueShape = ValueShape> extends Shape<T["_p
221
260
  readonly valueType: "array";
222
261
  readonly shape: T;
223
262
  }
224
- interface UnionValueShape<T extends ValueShape[] = ValueShape[]> extends Shape<T[number]["_plain"], T[number]["_draft"], T[number]["_emptyState"]> {
263
+ interface UnionValueShape<T extends ValueShape[] = ValueShape[]> extends Shape<T[number]["_plain"], T[number]["_draft"], T[number]["_placeholder"]> {
225
264
  readonly _type: "value";
226
265
  readonly valueType: "union";
227
266
  readonly shapes: T;
@@ -239,7 +278,7 @@ interface UnionValueShape<T extends ValueShape[] = ValueShape[]> extends Shape<T
239
278
  * @typeParam K - The discriminant key (e.g., "type")
240
279
  * @typeParam T - A record mapping discriminant values to their object shapes
241
280
  */
242
- interface DiscriminatedUnionValueShape<K extends string = string, T extends Record<string, ObjectValueShape> = Record<string, ObjectValueShape>> extends Shape<T[keyof T]["_plain"], T[keyof T]["_draft"], T[keyof T]["_emptyState"]> {
281
+ interface DiscriminatedUnionValueShape<K extends string = string, T extends Record<string, ObjectValueShape> = Record<string, ObjectValueShape>> extends Shape<T[keyof T]["_plain"], T[keyof T]["_draft"], T[keyof T]["_placeholder"]> {
243
282
  readonly _type: "value";
244
283
  readonly valueType: "discriminatedUnion";
245
284
  readonly discriminantKey: K;
@@ -247,11 +286,11 @@ interface DiscriminatedUnionValueShape<K extends string = string, T extends Reco
247
286
  }
248
287
  type ValueShape = StringValueShape | NumberValueShape | BooleanValueShape | NullValueShape | UndefinedValueShape | Uint8ArrayValueShape | ObjectValueShape | RecordValueShape | ArrayValueShape | UnionValueShape | DiscriminatedUnionValueShape;
249
288
  type ContainerOrValueShape = ContainerShape | ValueShape;
250
- interface Shape<Plain, Draft, EmptyState = Plain> {
289
+ interface Shape<Plain, Draft, Placeholder = Plain> {
251
290
  readonly _type: string;
252
291
  readonly _plain: Plain;
253
292
  readonly _draft: Draft;
254
- readonly _emptyState: EmptyState;
293
+ readonly _placeholder: Placeholder;
255
294
  }
256
295
  /**
257
296
  * The LoroShape factory object
@@ -262,24 +301,24 @@ interface Shape<Plain, Draft, EmptyState = Plain> {
262
301
  */
263
302
  declare const Shape: {
264
303
  doc: <T extends Record<string, ContainerShape>>(shape: T) => DocShape<T>;
265
- counter: () => CounterContainerShape;
304
+ counter: () => WithPlaceholder<CounterContainerShape>;
266
305
  list: <T extends ContainerOrValueShape>(shape: T) => ListContainerShape<T>;
267
306
  map: <T extends Record<string, ContainerOrValueShape>>(shape: T) => MapContainerShape<T>;
268
307
  record: <T extends ContainerOrValueShape>(shape: T) => RecordContainerShape<T>;
269
308
  movableList: <T extends ContainerOrValueShape>(shape: T) => MovableListContainerShape<T>;
270
- text: () => TextContainerShape;
309
+ text: () => WithPlaceholder<TextContainerShape>;
271
310
  tree: <T extends MapContainerShape>(shape: T) => TreeContainerShape;
272
311
  plain: {
273
- string: <T extends string = string>(...options: T[]) => StringValueShape<T>;
274
- number: () => NumberValueShape;
275
- boolean: () => BooleanValueShape;
312
+ string: <T extends string = string>(...options: T[]) => WithPlaceholder<StringValueShape<T>>;
313
+ number: () => WithPlaceholder<NumberValueShape>;
314
+ boolean: () => WithPlaceholder<BooleanValueShape>;
276
315
  null: () => NullValueShape;
277
316
  undefined: () => UndefinedValueShape;
278
317
  uint8Array: () => Uint8ArrayValueShape;
279
318
  object: <T extends Record<string, ValueShape>>(shape: T) => ObjectValueShape<T>;
280
319
  record: <T extends ValueShape>(shape: T) => RecordValueShape<T>;
281
320
  array: <T extends ValueShape>(shape: T) => ArrayValueShape<T>;
282
- union: <T extends ValueShape[]>(shapes: T) => UnionValueShape<T>;
321
+ union: <T extends ValueShape[]>(shapes: T) => WithPlaceholder<UnionValueShape<T>>;
283
322
  /**
284
323
  * Creates a discriminated union shape for type-safe tagged unions.
285
324
  *
@@ -306,11 +345,41 @@ declare const Shape: {
306
345
  * @param discriminantKey - The key used to discriminate between variants (e.g., "type")
307
346
  * @param variants - A record mapping discriminant values to their object shapes
308
347
  */
309
- discriminatedUnion: <K extends string, T extends Record<string, ObjectValueShape>>(discriminantKey: K, variants: T) => DiscriminatedUnionValueShape<K, T>;
348
+ discriminatedUnion: <K extends string, T extends Record<string, ObjectValueShape>>(discriminantKey: K, variants: T) => WithPlaceholder<DiscriminatedUnionValueShape<K, T>>;
310
349
  };
311
350
  };
312
351
  type ShapeToContainer<T extends DocShape | ContainerShape> = T extends TextContainerShape ? LoroText : T extends CounterContainerShape ? LoroCounter : T extends ListContainerShape ? LoroList : T extends MovableListContainerShape ? LoroMovableList : T extends MapContainerShape | RecordContainerShape ? LoroMap : T extends TreeContainerShape ? LoroTree : never;
313
352
 
353
+ /**
354
+ * Derives the placeholder state from a schema by composing placeholder values.
355
+ *
356
+ * For leaf nodes (text, counter, values): uses _placeholder directly
357
+ * For containers (map, list, record): recurses into nested shapes
358
+ */
359
+ declare function derivePlaceholder<T extends DocShape>(schema: T): InferPlaceholderType<T>;
360
+ /**
361
+ * Derives placeholder for a single shape.
362
+ *
363
+ * Leaf nodes: return _placeholder directly
364
+ * Containers: recurse into nested shapes (ignore _placeholder on containers)
365
+ */
366
+ declare function deriveShapePlaceholder(shape: ContainerOrValueShape): unknown;
367
+
368
+ /**
369
+ * Overlays CRDT state with placeholder defaults
370
+ */
371
+ declare function overlayPlaceholder<Shape extends DocShape>(shape: Shape, crdtValue: {
372
+ [key: string]: Value;
373
+ }, placeholderValue: {
374
+ [key: string]: Value;
375
+ }): {
376
+ [key: string]: Value;
377
+ };
378
+ /**
379
+ * Merges individual CRDT values with placeholder defaults
380
+ */
381
+ declare function mergeValue<Shape extends ContainerShape | ValueShape>(shape: Shape, crdtValue: Value, placeholderValue: Value): Value;
382
+
314
383
  /** biome-ignore-all lint/suspicious/noExplicitAny: JSON Patch values can be any type */
315
384
 
316
385
  type JsonPatchAddOperation = {
@@ -349,20 +418,28 @@ type JsonPatch = JsonPatchOperation[];
349
418
 
350
419
  declare class TypedDoc<Shape extends DocShape> {
351
420
  private shape;
352
- private emptyState;
421
+ private placeholder;
353
422
  private doc;
354
423
  /**
355
- * Creates a new TypedDoc with the given schema and empty state.
424
+ * Creates a new TypedDoc with the given schema.
425
+ * Placeholder state is automatically derived from the schema's placeholder values.
356
426
  *
357
- * @param shape - The document schema
358
- * @param emptyState - Default values for the document. For dynamic containers
359
- * (list, record, etc.), only empty values ([] or {}) are allowed. Use
360
- * `.change()` to add initial data after construction.
427
+ * @param shape - The document schema (with optional .placeholder() values)
361
428
  * @param doc - Optional existing LoroDoc to wrap
362
429
  */
363
- constructor(shape: Shape, emptyState: InferEmptyStateType<Shape>, doc?: LoroDoc);
364
- get value(): InferPlainType<Shape>;
365
- change(fn: (draft: Draft<Shape>) => void): InferPlainType<Shape>;
430
+ constructor(shape: Shape, doc?: LoroDoc);
431
+ /**
432
+ * Returns a read-only, live view of the document.
433
+ * Accessing properties on this object will read directly from the underlying CRDT.
434
+ * This is efficient (O(1) per access) and always up-to-date.
435
+ */
436
+ get value(): DeepReadonly<Infer<Shape>>;
437
+ /**
438
+ * Returns the full plain JavaScript object representation of the document.
439
+ * This is an expensive O(N) operation that serializes the entire document.
440
+ */
441
+ toJSON(): Infer<Shape>;
442
+ change(fn: (draft: Draft<Shape>) => void): Infer<Shape>;
366
443
  /**
367
444
  * Apply JSON Patch operations to the document
368
445
  *
@@ -378,32 +455,17 @@ declare class TypedDoc<Shape extends DocShape> {
378
455
  * ])
379
456
  * ```
380
457
  */
381
- applyPatch(patch: JsonPatch, pathPrefix?: (string | number)[]): InferPlainType<Shape>;
458
+ applyPatch(patch: JsonPatch, pathPrefix?: (string | number)[]): Infer<Shape>;
382
459
  get loroDoc(): LoroDoc;
383
460
  get docShape(): Shape;
384
461
  get rawValue(): any;
385
462
  }
386
- declare function createTypedDoc<Shape extends DocShape>(shape: Shape, emptyState: InferEmptyStateType<Shape>, existingDoc?: LoroDoc): TypedDoc<Shape>;
387
-
388
- /**
389
- * Overlays CRDT state with empty state defaults
390
- */
391
- declare function overlayEmptyState<Shape extends DocShape>(shape: Shape, crdtValue: {
392
- [key: string]: Value;
393
- }, emptyValue: {
394
- [key: string]: Value;
395
- }): {
396
- [key: string]: Value;
397
- };
398
- /**
399
- * Merges individual CRDT values with empty state defaults
400
- */
401
- declare function mergeValue<Shape extends ContainerShape | ValueShape>(shape: Shape, crdtValue: Value, emptyValue: Value): Value;
463
+ declare function createTypedDoc<Shape extends DocShape>(shape: Shape, existingDoc?: LoroDoc): TypedDoc<Shape>;
402
464
 
403
465
  /**
404
- * Validates empty state against schema structure without using Zod
405
- * Combines the functionality of createEmptyStateValidator and createValueValidator
466
+ * Validates placeholder against schema structure without using Zod
467
+ * Combines the functionality of createPlaceholderValidator and createValueValidator
406
468
  */
407
- declare function validateEmptyState<T extends DocShape>(emptyState: unknown, schema: T): InferPlainType<T>;
469
+ declare function validatePlaceholder<T extends DocShape>(placeholder: unknown, schema: T): Infer<T>;
408
470
 
409
- export { type ArrayValueShape, type ContainerOrValueShape, type ContainerShape, type CounterContainerShape, type DiscriminatedUnionValueShape, type DocShape, type Draft, type InferDraftType, type InferEmptyStateType, type InferPlainType, type ListContainerShape, type MapContainerShape, type MovableListContainerShape, type ObjectValueShape, type RecordContainerShape, type RecordValueShape, type ContainerType as RootContainerType, Shape, type TextContainerShape, type TreeContainerShape, TypedDoc, type UnionValueShape, type ValueShape, createTypedDoc, mergeValue, overlayEmptyState, validateEmptyState };
471
+ export { type ArrayValueShape, type ContainerOrValueShape, type ContainerShape, type CounterContainerShape, type DeepReadonly, type DiscriminatedUnionValueShape, type DocShape, type Draft, type Infer, type InferDraftType, type InferPlaceholderType, type ListContainerShape, type MapContainerShape, type MovableListContainerShape, type ObjectValueShape, type RecordContainerShape, type RecordValueShape, type ContainerType as RootContainerType, Shape, type TextContainerShape, type TreeContainerShape, TypedDoc, type UnionValueShape, type ValueShape, type WithPlaceholder, createTypedDoc, derivePlaceholder, deriveShapePlaceholder, mergeValue, overlayPlaceholder, validatePlaceholder };