@things-factory/figure-ui 10.1.75 → 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.
- package/client/figure-assistant.ts +3 -3
- package/client/graphql/{v3-store.ts → store.ts} +6 -6
- package/client/modeller/{v3-ai-proposal.ts → ai-proposal.ts} +8 -8
- package/client/modeller/{v3-align.ts → align.ts} +14 -14
- package/client/modeller/{v3-canvas.ts → canvas.ts} +13 -13
- package/client/modeller/{v3-clips.ts → clips.ts} +5 -5
- package/client/modeller/{v3-controls.ts → controls.ts} +2 -2
- package/client/modeller/{v3-editor.ts → editor.ts} +117 -117
- package/client/modeller/{figure-v3-capability.ts → figure-capability-panel.ts} +7 -7
- package/client/modeller/{figure-v3-clips.ts → figure-clips.ts} +10 -10
- package/client/modeller/{figure-v3-controls.ts → figure-controls.ts} +9 -9
- package/client/modeller/{v3-figure-facts.ts → figure-facts.ts} +11 -11
- package/client/modeller/{figure-v3-first-save.ts → figure-first-save.ts} +3 -3
- package/client/modeller/figure-history-panel.ts +1 -1
- package/client/modeller/{figure-v3-links.ts → figure-links.ts} +35 -35
- package/client/modeller/{figure-v3-material.ts → figure-material-panel.ts} +20 -20
- package/client/modeller/{figure-v3-parts.ts → figure-parts.ts} +15 -15
- package/client/modeller/{figure-v3-preview.ts → figure-preview.ts} +14 -14
- package/client/modeller/{figure-v3-properties.ts → figure-properties.ts} +25 -25
- package/client/modeller/{figure-v3-recipe-catalog.ts → figure-recipe-catalog.ts} +10 -10
- package/client/modeller/{figure-v3-verdict.ts → figure-verdict.ts} +24 -24
- package/client/modeller/gate-findings.ts +2 -2
- package/client/modeller/{v3-gizmo.ts → gizmo.ts} +11 -11
- package/client/modeller/{v3-joint-drag.ts → joint-drag.ts} +11 -11
- package/client/modeller/{v3-joint-fan.ts → joint-fan.ts} +13 -13
- package/client/modeller/{v3-links.ts → links.ts} +59 -59
- package/client/modeller/{v3-live.ts → live.ts} +9 -9
- package/client/modeller/{v3-maturity.ts → maturity.ts} +65 -65
- package/client/modeller/modeller-route.ts +1 -1
- package/client/modeller/{v3-occupancy.ts → occupancy.ts} +6 -6
- package/client/modeller/{v3-palette.ts → palette.ts} +3 -3
- package/client/modeller/{v3-preview-model.ts → preview-model.ts} +8 -8
- package/client/modeller/{v3-product-session.ts → product-session.ts} +25 -25
- package/client/modeller/{v3-recipe-source.ts → recipe-source.ts} +2 -2
- package/client/modeller/{v3-recipes.ts → recipes.ts} +9 -9
- package/client/modeller/{v3-renderer.ts → renderer.ts} +16 -16
- package/client/modeller/{v3-stage-model.ts → stage-model.ts} +15 -15
- package/client/modeller/{v3-thumbnail.ts → thumbnail.ts} +8 -8
- package/client/pages/figure-list-page.ts +4 -4
- package/client/pages/{figure-v3-modeller-page.ts → figure-modeller-page.ts} +37 -37
- package/client/route.ts +1 -5
- package/dist-client/figure-assistant.js +3 -3
- package/dist-client/figure-assistant.js.map +1 -1
- package/dist-client/graphql/store.d.ts +3 -0
- package/dist-client/graphql/{v3-store.js → store.js} +6 -6
- package/dist-client/graphql/store.js.map +1 -0
- package/dist-client/modeller/{v3-ai-proposal.d.ts → ai-proposal.d.ts} +7 -7
- package/dist-client/modeller/{v3-ai-proposal.js → ai-proposal.js} +1 -1
- package/dist-client/modeller/ai-proposal.js.map +1 -0
- package/dist-client/modeller/{v3-align.d.ts → align.d.ts} +8 -8
- package/dist-client/modeller/{v3-align.js → align.js} +6 -6
- package/dist-client/modeller/align.js.map +1 -0
- package/dist-client/modeller/{v3-canvas.d.ts → canvas.d.ts} +7 -7
- package/dist-client/modeller/{v3-canvas.js → canvas.js} +20 -20
- package/dist-client/modeller/canvas.js.map +1 -0
- package/dist-client/modeller/{v3-clips.d.ts → clips.d.ts} +4 -4
- package/dist-client/modeller/{v3-clips.js → clips.js} +1 -1
- package/dist-client/modeller/clips.js.map +1 -0
- package/dist-client/modeller/{v3-controls.d.ts → controls.d.ts} +2 -2
- package/dist-client/modeller/{v3-controls.js → controls.js} +1 -1
- package/dist-client/modeller/controls.js.map +1 -0
- package/dist-client/modeller/{v3-editor.d.ts → editor.d.ts} +19 -19
- package/dist-client/modeller/{v3-editor.js → editor.js} +103 -103
- package/dist-client/modeller/editor.js.map +1 -0
- package/dist-client/modeller/{v3-fields.js → fields.js} +1 -1
- package/dist-client/modeller/fields.js.map +1 -0
- package/dist-client/modeller/{figure-v3-capability.d.ts → figure-capability-panel.d.ts} +4 -4
- package/dist-client/modeller/{figure-v3-capability.js → figure-capability-panel.js} +12 -12
- package/dist-client/modeller/figure-capability-panel.js.map +1 -0
- package/dist-client/modeller/{figure-v3-clips.d.ts → figure-clips.d.ts} +4 -4
- package/dist-client/modeller/{figure-v3-clips.js → figure-clips.js} +16 -16
- package/dist-client/modeller/figure-clips.js.map +1 -0
- package/dist-client/modeller/{figure-v3-controls.d.ts → figure-controls.d.ts} +5 -5
- package/dist-client/modeller/{figure-v3-controls.js → figure-controls.js} +16 -16
- package/dist-client/modeller/figure-controls.js.map +1 -0
- package/dist-client/modeller/{v3-figure-facts.d.ts → figure-facts.d.ts} +5 -5
- package/dist-client/modeller/{v3-figure-facts.js → figure-facts.js} +5 -5
- package/dist-client/modeller/figure-facts.js.map +1 -0
- package/dist-client/modeller/{figure-v3-first-save.d.ts → figure-first-save.d.ts} +1 -1
- package/dist-client/modeller/{figure-v3-first-save.js → figure-first-save.js} +11 -11
- package/dist-client/modeller/figure-first-save.js.map +1 -0
- package/dist-client/modeller/figure-history-panel.d.ts +1 -1
- package/dist-client/modeller/figure-history-panel.js.map +1 -1
- package/dist-client/modeller/{figure-v3-links.d.ts → figure-links.d.ts} +5 -5
- package/dist-client/modeller/{figure-v3-links.js → figure-links.js} +24 -24
- package/dist-client/modeller/figure-links.js.map +1 -0
- package/dist-client/modeller/{figure-v3-material.d.ts → figure-material-panel.d.ts} +9 -9
- package/dist-client/modeller/{figure-v3-material.js → figure-material-panel.js} +19 -19
- package/dist-client/modeller/figure-material-panel.js.map +1 -0
- package/dist-client/modeller/{figure-v3-parts.d.ts → figure-parts.d.ts} +12 -12
- package/dist-client/modeller/{figure-v3-parts.js → figure-parts.js} +14 -14
- package/dist-client/modeller/figure-parts.js.map +1 -0
- package/dist-client/modeller/{figure-v3-preview.d.ts → figure-preview.d.ts} +4 -4
- package/dist-client/modeller/{figure-v3-preview.js → figure-preview.js} +21 -21
- package/dist-client/modeller/figure-preview.js.map +1 -0
- package/dist-client/modeller/{figure-v3-properties.d.ts → figure-properties.d.ts} +8 -8
- package/dist-client/modeller/{figure-v3-properties.js → figure-properties.js} +25 -25
- package/dist-client/modeller/figure-properties.js.map +1 -0
- package/dist-client/modeller/{figure-v3-recipe-catalog.d.ts → figure-recipe-catalog.d.ts} +4 -4
- package/dist-client/modeller/{figure-v3-recipe-catalog.js → figure-recipe-catalog.js} +21 -21
- package/dist-client/modeller/figure-recipe-catalog.js.map +1 -0
- package/dist-client/modeller/{figure-v3-verdict.d.ts → figure-verdict.d.ts} +2 -2
- package/dist-client/modeller/{figure-v3-verdict.js → figure-verdict.js} +26 -26
- package/dist-client/modeller/figure-verdict.js.map +1 -0
- package/dist-client/modeller/{v3-first-save.js → first-save.js} +1 -1
- package/dist-client/modeller/first-save.js.map +1 -0
- package/dist-client/modeller/gate-findings.d.ts +2 -2
- package/dist-client/modeller/gate-findings.js +2 -2
- package/dist-client/modeller/gate-findings.js.map +1 -1
- package/dist-client/modeller/{v3-gizmo.d.ts → gizmo.d.ts} +5 -5
- package/dist-client/modeller/{v3-gizmo.js → gizmo.js} +3 -3
- package/dist-client/modeller/gizmo.js.map +1 -0
- package/dist-client/modeller/{v3-help.js → help.js} +1 -1
- package/dist-client/modeller/help.js.map +1 -0
- package/dist-client/modeller/joint-drag.d.ts +19 -0
- package/dist-client/modeller/{v3-joint-drag.js → joint-drag.js} +4 -4
- package/dist-client/modeller/joint-drag.js.map +1 -0
- package/dist-client/modeller/{v3-joint-fan.d.ts → joint-fan.d.ts} +3 -3
- package/dist-client/modeller/{v3-joint-fan.js → joint-fan.js} +6 -6
- package/dist-client/modeller/joint-fan.js.map +1 -0
- package/dist-client/modeller/{v3-keys.js → keys.js} +1 -1
- package/dist-client/modeller/keys.js.map +1 -0
- package/dist-client/modeller/{v3-links.d.ts → links.d.ts} +48 -48
- package/dist-client/modeller/{v3-links.js → links.js} +15 -15
- package/dist-client/modeller/links.js.map +1 -0
- package/dist-client/modeller/{v3-live.d.ts → live.d.ts} +6 -6
- package/dist-client/modeller/{v3-live.js → live.js} +5 -5
- package/dist-client/modeller/live.js.map +1 -0
- package/dist-client/modeller/{v3-maturity.d.ts → maturity.d.ts} +26 -26
- package/dist-client/modeller/{v3-maturity.js → maturity.js} +28 -28
- package/dist-client/modeller/maturity.js.map +1 -0
- package/dist-client/modeller/modeller-route.d.ts +1 -1
- package/dist-client/modeller/modeller-route.js +1 -1
- package/dist-client/modeller/modeller-route.js.map +1 -1
- package/dist-client/modeller/{v3-occupancy.d.ts → occupancy.d.ts} +4 -4
- package/dist-client/modeller/{v3-occupancy.js → occupancy.js} +6 -6
- package/dist-client/modeller/occupancy.js.map +1 -0
- package/dist-client/modeller/palette.d.ts +7 -0
- package/dist-client/modeller/{v3-palette.js → palette.js} +1 -1
- package/dist-client/modeller/palette.js.map +1 -0
- package/dist-client/modeller/{v3-preview-model.d.ts → preview-model.d.ts} +3 -3
- package/dist-client/modeller/{v3-preview-model.js → preview-model.js} +6 -6
- package/dist-client/modeller/preview-model.js.map +1 -0
- package/dist-client/modeller/{v3-product-session.d.ts → product-session.d.ts} +56 -56
- package/dist-client/modeller/{v3-product-session.js → product-session.js} +7 -7
- package/dist-client/modeller/product-session.js.map +1 -0
- package/dist-client/modeller/{v3-recipe-source.d.ts → recipe-source.d.ts} +2 -2
- package/dist-client/modeller/{v3-recipe-source.js → recipe-source.js} +3 -3
- package/dist-client/modeller/recipe-source.js.map +1 -0
- package/dist-client/modeller/{v3-recipes.d.ts → recipes.d.ts} +7 -7
- package/dist-client/modeller/{v3-recipes.js → recipes.js} +4 -4
- package/dist-client/modeller/recipes.js.map +1 -0
- package/dist-client/modeller/{v3-refusals.js → refusals.js} +1 -1
- package/dist-client/modeller/refusals.js.map +1 -0
- package/dist-client/modeller/{v3-renderer.d.ts → renderer.d.ts} +6 -6
- package/dist-client/modeller/{v3-renderer.js → renderer.js} +13 -13
- package/dist-client/modeller/renderer.js.map +1 -0
- package/dist-client/modeller/{v3-stage-model.d.ts → stage-model.d.ts} +7 -7
- package/dist-client/modeller/{v3-stage-model.js → stage-model.js} +5 -5
- package/dist-client/modeller/stage-model.js.map +1 -0
- package/dist-client/modeller/thumbnail.d.ts +3 -0
- package/dist-client/modeller/{v3-thumbnail.js → thumbnail.js} +6 -6
- package/dist-client/modeller/thumbnail.js.map +1 -0
- package/dist-client/pages/figure-list-page.d.ts +1 -1
- package/dist-client/pages/figure-list-page.js +4 -4
- package/dist-client/pages/figure-list-page.js.map +1 -1
- package/dist-client/pages/{figure-v3-modeller-page.d.ts → figure-modeller-page.d.ts} +10 -10
- package/dist-client/pages/{figure-v3-modeller-page.js → figure-modeller-page.js} +42 -42
- package/dist-client/pages/figure-modeller-page.js.map +1 -0
- package/dist-client/route.d.ts +1 -1
- package/dist-client/route.js +1 -5
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/docs/product-cutover.md +25 -0
- package/package.json +5 -5
- package/test/{v3-ai-proposal.test.ts → ai-proposal.test.ts} +6 -6
- package/test/{v3-align.test.ts → align.test.ts} +8 -8
- package/test/browser/modeller-page.js +30 -30
- package/test/browser/modeller.check.mjs +14 -14
- package/test/browser/serve.mjs +1 -1
- package/test/browser/thumbnail-page.js +6 -6
- package/test/{v3-clips.test.ts → clips.test.ts} +18 -18
- package/test/{v3-controls.test.ts → controls.test.ts} +15 -15
- package/test/{v3-fields.test.ts → fields.test.ts} +13 -13
- package/test/figure-assistant-surface.test.ts +3 -3
- package/test/{v3-first-save.test.ts → first-save.test.ts} +10 -10
- package/test/fixtures/joint-column.json +2 -2
- package/test/fixtures/joint-roller.json +2 -2
- package/test/fixtures/robot-arm-6dof.json +2 -2
- package/test/{v3-gizmo.test.ts → gizmo.test.ts} +33 -33
- package/test/{v3-joint-drag.test.ts → joint-drag.test.ts} +17 -17
- package/test/{v3-joint-fan.test.ts → joint-fan.test.ts} +18 -18
- package/test/joints.ts +6 -6
- package/test/{v3-keys.test.ts → keys.test.ts} +2 -2
- package/test/{v3-layout.test.ts → layout.test.ts} +8 -8
- package/test/{v3-links.test.ts → links.test.ts} +201 -201
- package/test/{v3-live.test.ts → live.test.ts} +18 -18
- package/test/{v3-material.test.ts → material.test.ts} +12 -12
- package/test/{v3-maturity.test.ts → maturity.test.ts} +74 -74
- package/test/modeller-route.test.ts +5 -6
- package/test/{v3-palette-icons.test.ts → palette-icons.test.ts} +1 -1
- package/test/{v3-parts-wiring.test.ts → parts-wiring.test.ts} +5 -5
- package/test/{v3-preview.test.ts → preview.test.ts} +12 -12
- package/test/{v3-product-session.test.ts → product-session.test.ts} +17 -17
- package/test/{v3-product-write.test.ts → product-write.test.ts} +20 -20
- package/test/{v3-properties.test.ts → properties.test.ts} +24 -24
- package/test/{v3-recipes.test.ts → recipes.test.ts} +9 -9
- package/test/{v3-refusals.test.ts → refusals.test.ts} +43 -43
- package/test/{v3-release-panel.test.ts → release-panel.test.ts} +21 -21
- package/test/renderer.test.ts +24 -0
- package/test/resolve-ts-siblings.mjs +1 -1
- package/test/{v3-scene-canvas.test.ts → scene-canvas.test.ts} +6 -6
- package/test/{v3-stage-model.test.ts → stage-model.test.ts} +5 -5
- package/test/{v3-theme.test.ts → theme.test.ts} +4 -4
- package/test/{v3-thumbnail.test.ts → thumbnail.test.ts} +4 -4
- package/test/{v3-verdict.test.ts → verdict.test.ts} +17 -17
- package/test/{v3-view.test.ts → view.test.ts} +2 -2
- package/things-factory.config.js +2 -3
- package/translations/en.json +2 -2
- package/translations/ja.json +2 -2
- package/translations/ko.json +2 -2
- package/translations/ms.json +2 -2
- package/translations/zh.json +2 -2
- package/dist-client/graphql/v3-store.d.ts +0 -3
- package/dist-client/graphql/v3-store.js.map +0 -1
- package/dist-client/modeller/figure-v3-capability.js.map +0 -1
- package/dist-client/modeller/figure-v3-clips.js.map +0 -1
- package/dist-client/modeller/figure-v3-controls.js.map +0 -1
- package/dist-client/modeller/figure-v3-first-save.js.map +0 -1
- package/dist-client/modeller/figure-v3-links.js.map +0 -1
- package/dist-client/modeller/figure-v3-material.js.map +0 -1
- package/dist-client/modeller/figure-v3-parts.js.map +0 -1
- package/dist-client/modeller/figure-v3-preview.js.map +0 -1
- package/dist-client/modeller/figure-v3-properties.js.map +0 -1
- package/dist-client/modeller/figure-v3-recipe-catalog.js.map +0 -1
- package/dist-client/modeller/figure-v3-verdict.js.map +0 -1
- package/dist-client/modeller/v3-ai-proposal.js.map +0 -1
- package/dist-client/modeller/v3-align.js.map +0 -1
- package/dist-client/modeller/v3-canvas.js.map +0 -1
- package/dist-client/modeller/v3-clips.js.map +0 -1
- package/dist-client/modeller/v3-controls.js.map +0 -1
- package/dist-client/modeller/v3-editor.js.map +0 -1
- package/dist-client/modeller/v3-fields.js.map +0 -1
- package/dist-client/modeller/v3-figure-facts.js.map +0 -1
- package/dist-client/modeller/v3-first-save.js.map +0 -1
- package/dist-client/modeller/v3-gizmo.js.map +0 -1
- package/dist-client/modeller/v3-help.js.map +0 -1
- package/dist-client/modeller/v3-joint-drag.d.ts +0 -19
- package/dist-client/modeller/v3-joint-drag.js.map +0 -1
- package/dist-client/modeller/v3-joint-fan.js.map +0 -1
- package/dist-client/modeller/v3-keys.js.map +0 -1
- package/dist-client/modeller/v3-links.js.map +0 -1
- package/dist-client/modeller/v3-live.js.map +0 -1
- package/dist-client/modeller/v3-maturity.js.map +0 -1
- package/dist-client/modeller/v3-occupancy.js.map +0 -1
- package/dist-client/modeller/v3-palette.d.ts +0 -7
- package/dist-client/modeller/v3-palette.js.map +0 -1
- package/dist-client/modeller/v3-preview-model.js.map +0 -1
- package/dist-client/modeller/v3-product-session.js.map +0 -1
- package/dist-client/modeller/v3-recipe-source.js.map +0 -1
- package/dist-client/modeller/v3-recipes.js.map +0 -1
- package/dist-client/modeller/v3-refusals.js.map +0 -1
- package/dist-client/modeller/v3-renderer.js.map +0 -1
- package/dist-client/modeller/v3-stage-model.js.map +0 -1
- package/dist-client/modeller/v3-thumbnail.d.ts +0 -3
- package/dist-client/modeller/v3-thumbnail.js.map +0 -1
- package/dist-client/pages/figure-v3-modeller-page.js.map +0 -1
- package/dist-client/tsconfig.chk.tsbuildinfo +0 -1
- package/dist-client/tsconfig.fui.tsbuildinfo +0 -1
- package/dist-client/tsconfig.scratch-fm.tsbuildinfo +0 -1
- package/docs/v3-product-cutover.md +0 -25
- package/test/v3-renderer.test.ts +0 -24
- /package/client/modeller/{v3-fields.ts → fields.ts} +0 -0
- /package/client/modeller/{v3-first-save.ts → first-save.ts} +0 -0
- /package/client/modeller/{v3-help.ts → help.ts} +0 -0
- /package/client/modeller/{v3-keys.ts → keys.ts} +0 -0
- /package/client/modeller/{v3-refusals.ts → refusals.ts} +0 -0
- /package/dist-client/modeller/{v3-fields.d.ts → fields.d.ts} +0 -0
- /package/dist-client/modeller/{v3-first-save.d.ts → first-save.d.ts} +0 -0
- /package/dist-client/modeller/{v3-help.d.ts → help.d.ts} +0 -0
- /package/dist-client/modeller/{v3-keys.d.ts → keys.d.ts} +0 -0
- /package/dist-client/modeller/{v3-refusals.d.ts → refusals.d.ts} +0 -0
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import '@material/web/icon/icon.js';
|
|
2
2
|
import { LitElement, nothing } from 'lit';
|
|
3
|
-
import type {
|
|
4
|
-
declare const
|
|
3
|
+
import type { FigureAsset } from '@hatiolab/figure-model';
|
|
4
|
+
declare const FigureControls_base: (new (...args: any[]) => LitElement) & typeof LitElement;
|
|
5
5
|
/**
|
|
6
6
|
* The figure's controls and its pose tools: each value a board sets to pose the figure,
|
|
7
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
8
|
* pose it stands in when placed.
|
|
9
9
|
*
|
|
10
|
-
* Trying a value is an input change (`
|
|
10
|
+
* Trying a value is an input change (`state`, not saved as the default); naming, the range and the travel time are
|
|
11
11
|
* one `set-state-input` part edit each; keeping the pose is one `set-state-defaults` edit. A control is made with
|
|
12
12
|
* a motion on a part (「움직임」), which is where it gets its meaning.
|
|
13
13
|
*/
|
|
14
|
-
export declare class
|
|
14
|
+
export declare class FigureControls extends FigureControls_base {
|
|
15
15
|
static styles: import("lit").CSSResult[];
|
|
16
16
|
/** The asset being edited. */
|
|
17
|
-
asset?:
|
|
17
|
+
asset?: FigureAsset;
|
|
18
18
|
/** The values the editor holds now, by input id. */
|
|
19
19
|
values: Record<string, number>;
|
|
20
20
|
locked: boolean;
|
|
@@ -3,7 +3,7 @@ import '@material/web/icon/icon.js';
|
|
|
3
3
|
import { css, html, LitElement, nothing } from 'lit';
|
|
4
4
|
import { customElement, property, state } from 'lit/decorators.js';
|
|
5
5
|
import { i18next, localize } from '@operato/i18n';
|
|
6
|
-
import { controlsOf, poseAsDefault, poseDiffers } from './
|
|
6
|
+
import { controlsOf, poseAsDefault, poseDiffers } from './controls.js';
|
|
7
7
|
import { dialShape } from './angle-dial.js';
|
|
8
8
|
import { SidePanelStyles } from './side-panel-styles.js';
|
|
9
9
|
/**
|
|
@@ -11,11 +11,11 @@ import { SidePanelStyles } from './side-panel-styles.js';
|
|
|
11
11
|
* with a slider to try it, its name, range and travel time, and a button that keeps the pose being looked at as the
|
|
12
12
|
* pose it stands in when placed.
|
|
13
13
|
*
|
|
14
|
-
* Trying a value is an input change (`
|
|
14
|
+
* Trying a value is an input change (`state`, not saved as the default); naming, the range and the travel time are
|
|
15
15
|
* one `set-state-input` part edit each; keeping the pose is one `set-state-defaults` edit. A control is made with
|
|
16
16
|
* a motion on a part (「움직임」), which is where it gets its meaning.
|
|
17
17
|
*/
|
|
18
|
-
let
|
|
18
|
+
let FigureControls = class FigureControls extends localize(i18next)(LitElement) {
|
|
19
19
|
constructor() {
|
|
20
20
|
super(...arguments);
|
|
21
21
|
/** The values the editor holds now, by input id. */
|
|
@@ -183,7 +183,7 @@ let FigureV3Controls = class FigureV3Controls extends localize(i18next)(LitEleme
|
|
|
183
183
|
if (!Number.isFinite(value))
|
|
184
184
|
return;
|
|
185
185
|
this.live = { ...this.live, [c.id]: value };
|
|
186
|
-
this.dispatchEvent(new CustomEvent('
|
|
186
|
+
this.dispatchEvent(new CustomEvent('state-live', { detail: { input: c.id, value }, bubbles: true, composed: true }));
|
|
187
187
|
}
|
|
188
188
|
/** Try a value: the pose being looked at, clamped to the range. Not saved as the default. The slider sends it on
|
|
189
189
|
* release, so one drag is one step of the undo history rather than one per pixel. */
|
|
@@ -193,34 +193,34 @@ let FigureV3Controls = class FigureV3Controls extends localize(i18next)(LitEleme
|
|
|
193
193
|
const clamped = Math.min(Math.max(value, c.min), c.max);
|
|
194
194
|
const { [c.id]: _released, ...rest } = this.live;
|
|
195
195
|
this.live = rest;
|
|
196
|
-
this.dispatchEvent(new CustomEvent('
|
|
196
|
+
this.dispatchEvent(new CustomEvent('state', { detail: { input: c.id, unit: c.unit, value: clamped }, bubbles: true, composed: true }));
|
|
197
197
|
}
|
|
198
198
|
edit(edit) {
|
|
199
|
-
this.dispatchEvent(new CustomEvent('
|
|
199
|
+
this.dispatchEvent(new CustomEvent('part-edit', { detail: { edit }, bubbles: true, composed: true }));
|
|
200
200
|
}
|
|
201
201
|
};
|
|
202
202
|
__decorate([
|
|
203
203
|
property({ attribute: false }),
|
|
204
204
|
__metadata("design:type", Object)
|
|
205
|
-
],
|
|
205
|
+
], FigureControls.prototype, "asset", void 0);
|
|
206
206
|
__decorate([
|
|
207
207
|
property({ attribute: false }),
|
|
208
208
|
__metadata("design:type", Object)
|
|
209
|
-
],
|
|
209
|
+
], FigureControls.prototype, "values", void 0);
|
|
210
210
|
__decorate([
|
|
211
211
|
property({ type: Boolean }),
|
|
212
212
|
__metadata("design:type", Object)
|
|
213
|
-
],
|
|
213
|
+
], FigureControls.prototype, "locked", void 0);
|
|
214
214
|
__decorate([
|
|
215
215
|
state(),
|
|
216
216
|
__metadata("design:type", Object)
|
|
217
|
-
],
|
|
217
|
+
], FigureControls.prototype, "open", void 0);
|
|
218
218
|
__decorate([
|
|
219
219
|
state(),
|
|
220
220
|
__metadata("design:type", Object)
|
|
221
|
-
],
|
|
222
|
-
|
|
223
|
-
customElement('figure-
|
|
224
|
-
],
|
|
225
|
-
export {
|
|
226
|
-
//# sourceMappingURL=figure-
|
|
221
|
+
], FigureControls.prototype, "live", void 0);
|
|
222
|
+
FigureControls = __decorate([
|
|
223
|
+
customElement('figure-controls')
|
|
224
|
+
], FigureControls);
|
|
225
|
+
export { FigureControls };
|
|
226
|
+
//# sourceMappingURL=figure-controls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"figure-controls.js","sourceRoot":"","sources":["../../client/modeller/figure-controls.ts"],"names":[],"mappings":";AAAA,OAAO,4BAA4B,CAAA;AAEnC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAElE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAGjD,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAgB,MAAM,eAAe,CAAA;AACpF,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAExD;;;;;;;;GAQG;AAEI,IAAM,cAAc,GAApB,MAAM,cAAe,SAAQ,QAAQ,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC;IAA1D;;QA6EL,oDAAoD;QACpB,WAAM,GAA2B,EAAE,CAAA;QACtC,WAAM,GAAG,KAAK,CAAA;QAE3C,yCAAyC;QACxB,SAAI,GAAG,EAAE,CAAA;QAC1B,gHAAgH;QAC/F,SAAI,GAA2B,EAAE,CAAA;IAyGpD,CAAC;aA5LQ,WAAM,GAAG,CAAC,eAAe,EAAE,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEpC,CAAC,AAxEW,CAwEX;IAaF,MAAM;QACJ,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO,OAAO,CAAA;QAC/B,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QACpD,OAAO,IAAI,CAAA;YACH,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC;QACtC,QAAQ,CAAC,MAAM;YACf,CAAC,CAAC,IAAI,CAAA,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;oCACjC,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,WAAW,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;2CACjF,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC;sBACzD;YACd,CAAC,CAAC,IAAI,CAAA,WAAW,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC,MAAM;eACpD,CAAA;IACb,CAAC;IAEO,aAAa,CAAC,OAAgB;QACpC,MAAM,MAAM,GAAG,CAAC,CAAQ,EAAE,EAAE,CAAE,CAAC,CAAC,MAA2B,CAAC,aAAa,CAAA;QACzE,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAE,EAAE,CAAA;QACvG,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,CAAA;QAC/B,OAAO,IAAI,CAAA;2BACY,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,IAAI;UAC9C,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA,eAAe;;;gBAGrD,CAAC,CAAC,GAAG;gBACL,CAAC,CAAC,GAAG;iBACJ,CAAC,CAAC,IAAI;mBACJ,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;sBACZ,IAAI,CAAC,MAAM;uBACV,CAAC,CAAC,KAAK;mBACX,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;oBACpC,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;;iDAEP,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,cAAc,IAAI,CAAC,MAAM,eAAe,CAAC,CAAC,KAAK,YAAY,CAAC,CAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;;;0BAG7J,MAAM,CAAC,IAAI,CAAC;kBACpB,OAAO,CAAC,CAAC,CAAC,gCAAgC,CAAC;uBACtC,OAAO,CAAC,CAAC,CAAC,gCAAgC,CAAC;mBAC/C,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;;;;;QAK/C,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAA;IAC/C,CAAC;IAEO,UAAU,CAAC,CAAU;QAC3B,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAA;QAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,CAAA;QAChC,OAAO,IAAI,CAAA,0BAA0B,IAAI,IAAI,IAAI;gBACrC,IAAI,CAAC,MAAM;mBACR,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM;iBACpD,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;WAC/E,CAAA;IACT,CAAC;IAEO,cAAc,CAAC,CAAU;QAC/B,MAAM,MAAM,GAAG,CAAC,KAA0E,EAAE,EAAE,CAC5F,IAAI,CAAC,IAAI,CAAC;YACR,IAAI,EAAE,iBAAiB;YACvB,KAAK,EAAE,CAAC,CAAC,EAAE;YACX,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;YACrD,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK;YAC7B,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACtD,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvD,CAAC,CAAA;QACJ,MAAM,MAAM,GAAG,CAAC,CAAQ,EAAE,EAAE,CAAE,CAAC,CAAC,MAA2B,CAAC,aAAa,CAAA;QACzE,OAAO,IAAI,CAAA;;gBAEC,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC;wBAC9B,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,EAAE,cAAc,IAAI,CAAC,MAAM,YAAY,CAAC,CAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,EAAG,CAAC,CAAC,MAA2B,CAAC,KAAK,EAAE,CAAC;gBAC5J,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC,KAAK,CAAC,CAAC,IAAI;;mDAEf,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,MAAM,YAAY,CAAC,CAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;mDAC1F,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,IAAI,CAAC,MAAM,YAAY,CAAC,CAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;;gBAE7H,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC;yDACE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,IAAI,CAAC,MAAM,YAAY,CAAC,CAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;;eAExI,OAAO,CAAC,CAAC,CAAC,+BAA+B,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;WAChF,CAAA;IACT,CAAC;IAED,2GAA2G;IACnG,IAAI,CAAC,CAAU,EAAE,KAAa;QACpC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAM;QACnC,IAAI,CAAC,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAA;QAC3C,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IACtH,CAAC;IAED;yFACqF;IAC7E,GAAG,CAAC,CAAU,EAAE,KAAa;QACnC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAM;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAA;QACvD,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,CAAA;QAChD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IACxI,CAAC;IAEO,IAAI,CAAC,IAAa;QACxB,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;IACvG,CAAC;;AAhH+B;IAA/B,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;;6CAAoB;AAEnB;IAA/B,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;;8CAAoC;AACtC;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;;8CAAe;AAG1B;IAAhB,KAAK,EAAE;;4CAAkB;AAET;IAAhB,KAAK,EAAE;;4CAA0C;AApFvC,cAAc;IAD1B,aAAa,CAAC,iBAAiB,CAAC;GACpB,cAAc,CA6L1B","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 { FigureAsset } from '@hatiolab/figure-model'\n\nimport { controlsOf, poseAsDefault, poseDiffers, type Control } from './controls.js'\nimport { dialShape } from './angle-dial.js'\nimport { SidePanelStyles } from './side-panel-styles.js'\n\n/**\n * The figure's controls and its pose tools: each value a board sets to pose the figure,\n * with a slider to try it, its name, range and travel time, and a button that keeps the pose being looked at as the\n * pose it stands in when placed.\n *\n * Trying a value is an input change (`state`, not saved as the default); naming, the range and the travel time are\n * one `set-state-input` part edit each; keeping the pose is one `set-state-defaults` edit. A control is made with\n * a motion on a part (「움직임」), which is where it gets its meaning.\n */\n@customElement('figure-controls')\nexport class FigureControls extends localize(i18next)(LitElement) {\n static styles = [SidePanelStyles, css`\n :host {\n display: block;\n }\n /* One control, one line: its name, a dial for an angle, a thin slider, the value. */\n div[control] {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 18px minmax(64px, 1.2fr) 58px 22px;\n align-items: center;\n gap: 6px;\n min-height: 28px;\n }\n div[control] > span[name] {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n div[control] > span[name] em {\n font-style: normal;\n font-size: 0.64rem;\n color: var(--md-sys-color-on-surface-variant);\n }\n div[control] input[type='number'] {\n min-height: 24px;\n padding: 2px 5px;\n font-family: var(--mono-font, monospace);\n text-align: right;\n }\n svg[dial] {\n width: 18px;\n height: 18px;\n }\n svg[dial] path {\n fill: var(--md-sys-color-surface-container-high);\n }\n svg[dial] circle {\n fill: none;\n stroke: var(--md-sys-color-outline-variant);\n }\n svg[dial] line {\n stroke: var(--md-sys-color-primary);\n stroke-width: 2;\n stroke-linecap: round;\n }\n button[more] {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n padding: 0;\n border: none;\n border-radius: 4px;\n background: none;\n color: var(--md-sys-color-on-surface-variant);\n cursor: pointer;\n }\n button[more][aria-expanded='true'] {\n color: var(--md-sys-color-primary);\n background: var(--md-sys-color-surface-container);\n }\n button[more] md-icon {\n font-size: 16px;\n width: 16px;\n height: 16px;\n }\n /* The rarely changed: the name, the range, the travel time -- opened per control. */\n div[settings] {\n margin: 2px 0 8px;\n padding: 6px 0 6px 8px;\n border-left: 2px solid var(--md-sys-color-outline-variant);\n }\n `]\n\n /** The asset being edited. */\n @property({ attribute: false }) asset?: FigureAsset\n /** The values the editor holds now, by input id. */\n @property({ attribute: false }) values: Record<string, number> = {}\n @property({ type: Boolean }) locked = false\n\n /** Which control's settings are open. */\n @state() private open = ''\n /** Values in hand while a slider is dragged: the dial and the number follow them before the release commits. */\n @state() private live: Record<string, number> = {}\n\n render() {\n if (!this.asset) return nothing\n const controls = controlsOf(this.asset, this.values)\n return html`<section>\n <h3>${i18next.t('figure.label.controls')}</h3>\n ${controls.length\n ? html`${controls.map(control => this.renderControl(control))}\n <button act ?disabled=${this.locked || !poseDiffers(controls)} @click=${() => this.edit(poseAsDefault(controls))}>\n <md-icon>push_pin</md-icon>${i18next.t('figure.button.keep-pose')}\n </button>`\n : html`<p hint>${i18next.t('figure.text.no-controls')}</p>`}\n </section>`\n }\n\n private renderControl(control: Control) {\n const number = (e: Event) => (e.target as HTMLInputElement).valueAsNumber\n const c = this.live[control.id] === undefined ? control : { ...control, value: this.live[control.id]! }\n const open = this.open === c.id\n return html`<div control>\n <span name title=${c.id}>${c.label} <em>${c.unit}</em></span>\n ${c.unit === 'deg' ? this.renderDial(c) : html`<span></span>`}\n <input\n type=\"range\"\n min=${c.min}\n max=${c.max}\n step=${c.step}\n .value=${String(c.value)}\n ?disabled=${this.locked}\n aria-label=${c.label}\n @input=${(e: Event) => this.drag(c, number(e))}\n @change=${(e: Event) => this.try(c, number(e))}\n />\n <input type=\"number\" step=\"any\" .value=${String(Math.round(c.value * 100) / 100)} ?disabled=${this.locked} aria-label=${c.label} @change=${(e: Event) => this.try(c, number(e))} />\n <button\n more\n aria-expanded=${String(open)}\n title=${i18next.t('figure.button.control-settings')}\n aria-label=${i18next.t('figure.button.control-settings')}\n @click=${() => (this.open = open ? '' : c.id)}\n >\n <md-icon>tune</md-icon>\n </button>\n </div>\n ${open ? this.renderSettings(c) : nothing}`\n }\n\n private renderDial(c: Control) {\n const dial = dialShape(c.min, c.max, c.value)\n const span = dial.radius * 2 + 2\n return html`<svg dial viewBox=\"0 0 ${span} ${span}\" aria-hidden=\"true\">\n <path d=${dial.sector}></path>\n <circle cx=${dial.centre.x} cy=${dial.centre.y} r=${dial.radius}></circle>\n <line x1=${dial.centre.x} y1=${dial.centre.y} x2=${dial.needle.x} y2=${dial.needle.y}></line>\n </svg>`\n }\n\n private renderSettings(c: Control) {\n const policy = (patch: Partial<{ label: string; sweep: number; min: number; max: number }>) =>\n this.edit({\n kind: 'set-state-input',\n input: c.id,\n label: patch.label ?? (c.named ? c.label : undefined),\n sweep: patch.sweep ?? c.sweep,\n ...(patch.min !== undefined ? { min: patch.min } : {}),\n ...(patch.max !== undefined ? { max: patch.max } : {})\n })\n const number = (e: Event) => (e.target as HTMLInputElement).valueAsNumber\n return html`<div settings>\n <div form>\n <span>${i18next.t('figure.label.control-name')}</span>\n <input .value=${c.named ? c.label : ''} placeholder=${c.id} ?disabled=${this.locked} @change=${(e: Event) => policy({ label: (e.target as HTMLInputElement).value })} />\n <span>${i18next.t('figure.label.control-range')} (${c.unit})</span>\n <div pair>\n <input type=\"number\" step=\"any\" .value=${String(c.min)} ?disabled=${this.locked} @change=${(e: Event) => policy({ min: number(e) })} />\n <input type=\"number\" step=\"any\" .value=${String(c.max)} ?disabled=${this.locked} @change=${(e: Event) => policy({ max: number(e) })} />\n </div>\n <span>${i18next.t('figure.label.control-sweep')}</span>\n <input type=\"number\" min=\"0\" step=\"any\" .value=${String(c.sweep)} ?disabled=${this.locked} @change=${(e: Event) => policy({ sweep: number(e) })} />\n </div>\n <small>${i18next.t('figure.text.control-starts-at', { value: c.start, unit: c.unit })}</small>\n </div>`\n }\n\n /** While dragging: the value is told as live -- the editor draws that pose at once and records nothing. */\n private drag(c: Control, value: number) {\n if (!Number.isFinite(value)) return\n this.live = { ...this.live, [c.id]: value }\n this.dispatchEvent(new CustomEvent('state-live', { detail: { input: c.id, value }, bubbles: true, composed: true }))\n }\n\n /** Try a value: the pose being looked at, clamped to the range. Not saved as the default. The slider sends it on\n * release, so one drag is one step of the undo history rather than one per pixel. */\n private try(c: Control, value: number) {\n if (!Number.isFinite(value)) return\n const clamped = Math.min(Math.max(value, c.min), c.max)\n const { [c.id]: _released, ...rest } = this.live\n this.live = rest\n this.dispatchEvent(new CustomEvent('state', { detail: { input: c.id, unit: c.unit, value: clamped }, bubbles: true, composed: true }))\n }\n\n private edit(edit: unknown) {\n this.dispatchEvent(new CustomEvent('part-edit', { detail: { edit }, bubbles: true, composed: true }))\n }\n}\n"]}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { FigureFace } from '@hatiolab/figure-model';
|
|
2
2
|
export type Placement = 'floor' | 'ceiling' | 'center' | 'wall';
|
|
3
3
|
/** What the properties tab reads off the asset. Absent parts of the asset read as absent, never as a default. */
|
|
4
|
-
export interface
|
|
4
|
+
export interface FigureFigureFacts {
|
|
5
5
|
name: string;
|
|
6
6
|
parts: string[];
|
|
7
7
|
declared: boolean;
|
|
8
8
|
placement?: Placement;
|
|
9
9
|
mounting?: {
|
|
10
10
|
part: string;
|
|
11
|
-
face:
|
|
11
|
+
face: FigureFace;
|
|
12
12
|
};
|
|
13
13
|
/**
|
|
14
14
|
* Where the figure meets its plane, as its parts stand: the part whose bottom is lowest for a floor, whose top is
|
|
@@ -17,7 +17,7 @@ export interface V3FigureFacts {
|
|
|
17
17
|
*/
|
|
18
18
|
suggested?: {
|
|
19
19
|
part: string;
|
|
20
|
-
face:
|
|
20
|
+
face: FigureFace;
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
/**
|
|
@@ -27,7 +27,7 @@ export interface V3FigureFacts {
|
|
|
27
27
|
* records the face only as that node, so this is where the screen learns which one is chosen. Parts are the placed
|
|
28
28
|
* bodies (`place@1`), in the order the model lists them.
|
|
29
29
|
*/
|
|
30
|
-
export declare function
|
|
30
|
+
export declare function figureFigureFacts(source: string): FigureFigureFacts;
|
|
31
31
|
/**
|
|
32
32
|
* A tag line as a list: split on commas, drop a leading `#`, keep each once. An empty
|
|
33
33
|
* line is an empty list, so an author can clear every tag.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { compileFigureAsset, parseFigureAsset, figureOccupiedBoxesOf, figureWritersOf } from '@hatiolab/figure-model';
|
|
2
2
|
/**
|
|
3
3
|
* The asset's own facts, as the properties tab shows them.
|
|
4
4
|
*
|
|
@@ -6,8 +6,8 @@ import { compileV3Asset, parseV3Asset, v3OccupiedBoxesOf, v3WritersOf } from '@h
|
|
|
6
6
|
* records the face only as that node, so this is where the screen learns which one is chosen. Parts are the placed
|
|
7
7
|
* bodies (`place@1`), in the order the model lists them.
|
|
8
8
|
*/
|
|
9
|
-
export function
|
|
10
|
-
const asset =
|
|
9
|
+
export function figureFigureFacts(source) {
|
|
10
|
+
const asset = parseFigureAsset(source);
|
|
11
11
|
const parts = asset.document.model.nodes.filter(node => node.op === 'place@1').map(node => node.id);
|
|
12
12
|
const feature = asset.occupancy?.contact?.surface?.feature;
|
|
13
13
|
const found = feature?.match(/^(.+)\.mount\.(left|right|bottom|top|back|front)\.value$/);
|
|
@@ -26,7 +26,7 @@ function suggestedMountOf(asset, parts) {
|
|
|
26
26
|
return undefined;
|
|
27
27
|
let boxes;
|
|
28
28
|
try {
|
|
29
|
-
boxes =
|
|
29
|
+
boxes = figureOccupiedBoxesOf(compileFigureAsset(asset).evaluate().geometry, figureWritersOf(asset)).filter(b => parts.includes(b.part));
|
|
30
30
|
}
|
|
31
31
|
catch {
|
|
32
32
|
return undefined;
|
|
@@ -52,4 +52,4 @@ export function tagsOf(raw) {
|
|
|
52
52
|
.filter(one => one.length > 0))
|
|
53
53
|
];
|
|
54
54
|
}
|
|
55
|
-
//# sourceMappingURL=
|
|
55
|
+
//# sourceMappingURL=figure-facts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"figure-facts.js","sourceRoot":"","sources":["../../client/modeller/figure-facts.ts"],"names":[],"mappings":"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","sourcesContent":["import { compileFigureAsset, parseFigureAsset, figureOccupiedBoxesOf, figureWritersOf } from '@hatiolab/figure-model'\nimport type { FigureAsset, FigureFace } from '@hatiolab/figure-model'\n\n/*\n * What the properties tab reads, kept apart from the element so it can be tested without a browser.\n */\n\nexport type Placement = 'floor' | 'ceiling' | 'center' | 'wall'\n\n/** What the properties tab reads off the asset. Absent parts of the asset read as absent, never as a default. */\nexport interface FigureFigureFacts {\n name: string\n parts: string[]\n declared: boolean\n placement?: Placement\n mounting?: { part: string; face: FigureFace }\n /**\n * Where the figure meets its plane, as its parts stand: the part whose bottom is lowest for a floor, whose top is\n * highest for a ceiling, whose back is furthest back for a wall. What the mounting face is offered as before one is\n * chosen -- the first part in the list offered a conveyor's bed, 700 mm up on its legs (walk 1, 2026-09-26).\n */\n suggested?: { part: string; face: FigureFace }\n}\n\n/**\n * The asset's own facts, as the properties tab shows them.\n *\n * The mounting face is read back from the feature `set-mounting-face` writes (`<part>.mount.<face>`): the asset\n * records the face only as that node, so this is where the screen learns which one is chosen. Parts are the placed\n * bodies (`place@1`), in the order the model lists them.\n */\nexport function figureFigureFacts(source: string): FigureFigureFacts {\n const asset = parseFigureAsset(source) as FigureAsset & { document: { model: { nodes: Array<{ id: string; op: string }> } } }\n const parts = asset.document.model.nodes.filter(node => node.op === 'place@1').map(node => node.id)\n const feature = (asset.occupancy?.contact as { surface?: { feature?: string } } | undefined)?.surface?.feature\n const found = feature?.match(/^(.+)\\.mount\\.(left|right|bottom|top|back|front)\\.value$/)\n return {\n name: asset.name,\n parts,\n declared: !!asset.occupancy,\n placement: asset.occupancy?.placement as Placement | undefined,\n mounting: found ? { part: found[1], face: found[2] as FigureFace } : undefined,\n suggested: suggestedMountOf(asset, parts)\n }\n}\n\nfunction suggestedMountOf(asset: FigureAsset, parts: string[]): { part: string; face: FigureFace } | undefined {\n const placement = (asset.occupancy?.placement ?? 'floor') as Placement\n if (placement === 'center' || !parts.length) return undefined\n let boxes\n try {\n boxes = figureOccupiedBoxesOf(compileFigureAsset(asset).evaluate().geometry, figureWritersOf(asset)).filter(b => parts.includes(b.part))\n } catch {\n return undefined\n }\n const [axis, face, sign] = placement === 'wall' ? (['z', 'back', -1] as const) : placement === 'ceiling' ? (['y', 'top', 1] as const) : (['y', 'bottom', -1] as const)\n /* The side of each box that faces the plane; the one furthest toward it, the first in the list among equals. */\n const reach = (b: (typeof boxes)[number]) => sign * (b.centre[axis] + (sign * b.extent[axis]) / 2)\n let best: (typeof boxes)[number] | undefined\n for (const b of boxes) if (!best || reach(b) > reach(best) + 1e-6) best = b\n return best ? { part: best.part, face } : undefined\n}\n\n/**\n * A tag line as a list: split on commas, drop a leading `#`, keep each once. An empty\n * line is an empty list, so an author can clear every tag.\n */\nexport function tagsOf(raw: string): string[] {\n return [\n ...new Set(\n raw\n .split(',')\n .map(one => one.trim().replace(/^#+/, '').trim())\n .filter(one => one.length > 0)\n )\n ]\n}\n"]}
|
|
@@ -6,7 +6,7 @@ import '@material/web/button/text-button.js';
|
|
|
6
6
|
* The first save of a new figure: its type and its name, asked once, in the suite's popup look.
|
|
7
7
|
* Closes with the answer, or with nothing when cancelled -- then nothing is saved.
|
|
8
8
|
*/
|
|
9
|
-
export declare class
|
|
9
|
+
export declare class FigureFirstSave extends LitElement {
|
|
10
10
|
static styles: import("lit").CSSResult[];
|
|
11
11
|
/** The type the figure has so far -- empty for a temporary one, which is not offered. */
|
|
12
12
|
type: string;
|
|
@@ -7,12 +7,12 @@ import '@operato/popup/ox-popup-actions.js';
|
|
|
7
7
|
import { CommonPopupStyles, FormFieldStyles } from '@operato/styles';
|
|
8
8
|
import '@material/web/button/filled-button.js';
|
|
9
9
|
import '@material/web/button/text-button.js';
|
|
10
|
-
import { firstSaveRefusalOf, releasableType, typeOf } from './
|
|
10
|
+
import { firstSaveRefusalOf, releasableType, typeOf } from './first-save.js';
|
|
11
11
|
/**
|
|
12
12
|
* The first save of a new figure: its type and its name, asked once, in the suite's popup look.
|
|
13
13
|
* Closes with the answer, or with nothing when cancelled -- then nothing is saved.
|
|
14
14
|
*/
|
|
15
|
-
let
|
|
15
|
+
let FigureFirstSave = class FigureFirstSave extends LitElement {
|
|
16
16
|
constructor() {
|
|
17
17
|
super(...arguments);
|
|
18
18
|
/** The type the figure has so far -- empty for a temporary one, which is not offered. */
|
|
@@ -98,21 +98,21 @@ let FigureV3FirstSave = class FigureV3FirstSave extends LitElement {
|
|
|
98
98
|
__decorate([
|
|
99
99
|
property(),
|
|
100
100
|
__metadata("design:type", Object)
|
|
101
|
-
],
|
|
101
|
+
], FigureFirstSave.prototype, "type", void 0);
|
|
102
102
|
__decorate([
|
|
103
103
|
property(),
|
|
104
104
|
__metadata("design:type", Object)
|
|
105
|
-
],
|
|
105
|
+
], FigureFirstSave.prototype, "name", void 0);
|
|
106
106
|
__decorate([
|
|
107
107
|
property({ attribute: false }),
|
|
108
108
|
__metadata("design:type", Array)
|
|
109
|
-
],
|
|
109
|
+
], FigureFirstSave.prototype, "taken", void 0);
|
|
110
110
|
__decorate([
|
|
111
111
|
state(),
|
|
112
112
|
__metadata("design:type", Object)
|
|
113
|
-
],
|
|
114
|
-
|
|
115
|
-
customElement('figure-
|
|
116
|
-
],
|
|
117
|
-
export {
|
|
118
|
-
//# sourceMappingURL=figure-
|
|
113
|
+
], FigureFirstSave.prototype, "refusal", void 0);
|
|
114
|
+
FigureFirstSave = __decorate([
|
|
115
|
+
customElement('figure-first-save')
|
|
116
|
+
], FigureFirstSave);
|
|
117
|
+
export { FigureFirstSave };
|
|
118
|
+
//# sourceMappingURL=figure-first-save.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"figure-first-save.js","sourceRoot":"","sources":["../../client/modeller/figure-first-save.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport { i18next } from '@operato/i18n'\nimport { closePopup } from '@operato/popup'\nimport '@operato/popup/ox-popup-actions.js'\nimport { CommonPopupStyles, FormFieldStyles } from '@operato/styles'\nimport '@material/web/button/filled-button.js'\nimport '@material/web/button/text-button.js'\n\nimport { firstSaveRefusalOf, releasableType, typeOf, type FirstSave } from './first-save.js'\n\n/**\n * The first save of a new figure: its type and its name, asked once, in the suite's popup look.\n * Closes with the answer, or with nothing when cancelled -- then nothing is saved.\n */\n@customElement('figure-first-save')\nexport class FigureFirstSave extends LitElement {\n static styles = [\n FormFieldStyles,\n CommonPopupStyles,\n css`\n /* The popup's height is a share of the window (small is 40%): on a low window the buttons must still be reached. */\n :host {\n overflow-y: auto;\n }\n div[field] {\n display: grid;\n gap: 4px;\n }\n div[field] label {\n font-size: var(--popup-font-size-small);\n color: var(--md-sys-color-on-surface-variant);\n }\n div[field] input {\n box-sizing: border-box;\n width: 100%;\n }\n input[type-field] {\n font-family: var(--mono-font, monospace);\n }\n `\n ]\n\n /** The type the figure has so far -- empty for a temporary one, which is not offered. */\n @property() type = ''\n @property() name = ''\n /** Type names already used in this domain. */\n @property({ attribute: false }) taken: string[] = []\n @state() private refusal: { key: string; type?: string } | null = null\n\n render() {\n return html`\n <div class=\"what\">${i18next.t('figure.text.save-new-figure-desc')}</div>\n <div field>\n <label for=\"type\">${i18next.t('figure.label.figure-type')}</label>\n <input\n id=\"type\"\n type-field\n autofocus\n .value=${this.type}\n placeholder=${i18next.t('figure.text.figure-type-example')}\n @input=${(e: Event) => {\n this.type = typeOf((e.target as HTMLInputElement).value)\n ;(e.target as HTMLInputElement).value = this.type\n this.refusal = null\n }}\n @keydown=${this.onKey}\n />\n ${this.type && !releasableType(this.type) ? html`<div class=\"note\">${i18next.t('figure.text.type-name-will-not-release')}</div>` : nothing}\n </div>\n <div field>\n <label for=\"name\">${i18next.t('figure.label.name')}</label>\n <input\n id=\"name\"\n .value=${this.name}\n placeholder=${i18next.t('figure.text.figure-name-example')}\n @input=${(e: Event) => (this.name = (e.target as HTMLInputElement).value)}\n @keydown=${this.onKey}\n />\n </div>\n ${this.refusal ? html`<div class=\"failure\" role=\"alert\">${i18next.t(this.refusal.key, { type: this.refusal.type })}</div>` : nothing}\n <ox-popup-actions>\n <md-text-button slot=\"cancel\" @click=${() => closePopup(this)}>${i18next.t('figure.button.cancel')}</md-text-button>\n <md-filled-button slot=\"confirm\" ?disabled=${!this.type} @click=${this.confirm}>${i18next.t('figure.button.save')}</md-filled-button>\n </ox-popup-actions>\n `\n }\n\n private onKey = (e: KeyboardEvent) => {\n if (e.key === 'Enter' && !e.isComposing) this.confirm()\n }\n\n private confirm = () => {\n this.refusal = firstSaveRefusalOf(this.type, this.taken)\n if (this.refusal) return\n closePopup(this, { type: this.type, name: this.name.trim() || this.type } satisfies FirstSave)\n }\n}\n"]}
|
|
@@ -29,7 +29,7 @@ export declare class FigureHistoryPanel extends FigureHistoryPanel_base {
|
|
|
29
29
|
/** 저장하지 않은 것이 있나 — 있으면 발행을 막는다. */
|
|
30
30
|
dirty: boolean;
|
|
31
31
|
/**
|
|
32
|
-
* 행의 타입. 판정 하나(`type-is-placeholder`)가 이것을 본다 —
|
|
32
|
+
* 행의 타입. 판정 하나(`type-is-placeholder`)가 이것을 본다 — 자산은 타입을 원본에 적지 않아서, 타입을 바꾸면
|
|
33
33
|
* 원본도 dirty 도 그대로다. 그래서 이 값이 바뀌면 판정을 다시 묻는다. 안 그러면 타입을 정한 뒤에도 「임시 타입」
|
|
34
34
|
* 판정이 남아 발행 단추가 잠긴 채다.
|
|
35
35
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figure-history-panel.js","sourceRoot":"","sources":["../../client/modeller/figure-history-panel.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { gateFindingStyles, renderGateFinding } from './gate-findings.js'\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { fetchFigureVersions, inspectFigure, releaseFigure, revertFigureVersion } from '../graphql/index.js'\nimport type { FigureGateFinding, FigureInspection, FigureVersion } from '../types.js'\nimport { OxPrompt } from '@operato/popup'\n\n/**\n * 이력 — **발행하는 자리이자, 발행된 판들을 보는 자리.**\n *\n * ## 왜 저장 옆이 아니라 여기인가\n *\n * 저장은 하루에 수십 번이고 발행은 드물다. 두 단추를 나란히 두면 저장하려다 발행을 누른다.\n * 그리고 발행은 **소비처에게 하는 약속**이라, 무엇을 약속하는지(지금 몇 판인가 · 저장 안 한 것이\n * 있나 · 지난 판이 무엇이었나)를 함께 보여 주는 자리에 있어야 한다.\n *\n * ## 저장하지 않은 것이 있으면 발행하지 않는다\n *\n * 발행은 **저장된 것**을 내보낸다. 화면에 고친 것이 남아 있는 채로 발행하면, 저작자가 보고 있는\n * 것과 약속한 것이 다르다. 그래서 막고, 왜 막혔는지 적는다.\n *\n * ## 되돌리기는 초안으로 돌아온다\n *\n * 옛 판의 정본·속성·그림이 돌아오고 이름·설명은 그대로다. 되살렸다고 그 판이 다시 발행되지는\n * 않는다 — 다시 내보내려면 발행을 한 번 더 하고, 그때 번호는 이미 쓴 다음 번호를 받는다.\n */\n@customElement('figure-history-panel')\nexport class FigureHistoryPanel extends localize(i18next)(LitElement) {\n static styles = [\n gateFindingStyles,\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow-y: auto;\n background-color: var(--md-sys-color-surface-container-lowest);\n color: var(--md-sys-color-on-surface);\n font: var(--label-font, inherit);\n font-size: 0.76rem;\n }\n\n :host([off]) {\n display: none;\n }\n\n section {\n padding: var(--spacing-medium, 8px) var(--spacing-large, 12px);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n\n h3 {\n margin: 0 0 6px 0;\n font-size: var(--ui-t-micro, 11px);\n font-weight: 700;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /* 지금 무엇인가 — 발행을 누르기 전에 읽는 한 줄 */\n div[now] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 8px;\n }\n\n span[state] {\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 0.7rem;\n font-weight: 700;\n color: var(--md-sys-color-on-secondary-container);\n background-color: var(--md-sys-color-secondary-container);\n }\n\n span[state][released] {\n color: var(--md-sys-color-on-primary);\n background-color: var(--md-sys-color-primary);\n }\n\n span[ver] {\n font-family: var(--mono-font, monospace);\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n input,\n button {\n font: var(--input-field-font, inherit);\n font-size: 0.76rem;\n }\n\n input[note] {\n width: 100%;\n box-sizing: border-box;\n padding: 5px 8px;\n color: var(--md-sys-color-on-surface);\n background-color: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n\n button[release] {\n width: 100%;\n margin-top: 6px;\n padding: 6px 0;\n font-weight: 700;\n color: var(--ui-on-accent, #fff);\n background-color: var(--md-sys-color-primary);\n border: 0;\n border-radius: 6px;\n cursor: pointer;\n }\n\n button[release][disabled] {\n opacity: 0.45;\n cursor: default;\n }\n\n /* 왜 못 누르는지 — 눌러 보고 알게 하지 않는다 */\n p[why] {\n margin: 6px 0 0 0;\n font-size: 0.7rem;\n line-height: 1.5;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n p[failed] {\n margin: 6px 0 0 0;\n font-size: 0.7rem;\n line-height: 1.5;\n color: var(--md-sys-color-error);\n }\n\n ul {\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n li {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 4px 8px;\n align-items: baseline;\n padding: 7px 0;\n border-bottom: 1px dashed var(--md-sys-color-outline-variant);\n }\n\n li:last-child {\n border-bottom: 0;\n }\n\n li span[no] {\n font-family: var(--mono-font, monospace);\n font-weight: 700;\n }\n\n li span[when] {\n grid-column: 2 / 4;\n font-size: 0.7rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n li span[comment] {\n grid-column: 1 / 4;\n line-height: 1.5;\n }\n\n li button[revert] {\n padding: 2px 8px;\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n\n li button[revert]:hover {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n /*\n 게이트 사유. 막는 것은 색으로도 말하고, 알리는 것은 조용히 둔다 — 둘을 같은 톤으로 두면\n 「이 중 어느 것이 발행을 막았나」를 사람이 다시 세어야 한다.\n */\n\n p[quiet] {\n margin: 0;\n line-height: 1.6;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n `\n ]\n\n /** 지금 열려 있는 도형. 없으면(새로 만드는 중) 발행할 것이 없다. */\n @property({ type: String }) figureId?: string\n @property({ type: String }) figureState?: 'draft' | 'released'\n @property({ type: Number }) figureVersion = 0\n /** 저장하지 않은 것이 있나 — 있으면 발행을 막는다. */\n @property({ type: Boolean }) dirty = false\n /**\n * 행의 타입. 판정 하나(`type-is-placeholder`)가 이것을 본다 — V3 자산은 타입을 원본에 적지 않아서, 타입을 바꾸면\n * 원본도 dirty 도 그대로다. 그래서 이 값이 바뀌면 판정을 다시 묻는다. 안 그러면 타입을 정한 뒤에도 「임시 타입」\n * 판정이 남아 발행 단추가 잠긴 채다.\n */\n @property({ type: String }) figureType?: string\n\n @state() private versions: FigureVersion[] = []\n @state() private busy = false\n @state() private failure = ''\n /**\n * 발행 판정. **저장된 정본에 대한 것**이라 저장할 때마다 다시 묻는다(`figureVersion` 이 아니라\n * `dirty` 가 풀리는 순간이 그때다).\n */\n @state() private inspection?: FigureInspection\n\n updated(changes: Map<string, unknown>) {\n if (changes.has('figureId') || changes.has('figureVersion')) {\n void this.reload()\n }\n\n /*\n 저장이 끝난 순간(dirty 가 풀림) 정본이 바뀌었으니 판정을 다시 묻는다. 저작 중(dirty)에는\n 묻지 않는다 — 서버에 있는 것은 저장 전 정본이라, 그 답은 화면에 있는 것과 다른 것을 말한다.\n */\n if (changes.has('figureId') || changes.has('dirty') || changes.has('figureType')) {\n void this.inspect()\n }\n }\n\n private async inspect() {\n if (!this.figureId || this.dirty) {\n this.inspection = undefined\n return\n }\n\n try {\n this.inspection = await inspectFigure(this.figureId)\n } catch (e) {\n /* 판정을 못 받은 것을 「통과」로 두지 않는다 — 모르는 것이다. 단추는 서버가 막는다. */\n this.inspection = undefined\n this.failure = (e as Error).message\n }\n }\n\n private async reload() {\n if (!this.figureId) {\n this.versions = []\n return\n }\n\n try {\n this.versions = await fetchFigureVersions(this.figureId)\n this.failure = ''\n } catch (e) {\n this.failure = (e as Error).message\n }\n }\n\n render() {\n return html`\n <section>\n <h3>${i18next.t('figure.label.release')}</h3>\n ${this.figureId ? this.renderRelease() : html`<p quiet>${i18next.t('figure.text.save-the-figure-before-releasing')}</p>`}\n </section>\n\n <section>\n <h3>${i18next.t('figure.label.released-versions')}</h3>\n ${this.versions.length\n ? html`<ul>\n ${this.versions.map(version => this.renderVersion(version))}\n </ul>`\n : html`<p quiet>${i18next.t('figure.text.nothing-released-yet')}</p>`}\n </section>\n `\n }\n\n private renderRelease() {\n const released = this.figureState === 'released'\n\n /*\n 게이트가 막는 것과 알리는 것을 함께 낸다. **막는 것은 단추를 잠근다** — 눌러 보고 서버에게\n 거절당하는 것으로 알게 하지 않는다. 알리는 것은 잠그지 않고 그대로 보여 준다.\n */\n const blocking = (this.inspection?.findings ?? []).filter(finding => finding.blocking)\n const advisory = (this.inspection?.findings ?? []).filter(finding => !finding.blocking)\n\n /*\n ── 「발행되나」에 **한 번만** 답한다 ─────────────────────────────────────\n 전에는 막는 목록의 머리가 「이것들이 발행을 막습니다」, 알리는 목록의 머리가 「발행은 되지만\n 확인해 보십시오」였다. 두 줄이 나란히 서서 화면이 「막힌다」와 「된다」를 함께 말했고, 사람이\n 「그래서 되는 건가」를 되물었다.\n\n 답은 이 한 줄이 하고, 아래 목록들은 **이유**일 뿐이다 — 그래서 목록 머리는 문장이 아니라\n 이름씨다(「고쳐야 하는 것」·「막지는 않는 것」).\n */\n const why = this.dirty\n ? i18next.t('figure.text.release-needs-a-save-first')\n : released\n ? i18next.t('figure.text.already-released-edit-to-release-again')\n : blocking.length\n ? i18next.t('figure.text.cannot-release-now')\n : ''\n\n return html`\n <div now>\n <span state ?released=${released}>${i18next.t(released ? 'figure.label.figure-released' : 'figure.label.draft')}</span>\n <span ver>${i18next.t('figure.text.version-number', { version: this.figureVersion ?? 0 })}</span>\n </div>\n\n <input note placeholder=${i18next.t('figure.text.what-changed-in-this-release')} ?disabled=${!!why || this.busy} />\n\n <button release ?disabled=${!!why || this.busy} @click=${() => this.release()}>\n ${this.busy ? i18next.t('figure.text.releasing') : i18next.t('figure.button.release-figure')}\n </button>\n\n ${why ? html`<p why>${why}</p>` : nothing}\n ${blocking.length\n ? html`<ul gate>\n <li head>${i18next.t('figure.text.must-fix-to-release')}</li>\n ${blocking.map(finding => this.renderFinding(finding, true))}\n </ul>`\n : nothing}\n ${advisory.length\n ? html`<ul gate>\n <li head quiet>${i18next.t('figure.text.does-not-block')}</li>\n ${advisory.map(finding => this.renderFinding(finding, false))}\n </ul>`\n : nothing}\n ${this.failure ? html`<p failed>${this.failure}</p>` : nothing}\n `\n }\n\n /**\n * 사유 한 줄 — **잰 것 · 왜 · 어떻게** 셋을 함께 말한다.\n *\n * 잰 것만 보여 줬더니 「1 조각이 2 조각으로 갈라진다」에서 사람이 멈췄다. 왜 나쁜지도, 무엇을\n * 바꾸면 되는지도 알 수 없었다. 그 셋은 형식(`figure-model` 의 gate)이 만들고 여기서는 자리만\n * 준다 — 화면이 문장을 지으면 서버가 거절할 때와 다른 말을 하게 된다.\n */\n private renderFinding(finding: FigureGateFinding, blocking: boolean) {\n return renderGateFinding(finding, blocking, html`\n ${this.offersFit(finding.code)\n ? html`<button fit-base @click=${() => this.fitBase()}>\n ${i18next.t('figure.button.fit-base-to-parts')}\n </button>`\n : nothing}\n `)\n }\n\n /**\n * 넘친 것을 담는 길 하나를 여기서도 내민다 — **같은 동작이 속성 패널에도 있다**(「부품에 맞추기」).\n *\n * 그 단추를 아는 저작자는 거기서 누른다. 발행이 막혔다는 말을 여기서 읽은 사람은 그 단추가 있는\n * 것을 모르고, 문구는 그것을 가리킬 수 없다 — 문장은 형식이 쓰고 형식은 화면의 단추를 모른다.\n * 그래서 화면이 자기 자리에서 같은 동작을 낸다. 누르면 상자만 커지고 부품은 제자리이며, 저장은\n * 여전히 저작자가 따로 한다.\n */\n /**\n * 「부품에 맞추기」를 내미는 판정: 공간을 부품에서 다시 선언한다(`declare-occupancy`) — 부품은 그대로 두고 선언만\n * 바꾼다. 공간을 아직 선언하지 않은 도형도 같은 단추로 선언한다: 새로 만든 도형은 전부 그 판정으로 막히고, 화면에\n * 다른 길이 없다. 장착면이 떠 있는 것은 여기 없다 — 부품 하나를 평면에 붙여도 거기 붙지 않은 것은 따라오지 않는다.\n * 판정의 「어떻게」가 할 일을 말한다.\n */\n private offersFit(code: string): boolean {\n return code === 'part-outside-occupancy' || code === 'occupancy-undeclared'\n }\n\n private fitBase() {\n this.dispatchEvent(new CustomEvent('fit-base-to-parts', { bubbles: true, composed: true }))\n }\n\n private renderVersion(version: FigureVersion) {\n return html`\n <li>\n <span no>${i18next.t('figure.text.version-number', { version: version.version })}</span>\n <span when>\n ${version.updatedAt ? new Date(version.updatedAt).toLocaleString() : ''}\n ${version.updater?.name ? ` · ${version.updater.name}` : ''}\n </span>\n <button revert ?disabled=${this.busy} @click=${() => this.revert(version.version)}>\n ${i18next.t('figure.button.revert')}\n </button>\n ${version.comment ? html`<span comment>${version.comment}</span>` : nothing}\n </li>\n `\n }\n\n private async release() {\n const input = this.renderRoot.querySelector('input[note]') as HTMLInputElement\n const comment = input?.value?.trim()\n\n this.busy = true\n this.failure = ''\n\n try {\n const figure = await releaseFigure(this.figureId!, comment || undefined)\n if (input) input.value = ''\n /* 정본을 든 자리가 갱신한다 — 여기서 페이지 상태를 고쳐 쓰지 않는다. */\n this.dispatchEvent(new CustomEvent('figure-released', { detail: { figure }, bubbles: true, composed: true }))\n await this.reload()\n await this.inspect()\n } catch (e) {\n this.failure = (e as Error).message\n } finally {\n this.busy = false\n }\n }\n\n private async revert(version: number) {\n /* 되돌아갈 수 없는 조작은 아니지만(판본은 남는다), 지금 화면의 것이 덮인다 — 이름으로 확인한다. */\n const agreed = await OxPrompt.open({\n type: 'warning',\n title: i18next.t('figure.button.revert'),\n text: i18next.t('figure.text.revert-to-version-confirm', { version }),\n confirmButton: { text: i18next.t('figure.button.revert') },\n cancelButton: { text: i18next.t('figure.button.keep-editing') }\n })\n if (!agreed) {\n return\n }\n\n this.busy = true\n this.failure = ''\n\n try {\n const result = await revertFigureVersion(this.figureId!, version)\n this.dispatchEvent(new CustomEvent('figure-reverted', { detail: result, bubbles: true, composed: true }))\n await this.reload()\n /*\n **되돌리면 정본이 바뀌므로 판정도 바뀐다.** 이것을 안 하면 옛 판의 사유가 새 정본 위에\n 남아 화면이 거짓말한다 — 되돌리기는 `dirty` 도 `figureVersion` 도 건드리지 않으므로\n `updated` 의 감시로는 다시 묻지 않는다.\n */\n await this.inspect()\n } catch (e) {\n this.failure = (e as Error).message\n } finally {\n this.busy = false\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"figure-history-panel.js","sourceRoot":"","sources":["../../client/modeller/figure-history-panel.ts"],"names":[],"mappings":"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","sourcesContent":["import '@material/web/icon/icon.js'\n\nimport { gateFindingStyles, renderGateFinding } from './gate-findings.js'\nimport { css, html, LitElement, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { i18next, localize } from '@operato/i18n'\nimport { ScrollbarStyles } from '@operato/styles'\n\nimport { fetchFigureVersions, inspectFigure, releaseFigure, revertFigureVersion } from '../graphql/index.js'\nimport type { FigureGateFinding, FigureInspection, FigureVersion } from '../types.js'\nimport { OxPrompt } from '@operato/popup'\n\n/**\n * 이력 — **발행하는 자리이자, 발행된 판들을 보는 자리.**\n *\n * ## 왜 저장 옆이 아니라 여기인가\n *\n * 저장은 하루에 수십 번이고 발행은 드물다. 두 단추를 나란히 두면 저장하려다 발행을 누른다.\n * 그리고 발행은 **소비처에게 하는 약속**이라, 무엇을 약속하는지(지금 몇 판인가 · 저장 안 한 것이\n * 있나 · 지난 판이 무엇이었나)를 함께 보여 주는 자리에 있어야 한다.\n *\n * ## 저장하지 않은 것이 있으면 발행하지 않는다\n *\n * 발행은 **저장된 것**을 내보낸다. 화면에 고친 것이 남아 있는 채로 발행하면, 저작자가 보고 있는\n * 것과 약속한 것이 다르다. 그래서 막고, 왜 막혔는지 적는다.\n *\n * ## 되돌리기는 초안으로 돌아온다\n *\n * 옛 판의 정본·속성·그림이 돌아오고 이름·설명은 그대로다. 되살렸다고 그 판이 다시 발행되지는\n * 않는다 — 다시 내보내려면 발행을 한 번 더 하고, 그때 번호는 이미 쓴 다음 번호를 받는다.\n */\n@customElement('figure-history-panel')\nexport class FigureHistoryPanel extends localize(i18next)(LitElement) {\n static styles = [\n gateFindingStyles,\n ScrollbarStyles,\n css`\n :host {\n display: flex;\n flex-direction: column;\n min-height: 0;\n overflow-y: auto;\n background-color: var(--md-sys-color-surface-container-lowest);\n color: var(--md-sys-color-on-surface);\n font: var(--label-font, inherit);\n font-size: 0.76rem;\n }\n\n :host([off]) {\n display: none;\n }\n\n section {\n padding: var(--spacing-medium, 8px) var(--spacing-large, 12px);\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n }\n\n h3 {\n margin: 0 0 6px 0;\n font-size: var(--ui-t-micro, 11px);\n font-weight: 700;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n /* 지금 무엇인가 — 발행을 누르기 전에 읽는 한 줄 */\n div[now] {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 8px;\n }\n\n span[state] {\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 0.7rem;\n font-weight: 700;\n color: var(--md-sys-color-on-secondary-container);\n background-color: var(--md-sys-color-secondary-container);\n }\n\n span[state][released] {\n color: var(--md-sys-color-on-primary);\n background-color: var(--md-sys-color-primary);\n }\n\n span[ver] {\n font-family: var(--mono-font, monospace);\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n input,\n button {\n font: var(--input-field-font, inherit);\n font-size: 0.76rem;\n }\n\n input[note] {\n width: 100%;\n box-sizing: border-box;\n padding: 5px 8px;\n color: var(--md-sys-color-on-surface);\n background-color: var(--md-sys-color-surface-container-lowest);\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n }\n\n button[release] {\n width: 100%;\n margin-top: 6px;\n padding: 6px 0;\n font-weight: 700;\n color: var(--ui-on-accent, #fff);\n background-color: var(--md-sys-color-primary);\n border: 0;\n border-radius: 6px;\n cursor: pointer;\n }\n\n button[release][disabled] {\n opacity: 0.45;\n cursor: default;\n }\n\n /* 왜 못 누르는지 — 눌러 보고 알게 하지 않는다 */\n p[why] {\n margin: 6px 0 0 0;\n font-size: 0.7rem;\n line-height: 1.5;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n p[failed] {\n margin: 6px 0 0 0;\n font-size: 0.7rem;\n line-height: 1.5;\n color: var(--md-sys-color-error);\n }\n\n ul {\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n li {\n display: grid;\n grid-template-columns: auto 1fr auto;\n gap: 4px 8px;\n align-items: baseline;\n padding: 7px 0;\n border-bottom: 1px dashed var(--md-sys-color-outline-variant);\n }\n\n li:last-child {\n border-bottom: 0;\n }\n\n li span[no] {\n font-family: var(--mono-font, monospace);\n font-weight: 700;\n }\n\n li span[when] {\n grid-column: 2 / 4;\n font-size: 0.7rem;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n\n li span[comment] {\n grid-column: 1 / 4;\n line-height: 1.5;\n }\n\n li button[revert] {\n padding: 2px 8px;\n color: var(--md-sys-color-on-surface);\n background: none;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n cursor: pointer;\n }\n\n li button[revert]:hover {\n color: var(--md-sys-color-on-primary-container);\n background-color: var(--md-sys-color-primary-container);\n border-color: transparent;\n }\n\n /*\n 게이트 사유. 막는 것은 색으로도 말하고, 알리는 것은 조용히 둔다 — 둘을 같은 톤으로 두면\n 「이 중 어느 것이 발행을 막았나」를 사람이 다시 세어야 한다.\n */\n\n p[quiet] {\n margin: 0;\n line-height: 1.6;\n color: var(--md-sys-color-on-surface-variant, var(--md-sys-color-on-surface));\n }\n `\n ]\n\n /** 지금 열려 있는 도형. 없으면(새로 만드는 중) 발행할 것이 없다. */\n @property({ type: String }) figureId?: string\n @property({ type: String }) figureState?: 'draft' | 'released'\n @property({ type: Number }) figureVersion = 0\n /** 저장하지 않은 것이 있나 — 있으면 발행을 막는다. */\n @property({ type: Boolean }) dirty = false\n /**\n * 행의 타입. 판정 하나(`type-is-placeholder`)가 이것을 본다 — 자산은 타입을 원본에 적지 않아서, 타입을 바꾸면\n * 원본도 dirty 도 그대로다. 그래서 이 값이 바뀌면 판정을 다시 묻는다. 안 그러면 타입을 정한 뒤에도 「임시 타입」\n * 판정이 남아 발행 단추가 잠긴 채다.\n */\n @property({ type: String }) figureType?: string\n\n @state() private versions: FigureVersion[] = []\n @state() private busy = false\n @state() private failure = ''\n /**\n * 발행 판정. **저장된 정본에 대한 것**이라 저장할 때마다 다시 묻는다(`figureVersion` 이 아니라\n * `dirty` 가 풀리는 순간이 그때다).\n */\n @state() private inspection?: FigureInspection\n\n updated(changes: Map<string, unknown>) {\n if (changes.has('figureId') || changes.has('figureVersion')) {\n void this.reload()\n }\n\n /*\n 저장이 끝난 순간(dirty 가 풀림) 정본이 바뀌었으니 판정을 다시 묻는다. 저작 중(dirty)에는\n 묻지 않는다 — 서버에 있는 것은 저장 전 정본이라, 그 답은 화면에 있는 것과 다른 것을 말한다.\n */\n if (changes.has('figureId') || changes.has('dirty') || changes.has('figureType')) {\n void this.inspect()\n }\n }\n\n private async inspect() {\n if (!this.figureId || this.dirty) {\n this.inspection = undefined\n return\n }\n\n try {\n this.inspection = await inspectFigure(this.figureId)\n } catch (e) {\n /* 판정을 못 받은 것을 「통과」로 두지 않는다 — 모르는 것이다. 단추는 서버가 막는다. */\n this.inspection = undefined\n this.failure = (e as Error).message\n }\n }\n\n private async reload() {\n if (!this.figureId) {\n this.versions = []\n return\n }\n\n try {\n this.versions = await fetchFigureVersions(this.figureId)\n this.failure = ''\n } catch (e) {\n this.failure = (e as Error).message\n }\n }\n\n render() {\n return html`\n <section>\n <h3>${i18next.t('figure.label.release')}</h3>\n ${this.figureId ? this.renderRelease() : html`<p quiet>${i18next.t('figure.text.save-the-figure-before-releasing')}</p>`}\n </section>\n\n <section>\n <h3>${i18next.t('figure.label.released-versions')}</h3>\n ${this.versions.length\n ? html`<ul>\n ${this.versions.map(version => this.renderVersion(version))}\n </ul>`\n : html`<p quiet>${i18next.t('figure.text.nothing-released-yet')}</p>`}\n </section>\n `\n }\n\n private renderRelease() {\n const released = this.figureState === 'released'\n\n /*\n 게이트가 막는 것과 알리는 것을 함께 낸다. **막는 것은 단추를 잠근다** — 눌러 보고 서버에게\n 거절당하는 것으로 알게 하지 않는다. 알리는 것은 잠그지 않고 그대로 보여 준다.\n */\n const blocking = (this.inspection?.findings ?? []).filter(finding => finding.blocking)\n const advisory = (this.inspection?.findings ?? []).filter(finding => !finding.blocking)\n\n /*\n ── 「발행되나」에 **한 번만** 답한다 ─────────────────────────────────────\n 전에는 막는 목록의 머리가 「이것들이 발행을 막습니다」, 알리는 목록의 머리가 「발행은 되지만\n 확인해 보십시오」였다. 두 줄이 나란히 서서 화면이 「막힌다」와 「된다」를 함께 말했고, 사람이\n 「그래서 되는 건가」를 되물었다.\n\n 답은 이 한 줄이 하고, 아래 목록들은 **이유**일 뿐이다 — 그래서 목록 머리는 문장이 아니라\n 이름씨다(「고쳐야 하는 것」·「막지는 않는 것」).\n */\n const why = this.dirty\n ? i18next.t('figure.text.release-needs-a-save-first')\n : released\n ? i18next.t('figure.text.already-released-edit-to-release-again')\n : blocking.length\n ? i18next.t('figure.text.cannot-release-now')\n : ''\n\n return html`\n <div now>\n <span state ?released=${released}>${i18next.t(released ? 'figure.label.figure-released' : 'figure.label.draft')}</span>\n <span ver>${i18next.t('figure.text.version-number', { version: this.figureVersion ?? 0 })}</span>\n </div>\n\n <input note placeholder=${i18next.t('figure.text.what-changed-in-this-release')} ?disabled=${!!why || this.busy} />\n\n <button release ?disabled=${!!why || this.busy} @click=${() => this.release()}>\n ${this.busy ? i18next.t('figure.text.releasing') : i18next.t('figure.button.release-figure')}\n </button>\n\n ${why ? html`<p why>${why}</p>` : nothing}\n ${blocking.length\n ? html`<ul gate>\n <li head>${i18next.t('figure.text.must-fix-to-release')}</li>\n ${blocking.map(finding => this.renderFinding(finding, true))}\n </ul>`\n : nothing}\n ${advisory.length\n ? html`<ul gate>\n <li head quiet>${i18next.t('figure.text.does-not-block')}</li>\n ${advisory.map(finding => this.renderFinding(finding, false))}\n </ul>`\n : nothing}\n ${this.failure ? html`<p failed>${this.failure}</p>` : nothing}\n `\n }\n\n /**\n * 사유 한 줄 — **잰 것 · 왜 · 어떻게** 셋을 함께 말한다.\n *\n * 잰 것만 보여 줬더니 「1 조각이 2 조각으로 갈라진다」에서 사람이 멈췄다. 왜 나쁜지도, 무엇을\n * 바꾸면 되는지도 알 수 없었다. 그 셋은 형식(`figure-model` 의 gate)이 만들고 여기서는 자리만\n * 준다 — 화면이 문장을 지으면 서버가 거절할 때와 다른 말을 하게 된다.\n */\n private renderFinding(finding: FigureGateFinding, blocking: boolean) {\n return renderGateFinding(finding, blocking, html`\n ${this.offersFit(finding.code)\n ? html`<button fit-base @click=${() => this.fitBase()}>\n ${i18next.t('figure.button.fit-base-to-parts')}\n </button>`\n : nothing}\n `)\n }\n\n /**\n * 넘친 것을 담는 길 하나를 여기서도 내민다 — **같은 동작이 속성 패널에도 있다**(「부품에 맞추기」).\n *\n * 그 단추를 아는 저작자는 거기서 누른다. 발행이 막혔다는 말을 여기서 읽은 사람은 그 단추가 있는\n * 것을 모르고, 문구는 그것을 가리킬 수 없다 — 문장은 형식이 쓰고 형식은 화면의 단추를 모른다.\n * 그래서 화면이 자기 자리에서 같은 동작을 낸다. 누르면 상자만 커지고 부품은 제자리이며, 저장은\n * 여전히 저작자가 따로 한다.\n */\n /**\n * 「부품에 맞추기」를 내미는 판정: 공간을 부품에서 다시 선언한다(`declare-occupancy`) — 부품은 그대로 두고 선언만\n * 바꾼다. 공간을 아직 선언하지 않은 도형도 같은 단추로 선언한다: 새로 만든 도형은 전부 그 판정으로 막히고, 화면에\n * 다른 길이 없다. 장착면이 떠 있는 것은 여기 없다 — 부품 하나를 평면에 붙여도 거기 붙지 않은 것은 따라오지 않는다.\n * 판정의 「어떻게」가 할 일을 말한다.\n */\n private offersFit(code: string): boolean {\n return code === 'part-outside-occupancy' || code === 'occupancy-undeclared'\n }\n\n private fitBase() {\n this.dispatchEvent(new CustomEvent('fit-base-to-parts', { bubbles: true, composed: true }))\n }\n\n private renderVersion(version: FigureVersion) {\n return html`\n <li>\n <span no>${i18next.t('figure.text.version-number', { version: version.version })}</span>\n <span when>\n ${version.updatedAt ? new Date(version.updatedAt).toLocaleString() : ''}\n ${version.updater?.name ? ` · ${version.updater.name}` : ''}\n </span>\n <button revert ?disabled=${this.busy} @click=${() => this.revert(version.version)}>\n ${i18next.t('figure.button.revert')}\n </button>\n ${version.comment ? html`<span comment>${version.comment}</span>` : nothing}\n </li>\n `\n }\n\n private async release() {\n const input = this.renderRoot.querySelector('input[note]') as HTMLInputElement\n const comment = input?.value?.trim()\n\n this.busy = true\n this.failure = ''\n\n try {\n const figure = await releaseFigure(this.figureId!, comment || undefined)\n if (input) input.value = ''\n /* 정본을 든 자리가 갱신한다 — 여기서 페이지 상태를 고쳐 쓰지 않는다. */\n this.dispatchEvent(new CustomEvent('figure-released', { detail: { figure }, bubbles: true, composed: true }))\n await this.reload()\n await this.inspect()\n } catch (e) {\n this.failure = (e as Error).message\n } finally {\n this.busy = false\n }\n }\n\n private async revert(version: number) {\n /* 되돌아갈 수 없는 조작은 아니지만(판본은 남는다), 지금 화면의 것이 덮인다 — 이름으로 확인한다. */\n const agreed = await OxPrompt.open({\n type: 'warning',\n title: i18next.t('figure.button.revert'),\n text: i18next.t('figure.text.revert-to-version-confirm', { version }),\n confirmButton: { text: i18next.t('figure.button.revert') },\n cancelButton: { text: i18next.t('figure.button.keep-editing') }\n })\n if (!agreed) {\n return\n }\n\n this.busy = true\n this.failure = ''\n\n try {\n const result = await revertFigureVersion(this.figureId!, version)\n this.dispatchEvent(new CustomEvent('figure-reverted', { detail: result, bubbles: true, composed: true }))\n await this.reload()\n /*\n **되돌리면 정본이 바뀌므로 판정도 바뀐다.** 이것을 안 하면 옛 판의 사유가 새 정본 위에\n 남아 화면이 거짓말한다 — 되돌리기는 `dirty` 도 `figureVersion` 도 건드리지 않으므로\n `updated` 의 감시로는 다시 묻지 않는다.\n */\n await this.inspect()\n } catch (e) {\n this.failure = (e as Error).message\n } finally {\n this.busy = false\n }\n }\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import '@material/web/icon/icon.js';
|
|
2
2
|
import { LitElement, nothing } from 'lit';
|
|
3
|
-
import type {
|
|
4
|
-
declare const
|
|
3
|
+
import type { FigureAsset } from '@hatiolab/figure-model';
|
|
4
|
+
declare const FigureLinks_base: (new (...args: any[]) => LitElement) & typeof LitElement;
|
|
5
5
|
/**
|
|
6
6
|
* What a part is tied to — its size response, what it is fastened to, how it moves.
|
|
7
7
|
*
|
|
@@ -11,15 +11,15 @@ declare const FigureV3Links_base: (new (...args: any[]) => LitElement) & typeof
|
|
|
11
11
|
* parts that come away — this is where they do it. Motion is a joint: a slide or a turn driven by a control.
|
|
12
12
|
*
|
|
13
13
|
* The sections are dimensions, placement and joint, in that order. Every
|
|
14
|
-
* change is one figure-model authoring command, sent as `
|
|
14
|
+
* change is one figure-model authoring command, sent as `command` and run by the editor through the session — one
|
|
15
15
|
* step of the undo history. Choices the command would refuse (a round body fastened, a size following an instance
|
|
16
16
|
* size the figure does not declare) are not offered, so the author is not sent into a refusal.
|
|
17
17
|
*/
|
|
18
|
-
export declare class
|
|
18
|
+
export declare class FigureLinks extends FigureLinks_base {
|
|
19
19
|
private readonly help;
|
|
20
20
|
static styles: import("lit").CSSResult[];
|
|
21
21
|
/** The asset being edited. */
|
|
22
|
-
asset?:
|
|
22
|
+
asset?: FigureAsset;
|
|
23
23
|
/** The selected part. */
|
|
24
24
|
partId: string;
|
|
25
25
|
/** The part's own extent along its axes now, in mm — what a dimension is fixed at when it stops following. */
|
|
@@ -3,11 +3,11 @@ import '@material/web/icon/icon.js';
|
|
|
3
3
|
import { css, html, LitElement, nothing } from 'lit';
|
|
4
4
|
import { customElement, property, state } from 'lit/decorators.js';
|
|
5
5
|
import { i18next, localize } from '@operato/i18n';
|
|
6
|
-
import {
|
|
7
|
-
import { acceptsOf, alignAxesOf, mountingPlaneOf, alignOf, AXES, canFasten, facesOf, canFollow, dimensionNow, followableAxes, positionIsShare, choiceOf, heldBy, followOf, hangsFrom, shownWhenOf, visibilityControlsOf, placeKeptOf, fasteningOf, hasInstanceSize, holdsThings, leadersFor, motionOf, motionFormOf, motionJoint, placeFacesOf, placeIdFor, placesOn, rowAxesOf, positionsWorkedOut } from './
|
|
6
|
+
import { FIGURE_FACES } from '@hatiolab/figure-model';
|
|
7
|
+
import { acceptsOf, alignAxesOf, mountingPlaneOf, alignOf, AXES, canFasten, facesOf, canFollow, dimensionNow, followableAxes, positionIsShare, choiceOf, heldBy, followOf, hangsFrom, shownWhenOf, visibilityControlsOf, placeKeptOf, fasteningOf, hasInstanceSize, holdsThings, leadersFor, motionOf, motionFormOf, motionJoint, placeFacesOf, placeIdFor, placesOn, rowAxesOf, positionsWorkedOut } from './links.js';
|
|
8
8
|
import { SidePanelStyles } from './side-panel-styles.js';
|
|
9
|
-
import { HelpToggles } from './
|
|
10
|
-
const FACES = Object.keys(
|
|
9
|
+
import { HelpToggles } from './help.js';
|
|
10
|
+
const FACES = Object.keys(FIGURE_FACES);
|
|
11
11
|
const freshFasten = () => ({
|
|
12
12
|
face: 'bottom',
|
|
13
13
|
toPlane: false,
|
|
@@ -31,11 +31,11 @@ const freshPlace = () => ({ role: 'grip', face: 'top', label: '', accepts: '', c
|
|
|
31
31
|
* parts that come away — this is where they do it. Motion is a joint: a slide or a turn driven by a control.
|
|
32
32
|
*
|
|
33
33
|
* The sections are dimensions, placement and joint, in that order. Every
|
|
34
|
-
* change is one figure-model authoring command, sent as `
|
|
34
|
+
* change is one figure-model authoring command, sent as `command` and run by the editor through the session — one
|
|
35
35
|
* step of the undo history. Choices the command would refuse (a round body fastened, a size following an instance
|
|
36
36
|
* size the figure does not declare) are not offered, so the author is not sent into a refusal.
|
|
37
37
|
*/
|
|
38
|
-
let
|
|
38
|
+
let FigureLinks = class FigureLinks extends localize(i18next)(LitElement) {
|
|
39
39
|
constructor() {
|
|
40
40
|
super(...arguments);
|
|
41
41
|
this.help = new HelpToggles(this);
|
|
@@ -180,7 +180,7 @@ let FigureV3Links = class FigureV3Links extends localize(i18next)(LitElement) {
|
|
|
180
180
|
/** The figure holds things: `Capacity` and `Holdable`, the ladder's middle rung. One part edit, one undo step. */
|
|
181
181
|
declareHolding(asset) {
|
|
182
182
|
const names = [...new Set([...(asset.document.capabilities.names ?? []), 'Capacity', 'Holdable'])];
|
|
183
|
-
this.dispatchEvent(new CustomEvent('
|
|
183
|
+
this.dispatchEvent(new CustomEvent('part-edit', { detail: { edit: { kind: 'set-capabilities', names } }, bubbles: true, composed: true }));
|
|
184
184
|
}
|
|
185
185
|
renderDimensions(asset) {
|
|
186
186
|
const others = asset.appearance.map(look => look.target).filter(one => one !== this.partId && canFollow(asset, one));
|
|
@@ -448,7 +448,7 @@ let FigureV3Links = class FigureV3Links extends localize(i18next)(LitElement) {
|
|
|
448
448
|
if (!controls.length)
|
|
449
449
|
return nothing;
|
|
450
450
|
const now = shownWhenOf(asset, this.partId);
|
|
451
|
-
const send = (shownWhen) => this.dispatchEvent(new CustomEvent('
|
|
451
|
+
const send = (shownWhen) => this.dispatchEvent(new CustomEvent('part-edit', { detail: { edit: { kind: 'set-visibility', target: this.partId, shownWhen } }, bubbles: true, composed: true }));
|
|
452
452
|
const first = (id) => {
|
|
453
453
|
const c = controls.find(one => one.id === id);
|
|
454
454
|
return Math.round((c.min + (c.max - c.min) * 0.01) * 1000) / 1000;
|
|
@@ -599,51 +599,51 @@ let FigureV3Links = class FigureV3Links extends localize(i18next)(LitElement) {
|
|
|
599
599
|
this.motion = kind === 'slide' ? { ...this.motion, kind, min: 0, max: 500 } : { ...this.motion, kind, min: -90, max: 90 };
|
|
600
600
|
}
|
|
601
601
|
command(action) {
|
|
602
|
-
this.dispatchEvent(new CustomEvent('
|
|
602
|
+
this.dispatchEvent(new CustomEvent('command', { detail: { action }, bubbles: true, composed: true }));
|
|
603
603
|
}
|
|
604
604
|
};
|
|
605
605
|
__decorate([
|
|
606
606
|
property({ attribute: false }),
|
|
607
607
|
__metadata("design:type", Object)
|
|
608
|
-
],
|
|
608
|
+
], FigureLinks.prototype, "asset", void 0);
|
|
609
609
|
__decorate([
|
|
610
610
|
property(),
|
|
611
611
|
__metadata("design:type", Object)
|
|
612
|
-
],
|
|
612
|
+
], FigureLinks.prototype, "partId", void 0);
|
|
613
613
|
__decorate([
|
|
614
614
|
property({ attribute: false }),
|
|
615
615
|
__metadata("design:type", Array)
|
|
616
|
-
],
|
|
616
|
+
], FigureLinks.prototype, "dims", void 0);
|
|
617
617
|
__decorate([
|
|
618
618
|
property({ type: Boolean }),
|
|
619
619
|
__metadata("design:type", Object)
|
|
620
|
-
],
|
|
620
|
+
], FigureLinks.prototype, "locked", void 0);
|
|
621
621
|
__decorate([
|
|
622
622
|
property(),
|
|
623
623
|
__metadata("design:type", String)
|
|
624
|
-
],
|
|
624
|
+
], FigureLinks.prototype, "section", void 0);
|
|
625
625
|
__decorate([
|
|
626
626
|
state(),
|
|
627
627
|
__metadata("design:type", Object)
|
|
628
|
-
],
|
|
628
|
+
], FigureLinks.prototype, "fasten", void 0);
|
|
629
629
|
__decorate([
|
|
630
630
|
state(),
|
|
631
631
|
__metadata("design:type", Object)
|
|
632
|
-
],
|
|
632
|
+
], FigureLinks.prototype, "motion", void 0);
|
|
633
633
|
__decorate([
|
|
634
634
|
state(),
|
|
635
635
|
__metadata("design:type", Object)
|
|
636
|
-
],
|
|
636
|
+
], FigureLinks.prototype, "place", void 0);
|
|
637
637
|
__decorate([
|
|
638
638
|
state(),
|
|
639
639
|
__metadata("design:type", Object)
|
|
640
|
-
],
|
|
640
|
+
], FigureLinks.prototype, "row", void 0);
|
|
641
641
|
__decorate([
|
|
642
642
|
state(),
|
|
643
643
|
__metadata("design:type", Object)
|
|
644
|
-
],
|
|
645
|
-
|
|
646
|
-
customElement('figure-
|
|
647
|
-
],
|
|
648
|
-
export {
|
|
649
|
-
//# sourceMappingURL=figure-
|
|
644
|
+
], FigureLinks.prototype, "editingMotion", void 0);
|
|
645
|
+
FigureLinks = __decorate([
|
|
646
|
+
customElement('figure-links')
|
|
647
|
+
], FigureLinks);
|
|
648
|
+
export { FigureLinks };
|
|
649
|
+
//# sourceMappingURL=figure-links.js.map
|