@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/figure-ui",
3
- "version": "10.1.76",
3
+ "version": "10.1.77",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "@things-factory:registry": "https://registry.npmjs.org"
@@ -44,5 +44,5 @@
44
44
  "@things-factory/figure-service": "^10.1.76",
45
45
  "three": "^0.185.1"
46
46
  },
47
- "gitHead": "66a70458dfea95fe8c835067f0fd857b38736203"
47
+ "gitHead": "f5ff07816a0f96325cc599c73d7fba06dd719c6f"
48
48
  }
@@ -1,3 +0,0 @@
1
- import type { V3ProductStore } from '../modeller/v3-product-session.js';
2
- /** V3 source is sent intact. No conversion into the old parts/base authoring representation. */
3
- export declare const v3ProductStore: V3ProductStore;
@@ -1,39 +0,0 @@
1
- import gql from 'graphql-tag';
2
- import { client } from '@operato/graphql';
3
- import { fetchFigure } from './index.js';
4
- /** V3 source is sent intact. No conversion into the old parts/base authoring representation. */
5
- export const v3ProductStore = {
6
- async load(id) {
7
- const record = await fetchFigure(id);
8
- if (!record?.source)
9
- throw Error('Figure 정본이 없습니다.');
10
- return { id: record.id, source: record.source };
11
- },
12
- async save(request) {
13
- const response = await client.mutate({
14
- mutation: gql `
15
- mutation SaveFigureV3($source: String!, $id: String, $expectedSource: String, $creationId: String, $thumbnail: String, $type: String) {
16
- saveFigureV3(
17
- source: $source
18
- id: $id
19
- expectedSource: $expectedSource
20
- creationId: $creationId
21
- thumbnail: $thumbnail
22
- type: $type
23
- ) {
24
- id
25
- source
26
- }
27
- }
28
- `,
29
- variables: request
30
- });
31
- if (response.errors?.length)
32
- throw Error(response.errors.map(e => e.message).join('\n'));
33
- const result = response.data?.saveFigureV3;
34
- if (!result?.id || !result.source)
35
- throw Error('서버가 저장 결과를 돌려주지 않았습니다.');
36
- return result;
37
- }
38
- };
39
- //# sourceMappingURL=v3-store.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"v3-store.js","sourceRoot":"","sources":["../../client/graphql/v3-store.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,aAAa,CAAA;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAGxC,gGAAgG;AAChG,MAAM,CAAC,MAAM,cAAc,GAAmB;IAC5C,KAAK,CAAC,IAAI,CAAC,EAAE;QACX,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,EAAE,CAAC,CAAA;QACpC,IAAI,CAAC,MAAM,EAAE,MAAM;YAAE,MAAM,KAAK,CAAC,kBAAkB,CAAC,CAAA;QACpD,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAA;IACjD,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,OAAO;QAChB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC;YACnC,QAAQ,EAAE,GAAG,CAAA;;;;;;;;;;;;;;OAcZ;YACD,SAAS,EAAE,OAAO;SACnB,CAAC,CAAA;QACF,IAAI,QAAQ,CAAC,MAAM,EAAE,MAAM;YAAE,MAAM,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;QACxF,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,YAA2C,CAAA;QACzE,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,MAAM,KAAK,CAAC,wBAAwB,CAAC,CAAA;QACxE,OAAO,MAAM,CAAA;IACf,CAAC;CACF,CAAA","sourcesContent":["import gql from 'graphql-tag'\nimport { client } from '@operato/graphql'\nimport { fetchFigure } from './index.js'\nimport type { V3ProductStore, V3ProductRecord } from '../modeller/v3-product-session.js'\n\n/** V3 source is sent intact. No conversion into the old parts/base authoring representation. */\nexport const v3ProductStore: V3ProductStore = {\n async load(id) {\n const record = await fetchFigure(id)\n if (!record?.source) throw Error('Figure 정본이 없습니다.')\n return { id: record.id, source: record.source }\n },\n async save(request) {\n const response = await client.mutate({\n mutation: gql`\n mutation SaveFigureV3($source: String!, $id: String, $expectedSource: String, $creationId: String, $thumbnail: String, $type: String) {\n saveFigureV3(\n source: $source\n id: $id\n expectedSource: $expectedSource\n creationId: $creationId\n thumbnail: $thumbnail\n type: $type\n ) {\n id\n source\n }\n }\n `,\n variables: request\n })\n if (response.errors?.length) throw Error(response.errors.map(e => e.message).join('\\n'))\n const result = response.data?.saveFigureV3 as V3ProductRecord | undefined\n if (!result?.id || !result.source) throw Error('서버가 저장 결과를 돌려주지 않았습니다.')\n return result\n }\n}\n"]}
@@ -1,22 +0,0 @@
1
- import { LitElement, nothing } from 'lit';
2
- import type { V3Asset } from '@hatiolab/figure-model';
3
- type Rung = 'none' | 'hold' | 'flow';
4
- /** Which rung a set of names is, or null when it is none of them -- not invented. */
5
- export declare function rungOf(names: readonly string[] | undefined): Rung | null;
6
- declare const FigureV3Capability_base: (new (...args: any[]) => LitElement) & typeof LitElement;
7
- /**
8
- * 자리·능력 — what the figure does on a board: the ladder from drawing only, to
9
- * holding things, to passing them on, and every place things are held, whatever part it is on. A place is not drawn,
10
- * so the list is the only way to find one; choosing a row selects its part, where the place is edited.
11
- */
12
- export declare class FigureV3Capability extends FigureV3Capability_base {
13
- static styles: import("lit").CSSResult[];
14
- asset?: V3Asset;
15
- /** The selected part, whose places are marked. */
16
- selected: string;
17
- locked: boolean;
18
- render(): import("lit-html").TemplateResult<1> | typeof nothing;
19
- private setRung;
20
- private pick;
21
- }
22
- export {};
@@ -1,141 +0,0 @@
1
- import { __decorate, __metadata } from "tslib";
2
- import { css, html, LitElement, nothing } from 'lit';
3
- import { customElement, property } from 'lit/decorators.js';
4
- import { live } from 'lit/directives/live.js';
5
- import { i18next, localize } from '@operato/i18n';
6
- import { v3BindingsOf } from '@hatiolab/figure-model';
7
- import { SidePanelStyles } from './side-panel-styles.js';
8
- const RUNGS = Object.freeze({
9
- none: [],
10
- hold: ['Capacity', 'Holdable'],
11
- flow: ['FlowNode']
12
- });
13
- /** Which rung a set of names is, or null when it is none of them -- not invented. */
14
- export function rungOf(names) {
15
- const has = new Set(names ?? []);
16
- if (has.size === 0)
17
- return 'none';
18
- for (const [rung, wanted] of Object.entries(RUNGS))
19
- if (wanted.length === has.size && wanted.every(name => has.has(name)))
20
- return rung;
21
- return null;
22
- }
23
- /**
24
- * 자리·능력 — what the figure does on a board: the ladder from drawing only, to
25
- * holding things, to passing them on, and every place things are held, whatever part it is on. A place is not drawn,
26
- * so the list is the only way to find one; choosing a row selects its part, where the place is edited.
27
- */
28
- let FigureV3Capability = class FigureV3Capability extends localize(i18next)(LitElement) {
29
- constructor() {
30
- super(...arguments);
31
- /** The selected part, whose places are marked. */
32
- this.selected = '';
33
- this.locked = false;
34
- }
35
- static { this.styles = [SidePanelStyles, css `
36
- :host {
37
- display: block;
38
- }
39
- label[rung] {
40
- display: flex;
41
- gap: 8px;
42
- align-items: flex-start;
43
- padding: 8px;
44
- border: 1px solid var(--md-sys-color-outline-variant);
45
- border-radius: 8px;
46
- cursor: pointer;
47
- }
48
- label[rung][on] {
49
- border-color: var(--md-sys-color-primary);
50
- background: var(--md-sys-color-secondary-container);
51
- color: var(--md-sys-color-on-secondary-container);
52
- }
53
- label[rung] span {
54
- display: grid;
55
- gap: 2px;
56
- }
57
- label[rung] em,
58
- p[hint],
59
- small {
60
- font-style: normal;
61
- margin: 0;
62
- color: var(--md-sys-color-on-surface-variant);
63
- }
64
- button[place] {
65
- display: grid;
66
- gap: 2px;
67
- text-align: left;
68
- padding: 6px 8px;
69
- font: inherit;
70
- color: inherit;
71
- border: 1px solid var(--md-sys-color-outline-variant);
72
- border-radius: 8px;
73
- background: none;
74
- cursor: pointer;
75
- }
76
- button[place][on] {
77
- border-color: var(--md-sys-color-primary);
78
- }
79
- code {
80
- font-size: 0.9em;
81
- color: var(--md-sys-color-on-surface-variant);
82
- }
83
- `]; }
84
- render() {
85
- const asset = this.asset;
86
- if (!asset)
87
- return nothing;
88
- const names = asset.document.capabilities.names ?? [];
89
- const rung = rungOf(names);
90
- const places = v3BindingsOf(asset);
91
- return html `<section>
92
- <h3>${i18next.t('figure.label.what-this-does')}</h3>
93
- ${['none', 'hold', 'flow'].map(which => html `<label rung ?on=${rung === which}>
94
- <input type="radio" name="rung" .checked=${live(rung === which)} ?disabled=${this.locked} @change=${() => this.setRung(which)} />
95
- <span>
96
- <strong>${i18next.t(`figure.label.rung-${which}`)}</strong>
97
- <em>${i18next.t(`figure.text.rung-${which}-note`)}</em>
98
- </span>
99
- </label>`)}
100
- ${rung === null ? html `<p hint>${i18next.t('figure.text.capability-hand-written')}</p>` : nothing}
101
- ${names.length ? html `<code>${names.join(' · ')}</code>` : nothing}
102
- </section>
103
- <section>
104
- <h3>${i18next.t('figure.label.places')}</h3>
105
- ${places.length
106
- ? places.map(one => html `<button place ?on=${one.part === this.selected} @click=${() => one.part && this.pick(one.part)}>
107
- <strong>${one.label}</strong>
108
- <small>
109
- ${i18next.t('figure.label.place-' + one.role)} · ${one.part ?? '?'}${one.face ? ' · ' + i18next.t('figure.label.face-' + one.face) : ''} ·
110
- ${one.accepts.join(', ')} · ${i18next.t('figure.label.place-holds', { count: one.capacity })}
111
- </small>
112
- </button>`)
113
- : html `<p hint>${i18next.t('figure.text.no-places')}</p>`}
114
- ${places.length && rung === 'none' ? html `<p hint>${i18next.t('figure.text.place-needs-holding')}</p>` : nothing}
115
- </section>
116
- `;
117
- }
118
- setRung(which) {
119
- this.dispatchEvent(new CustomEvent('v3-part-edit', { detail: { edit: { kind: 'set-capabilities', names: [...RUNGS[which]] } }, bubbles: true, composed: true }));
120
- }
121
- pick(part) {
122
- this.dispatchEvent(new CustomEvent('select-part', { detail: { id: part }, bubbles: true, composed: true }));
123
- }
124
- };
125
- __decorate([
126
- property({ attribute: false }),
127
- __metadata("design:type", Object)
128
- ], FigureV3Capability.prototype, "asset", void 0);
129
- __decorate([
130
- property(),
131
- __metadata("design:type", Object)
132
- ], FigureV3Capability.prototype, "selected", void 0);
133
- __decorate([
134
- property({ type: Boolean }),
135
- __metadata("design:type", Object)
136
- ], FigureV3Capability.prototype, "locked", void 0);
137
- FigureV3Capability = __decorate([
138
- customElement('figure-v3-capability')
139
- ], FigureV3Capability);
140
- export { FigureV3Capability };
141
- //# sourceMappingURL=figure-v3-capability.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"figure-v3-capability.js","sourceRoot":"","sources":["../../client/modeller/figure-v3-capability.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { live } from 'lit/directives/live.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { v3BindingsOf } from '@hatiolab/figure-model'\nimport type { FigureCapability, V3Asset } from '@hatiolab/figure-model'\nimport { SidePanelStyles } from './side-panel-styles.js'\n\n/*\n One rung per set of the format's capability names. Typed as the format's names, so a misspelt rung does not pass\n (ADR-0051 ④).\n*/\ntype Rung = 'none' | 'hold' | 'flow'\nconst RUNGS: Readonly<Record<Rung, readonly FigureCapability[]>> = Object.freeze({\n none: [],\n hold: ['Capacity', 'Holdable'],\n flow: ['FlowNode']\n})\n\n/** Which rung a set of names is, or null when it is none of them -- not invented. */\nexport function rungOf(names: readonly string[] | undefined): Rung | null {\n const has = new Set(names ?? [])\n if (has.size === 0) return 'none'\n for (const [rung, wanted] of Object.entries(RUNGS) as [Rung, readonly FigureCapability[]][])\n if (wanted.length === has.size && wanted.every(name => has.has(name))) return rung\n return null\n}\n\n/**\n * 자리·능력 — what the figure does on a board: the ladder from drawing only, to\n * holding things, to passing them on, and every place things are held, whatever part it is on. A place is not drawn,\n * so the list is the only way to find one; choosing a row selects its part, where the place is edited.\n */\n@customElement('figure-v3-capability')\nexport class FigureV3Capability extends localize(i18next)(LitElement) {\n static styles = [SidePanelStyles, css`\n :host {\n display: block;\n }\n label[rung] {\n display: flex;\n gap: 8px;\n align-items: flex-start;\n padding: 8px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n cursor: pointer;\n }\n label[rung][on] {\n border-color: var(--md-sys-color-primary);\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n }\n label[rung] span {\n display: grid;\n gap: 2px;\n }\n label[rung] em,\n p[hint],\n small {\n font-style: normal;\n margin: 0;\n color: var(--md-sys-color-on-surface-variant);\n }\n button[place] {\n display: grid;\n gap: 2px;\n text-align: left;\n padding: 6px 8px;\n font: inherit;\n color: inherit;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n background: none;\n cursor: pointer;\n }\n button[place][on] {\n border-color: var(--md-sys-color-primary);\n }\n code {\n font-size: 0.9em;\n color: var(--md-sys-color-on-surface-variant);\n }\n `]\n\n @property({ attribute: false }) asset?: V3Asset\n /** The selected part, whose places are marked. */\n @property() selected = ''\n @property({ type: Boolean }) locked = false\n\n render() {\n const asset = this.asset\n if (!asset) return nothing\n const names = asset.document.capabilities.names ?? []\n const rung = rungOf(names)\n const places = v3BindingsOf(asset)\n return html`<section>\n <h3>${i18next.t('figure.label.what-this-does')}</h3>\n ${(['none', 'hold', 'flow'] as const).map(\n which => html`<label rung ?on=${rung === which}>\n <input type=\"radio\" name=\"rung\" .checked=${live(rung === which)} ?disabled=${this.locked} @change=${() => this.setRung(which)} />\n <span>\n <strong>${i18next.t(`figure.label.rung-${which}`)}</strong>\n <em>${i18next.t(`figure.text.rung-${which}-note`)}</em>\n </span>\n </label>`\n )}\n ${rung === null ? html`<p hint>${i18next.t('figure.text.capability-hand-written')}</p>` : nothing}\n ${names.length ? html`<code>${names.join(' · ')}</code>` : nothing}\n </section>\n <section>\n <h3>${i18next.t('figure.label.places')}</h3>\n ${places.length\n ? places.map(\n one => html`<button place ?on=${one.part === this.selected} @click=${() => one.part && this.pick(one.part)}>\n <strong>${one.label}</strong>\n <small>\n ${i18next.t('figure.label.place-' + one.role)} · ${one.part ?? '?'}${one.face ? ' · ' + i18next.t('figure.label.face-' + one.face) : ''} ·\n ${one.accepts.join(', ')} · ${i18next.t('figure.label.place-holds', { count: one.capacity })}\n </small>\n </button>`\n )\n : html`<p hint>${i18next.t('figure.text.no-places')}</p>`}\n ${places.length && rung === 'none' ? html`<p hint>${i18next.t('figure.text.place-needs-holding')}</p>` : nothing}\n </section>\n `\n }\n\n private setRung(which: Rung) {\n this.dispatchEvent(new CustomEvent('v3-part-edit', { detail: { edit: { kind: 'set-capabilities', names: [...RUNGS[which]] } }, bubbles: true, composed: true }))\n }\n\n private pick(part: string) {\n this.dispatchEvent(new CustomEvent('select-part', { detail: { id: part }, bubbles: true, composed: true }))\n }\n}\n"]}
@@ -1,31 +0,0 @@
1
- import '@material/web/icon/icon.js';
2
- import { LitElement, nothing } from 'lit';
3
- import type { V3Asset } from '@hatiolab/figure-model';
4
- declare const FigureV3Clips_base: (new (...args: any[]) => LitElement) & typeof LitElement;
5
- /**
6
- * 클립 — controls played by keys over time. A clip is one clock; each track plays one
7
- * control. Scrubbing a clip shows its pose at that moment (one batch of input changes, not saved as the default); a key
8
- * is added at the scrubbed moment with the control's value there, so a pose is made with the controls' sliders and
9
- * then kept as a key. Every change is one part edit.
10
- */
11
- export declare class FigureV3Clips extends FigureV3Clips_base {
12
- private readonly help;
13
- static styles: import("lit").CSSResult[];
14
- asset?: V3Asset;
15
- /** The values the editor holds now, by input id -- what a new key takes. */
16
- values: Record<string, number>;
17
- locked: boolean;
18
- /** Where each clip is scrubbed to, in seconds. */
19
- private at;
20
- private adding;
21
- render(): import("lit-html").TemplateResult<1> | typeof nothing;
22
- private renderClip;
23
- private renderTrack;
24
- private renderAdd;
25
- /** Show the clip's pose at a moment: one batch of input changes, not saved as the default. */
26
- /** Show the clip's pose at a moment. While the bar is dragged the pose is live (drawn, not recorded); the release
27
- * applies it as one batch of input changes. */
28
- private scrub;
29
- private edit;
30
- }
31
- export {};
@@ -1,268 +0,0 @@
1
- import { __decorate, __metadata } from "tslib";
2
- import '@material/web/icon/icon.js';
3
- import { css, html, LitElement, nothing } from 'lit';
4
- import { customElement, property, state } from 'lit/decorators.js';
5
- import { i18next, localize } from '@operato/i18n';
6
- import { clipsOf, poseAt, trackEdit, undrivenOf, withKey, withoutKey } from './v3-clips.js';
7
- import { SidePanelStyles } from './side-panel-styles.js';
8
- import { HelpToggles } from './v3-help.js';
9
- /**
10
- * 클립 — controls played by keys over time. A clip is one clock; each track plays one
11
- * control. Scrubbing a clip shows its pose at that moment (one batch of input changes, not saved as the default); a key
12
- * is added at the scrubbed moment with the control's value there, so a pose is made with the controls' sliders and
13
- * then kept as a key. Every change is one part edit.
14
- */
15
- let FigureV3Clips = class FigureV3Clips extends localize(i18next)(LitElement) {
16
- constructor() {
17
- super(...arguments);
18
- this.help = new HelpToggles(this);
19
- /** The values the editor holds now, by input id -- what a new key takes. */
20
- this.values = {};
21
- this.locked = false;
22
- /** Where each clip is scrubbed to, in seconds. */
23
- this.at = {};
24
- this.adding = { state: '', clip: '', name: '', duration: 2 };
25
- }
26
- static { this.styles = [SidePanelStyles, css `
27
- :host {
28
- display: block;
29
- }
30
- section[clip] {
31
- display: grid;
32
- gap: 8px;
33
- padding: 8px;
34
- border: 1px solid var(--md-sys-color-outline-variant);
35
- border-radius: 8px;
36
- }
37
- div[row] {
38
- display: grid;
39
- grid-template-columns: minmax(0, 1fr) 72px;
40
- gap: 6px;
41
- align-items: center;
42
- }
43
- div[track] {
44
- display: grid;
45
- gap: 4px;
46
- padding-top: 6px;
47
- border-top: 1px dashed var(--md-sys-color-outline-variant);
48
- }
49
- /*
50
- The track's name on its own line, then how it repeats and the button that removes it. A flex row let the shared
51
- full-width select and button squeeze the name to one letter a line (user, 2026-09-24).
52
- */
53
- div[track-head] {
54
- display: grid;
55
- grid-template-columns: minmax(0, 1fr) 30px;
56
- gap: 4px 6px;
57
- align-items: center;
58
- }
59
- div[track-head] strong {
60
- grid-column: 1 / -1;
61
- min-width: 0;
62
- overflow-wrap: anywhere;
63
- }
64
- div[track-head] button[act] {
65
- width: 30px;
66
- min-height: var(--figure-control-height);
67
- margin: 0;
68
- padding: 0;
69
- }
70
- div[keys] {
71
- display: flex;
72
- flex-wrap: wrap;
73
- gap: 4px;
74
- }
75
- span[key] {
76
- display: inline-flex;
77
- align-items: center;
78
- gap: 2px;
79
- padding: 0 2px 0 8px;
80
- border-radius: 999em;
81
- background: var(--md-sys-color-surface-container);
82
- font-variant-numeric: tabular-nums;
83
- }
84
- span[key] button {
85
- width: 22px;
86
- height: 22px;
87
- padding: 0;
88
- border: none;
89
- background: none;
90
- }
91
- md-icon {
92
- font-size: 16px;
93
- width: 16px;
94
- height: 16px;
95
- }
96
- `]; }
97
- render() {
98
- const asset = this.asset;
99
- if (!asset)
100
- return nothing;
101
- const clips = clipsOf(asset);
102
- return html `
103
- <section>
104
- <h3>${i18next.t('figure.label.clips')}${this.help.button('figure.text.clips-explained')}</h3>
105
- ${this.help.hint('figure.text.clips-explained')}
106
- ${clips.map(clip => this.renderClip(clip))}
107
- </section>
108
- ${this.renderAdd(asset, clips)}
109
- `;
110
- }
111
- renderClip(clip) {
112
- const at = Math.min(this.at[clip.name] ?? 0, clip.duration);
113
- const number = (e) => e.target.valueAsNumber;
114
- return html `<section clip>
115
- <div form>
116
- <span>${i18next.t('figure.label.clip-name')}</span>
117
- <input .value=${clip.name} ?disabled=${this.locked} @change=${(e) => this.edit({ kind: 'set-clip', clip: clip.name, name: e.target.value })} />
118
- <span>${i18next.t('figure.label.clip-duration')}</span>
119
- <input type="number" min="0.1" step="any" .value=${String(clip.duration)} ?disabled=${this.locked} @change=${(e) => this.edit({ kind: 'set-clip', clip: clip.name, duration: number(e) })} />
120
- </div>
121
- <div row>
122
- <input
123
- type="range"
124
- min="0"
125
- max=${clip.duration}
126
- step=${clip.duration / 100}
127
- .value=${String(at)}
128
- ?disabled=${this.locked}
129
- aria-label=${i18next.t('figure.label.clip-time')}
130
- @input=${(e) => this.scrub(clip, number(e), true)}
131
- @change=${(e) => this.scrub(clip, number(e))}
132
- />
133
- <small>${at.toFixed(2)} s</small>
134
- </div>
135
- ${clip.tracks.map(track => this.renderTrack(clip, track, at))}
136
- </section>`;
137
- }
138
- renderTrack(clip, track, at) {
139
- const current = this.values[track.state];
140
- return html `<div track>
141
- <div track-head>
142
- <strong>${track.label} <small>(${track.unit})</small></strong>
143
- <select
144
- aria-label=${i18next.t('figure.label.clip-loop')}
145
- ?disabled=${this.locked}
146
- @change=${(e) => this.edit(trackEdit(clip, track, { loop: e.target.value }))}
147
- >
148
- <option value="wrap" ?selected=${track.loop === 'wrap'}>${i18next.t('figure.label.clip-loop-wrap')}</option>
149
- <option value="hold" ?selected=${track.loop === 'hold'}>${i18next.t('figure.label.clip-loop-hold')}</option>
150
- </select>
151
- <button act ?disabled=${this.locked} title=${i18next.t('figure.button.remove-track')} @click=${() => this.edit({ kind: 'remove-driver', state: track.state })}>
152
- <md-icon>close</md-icon>
153
- </button>
154
- </div>
155
- <div keys>
156
- ${track.keys.map((key, i) => html `<span key
157
- >${key.seconds}s → ${key.value}
158
- <button
159
- ?disabled=${this.locked || !withoutKey(track.keys, i)}
160
- title=${i18next.t('figure.button.remove-key')}
161
- aria-label=${i18next.t('figure.button.remove-key')}
162
- @click=${() => this.edit(trackEdit(clip, track, { keys: withoutKey(track.keys, i) }))}
163
- >
164
- <md-icon>close</md-icon>
165
- </button></span
166
- >`)}
167
- </div>
168
- <button
169
- act
170
- ?disabled=${this.locked || current === undefined}
171
- @click=${() => this.edit(trackEdit(clip, track, { keys: withKey(track.keys, { seconds: Math.round(at * 1000) / 1000, value: current }) }))}
172
- >
173
- <md-icon>add</md-icon>${i18next.t('figure.button.add-key-here', { seconds: at.toFixed(2), value: current ?? '' })}
174
- </button>
175
- </div>`;
176
- }
177
- renderAdd(asset, clips) {
178
- const free = undrivenOf(asset);
179
- if (!free.length)
180
- return clips.length ? nothing : html `<p hint>${i18next.t('figure.text.no-controls')}</p>`;
181
- const a = this.adding;
182
- const stateId = free.includes(a.state) ? a.state : free[0];
183
- const joining = clips.find(c => c.name === a.clip);
184
- const name = joining ? joining.name : a.name.trim();
185
- const input = asset.document.model.inputs.find(i => i.id === stateId);
186
- const duration = joining ? joining.duration : a.duration;
187
- const ready = !!name && duration > 0;
188
- return html `<section><h3>${i18next.t('figure.label.add-track')}</h3>
189
- <div form>
190
- <span>${i18next.t('figure.label.controls')}</span>
191
- <select @change=${(e) => (this.adding = { ...a, state: e.target.value })}>
192
- ${free.map(id => html `<option value=${id} ?selected=${id === stateId}>${asset.stateInputs?.[id]?.label ?? id}</option>`)}
193
- </select>
194
- <span>${i18next.t('figure.label.clip')}</span>
195
- <select @change=${(e) => (this.adding = { ...a, clip: e.target.value })}>
196
- <option value="" ?selected=${!joining}>${i18next.t('figure.label.new-clip')}</option>
197
- ${clips.map(c => html `<option value=${c.name} ?selected=${c === joining}>${c.name}</option>`)}
198
- </select>
199
- ${joining
200
- ? nothing
201
- : html `<span>${i18next.t('figure.label.clip-name')}</span>
202
- <input .value=${a.name} placeholder="cycle" @input=${(e) => (this.adding = { ...a, name: e.target.value })} />
203
- <span>${i18next.t('figure.label.clip-duration')}</span>
204
- <input type="number" min="0.1" step="any" .value=${String(a.duration)} @change=${(e) => (this.adding = { ...a, duration: e.target.valueAsNumber })} />`}
205
- </div>
206
- <button
207
- act
208
- ?disabled=${this.locked || !ready}
209
- @click=${() => this.edit({
210
- kind: 'set-driver',
211
- state: stateId,
212
- clip: name,
213
- ...(joining ? {} : { duration }),
214
- keys: [
215
- { seconds: 0, value: input.min },
216
- { seconds: duration, value: input.max }
217
- ]
218
- })}
219
- >
220
- <md-icon>add</md-icon>${i18next.t('figure.button.add-track')}
221
- </button></section>`;
222
- }
223
- /** Show the clip's pose at a moment: one batch of input changes, not saved as the default. */
224
- /** Show the clip's pose at a moment. While the bar is dragged the pose is live (drawn, not recorded); the release
225
- * applies it as one batch of input changes. */
226
- scrub(clip, seconds, live = false) {
227
- if (!this.asset || !Number.isFinite(seconds))
228
- return;
229
- this.at = { ...this.at, [clip.name]: seconds };
230
- const changes = poseAt(this.asset, clip.name, seconds);
231
- if (!changes.length)
232
- return;
233
- if (live) {
234
- const values = Object.fromEntries(changes.map(c => [c.input, c.value]));
235
- this.dispatchEvent(new CustomEvent('v3-states-live', { detail: { values }, bubbles: true, composed: true }));
236
- return;
237
- }
238
- this.dispatchEvent(new CustomEvent('v3-states', { detail: { changes }, bubbles: true, composed: true }));
239
- }
240
- edit(edit) {
241
- this.dispatchEvent(new CustomEvent('v3-part-edit', { detail: { edit }, bubbles: true, composed: true }));
242
- }
243
- };
244
- __decorate([
245
- property({ attribute: false }),
246
- __metadata("design:type", Object)
247
- ], FigureV3Clips.prototype, "asset", void 0);
248
- __decorate([
249
- property({ attribute: false }),
250
- __metadata("design:type", Object)
251
- ], FigureV3Clips.prototype, "values", void 0);
252
- __decorate([
253
- property({ type: Boolean }),
254
- __metadata("design:type", Object)
255
- ], FigureV3Clips.prototype, "locked", void 0);
256
- __decorate([
257
- state(),
258
- __metadata("design:type", Object)
259
- ], FigureV3Clips.prototype, "at", void 0);
260
- __decorate([
261
- state(),
262
- __metadata("design:type", Object)
263
- ], FigureV3Clips.prototype, "adding", void 0);
264
- FigureV3Clips = __decorate([
265
- customElement('figure-v3-clips')
266
- ], FigureV3Clips);
267
- export { FigureV3Clips };
268
- //# sourceMappingURL=figure-v3-clips.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"figure-v3-clips.js","sourceRoot":"","sources":["../../client/modeller/figure-v3-clips.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport type { V3Asset } from '@hatiolab/figure-model'\n\nimport { clipsOf, poseAt, trackEdit, undrivenOf, withKey, withoutKey, type Clip, type ClipTrack } from './v3-clips.js'\nimport { SidePanelStyles } from './side-panel-styles.js'\nimport { HelpToggles } from './v3-help.js'\n\n/**\n * 클립 — controls played by keys over time. A clip is one clock; each track plays one\n * control. Scrubbing a clip shows its pose at that moment (one batch of input changes, not saved as the default); a key\n * is added at the scrubbed moment with the control's value there, so a pose is made with the controls' sliders and\n * then kept as a key. Every change is one part edit.\n */\n@customElement('figure-v3-clips')\nexport class FigureV3Clips extends localize(i18next)(LitElement) {\n private readonly help = new HelpToggles(this)\n static styles = [SidePanelStyles, css`\n :host {\n display: block;\n }\n section[clip] {\n display: grid;\n gap: 8px;\n padding: 8px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 8px;\n }\n div[row] {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 72px;\n gap: 6px;\n align-items: center;\n }\n div[track] {\n display: grid;\n gap: 4px;\n padding-top: 6px;\n border-top: 1px dashed var(--md-sys-color-outline-variant);\n }\n /*\n The track's name on its own line, then how it repeats and the button that removes it. A flex row let the shared\n full-width select and button squeeze the name to one letter a line (user, 2026-09-24).\n */\n div[track-head] {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 30px;\n gap: 4px 6px;\n align-items: center;\n }\n div[track-head] strong {\n grid-column: 1 / -1;\n min-width: 0;\n overflow-wrap: anywhere;\n }\n div[track-head] button[act] {\n width: 30px;\n min-height: var(--figure-control-height);\n margin: 0;\n padding: 0;\n }\n div[keys] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n }\n span[key] {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n padding: 0 2px 0 8px;\n border-radius: 999em;\n background: var(--md-sys-color-surface-container);\n font-variant-numeric: tabular-nums;\n }\n span[key] button {\n width: 22px;\n height: 22px;\n padding: 0;\n border: none;\n background: none;\n }\n md-icon {\n font-size: 16px;\n width: 16px;\n height: 16px;\n }\n `]\n\n @property({ attribute: false }) asset?: V3Asset\n /** The values the editor holds now, by input id -- what a new key takes. */\n @property({ attribute: false }) values: Record<string, number> = {}\n @property({ type: Boolean }) locked = false\n\n /** Where each clip is scrubbed to, in seconds. */\n @state() private at: Record<string, number> = {}\n @state() private adding = { state: '', clip: '', name: '', duration: 2 }\n\n render() {\n const asset = this.asset\n if (!asset) return nothing\n const clips = clipsOf(asset)\n return html`\n <section>\n <h3>${i18next.t('figure.label.clips')}${this.help.button('figure.text.clips-explained')}</h3>\n ${this.help.hint('figure.text.clips-explained')}\n ${clips.map(clip => this.renderClip(clip))}\n </section>\n ${this.renderAdd(asset, clips)}\n `\n }\n\n private renderClip(clip: Clip) {\n const at = Math.min(this.at[clip.name] ?? 0, clip.duration)\n const number = (e: Event) => (e.target as HTMLInputElement).valueAsNumber\n return html`<section clip>\n <div form>\n <span>${i18next.t('figure.label.clip-name')}</span>\n <input .value=${clip.name} ?disabled=${this.locked} @change=${(e: Event) => this.edit({ kind: 'set-clip', clip: clip.name, name: (e.target as HTMLInputElement).value })} />\n <span>${i18next.t('figure.label.clip-duration')}</span>\n <input type=\"number\" min=\"0.1\" step=\"any\" .value=${String(clip.duration)} ?disabled=${this.locked} @change=${(e: Event) => this.edit({ kind: 'set-clip', clip: clip.name, duration: number(e) })} />\n </div>\n <div row>\n <input\n type=\"range\"\n min=\"0\"\n max=${clip.duration}\n step=${clip.duration / 100}\n .value=${String(at)}\n ?disabled=${this.locked}\n aria-label=${i18next.t('figure.label.clip-time')}\n @input=${(e: Event) => this.scrub(clip, number(e), true)}\n @change=${(e: Event) => this.scrub(clip, number(e))}\n />\n <small>${at.toFixed(2)} s</small>\n </div>\n ${clip.tracks.map(track => this.renderTrack(clip, track, at))}\n </section>`\n }\n\n private renderTrack(clip: Clip, track: ClipTrack, at: number) {\n const current = this.values[track.state]\n return html`<div track>\n <div track-head>\n <strong>${track.label} <small>(${track.unit})</small></strong>\n <select\n aria-label=${i18next.t('figure.label.clip-loop')}\n ?disabled=${this.locked}\n @change=${(e: Event) => this.edit(trackEdit(clip, track, { loop: (e.target as HTMLSelectElement).value as 'wrap' | 'hold' }))}\n >\n <option value=\"wrap\" ?selected=${track.loop === 'wrap'}>${i18next.t('figure.label.clip-loop-wrap')}</option>\n <option value=\"hold\" ?selected=${track.loop === 'hold'}>${i18next.t('figure.label.clip-loop-hold')}</option>\n </select>\n <button act ?disabled=${this.locked} title=${i18next.t('figure.button.remove-track')} @click=${() => this.edit({ kind: 'remove-driver', state: track.state })}>\n <md-icon>close</md-icon>\n </button>\n </div>\n <div keys>\n ${track.keys.map(\n (key, i) => html`<span key\n >${key.seconds}s → ${key.value}\n <button\n ?disabled=${this.locked || !withoutKey(track.keys, i)}\n title=${i18next.t('figure.button.remove-key')}\n aria-label=${i18next.t('figure.button.remove-key')}\n @click=${() => this.edit(trackEdit(clip, track, { keys: withoutKey(track.keys, i)! }))}\n >\n <md-icon>close</md-icon>\n </button></span\n >`\n )}\n </div>\n <button\n act\n ?disabled=${this.locked || current === undefined}\n @click=${() => this.edit(trackEdit(clip, track, { keys: withKey(track.keys, { seconds: Math.round(at * 1000) / 1000, value: current! }) }))}\n >\n <md-icon>add</md-icon>${i18next.t('figure.button.add-key-here', { seconds: at.toFixed(2), value: current ?? '' })}\n </button>\n </div>`\n }\n\n private renderAdd(asset: V3Asset, clips: Clip[]) {\n const free = undrivenOf(asset)\n if (!free.length) return clips.length ? nothing : html`<p hint>${i18next.t('figure.text.no-controls')}</p>`\n const a = this.adding\n const stateId = free.includes(a.state) ? a.state : free[0]!\n const joining = clips.find(c => c.name === a.clip)\n const name = joining ? joining.name : a.name.trim()\n const input = asset.document.model.inputs.find(i => i.id === stateId)!\n const duration = joining ? joining.duration : a.duration\n const ready = !!name && duration > 0\n return html`<section><h3>${i18next.t('figure.label.add-track')}</h3>\n <div form>\n <span>${i18next.t('figure.label.controls')}</span>\n <select @change=${(e: Event) => (this.adding = { ...a, state: (e.target as HTMLSelectElement).value })}>\n ${free.map(id => html`<option value=${id} ?selected=${id === stateId}>${asset.stateInputs?.[id]?.label ?? id}</option>`)}\n </select>\n <span>${i18next.t('figure.label.clip')}</span>\n <select @change=${(e: Event) => (this.adding = { ...a, clip: (e.target as HTMLSelectElement).value })}>\n <option value=\"\" ?selected=${!joining}>${i18next.t('figure.label.new-clip')}</option>\n ${clips.map(c => html`<option value=${c.name} ?selected=${c === joining}>${c.name}</option>`)}\n </select>\n ${joining\n ? nothing\n : html`<span>${i18next.t('figure.label.clip-name')}</span>\n <input .value=${a.name} placeholder=\"cycle\" @input=${(e: Event) => (this.adding = { ...a, name: (e.target as HTMLInputElement).value })} />\n <span>${i18next.t('figure.label.clip-duration')}</span>\n <input type=\"number\" min=\"0.1\" step=\"any\" .value=${String(a.duration)} @change=${(e: Event) => (this.adding = { ...a, duration: (e.target as HTMLInputElement).valueAsNumber })} />`}\n </div>\n <button\n act\n ?disabled=${this.locked || !ready}\n @click=${() =>\n this.edit({\n kind: 'set-driver',\n state: stateId,\n clip: name,\n ...(joining ? {} : { duration }),\n keys: [\n { seconds: 0, value: input.min },\n { seconds: duration, value: input.max }\n ]\n })}\n >\n <md-icon>add</md-icon>${i18next.t('figure.button.add-track')}\n </button></section>`\n }\n\n /** Show the clip's pose at a moment: one batch of input changes, not saved as the default. */\n /** Show the clip's pose at a moment. While the bar is dragged the pose is live (drawn, not recorded); the release\n * applies it as one batch of input changes. */\n private scrub(clip: Clip, seconds: number, live = false) {\n if (!this.asset || !Number.isFinite(seconds)) return\n this.at = { ...this.at, [clip.name]: seconds }\n const changes = poseAt(this.asset, clip.name, seconds)\n if (!changes.length) return\n if (live) {\n const values = Object.fromEntries(changes.map(c => [c.input, c.value]))\n this.dispatchEvent(new CustomEvent('v3-states-live', { detail: { values }, bubbles: true, composed: true }))\n return\n }\n this.dispatchEvent(new CustomEvent('v3-states', { detail: { changes }, bubbles: true, composed: true }))\n }\n\n private edit(edit: unknown) {\n this.dispatchEvent(new CustomEvent('v3-part-edit', { detail: { edit }, bubbles: true, composed: true }))\n }\n}\n"]}
@@ -1,36 +0,0 @@
1
- import '@material/web/icon/icon.js';
2
- import { LitElement, nothing } from 'lit';
3
- import type { V3Asset } from '@hatiolab/figure-model';
4
- declare const FigureV3Controls_base: (new (...args: any[]) => LitElement) & typeof LitElement;
5
- /**
6
- * The figure's controls and its pose tools: each value a board sets to pose the figure,
7
- * with a slider to try it, its name, range and travel time, and a button that keeps the pose being looked at as the
8
- * pose it stands in when placed.
9
- *
10
- * Trying a value is an input change (`v3-state`, not saved as the default); naming, the range and the travel time are
11
- * one `set-state-input` part edit each; keeping the pose is one `set-state-defaults` edit. A control is made with
12
- * a motion on a part (「움직임」), which is where it gets its meaning.
13
- */
14
- export declare class FigureV3Controls extends FigureV3Controls_base {
15
- static styles: import("lit").CSSResult[];
16
- /** The asset being edited. */
17
- asset?: V3Asset;
18
- /** The values the editor holds now, by input id. */
19
- values: Record<string, number>;
20
- locked: boolean;
21
- /** Which control's settings are open. */
22
- private open;
23
- /** Values in hand while a slider is dragged: the dial and the number follow them before the release commits. */
24
- private live;
25
- render(): import("lit-html").TemplateResult<1> | typeof nothing;
26
- private renderControl;
27
- private renderDial;
28
- private renderSettings;
29
- /** While dragging: the value is told as live -- the editor draws that pose at once and records nothing. */
30
- private drag;
31
- /** Try a value: the pose being looked at, clamped to the range. Not saved as the default. The slider sends it on
32
- * release, so one drag is one step of the undo history rather than one per pixel. */
33
- private try;
34
- private edit;
35
- }
36
- export {};