@things-factory/figure-ui 10.1.76 → 10.1.77

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.
Files changed (125) hide show
  1. package/dist-client/tsconfig.tsbuildinfo +1 -1
  2. package/package.json +2 -2
  3. package/dist-client/graphql/v3-store.d.ts +0 -3
  4. package/dist-client/graphql/v3-store.js +0 -39
  5. package/dist-client/graphql/v3-store.js.map +0 -1
  6. package/dist-client/modeller/figure-v3-capability.d.ts +0 -22
  7. package/dist-client/modeller/figure-v3-capability.js +0 -141
  8. package/dist-client/modeller/figure-v3-capability.js.map +0 -1
  9. package/dist-client/modeller/figure-v3-clips.d.ts +0 -31
  10. package/dist-client/modeller/figure-v3-clips.js +0 -268
  11. package/dist-client/modeller/figure-v3-clips.js.map +0 -1
  12. package/dist-client/modeller/figure-v3-controls.d.ts +0 -36
  13. package/dist-client/modeller/figure-v3-controls.js +0 -226
  14. package/dist-client/modeller/figure-v3-controls.js.map +0 -1
  15. package/dist-client/modeller/figure-v3-first-save.d.ts +0 -20
  16. package/dist-client/modeller/figure-v3-first-save.js +0 -118
  17. package/dist-client/modeller/figure-v3-first-save.js.map +0 -1
  18. package/dist-client/modeller/figure-v3-links.d.ts +0 -77
  19. package/dist-client/modeller/figure-v3-links.js +0 -649
  20. package/dist-client/modeller/figure-v3-links.js.map +0 -1
  21. package/dist-client/modeller/figure-v3-material.d.ts +0 -39
  22. package/dist-client/modeller/figure-v3-material.js +0 -323
  23. package/dist-client/modeller/figure-v3-material.js.map +0 -1
  24. package/dist-client/modeller/figure-v3-parts.d.ts +0 -69
  25. package/dist-client/modeller/figure-v3-parts.js +0 -559
  26. package/dist-client/modeller/figure-v3-parts.js.map +0 -1
  27. package/dist-client/modeller/figure-v3-preview.d.ts +0 -34
  28. package/dist-client/modeller/figure-v3-preview.js +0 -346
  29. package/dist-client/modeller/figure-v3-preview.js.map +0 -1
  30. package/dist-client/modeller/figure-v3-properties.d.ts +0 -45
  31. package/dist-client/modeller/figure-v3-properties.js +0 -239
  32. package/dist-client/modeller/figure-v3-properties.js.map +0 -1
  33. package/dist-client/modeller/figure-v3-recipe-catalog.d.ts +0 -38
  34. package/dist-client/modeller/figure-v3-recipe-catalog.js +0 -399
  35. package/dist-client/modeller/figure-v3-recipe-catalog.js.map +0 -1
  36. package/dist-client/modeller/figure-v3-verdict.d.ts +0 -64
  37. package/dist-client/modeller/figure-v3-verdict.js +0 -787
  38. package/dist-client/modeller/figure-v3-verdict.js.map +0 -1
  39. package/dist-client/modeller/v3-ai-proposal.d.ts +0 -51
  40. package/dist-client/modeller/v3-ai-proposal.js +0 -64
  41. package/dist-client/modeller/v3-ai-proposal.js.map +0 -1
  42. package/dist-client/modeller/v3-align.d.ts +0 -30
  43. package/dist-client/modeller/v3-align.js +0 -75
  44. package/dist-client/modeller/v3-align.js.map +0 -1
  45. package/dist-client/modeller/v3-canvas.d.ts +0 -72
  46. package/dist-client/modeller/v3-canvas.js +0 -379
  47. package/dist-client/modeller/v3-canvas.js.map +0 -1
  48. package/dist-client/modeller/v3-clips.d.ts +0 -39
  49. package/dist-client/modeller/v3-clips.js +0 -58
  50. package/dist-client/modeller/v3-clips.js.map +0 -1
  51. package/dist-client/modeller/v3-controls.d.ts +0 -28
  52. package/dist-client/modeller/v3-controls.js +0 -28
  53. package/dist-client/modeller/v3-controls.js.map +0 -1
  54. package/dist-client/modeller/v3-editor.d.ts +0 -203
  55. package/dist-client/modeller/v3-editor.js +0 -1526
  56. package/dist-client/modeller/v3-editor.js.map +0 -1
  57. package/dist-client/modeller/v3-fields.d.ts +0 -45
  58. package/dist-client/modeller/v3-fields.js +0 -83
  59. package/dist-client/modeller/v3-fields.js.map +0 -1
  60. package/dist-client/modeller/v3-figure-facts.d.ts +0 -35
  61. package/dist-client/modeller/v3-figure-facts.js +0 -55
  62. package/dist-client/modeller/v3-figure-facts.js.map +0 -1
  63. package/dist-client/modeller/v3-first-save.d.ts +0 -17
  64. package/dist-client/modeller/v3-first-save.js +0 -26
  65. package/dist-client/modeller/v3-first-save.js.map +0 -1
  66. package/dist-client/modeller/v3-gizmo.d.ts +0 -72
  67. package/dist-client/modeller/v3-gizmo.js +0 -111
  68. package/dist-client/modeller/v3-gizmo.js.map +0 -1
  69. package/dist-client/modeller/v3-help.d.ts +0 -18
  70. package/dist-client/modeller/v3-help.js +0 -37
  71. package/dist-client/modeller/v3-help.js.map +0 -1
  72. package/dist-client/modeller/v3-joint-drag.d.ts +0 -19
  73. package/dist-client/modeller/v3-joint-drag.js +0 -97
  74. package/dist-client/modeller/v3-joint-drag.js.map +0 -1
  75. package/dist-client/modeller/v3-joint-fan.d.ts +0 -9
  76. package/dist-client/modeller/v3-joint-fan.js +0 -276
  77. package/dist-client/modeller/v3-joint-fan.js.map +0 -1
  78. package/dist-client/modeller/v3-keys.d.ts +0 -22
  79. package/dist-client/modeller/v3-keys.js +0 -26
  80. package/dist-client/modeller/v3-keys.js.map +0 -1
  81. package/dist-client/modeller/v3-links.d.ts +0 -267
  82. package/dist-client/modeller/v3-links.js +0 -480
  83. package/dist-client/modeller/v3-links.js.map +0 -1
  84. package/dist-client/modeller/v3-live.d.ts +0 -37
  85. package/dist-client/modeller/v3-live.js +0 -68
  86. package/dist-client/modeller/v3-live.js.map +0 -1
  87. package/dist-client/modeller/v3-maturity.d.ts +0 -120
  88. package/dist-client/modeller/v3-maturity.js +0 -313
  89. package/dist-client/modeller/v3-maturity.js.map +0 -1
  90. package/dist-client/modeller/v3-occupancy.d.ts +0 -18
  91. package/dist-client/modeller/v3-occupancy.js +0 -24
  92. package/dist-client/modeller/v3-occupancy.js.map +0 -1
  93. package/dist-client/modeller/v3-palette.d.ts +0 -7
  94. package/dist-client/modeller/v3-palette.js +0 -46
  95. package/dist-client/modeller/v3-palette.js.map +0 -1
  96. package/dist-client/modeller/v3-preview-model.d.ts +0 -47
  97. package/dist-client/modeller/v3-preview-model.js +0 -68
  98. package/dist-client/modeller/v3-preview-model.js.map +0 -1
  99. package/dist-client/modeller/v3-product-session.d.ts +0 -510
  100. package/dist-client/modeller/v3-product-session.js +0 -157
  101. package/dist-client/modeller/v3-product-session.js.map +0 -1
  102. package/dist-client/modeller/v3-recipe-source.d.ts +0 -8
  103. package/dist-client/modeller/v3-recipe-source.js +0 -14
  104. package/dist-client/modeller/v3-recipe-source.js.map +0 -1
  105. package/dist-client/modeller/v3-recipes.d.ts +0 -37
  106. package/dist-client/modeller/v3-recipes.js +0 -103
  107. package/dist-client/modeller/v3-recipes.js.map +0 -1
  108. package/dist-client/modeller/v3-refusals.d.ts +0 -68
  109. package/dist-client/modeller/v3-refusals.js +0 -142
  110. package/dist-client/modeller/v3-refusals.js.map +0 -1
  111. package/dist-client/modeller/v3-renderer.d.ts +0 -40
  112. package/dist-client/modeller/v3-renderer.js +0 -73
  113. package/dist-client/modeller/v3-renderer.js.map +0 -1
  114. package/dist-client/modeller/v3-stage-model.d.ts +0 -39
  115. package/dist-client/modeller/v3-stage-model.js +0 -147
  116. package/dist-client/modeller/v3-stage-model.js.map +0 -1
  117. package/dist-client/modeller/v3-thumbnail.d.ts +0 -3
  118. package/dist-client/modeller/v3-thumbnail.js +0 -75
  119. package/dist-client/modeller/v3-thumbnail.js.map +0 -1
  120. package/dist-client/pages/figure-v3-modeller-page.d.ts +0 -102
  121. package/dist-client/pages/figure-v3-modeller-page.js +0 -548
  122. package/dist-client/pages/figure-v3-modeller-page.js.map +0 -1
  123. package/dist-client/tsconfig.chk.tsbuildinfo +0 -1
  124. package/dist-client/tsconfig.fui.tsbuildinfo +0 -1
  125. package/dist-client/tsconfig.scratch-fm.tsbuildinfo +0 -1
