@things-factory/figure-ui 10.1.34 → 10.1.36

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 (49) hide show
  1. package/client/graphql/index.ts +13 -0
  2. package/client/graphql/v3-store.ts +30 -0
  3. package/client/modeller/figure-history-panel.ts +29 -2
  4. package/client/modeller/v3-canvas.ts +145 -0
  5. package/client/modeller/v3-editor.ts +317 -0
  6. package/client/modeller/v3-product-session.ts +141 -0
  7. package/client/modeller/v3-renderer.ts +61 -0
  8. package/client/pages/figure-modeller-page.ts +50 -3
  9. package/client/pages/figure-v3-modeller-page.ts +117 -0
  10. package/client/types.ts +8 -0
  11. package/dist-client/graphql/index.js +13 -0
  12. package/dist-client/graphql/index.js.map +1 -1
  13. package/dist-client/graphql/v3-store.d.ts +3 -0
  14. package/dist-client/graphql/v3-store.js +32 -0
  15. package/dist-client/graphql/v3-store.js.map +1 -0
  16. package/dist-client/modeller/figure-history-panel.d.ts +2 -0
  17. package/dist-client/modeller/figure-history-panel.js +28 -1
  18. package/dist-client/modeller/figure-history-panel.js.map +1 -1
  19. package/dist-client/modeller/v3-canvas.d.ts +28 -0
  20. package/dist-client/modeller/v3-canvas.js +157 -0
  21. package/dist-client/modeller/v3-canvas.js.map +1 -0
  22. package/dist-client/modeller/v3-editor.d.ts +19 -0
  23. package/dist-client/modeller/v3-editor.js +332 -0
  24. package/dist-client/modeller/v3-editor.js.map +1 -0
  25. package/dist-client/modeller/v3-product-session.d.ts +366 -0
  26. package/dist-client/modeller/v3-product-session.js +130 -0
  27. package/dist-client/modeller/v3-product-session.js.map +1 -0
  28. package/dist-client/modeller/v3-renderer.d.ts +31 -0
  29. package/dist-client/modeller/v3-renderer.js +81 -0
  30. package/dist-client/modeller/v3-renderer.js.map +1 -0
  31. package/dist-client/pages/figure-modeller-page.d.ts +7 -0
  32. package/dist-client/pages/figure-modeller-page.js +55 -2
  33. package/dist-client/pages/figure-modeller-page.js.map +1 -1
  34. package/dist-client/pages/figure-v3-modeller-page.d.ts +26 -0
  35. package/dist-client/pages/figure-v3-modeller-page.js +140 -0
  36. package/dist-client/pages/figure-v3-modeller-page.js.map +1 -0
  37. package/dist-client/tsconfig.tsbuildinfo +1 -1
  38. package/dist-client/types.d.ts +7 -0
  39. package/dist-client/types.js.map +1 -1
  40. package/docs/v3-product-cutover.md +35 -0
  41. package/package.json +4 -4
  42. package/test/v3-product-session.test.ts +133 -0
  43. package/test/v3-product-write.test.ts +48 -0
  44. package/test/v3-renderer.test.ts +24 -0
  45. package/translations/en.json +3 -0
  46. package/translations/ja.json +3 -0
  47. package/translations/ko.json +3 -0
  48. package/translations/ms.json +3 -0
  49. package/translations/zh.json +3 -0