@@ -1,510 +0,0 @@
1
- import { type V3InputChange, type V3PrimitiveCreation, type V3PartEdit, type V3AuthoringAction, type V3ProposalStep } from '@hatiolab/figure-model';
2
- export interface V3ProductRecord {
3
- id: string;
4
- source: string;
5
- }
6
- /** Persistence is injected; neither the model engine nor the renderer owns the product ID. */
7
- export interface V3ProductStore {
8
- load(id: string): Promise<V3ProductRecord>;
9
- save(request: {
10
- id?: string;
11
- source: string;
12
- expectedSource?: string;
13
- creationId?: string;
14
- /** The card's picture. Absent when the browser could not draw one; the source is saved either way. */
15
- thumbnail?: string;
16
- /** The type name a new figure is created under (the first save asks for it). Not sent for an existing one. */
17
- type?: string;
18
- }): Promise<V3ProductRecord>;
19
- }
20
- /** Product lifecycle boundary. A late response can never change another editor's asset or ID. */
21
- export declare function createV3ProductSession(store: V3ProductStore): {
22
- read: () => {
23
- id: string | undefined;
24
- loading: boolean;
25
- saving: boolean;
26
- error: string | undefined;
27
- context: null;
28
- name: null;
29
- fields: never[];
30
- geometry: never[];
31
- bindings: never[];
32
- dirty: boolean;
33
- revision: null;
34
- canUndo?: undefined;
35
- canRedo?: undefined;
36
- palette?: undefined;
37
- } | {
38
- id: string | undefined;
39
- loading: boolean;
40
- saving: boolean;
41
- error: string | undefined;
42
- context: string;
43
- name: string;
44
- revision: number;
45
- dirty: boolean;
46
- canUndo: boolean;
47
- canRedo: boolean;
48
- fields: {
49
- value: number;
50
- id: string;
51
- unit: import("@hatiolab/figure-model").V3Unit;
52
- min: number;
53
- max: number;
54
- role?: "design" | "state";
55
- }[];
56
- geometry: import("@hatiolab/figure-model").V3AssetGeometry[];
57
- bindings: import("@hatiolab/figure-model").V3EvaluatedBinding[];
58
- palette: Record<string, string>;
59
- };
60
- startNew({ discard }?: {
61
- discard?: boolean | undefined;
62
- }): {
63
- id: string | undefined;
64
- loading: boolean;
65
- saving: boolean;
66
- error: string | undefined;
67
- context: null;
68
- name: null;
69
- fields: never[];
70
- geometry: never[];
71
- bindings: never[];
72
- dirty: boolean;
73
- revision: null;
74
- canUndo?: undefined;
75
- canRedo?: undefined;
76
- palette?: undefined;
77
- } | {
78
- id: string | undefined;
79
- loading: boolean;
80
- saving: boolean;
81
- error: string | undefined;
82
- context: string;
83
- name: string;
84
- revision: number;
85
- dirty: boolean;
86
- canUndo: boolean;
87
- canRedo: boolean;
88
- fields: {
89
- value: number;
90
- id: string;
91
- unit: import("@hatiolab/figure-model").V3Unit;
92
- min: number;
93
- max: number;
94
- role?: "design" | "state";
95
- }[];
96
- geometry: import("@hatiolab/figure-model").V3AssetGeometry[];
97
- bindings: import("@hatiolab/figure-model").V3EvaluatedBinding[];
98
- palette: Record<string, string>;
99
- };
100
- open(nextId: string, { discard }?: {
101
- discard?: boolean | undefined;
102
- }): Promise<{
103
- id: string | undefined;
104
- loading: boolean;
105
- saving: boolean;
106
- error: string | undefined;
107
- context: null;
108
- name: null;
109
- fields: never[];
110
- geometry: never[];
111
- bindings: never[];
112
- dirty: boolean;
113
- revision: null;
114
- canUndo?: undefined;
115
- canRedo?: undefined;
116
- palette?: undefined;
117
- } | {
118
- id: string | undefined;
119
- loading: boolean;
120
- saving: boolean;
121
- error: string | undefined;
122
- context: string;
123
- name: string;
124
- revision: number;
125
- dirty: boolean;
126
- canUndo: boolean;
127
- canRedo: boolean;
128
- fields: {
129
- value: number;
130
- id: string;
131
- unit: import("@hatiolab/figure-model").V3Unit;
132
- min: number;
133
- max: number;
134
- role?: "design" | "state";
135
- }[];
136
- geometry: import("@hatiolab/figure-model").V3AssetGeometry[];
137
- bindings: import("@hatiolab/figure-model").V3EvaluatedBinding[];
138
- palette: Record<string, string>;
139
- }>;
140
- close({ discard }?: {
141
- discard?: boolean | undefined;
142
- }): {
143
- id: string | undefined;
144
- loading: boolean;
145
- saving: boolean;
146
- error: string | undefined;
147
- context: null;
148
- name: null;
149
- fields: never[];
150
- geometry: never[];
151
- bindings: never[];
152
- dirty: boolean;
153
- revision: null;
154
- canUndo?: undefined;
155
- canRedo?: undefined;
156
- palette?: undefined;
157
- } | {
158
- id: string | undefined;
159
- loading: boolean;
160
- saving: boolean;
161
- error: string | undefined;
162
- context: string;
163
- name: string;
164
- revision: number;
165
- dirty: boolean;
166
- canUndo: boolean;
167
- canRedo: boolean;
168
- fields: {
169
- value: number;
170
- id: string;
171
- unit: import("@hatiolab/figure-model").V3Unit;
172
- min: number;
173
- max: number;
174
- role?: "design" | "state";
175
- }[];
176
- geometry: import("@hatiolab/figure-model").V3AssetGeometry[];
177
- bindings: import("@hatiolab/figure-model").V3EvaluatedBinding[];
178
- palette: Record<string, string>;
179
- };
180
- apply(changes: V3InputChange[], origin?: "ui" | "ai", expectedRevision?: number, context?: string): {
181
- context: null;
182
- name: null;
183
- fields: never[];
184
- geometry: never[];
185
- bindings: never[];
186
- dirty: boolean;
187
- revision: null;
188
- canUndo?: undefined;
189
- canRedo?: undefined;
190
- palette?: undefined;
191
- } | {
192
- context: string;
193
- name: string;
194
- revision: number;
195
- dirty: boolean;
196
- canUndo: boolean;
197
- canRedo: boolean;
198
- fields: {
199
- value: number;
200
- id: string;
201
- unit: import("@hatiolab/figure-model").V3Unit;
202
- min: number;
203
- max: number;
204
- role?: "design" | "state";
205
- }[];
206
- geometry: import("@hatiolab/figure-model").V3AssetGeometry[];
207
- bindings: import("@hatiolab/figure-model").V3EvaluatedBinding[];
208
- palette: Record<string, string>;
209
- };
210
- /**
211
- * An AI proposal (ADR-0094): the modeller's commands, as one step of the history, on the version the model saw.
212
- * Never on the current one instead -- a person's edit in between makes the proposal stale, and it is refused.
213
- */
214
- applyProposal(steps: readonly V3ProposalStep[], expectedRevision: number, context: string): {
215
- context: null;
216
- name: null;
217
- fields: never[];
218
- geometry: never[];
219
- bindings: never[];
220
- dirty: boolean;
221
- revision: null;
222
- canUndo?: undefined;
223
- canRedo?: undefined;
224
- palette?: undefined;
225
- } | {
226
- context: string;
227
- name: string;
228
- revision: number;
229
- dirty: boolean;
230
- canUndo: boolean;
231
- canRedo: boolean;
232
- fields: {
233
- value: number;
234
- id: string;
235
- unit: import("@hatiolab/figure-model").V3Unit;
236
- min: number;
237
- max: number;
238
- role?: "design" | "state";
239
- }[];
240
- geometry: import("@hatiolab/figure-model").V3AssetGeometry[];
241
- bindings: import("@hatiolab/figure-model").V3EvaluatedBinding[];
242
- palette: Record<string, string>;
243
- };
244
- /**
245
- * A recipe put in by the person (ADR-0095): its resolved commands, as one step of the history, on the version open
246
- * now. The same path as a proposal; the person is its origin.
247
- */
248
- applyRecipe(steps: readonly V3ProposalStep[]): {
249
- context: null;
250
- name: null;
251
- fields: never[];
252
- geometry: never[];
253
- bindings: never[];
254
- dirty: boolean;
255
- revision: null;
256
- canUndo?: undefined;
257
- canRedo?: undefined;
258
- palette?: undefined;
259
- } | {
260
- context: string;
261
- name: string;
262
- revision: number;
263
- dirty: boolean;
264
- canUndo: boolean;
265
- canRedo: boolean;
266
- fields: {
267
- value: number;
268
- id: string;
269
- unit: import("@hatiolab/figure-model").V3Unit;
270
- min: number;
271
- max: number;
272
- role?: "design" | "state";
273
- }[];
274
- geometry: import("@hatiolab/figure-model").V3AssetGeometry[];
275
- bindings: import("@hatiolab/figure-model").V3EvaluatedBinding[];
276
- palette: Record<string, string>;
277
- };
278
- add(part: V3PrimitiveCreation): {
279
- context: null;
280
- name: null;
281
- fields: never[];
282
- geometry: never[];
283
- bindings: never[];
284
- dirty: boolean;
285
- revision: null;
286
- canUndo?: undefined;
287
- canRedo?: undefined;
288
- palette?: undefined;
289
- } | {
290
- context: string;
291
- name: string;
292
- revision: number;
293
- dirty: boolean;
294
- canUndo: boolean;
295
- canRedo: boolean;
296
- fields: {
297
- value: number;
298
- id: string;
299
- unit: import("@hatiolab/figure-model").V3Unit;
300
- min: number;
301
- max: number;
302
- role?: "design" | "state";
303
- }[];
304
- geometry: import("@hatiolab/figure-model").V3AssetGeometry[];
305
- bindings: import("@hatiolab/figure-model").V3EvaluatedBinding[];
306
- palette: Record<string, string>;
307
- };
308
- edit(edit: V3PartEdit): {
309
- context: null;
310
- name: null;
311
- fields: never[];
312
- geometry: never[];
313
- bindings: never[];
314
- dirty: boolean;
315
- revision: null;
316
- canUndo?: undefined;
317
- canRedo?: undefined;
318
- palette?: undefined;
319
- } | {
320
- context: string;
321
- name: string;
322
- revision: number;
323
- dirty: boolean;
324
- canUndo: boolean;
325
- canRedo: boolean;
326
- fields: {
327
- value: number;
328
- id: string;
329
- unit: import("@hatiolab/figure-model").V3Unit;
330
- min: number;
331
- max: number;
332
- role?: "design" | "state";
333
- }[];
334
- geometry: import("@hatiolab/figure-model").V3AssetGeometry[];
335
- bindings: import("@hatiolab/figure-model").V3EvaluatedBinding[];
336
- palette: Record<string, string>;
337
- } | {
338
- removal: import("@hatiolab/figure-model").RemovalNotice;
339
- context: null;
340
- name: null;
341
- fields: never[];
342
- geometry: never[];
343
- bindings: never[];
344
- dirty: boolean;
345
- revision: null;
346
- canUndo?: undefined;
347
- canRedo?: undefined;
348
- palette?: undefined;
349
- } | {
350
- removal: import("@hatiolab/figure-model").RemovalNotice;
351
- context: string;
352
- name: string;
353
- revision: number;
354
- dirty: boolean;
355
- canUndo: boolean;
356
- canRedo: boolean;
357
- fields: {
358
- value: number;
359
- id: string;
360
- unit: import("@hatiolab/figure-model").V3Unit;
361
- min: number;
362
- max: number;
363
- role?: "design" | "state";
364
- }[];
365
- geometry: import("@hatiolab/figure-model").V3AssetGeometry[];
366
- bindings: import("@hatiolab/figure-model").V3EvaluatedBinding[];
367
- palette: Record<string, string>;
368
- };
369
- /** One authoring command — what a person means, not a graph edit — as one step of the same history. */
370
- command(action: V3AuthoringAction): {
371
- context: null;
372
- name: null;
373
- fields: never[];
374
- geometry: never[];
375
- bindings: never[];
376
- dirty: boolean;
377
- revision: null;
378
- canUndo?: undefined;
379
- canRedo?: undefined;
380
- palette?: undefined;
381
- } | {
382
- context: string;
383
- name: string;
384
- revision: number;
385
- dirty: boolean;
386
- canUndo: boolean;
387
- canRedo: boolean;
388
- fields: {
389
- value: number;
390
- id: string;
391
- unit: import("@hatiolab/figure-model").V3Unit;
392
- min: number;
393
- max: number;
394
- role?: "design" | "state";
395
- }[];
396
- geometry: import("@hatiolab/figure-model").V3AssetGeometry[];
397
- bindings: import("@hatiolab/figure-model").V3EvaluatedBinding[];
398
- palette: Record<string, string>;
399
- };
400
- undo(): {
401
- context: null;
402
- name: null;
403
- fields: never[];
404
- geometry: never[];
405
- bindings: never[];
406
- dirty: boolean;
407
- revision: null;
408
- canUndo?: undefined;
409
- canRedo?: undefined;
410
- palette?: undefined;
411
- } | {
412
- context: string;
413
- name: string;
414
- revision: number;
415
- dirty: boolean;
416
- canUndo: boolean;
417
- canRedo: boolean;
418
- fields: {
419
- value: number;
420
- id: string;
421
- unit: import("@hatiolab/figure-model").V3Unit;
422
- min: number;
423
- max: number;
424
- role?: "design" | "state";
425
- }[];
426
- geometry: import("@hatiolab/figure-model").V3AssetGeometry[];
427
- bindings: import("@hatiolab/figure-model").V3EvaluatedBinding[];
428
- palette: Record<string, string>;
429
- };
430
- redo(): {
431
- context: null;
432
- name: null;
433
- fields: never[];
434
- geometry: never[];
435
- bindings: never[];
436
- dirty: boolean;
437
- revision: null;
438
- canUndo?: undefined;
439
- canRedo?: undefined;
440
- palette?: undefined;
441
- } | {
442
- context: string;
443
- name: string;
444
- revision: number;
445
- dirty: boolean;
446
- canUndo: boolean;
447
- canRedo: boolean;
448
- fields: {
449
- value: number;
450
- id: string;
451
- unit: import("@hatiolab/figure-model").V3Unit;
452
- min: number;
453
- max: number;
454
- role?: "design" | "state";
455
- }[];
456
- geometry: import("@hatiolab/figure-model").V3AssetGeometry[];
457
- bindings: import("@hatiolab/figure-model").V3EvaluatedBinding[];
458
- palette: Record<string, string>;
459
- };
460
- source(): string;
461
- /**
462
- * Saves the model, and the card's picture when the caller managed to take one.
463
- *
464
- * The picture is the caller's because taking it needs a canvas, and this session is the place that knows
465
- * nothing about drawing. A save with no picture is a save: a tab in the background cannot draw, and the
466
- * source matters more than the card (see `v3-thumbnail.ts`).
467
- */
468
- save({ thumbnail, type }?: {
469
- thumbnail?: string;
470
- type?: string;
471
- }): Promise<{
472
- id: string | undefined;
473
- loading: boolean;
474
- saving: boolean;
475
- error: string | undefined;
476
- context: null;
477
- name: null;
478
- fields: never[];
479
- geometry: never[];
480
- bindings: never[];
481
- dirty: boolean;
482
- revision: null;
483
- canUndo?: undefined;
484
- canRedo?: undefined;
485
- palette?: undefined;
486
- } | {
487
- id: string | undefined;
488
- loading: boolean;
489
- saving: boolean;
490
- error: string | undefined;
491
- context: string;
492
- name: string;
493
- revision: number;
494
- dirty: boolean;
495
- canUndo: boolean;
496
- canRedo: boolean;
497
- fields: {
498
- value: number;
499
- id: string;
500
- unit: import("@hatiolab/figure-model").V3Unit;
501
- min: number;
502
- max: number;
503
- role?: "design" | "state";
504
- }[];
505
- geometry: import("@hatiolab/figure-model").V3AssetGeometry[];
506
- bindings: import("@hatiolab/figure-model").V3EvaluatedBinding[];
507
- palette: Record<string, string>;
508
- }>;
509
- };
510
- export type V3ProductSession = ReturnType<typeof createV3ProductSession>;
@@ -1,157 +0,0 @@
1
- import { createV3Asset, createV3EditorWorkspace, serializeV3Asset, parseV3Asset } from '@hatiolab/figure-model';
2
- /** Product lifecycle boundary. A late response can never change another editor's asset or ID. */
3
- export function createV3ProductSession(store) {
4
- const workspace = createV3EditorWorkspace();
5
- let epoch = 0, id, baseline;
6
- let loading = false, saving = false, error;
7
- let creationId;
8
- function read() {
9
- return { ...workspace.read(), id, loading, saving, error };
10
- }
11
- function writable() {
12
- const view = workspace.read();
13
- if (loading || error || !view.context || view.revision === null)
14
- throw Error('먼저 모델을 정상적으로 열어 주세요.');
15
- // Serializing writes also makes create retries safe: no second create while the first is pending.
16
- if (saving)
17
- throw Error('저장이 끝난 뒤 편집해 주세요.');
18
- return { context: view.context, expectedRevision: view.revision, origin: 'ui' };
19
- }
20
- function clear() {
21
- workspace.close({ discardDesignChanges: true });
22
- id = undefined;
23
- baseline = undefined;
24
- error = undefined;
25
- saving = false;
26
- creationId = undefined;
27
- }
28
- function canLeave(discard) {
29
- if (saving)
30
- throw Error('저장이 끝난 뒤 모델을 전환해 주세요.');
31
- if (workspace.read().dirty && !discard)
32
- throw Error('저장하지 않은 변경이 있습니다.');
33
- }
34
- return {
35
- read,
36
- startNew({ discard = false } = {}) {
37
- canLeave(discard);
38
- ++epoch;
39
- clear();
40
- loading = false;
41
- workspace.open(serializeV3Asset(createV3Asset('새 Figure')));
42
- creationId = crypto.randomUUID();
43
- return read();
44
- },
45
- async open(nextId, { discard = false } = {}) {
46
- canLeave(discard);
47
- const requestEpoch = ++epoch;
48
- clear();
49
- loading = true;
50
- try {
51
- const record = await store.load(nextId);
52
- if (requestEpoch !== epoch)
53
- return read();
54
- if (record.id !== nextId)
55
- throw Error('요청한 Figure와 응답의 대상이 다릅니다.');
56
- workspace.open(record.source);
57
- id = nextId;
58
- baseline = record.source;
59
- }
60
- catch (cause) {
61
- if (requestEpoch === epoch)
62
- error = cause instanceof Error ? cause.message : String(cause);
63
- }
64
- finally {
65
- if (requestEpoch === epoch)
66
- loading = false;
67
- }
68
- return read();
69
- },
70
- close({ discard = false } = {}) {
71
- canLeave(discard);
72
- ++epoch;
73
- clear();
74
- loading = false;
75
- return read();
76
- },
77
- apply(changes, origin = 'ui', expectedRevision, context) {
78
- const control = writable();
79
- // AI must supply the context AND revision captured when it started. Never substitute current values.
80
- if (origin === 'ai' && (context === undefined || expectedRevision === undefined))
81
- throw Error('AI 편집에는 요청 당시의 모델 문맥과 리비전이 필요합니다.');
82
- return workspace.apply({
83
- ...control,
84
- origin,
85
- context: context ?? control.context,
86
- expectedRevision: expectedRevision ?? control.expectedRevision,
87
- changes
88
- });
89
- },
90
- /**
91
- * An AI proposal (ADR-0094): the modeller's commands, as one step of the history, on the version the model saw.
92
- * Never on the current one instead -- a person's edit in between makes the proposal stale, and it is refused.
93
- */
94
- applyProposal(steps, expectedRevision, context) {
95
- writable();
96
- return workspace.applyProposal({ origin: 'ai', context, expectedRevision, steps });
97
- },
98
- /**
99
- * A recipe put in by the person (ADR-0095): its resolved commands, as one step of the history, on the version open
100
- * now. The same path as a proposal; the person is its origin.
101
- */
102
- applyRecipe(steps) {
103
- const at = writable();
104
- return workspace.applyProposal({ origin: 'ui', context: at.context, expectedRevision: at.expectedRevision, steps });
105
- },
106
- add(part) {
107
- return workspace.addPrimitive({ ...writable(), part });
108
- },
109
- edit(edit) {
110
- return workspace.editPart({ ...writable(), edit });
111
- },
112
- /** One authoring command — what a person means, not a graph edit — as one step of the same history. */
113
- command(action) {
114
- return workspace.command({ ...writable(), action });
115
- },
116
- undo() {
117
- return workspace.undo(writable());
118
- },
119
- redo() {
120
- return workspace.redo(writable());
121
- },
122
- source() {
123
- const { context } = writable();
124
- return workspace.export({ context }).text;
125
- },
126
- /**
127
- * Saves the model, and the card's picture when the caller managed to take one.
128
- *
129
- * The picture is the caller's because taking it needs a canvas, and this session is the place that knows
130
- * nothing about drawing. A save with no picture is a save: a tab in the background cannot draw, and the
131
- * source matters more than the card (see `v3-thumbnail.ts`).
132
- */
133
- async save({ thumbnail, type } = {}) {
134
- const control = writable(), requestEpoch = epoch;
135
- const exported = workspace.export(control);
136
- saving = true;
137
- try {
138
- const record = await store.save({ id, source: exported.text, expectedSource: baseline, creationId, thumbnail, ...(id || !type ? {} : { type }) });
139
- if (requestEpoch !== epoch)
140
- return read();
141
- if (!record.id || (id !== undefined && record.id !== id))
142
- throw Error('저장 응답의 Figure 대상이 다릅니다.');
143
- if (serializeV3Asset(parseV3Asset(record.source)) !== exported.text)
144
- throw Error('저장 응답이 보낸 모델과 다릅니다. 저장 상태를 다시 확인해 주세요.');
145
- workspace.acknowledgeSaved(exported);
146
- id = record.id;
147
- baseline = record.source;
148
- }
149
- finally {
150
- if (requestEpoch === epoch)
151
- saving = false;
152
- }
153
- return read();
154
- }
155
- };
156
- }
157
- //# sourceMappingURL=v3-product-session.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"v3-product-session.js","sourceRoot":"","sources":["../../client/modeller/v3-product-session.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createV3Asset,\n createV3EditorWorkspace,\n serializeV3Asset,\n parseV3Asset,\n type V3InputChange,\n type V3PrimitiveCreation,\n type V3PartEdit,\n type V3AuthoringAction,\n type V3ProposalStep\n} from '@hatiolab/figure-model'\n\nexport interface V3ProductRecord {\n id: string\n source: string\n}\n\n/** Persistence is injected; neither the model engine nor the renderer owns the product ID. */\nexport interface V3ProductStore {\n load(id: string): Promise<V3ProductRecord>\n save(request: {\n id?: string\n source: string\n expectedSource?: string\n creationId?: string\n /** The card's picture. Absent when the browser could not draw one; the source is saved either way. */\n thumbnail?: string\n /** The type name a new figure is created under (the first save asks for it). Not sent for an existing one. */\n type?: string\n }): Promise<V3ProductRecord>\n}\n\n/** Product lifecycle boundary. A late response can never change another editor's asset or ID. */\nexport function createV3ProductSession(store: V3ProductStore) {\n const workspace = createV3EditorWorkspace()\n let epoch = 0,\n id: string | undefined,\n baseline: string | undefined\n let loading = false,\n saving = false,\n error: string | undefined\n let creationId: string | undefined\n function read() {\n return { ...workspace.read(), id, loading, saving, error }\n }\n function writable() {\n const view = workspace.read()\n if (loading || error || !view.context || view.revision === null) throw Error('먼저 모델을 정상적으로 열어 주세요.')\n // Serializing writes also makes create retries safe: no second create while the first is pending.\n if (saving) throw Error('저장이 끝난 뒤 편집해 주세요.')\n return { context: view.context, expectedRevision: view.revision, origin: 'ui' as const }\n }\n function clear() {\n workspace.close({ discardDesignChanges: true })\n id = undefined\n baseline = undefined\n error = undefined\n saving = false\n creationId = undefined\n }\n function canLeave(discard: boolean) {\n if (saving) throw Error('저장이 끝난 뒤 모델을 전환해 주세요.')\n if (workspace.read().dirty && !discard) throw Error('저장하지 않은 변경이 있습니다.')\n }\n return {\n read,\n startNew({ discard = false } = {}) {\n canLeave(discard)\n ++epoch\n clear()\n loading = false\n workspace.open(serializeV3Asset(createV3Asset('새 Figure')))\n creationId = crypto.randomUUID()\n return read()\n },\n async open(nextId: string, { discard = false } = {}) {\n canLeave(discard)\n const requestEpoch = ++epoch\n clear()\n loading = true\n try {\n const record = await store.load(nextId)\n if (requestEpoch !== epoch) return read()\n if (record.id !== nextId) throw Error('요청한 Figure와 응답의 대상이 다릅니다.')\n workspace.open(record.source)\n id = nextId\n baseline = record.source\n } catch (cause) {\n if (requestEpoch === epoch) error = cause instanceof Error ? cause.message : String(cause)\n } finally {\n if (requestEpoch === epoch) loading = false\n }\n return read()\n },\n close({ discard = false } = {}) {\n canLeave(discard)\n ++epoch\n clear()\n loading = false\n return read()\n },\n apply(changes: V3InputChange[], origin: 'ui' | 'ai' = 'ui', expectedRevision?: number, context?: string) {\n const control = writable()\n // AI must supply the context AND revision captured when it started. Never substitute current values.\n if (origin === 'ai' && (context === undefined || expectedRevision === undefined))\n throw Error('AI 편집에는 요청 당시의 모델 문맥과 리비전이 필요합니다.')\n return workspace.apply({\n ...control,\n origin,\n context: context ?? control.context,\n expectedRevision: expectedRevision ?? control.expectedRevision,\n changes\n })\n },\n /**\n * An AI proposal (ADR-0094): the modeller's commands, as one step of the history, on the version the model saw.\n * Never on the current one instead -- a person's edit in between makes the proposal stale, and it is refused.\n */\n applyProposal(steps: readonly V3ProposalStep[], expectedRevision: number, context: string) {\n writable()\n return workspace.applyProposal({ origin: 'ai', context, expectedRevision, steps })\n },\n /**\n * A recipe put in by the person (ADR-0095): its resolved commands, as one step of the history, on the version open\n * now. The same path as a proposal; the person is its origin.\n */\n applyRecipe(steps: readonly V3ProposalStep[]) {\n const at = writable()\n return workspace.applyProposal({ origin: 'ui', context: at.context, expectedRevision: at.expectedRevision, steps })\n },\n add(part: V3PrimitiveCreation) {\n return workspace.addPrimitive({ ...writable(), part })\n },\n edit(edit: V3PartEdit) {\n return workspace.editPart({ ...writable(), edit })\n },\n /** One authoring command — what a person means, not a graph edit — as one step of the same history. */\n command(action: V3AuthoringAction) {\n return workspace.command({ ...writable(), action })\n },\n undo() {\n return workspace.undo(writable())\n },\n redo() {\n return workspace.redo(writable())\n },\n source() {\n const { context } = writable()\n return workspace.export({ context }).text\n },\n /**\n * Saves the model, and the card's picture when the caller managed to take one.\n *\n * The picture is the caller's because taking it needs a canvas, and this session is the place that knows\n * nothing about drawing. A save with no picture is a save: a tab in the background cannot draw, and the\n * source matters more than the card (see `v3-thumbnail.ts`).\n */\n async save({ thumbnail, type }: { thumbnail?: string; type?: string } = {}) {\n const control = writable(),\n requestEpoch = epoch\n const exported = workspace.export(control)\n saving = true\n try {\n const record = await store.save({ id, source: exported.text, expectedSource: baseline, creationId, thumbnail, ...(id || !type ? {} : { type }) })\n if (requestEpoch !== epoch) return read()\n if (!record.id || (id !== undefined && record.id !== id)) throw Error('저장 응답의 Figure 대상이 다릅니다.')\n if (serializeV3Asset(parseV3Asset(record.source)) !== exported.text)\n throw Error('저장 응답이 보낸 모델과 다릅니다. 저장 상태를 다시 확인해 주세요.')\n workspace.acknowledgeSaved(exported)\n id = record.id\n baseline = record.source\n } finally {\n if (requestEpoch === epoch) saving = false\n }\n return read()\n }\n }\n}\nexport type V3ProductSession = ReturnType<typeof createV3ProductSession>\n"]}