@@ -0,0 +1,26 @@
1
+ import { PageView } from '@operato/shell';
2
+ import '../modeller/v3-editor.js';
3
+ /** The V3 product page has exactly one authoritative workspace for UI and AI input transactions. */
4
+ export declare class FigureV3ModellerPage extends PageView {
5
+ static styles: import("lit").CSSResult;
6
+ private readonly session;
7
+ private routeId;
8
+ private discardApproved;
9
+ private revision;
10
+ private error;
11
+ private announce;
12
+ private changed;
13
+ /** The dock must explicitly use this checked transaction contract, never an unversioned overwrite. */
14
+ private applyAI;
15
+ connectedCallback(): void;
16
+ disconnectedCallback(): void;
17
+ canDeactivate(): Promise<boolean>;
18
+ pageUpdated(changes: Record<string, unknown>, lifecycle: {
19
+ resourceId?: string;
20
+ }): Promise<void>;
21
+ get context(): {
22
+ title: string;
23
+ actions: never[];
24
+ };
25
+ render(): import("lit-html").TemplateResult<1>;
26
+ }
@@ -0,0 +1,140 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { html, css } from 'lit';
3
+ import { customElement, state } from 'lit/decorators.js';
4
+ import { PageView } from '@operato/shell';
5
+ import { createV3ProductSession } from '../modeller/v3-product-session.js';
6
+ import { v3ProductStore } from '../graphql/v3-store.js';
7
+ import '../modeller/v3-editor.js';
8
+ /** The V3 product page has exactly one authoritative workspace for UI and AI input transactions. */
9
+ let FigureV3ModellerPage = class FigureV3ModellerPage extends PageView {
10
+ constructor() {
11
+ super(...arguments);
12
+ this.session = createV3ProductSession(v3ProductStore);
13
+ this.discardApproved = false;
14
+ this.revision = 0;
15
+ this.error = '';
16
+ this.announce = () => {
17
+ const view = this.session.read();
18
+ if (!this.active || view.loading || view.saving || view.error || !view.context)
19
+ return;
20
+ window.dispatchEvent(new CustomEvent('figure-ai-context', {
21
+ detail: {
22
+ figureId: view.id,
23
+ source: JSON.parse(this.session.source()),
24
+ context: view.context,
25
+ revision: view.revision,
26
+ format: 'v3'
27
+ }
28
+ }));
29
+ };
30
+ this.changed = () => {
31
+ this.revision++;
32
+ if (!this.session.read().saving)
33
+ this.announce();
34
+ };
35
+ /** The dock must explicitly use this checked transaction contract, never an unversioned overwrite. */
36
+ this.applyAI = (event) => {
37
+ const detail = event.detail;
38
+ if (!this.active || !detail)
39
+ return;
40
+ try {
41
+ this.session.apply(detail.changes, 'ai', detail.revision, detail.context);
42
+ detail.applied = true;
43
+ this.changed();
44
+ }
45
+ catch (error) {
46
+ detail.applied = false;
47
+ detail.error = error instanceof Error ? error.message : String(error);
48
+ }
49
+ };
50
+ }
51
+ static { this.styles = css `
52
+ :host {
53
+ display: flex;
54
+ flex-direction: column;
55
+ height: 100%;
56
+ min-height: 0;
57
+ }
58
+ figure-v3-editor {
59
+ flex: 1;
60
+ min-height: 0;
61
+ }
62
+ .error {
63
+ padding: 16px;
64
+ color: #922716;
65
+ }
66
+ `; }
67
+ connectedCallback() {
68
+ super.connectedCallback();
69
+ window.addEventListener('figure-ai-context-request', this.announce);
70
+ window.addEventListener('figure-v3-apply', this.applyAI);
71
+ }
72
+ disconnectedCallback() {
73
+ window.removeEventListener('figure-ai-context-request', this.announce);
74
+ window.removeEventListener('figure-v3-apply', this.applyAI);
75
+ super.disconnectedCallback();
76
+ }
77
+ async canDeactivate() {
78
+ const view = this.session.read();
79
+ if (view.saving)
80
+ return false;
81
+ if (!view.dirty)
82
+ return true;
83
+ // The shell invokes this while the edited model is still visible, before navigating away.
84
+ this.discardApproved = window.confirm('저장하지 않은 변경을 버리고 이동하시겠습니까?');
85
+ return this.discardApproved;
86
+ }
87
+ async pageUpdated(changes, lifecycle) {
88
+ if (!this.active) {
89
+ if (this.session.read().loading)
90
+ this.session.close();
91
+ window.dispatchEvent(new CustomEvent('figure-ai-context', { detail: undefined }));
92
+ return;
93
+ }
94
+ const id = lifecycle?.resourceId;
95
+ if (this.session.read().context && id === this.routeId && !changes.active)
96
+ return;
97
+ try {
98
+ const discard = this.discardApproved;
99
+ this.discardApproved = false;
100
+ if (id) {
101
+ const opening = this.session.open(id, { discard });
102
+ this.changed();
103
+ await opening;
104
+ }
105
+ else
106
+ this.session.startNew({ discard });
107
+ this.routeId = id;
108
+ this.error = '';
109
+ this.changed();
110
+ }
111
+ catch (error) {
112
+ this.error = error instanceof Error ? error.message : String(error);
113
+ }
114
+ }
115
+ get context() {
116
+ return { title: this.session.read().name ?? 'Figure', actions: [] };
117
+ }
118
+ render() {
119
+ return this.error
120
+ ? html `<p role="alert" class="error">${this.error}</p>`
121
+ : html `<figure-v3-editor
122
+ .session=${this.session}
123
+ .revision=${this.revision}
124
+ @v3-changed=${this.changed}
125
+ ></figure-v3-editor>`;
126
+ }
127
+ };
128
+ __decorate([
129
+ state(),
130
+ __metadata("design:type", Object)
131
+ ], FigureV3ModellerPage.prototype, "revision", void 0);
132
+ __decorate([
133
+ state(),
134
+ __metadata("design:type", Object)
135
+ ], FigureV3ModellerPage.prototype, "error", void 0);
136
+ FigureV3ModellerPage = __decorate([
137
+ customElement('figure-modeller-page')
138
+ ], FigureV3ModellerPage);
139
+ export { FigureV3ModellerPage };
140
+ //# sourceMappingURL=figure-v3-modeller-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figure-v3-modeller-page.js","sourceRoot":"","sources":["../../client/pages/figure-v3-modeller-page.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, css } from 'lit'\nimport { customElement, state } from 'lit/decorators.js'\nimport { PageView } from '@operato/shell'\nimport { createV3ProductSession } from '../modeller/v3-product-session.js'\nimport { v3ProductStore } from '../graphql/v3-store.js'\nimport '../modeller/v3-editor.js'\n\n/** The V3 product page has exactly one authoritative workspace for UI and AI input transactions. */\n@customElement('figure-modeller-page')\nexport class FigureV3ModellerPage extends PageView {\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n }\n figure-v3-editor {\n flex: 1;\n min-height: 0;\n }\n .error {\n padding: 16px;\n color: #922716;\n }\n `\n private readonly session = createV3ProductSession(v3ProductStore)\n private routeId: string | undefined\n private discardApproved = false\n @state() private revision = 0\n @state() private error = ''\n private announce = () => {\n const view = this.session.read()\n if (!this.active || view.loading || view.saving || view.error || !view.context) return\n window.dispatchEvent(\n new CustomEvent('figure-ai-context', {\n detail: {\n figureId: view.id,\n source: JSON.parse(this.session.source()),\n context: view.context,\n revision: view.revision,\n format: 'v3'\n }\n })\n )\n }\n private changed = () => {\n this.revision++\n if (!this.session.read().saving) this.announce()\n }\n /** The dock must explicitly use this checked transaction contract, never an unversioned overwrite. */\n private applyAI = (event: Event) => {\n const detail = (event as CustomEvent).detail\n if (!this.active || !detail) return\n try {\n this.session.apply(detail.changes, 'ai', detail.revision, detail.context)\n detail.applied = true\n this.changed()\n } catch (error) {\n detail.applied = false\n detail.error = error instanceof Error ? error.message : String(error)\n }\n }\n connectedCallback() {\n super.connectedCallback()\n window.addEventListener('figure-ai-context-request', this.announce)\n window.addEventListener('figure-v3-apply', this.applyAI)\n }\n disconnectedCallback() {\n window.removeEventListener('figure-ai-context-request', this.announce)\n window.removeEventListener('figure-v3-apply', this.applyAI)\n super.disconnectedCallback()\n }\n async canDeactivate() {\n const view = this.session.read()\n if (view.saving) return false\n if (!view.dirty) return true\n // The shell invokes this while the edited model is still visible, before navigating away.\n this.discardApproved = window.confirm('저장하지 않은 변경을 버리고 이동하시겠습니까?')\n return this.discardApproved\n }\n async pageUpdated(changes: Record<string, unknown>, lifecycle: { resourceId?: string }) {\n if (!this.active) {\n if (this.session.read().loading) this.session.close()\n window.dispatchEvent(new CustomEvent('figure-ai-context', { detail: undefined }))\n return\n }\n const id = lifecycle?.resourceId\n if (this.session.read().context && id === this.routeId && !changes.active) return\n try {\n const discard = this.discardApproved\n this.discardApproved = false\n if (id) {\n const opening = this.session.open(id, { discard })\n this.changed()\n await opening\n } else this.session.startNew({ discard })\n this.routeId = id\n this.error = ''\n this.changed()\n } catch (error) {\n this.error = error instanceof Error ? error.message : String(error)\n }\n }\n get context() {\n return { title: this.session.read().name ?? 'Figure', actions: [] }\n }\n render() {\n return this.error\n ? html`<p role=\"alert\" class=\"error\">${this.error}</p>`\n : html`<figure-v3-editor\n .session=${this.session}\n .revision=${this.revision}\n @v3-changed=${this.changed}\n ></figure-v3-editor>`\n }\n}\n"]}