@things-factory/figure-ui 10.1.44 → 10.1.46
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/modeller/figure-v3-links.ts +394 -0
- package/client/modeller/modeller-route.ts +6 -21
- package/client/modeller/v3-editor.ts +47 -5
- package/client/modeller/v3-gizmo.ts +13 -2
- package/client/modeller/v3-links.ts +170 -0
- package/client/pages/figure-v3-modeller-page.ts +2 -5
- package/client/route.ts +2 -6
- package/dist-client/modeller/figure-v3-links.d.ts +47 -0
- package/dist-client/modeller/figure-v3-links.js +379 -0
- package/dist-client/modeller/figure-v3-links.js.map +1 -0
- package/dist-client/modeller/modeller-route.d.ts +4 -11
- package/dist-client/modeller/modeller-route.js +5 -22
- package/dist-client/modeller/modeller-route.js.map +1 -1
- package/dist-client/modeller/v3-editor.d.ts +5 -0
- package/dist-client/modeller/v3-editor.js +49 -4
- package/dist-client/modeller/v3-editor.js.map +1 -1
- package/dist-client/modeller/v3-gizmo.js +11 -1
- package/dist-client/modeller/v3-gizmo.js.map +1 -1
- package/dist-client/modeller/v3-links.d.ts +67 -0
- package/dist-client/modeller/v3-links.js +141 -0
- package/dist-client/modeller/v3-links.js.map +1 -0
- package/dist-client/pages/figure-v3-modeller-page.d.ts +2 -5
- package/dist-client/pages/figure-v3-modeller-page.js +2 -5
- package/dist-client/pages/figure-v3-modeller-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/route.js +2 -5
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.scratch-fm.tsbuildinfo +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/test/ai-proposal-contract.test.ts +0 -88
- package/test/figure-source.test.ts +0 -102
- package/test/i18n-prefix-guard.test.ts +0 -24
- package/test/modeller-route.test.ts +14 -25
- package/test/part-edits.test.ts +0 -7
- package/test/scene-budget.test.ts +0 -7
- package/test/v3-gizmo.test.ts +10 -0
- package/test/v3-links.test.ts +163 -0
- package/things-factory.config.js +2 -5
- package/translations/en.json +21 -1
- package/translations/ja.json +21 -1
- package/translations/ko.json +21 -1
- package/translations/ms.json +21 -1
- package/translations/zh.json +21 -1
- package/client/modeller/angle-dial.ts +0 -70
- package/client/modeller/base-box.ts +0 -175
- package/client/modeller/figure-animations.ts +0 -1249
- package/client/modeller/figure-canvas.ts +0 -567
- package/client/modeller/figure-capabilities.ts +0 -379
- package/client/modeller/figure-inspector.ts +0 -2208
- package/client/modeller/figure-parts.ts +0 -479
- package/client/modeller/figure-preview.ts +0 -598
- package/client/modeller/figure-report.ts +0 -966
- package/client/modeller/figure-settings.ts +0 -328
- package/client/modeller/figure-side.ts +0 -272
- package/client/modeller/figure-thumbnail.ts +0 -123
- package/client/modeller/figure-view.ts +0 -152
- package/client/modeller/joint-edits.ts +0 -262
- package/client/modeller/joint-gizmo.ts +0 -180
- package/client/modeller/maturity.ts +0 -288
- package/client/modeller/new-figure-entry.ts +0 -4
- package/client/modeller/pose-defaults.ts +0 -67
- package/client/pages/figure-modeller-page.ts +0 -2082
- package/dist-client/modeller/angle-dial.d.ts +0 -32
- package/dist-client/modeller/angle-dial.js +0 -41
- package/dist-client/modeller/angle-dial.js.map +0 -1
- package/dist-client/modeller/base-box.d.ts +0 -71
- package/dist-client/modeller/base-box.js +0 -110
- package/dist-client/modeller/base-box.js.map +0 -1
- package/dist-client/modeller/figure-animations.d.ts +0 -159
- package/dist-client/modeller/figure-animations.js +0 -1132
- package/dist-client/modeller/figure-animations.js.map +0 -1
- package/dist-client/modeller/figure-canvas.d.ts +0 -150
- package/dist-client/modeller/figure-canvas.js +0 -506
- package/dist-client/modeller/figure-canvas.js.map +0 -1
- package/dist-client/modeller/figure-capabilities.d.ts +0 -42
- package/dist-client/modeller/figure-capabilities.js +0 -349
- package/dist-client/modeller/figure-capabilities.js.map +0 -1
- package/dist-client/modeller/figure-inspector.d.ts +0 -329
- package/dist-client/modeller/figure-inspector.js +0 -2095
- package/dist-client/modeller/figure-inspector.js.map +0 -1
- package/dist-client/modeller/figure-parts.d.ts +0 -64
- package/dist-client/modeller/figure-parts.js +0 -478
- package/dist-client/modeller/figure-parts.js.map +0 -1
- package/dist-client/modeller/figure-preview.d.ts +0 -138
- package/dist-client/modeller/figure-preview.js +0 -549
- package/dist-client/modeller/figure-preview.js.map +0 -1
- package/dist-client/modeller/figure-report.d.ts +0 -165
- package/dist-client/modeller/figure-report.js +0 -952
- package/dist-client/modeller/figure-report.js.map +0 -1
- package/dist-client/modeller/figure-settings.d.ts +0 -39
- package/dist-client/modeller/figure-settings.js +0 -317
- package/dist-client/modeller/figure-settings.js.map +0 -1
- package/dist-client/modeller/figure-side.d.ts +0 -78
- package/dist-client/modeller/figure-side.js +0 -317
- package/dist-client/modeller/figure-side.js.map +0 -1
- package/dist-client/modeller/figure-thumbnail.d.ts +0 -3
- package/dist-client/modeller/figure-thumbnail.js +0 -95
- package/dist-client/modeller/figure-thumbnail.js.map +0 -1
- package/dist-client/modeller/figure-view.d.ts +0 -118
- package/dist-client/modeller/figure-view.js +0 -78
- package/dist-client/modeller/figure-view.js.map +0 -1
- package/dist-client/modeller/joint-edits.d.ts +0 -49
- package/dist-client/modeller/joint-edits.js +0 -223
- package/dist-client/modeller/joint-edits.js.map +0 -1
- package/dist-client/modeller/joint-gizmo.d.ts +0 -34
- package/dist-client/modeller/joint-gizmo.js +0 -158
- package/dist-client/modeller/joint-gizmo.js.map +0 -1
- package/dist-client/modeller/maturity.d.ts +0 -55
- package/dist-client/modeller/maturity.js +0 -212
- package/dist-client/modeller/maturity.js.map +0 -1
- package/dist-client/modeller/new-figure-entry.d.ts +0 -2
- package/dist-client/modeller/new-figure-entry.js +0 -5
- package/dist-client/modeller/new-figure-entry.js.map +0 -1
- package/dist-client/modeller/pose-defaults.d.ts +0 -9
- package/dist-client/modeller/pose-defaults.js +0 -35
- package/dist-client/modeller/pose-defaults.js.map +0 -1
- package/dist-client/pages/figure-modeller-page.d.ts +0 -419
- package/dist-client/pages/figure-modeller-page.js +0 -2060
- package/dist-client/pages/figure-modeller-page.js.map +0 -1
- package/test/angle-dial.test.ts +0 -78
- package/test/base-box.test.ts +0 -235
- package/test/joint-edits.test.ts +0 -165
- package/test/joint-gizmo.test.ts +0 -174
- package/test/joint-needle.test.ts +0 -162
- package/test/modeller-undo-redo.test.ts +0 -33
- package/test/new-figure-entry.test.ts +0 -15
- package/test/pose-defaults.test.ts +0 -71
- package/test/preview-board-depth.test.ts +0 -27
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"figure-v3-links.js","sourceRoot":"","sources":["../../client/modeller/figure-v3-links.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 { V3_FACES } from '@hatiolab/figure-model'\nimport type { V3Asset, V3AuthoringAction, V3DimensionSource, V3Face } from '@hatiolab/figure-model'\n\nimport {\n acceptsOf,\n AXES,\n canFasten,\n canFollow,\n choiceOf,\n fastenedTo,\n followOf,\n hasInstanceSize,\n holdsThings,\n motionOf,\n placeFacesOf,\n placeIdFor,\n placesOn,\n positionsWorkedOut,\n type Axis,\n type Follow\n} from './v3-links.js'\n\nconst FACES = Object.keys(V3_FACES) as V3Face[]\n\n/**\n * What a part is tied to — its size response, what it is fastened to, how it moves (parity rows ④ ⑤ ⑥).\n *\n * 「Build Once, Fit Anywhere」 lives here: a dimension that follows the instance size or another part is what lets\n * a figure be placed at any size, and a part fastened to the face it rests on is what keeps it there when that\n * happens. The release gate refuses a figure that falls apart when resized, and tells the author to fasten the\n * parts that come away — this is where they do it. Motion is the V2 joint: a slide or a turn driven by a control.\n *\n * The V2 inspector has these as its dimensions, placement and joint sections, in that order; so does this. Every\n * change is one figure-model authoring command, sent as `v3-command` and run by the editor through the session — one\n * step of the undo history. Choices the command would refuse (a round body fastened, a size following an instance\n * size the figure does not declare) are not offered, so the author is not sent into a refusal.\n */\n@customElement('figure-v3-links')\nexport class FigureV3Links extends localize(i18next)(LitElement) {\n static styles = css`\n :host {\n display: grid;\n gap: 10px;\n }\n h3 {\n font-size: var(--ui-t-body, 13px);\n margin: 12px 0 0;\n }\n div[row] {\n display: grid;\n grid-template-columns: 24px minmax(0, 1fr);\n gap: 6px;\n align-items: center;\n }\n div[form] {\n display: grid;\n grid-template-columns: 96px minmax(0, 1fr);\n gap: 6px;\n align-items: center;\n }\n div[pair] {\n display: flex;\n gap: 6px;\n }\n div[pair] > * {\n flex: 1;\n min-width: 0;\n }\n select,\n input,\n button {\n font: inherit;\n min-width: 0;\n }\n button[act] {\n justify-self: start;\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 10px;\n border: none;\n border-radius: 999em;\n cursor: pointer;\n color: var(--md-sys-color-on-secondary-container);\n background: var(--md-sys-color-secondary-container);\n }\n button[act]:disabled {\n opacity: 0.5;\n cursor: default;\n }\n button[act] md-icon {\n font-size: 16px;\n width: 16px;\n height: 16px;\n }\n small,\n p[hint] {\n margin: 0;\n color: var(--md-sys-color-on-surface-variant);\n }\n b[bound] {\n font-weight: 600;\n }\n label[toggle] {\n display: flex;\n align-items: center;\n gap: 6px;\n }\n `\n\n /** The asset being edited. */\n @property({ attribute: false }) asset?: V3Asset\n /** The selected part. */\n @property() partId = ''\n /** The part's own extent along its axes now, in mm — what a dimension is fixed at when it stops following. */\n @property({ attribute: false }) dims?: [number, number, number]\n @property({ type: Boolean }) locked = false\n\n @state() private fasten = { face: 'bottom' as V3Face, toPlane: false, target: '', targetFace: 'top' as V3Face, facing: 'meet' as 'meet' | 'flush', gap: 0 }\n @state() private motion = { kind: 'slide' as 'slide' | 'turn', axis: 'x' as Axis, id: '', min: 0, max: 500 }\n @state() private place = { role: 'grip' as 'seat' | 'grip', face: 'top' as V3Face, label: '', accepts: '', capacity: 1 }\n\n render() {\n const asset = this.asset\n if (!asset || !this.partId) return nothing\n return html`\n <h3>${i18next.t('figure.label.dimensions')}</h3>\n ${canFollow(asset, this.partId) ? this.renderDimensions(asset) : html`<p hint>${i18next.t('figure.text.links-need-a-box')}</p>`}\n <h3>${i18next.t('figure.label.placement')}</h3>\n ${this.renderPositions(asset)}\n ${canFasten(asset, this.partId) ? this.renderFastening(asset) : html`<p hint>${i18next.t('figure.text.links-need-a-box')}</p>`}\n <h3>${i18next.t('figure.label.motion')}</h3>\n ${this.renderMotion(asset)}\n <h3>${i18next.t('figure.label.places')}</h3>\n ${placeFacesOf(asset, this.partId).length ? this.renderPlaces(asset) : html`<p hint>${i18next.t('figure.text.places-need-a-box')}</p>`}\n `\n }\n\n /** Where things are held on this part: a seat things rest on, or a grip things are held in (parity row ⑤). */\n private renderPlaces(asset: V3Asset) {\n const faces = placeFacesOf(asset, this.partId)\n const p = this.place\n const face = faces.includes(p.face) ? p.face : faces[0]!\n const accepts = acceptsOf(p.accepts)\n const capacityOk = Number.isSafeInteger(p.capacity) && p.capacity >= 1\n const roleName = (role: string) => i18next.t('figure.label.place-' + role)\n return html`\n ${placesOn(asset, this.partId).map(\n one => html`<div pair>\n <span>\n <b bound>${one.label}</b>\n <small>${roleName(one.role)} · ${one.face ? i18next.t('figure.label.face-' + one.face) : ''} · ${one.accepts.join(', ')} · ${i18next.t('figure.label.place-holds', { count: one.capacity })}</small>\n </span>\n <button act ?disabled=${this.locked} @click=${() => this.command({ kind: 'remove-binding', id: one.id })}>\n <md-icon>close</md-icon>${i18next.t('figure.button.remove-place')}\n </button>\n </div>`\n )}\n <p hint>${i18next.t('figure.text.place-explained')}</p>\n ${holdsThings(asset)\n ? nothing\n : html`<p hint>${i18next.t('figure.text.place-needs-holding')}</p>\n <button act ?disabled=${this.locked} @click=${() => this.declareHolding(asset)}>\n <md-icon>inventory_2</md-icon>${i18next.t('figure.button.declare-holding')}\n </button>`}\n <div pair>\n <select @change=${(e: Event) => (this.place = { ...p, role: (e.target as HTMLSelectElement).value as 'seat' | 'grip' })}>\n <option value=\"grip\" ?selected=${p.role === 'grip'}>${roleName('grip')}</option>\n <option value=\"seat\" ?selected=${p.role === 'seat'}>${roleName('seat')}</option>\n </select>\n <select @change=${(e: Event) => (this.place = { ...p, face: (e.target as HTMLSelectElement).value as V3Face })}>\n ${faces.map(one => html`<option value=${one} ?selected=${one === face}>${i18next.t('figure.label.face-' + one)}</option>`)}\n </select>\n </div>\n <div form>\n <span>${i18next.t('figure.label.place-name')}</span>\n <input .value=${p.label} placeholder=${roleName(p.role)} @change=${(e: Event) => (this.place = { ...p, label: (e.target as HTMLInputElement).value })} />\n <span>${i18next.t('figure.label.place-accepts')}</span>\n <input .value=${p.accepts} placeholder=\"BOX, TOTE\" @input=${(e: Event) => (this.place = { ...p, accepts: (e.target as HTMLInputElement).value })} />\n <span>${i18next.t('figure.label.place-capacity')}</span>\n <input type=\"number\" min=\"1\" step=\"1\" .value=${String(p.capacity)} @change=${(e: Event) => (this.place = { ...p, capacity: (e.target as HTMLInputElement).valueAsNumber })} />\n </div>\n ${accepts.length ? nothing : html`<small>${i18next.t('figure.text.place-accepts-needed')}</small>`}\n <button\n act\n ?disabled=${this.locked || !accepts.length || !capacityOk}\n @click=${() =>\n this.command({\n kind: 'add-binding',\n id: placeIdFor(asset, this.partId, p.role),\n label: p.label.trim() || roleName(p.role),\n role: p.role,\n part: this.partId,\n face,\n accepts,\n capacity: p.capacity\n })}\n >\n <md-icon>back_hand</md-icon>${i18next.t('figure.button.add-place')}\n </button>\n `\n }\n\n /** The figure holds things: `Capacity` and `Holdable`, the ladder's middle rung. One part edit, one undo step. */\n private declareHolding(asset: V3Asset) {\n const names = [...new Set([...(asset.document.capabilities.names ?? []), 'Capacity', 'Holdable'])]\n this.dispatchEvent(new CustomEvent('v3-part-edit', { detail: { edit: { kind: 'set-capabilities', names } }, bubbles: true, composed: true }))\n }\n\n private renderDimensions(asset: V3Asset) {\n const others = asset.appearance.map(look => look.target).filter(one => one !== this.partId && canFollow(asset, one))\n return AXES.map(axis => {\n const now = followOf(asset, this.partId, axis)\n const value = choiceOf(now)\n return html`<div row>\n <b>${axis.toUpperCase()}</b>\n <select ?disabled=${this.locked || now.of === 'expression'} @change=${(e: Event) => this.follow(axis, (e.target as HTMLSelectElement).value, now)}>\n <option value=\"own\" ?selected=${value === 'own'}>${i18next.t('figure.label.follows-nothing')}</option>\n ${AXES.filter(one => hasInstanceSize(asset, one)).map(\n one => html`<option value=${`instance:${one}`} ?selected=${value === `instance:${one}`}>\n ${i18next.t('figure.label.follows-instance')} · ${one.toUpperCase()}\n </option>`\n )}\n ${others.flatMap(other =>\n AXES.map(\n one => html`<option value=${`part:${other}:${one}`} ?selected=${value === `part:${other}:${one}`}>${other} · ${one.toUpperCase()}</option>`\n )\n )}\n ${now.of === 'expression' || now.of === 'input'\n ? html`<option value=${value} selected>${now.of === 'input' ? now.input : i18next.t('figure.label.follows-expression')}</option>`\n : nothing}\n </select>\n </div>`\n })\n }\n\n private follow(axis: Axis, choice: string, now: Follow) {\n const following = now.of !== 'own'\n if (choice === 'own') {\n if (!following) return\n const mm = Math.max(1, Math.round(this.dims?.[AXES.indexOf(axis)] ?? 100))\n this.command({ kind: 'unlink-dimension', part: this.partId, axis, mm })\n return\n }\n const [of, a, b] = choice.split(':')\n const source: V3DimensionSource = of === 'instance' ? { of: 'instance', axis: a as Axis } : { of: 'part', part: a!, axis: b as Axis }\n this.command({ kind: 'link-dimension', part: this.partId, axis, source, replace: following })\n }\n\n /**\n * Positions worked out from other values — V2's anchor rules, as the converter wrote them — each with the way to\n * keep it where it is. This is the way out the release gate names when a resize leaves a part in the air.\n */\n private renderPositions(asset: V3Asset) {\n return positionsWorkedOut(asset, this.partId).map(\n axis => html`<div pair>\n <span>${axis.toUpperCase()} · ${i18next.t('figure.label.position-worked-out')}</span>\n <button act ?disabled=${this.locked} @click=${() => this.command({ kind: 'fix-position', part: this.partId, axis })}>\n <md-icon>push_pin</md-icon>${i18next.t('figure.button.fix-position')}\n </button>\n </div>`\n )\n }\n\n private renderFastening(asset: V3Asset) {\n const to = fastenedTo(asset, this.partId)\n const f = this.fasten\n const targets = asset.appearance.map(look => look.target).filter(one => one !== this.partId && canFasten(asset, one))\n return html`\n ${to\n ? html`<div pair>\n <span>${i18next.t('figure.label.fastened-to')}: <b bound>${to}</b></span>\n <button act ?disabled=${this.locked} @click=${() => this.command({ kind: 'detach', part: this.partId })}>\n <md-icon>link_off</md-icon>${i18next.t('figure.button.detach')}\n </button>\n </div>`\n : html`<p hint>${i18next.t('figure.text.fastening-explained')}</p>`}\n <div form>\n <span>${i18next.t('figure.label.my-face')}</span>\n <select @change=${(e: Event) => (this.fasten = { ...f, face: (e.target as HTMLSelectElement).value as V3Face })}>\n ${FACES.map(face => html`<option value=${face} ?selected=${face === f.face}>${i18next.t('figure.label.face-' + face)}</option>`)}\n </select>\n </div>\n <label toggle>\n <input type=\"checkbox\" .checked=${f.toPlane} @change=${(e: Event) => (this.fasten = { ...f, toPlane: (e.target as HTMLInputElement).checked })} />\n ${i18next.t('figure.label.stands-on-plane')}\n </label>\n ${f.toPlane\n ? nothing\n : html`<div form>\n <span>${i18next.t('figure.label.target-part')}</span>\n <select @change=${(e: Event) => (this.fasten = { ...f, target: (e.target as HTMLSelectElement).value })}>\n <option value=\"\" ?selected=${!f.target}>—</option>\n ${targets.map(one => html`<option value=${one} ?selected=${one === f.target}>${one}</option>`)}\n </select>\n <span>${i18next.t('figure.label.target-face')}</span>\n <select @change=${(e: Event) => (this.fasten = { ...f, targetFace: (e.target as HTMLSelectElement).value as V3Face })}>\n ${FACES.map(face => html`<option value=${face} ?selected=${face === f.targetFace}>${i18next.t('figure.label.face-' + face)}</option>`)}\n </select>\n <span>${i18next.t('figure.label.facing-meet')}</span>\n <select @change=${(e: Event) => (this.fasten = { ...f, facing: (e.target as HTMLSelectElement).value as 'meet' | 'flush' })}>\n <option value=\"meet\" ?selected=${f.facing === 'meet'}>${i18next.t('figure.label.facing-meet')}</option>\n <option value=\"flush\" ?selected=${f.facing === 'flush'}>${i18next.t('figure.label.facing-flush')}</option>\n </select>\n </div>`}\n <div form>\n <span>${i18next.t('figure.label.gap')}</span>\n <input type=\"number\" step=\"any\" .value=${String(f.gap)} @change=${(e: Event) => (this.fasten = { ...f, gap: Number((e.target as HTMLInputElement).value) || 0 })} />\n </div>\n <button\n act\n ?disabled=${this.locked || (!f.toPlane && !f.target)}\n @click=${() =>\n this.command({\n kind: 'attach',\n part: this.partId,\n face: f.face,\n to: f.toPlane ? { plane: 'mounting-plane' } : { part: f.target, face: f.targetFace },\n ...(f.toPlane ? {} : { facing: f.facing }),\n ...(f.gap ? { gap: f.gap } : {}),\n replace: !!to\n } as V3AuthoringAction)}\n >\n <md-icon>link</md-icon>${i18next.t('figure.button.fasten')}\n </button>\n `\n }\n\n private renderMotion(asset: V3Asset) {\n const now = motionOf(asset, this.partId)\n if (now) {\n return html`<div pair>\n <span>\n ${i18next.t('figure.label.motion-' + now.kind)} · ${String(now.axis).toUpperCase()}\n ${now.control ? html`<small>${now.control.id} (${now.control.unit}) ${now.control.min} … ${now.control.max}</small>` : nothing}\n </span>\n <button act ?disabled=${this.locked} @click=${() => this.command({ kind: 'remove-motion', part: this.partId })}>\n <md-icon>close</md-icon>${i18next.t('figure.button.remove-motion')}\n </button>\n </div>`\n }\n const m = this.motion\n const unit = m.kind === 'turn' ? 'deg' : 'mm'\n return html`\n <p hint>${i18next.t('figure.text.motion-explained')}</p>\n <div pair>\n <select @change=${(e: Event) => this.setKind((e.target as HTMLSelectElement).value as 'slide' | 'turn')}>\n <option value=\"slide\" ?selected=${m.kind === 'slide'}>${i18next.t('figure.label.motion-slide')}</option>\n <option value=\"turn\" ?selected=${m.kind === 'turn'}>${i18next.t('figure.label.motion-turn')}</option>\n </select>\n <select @change=${(e: Event) => (this.motion = { ...m, axis: (e.target as HTMLSelectElement).value as Axis })}>\n ${AXES.map(a => html`<option value=${a} ?selected=${a === m.axis}>${i18next.t('figure.label.motion-axis')} ${a.toUpperCase()}</option>`)}\n </select>\n </div>\n <div form>\n <span>${i18next.t('figure.label.control-id')}</span>\n <input .value=${m.id} placeholder=${`${this.partId}-${m.kind}`} @change=${(e: Event) => (this.motion = { ...m, id: (e.target as HTMLInputElement).value.trim() })} />\n <span>${i18next.t('figure.label.control-range')} (${unit})</span>\n <div pair>\n <input type=\"number\" step=\"any\" .value=${String(m.min)} @change=${(e: Event) => (this.motion = { ...m, min: Number((e.target as HTMLInputElement).value) })} />\n <input type=\"number\" step=\"any\" .value=${String(m.max)} @change=${(e: Event) => (this.motion = { ...m, max: Number((e.target as HTMLInputElement).value) })} />\n </div>\n </div>\n <button\n act\n ?disabled=${this.locked || !(m.max > m.min)}\n @click=${() =>\n this.command({\n kind: 'add-motion',\n part: this.partId,\n motion: { kind: m.kind, axis: m.axis },\n state: { id: m.id || `${this.partId}-${m.kind}`, unit, min: m.min, max: m.max, start: m.min }\n })}\n >\n <md-icon>animation</md-icon>${i18next.t('figure.button.add-motion')}\n </button>\n `\n }\n\n private setKind(kind: 'slide' | 'turn') {\n this.motion = kind === 'turn' ? { ...this.motion, kind, min: -90, max: 90 } : { ...this.motion, kind, min: 0, max: 500 }\n }\n\n private command(action: V3AuthoringAction) {\n this.dispatchEvent(new CustomEvent('v3-command', { detail: { action }, bubbles: true, composed: true }))\n }\n}\n\n"]}
|
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* page's address (2026-09-24). A new figure starts in V3: new V2 figures would only add to what the cutover has to
|
|
6
|
-
* convert (ADR-0087). A figure is opened in V3 only when the server says it is V3 — an unknown format goes to the
|
|
7
|
-
* V2 page, which reports what it could not read.
|
|
2
|
+
* The one modeller. Every figure is V3 since ADR-0087 step 5 (2026-09-24, user decision: V2 is not kept), so the
|
|
3
|
+
* catalogue, a new figure and an old address all open the same page. `figure-v3-modeller` stays as an alias so a
|
|
4
|
+
* link written before the switch still lands.
|
|
8
5
|
*/
|
|
9
|
-
export declare const
|
|
10
|
-
export declare const V2_MODELLER = "figure-modeller";
|
|
6
|
+
export declare const MODELLER = "figure-modeller";
|
|
11
7
|
export declare function modellerPathOf(figure?: {
|
|
12
8
|
id?: string;
|
|
13
|
-
format?: string | null;
|
|
14
9
|
}): string;
|
|
15
|
-
/** The version a V3 asset stamps on itself. The V2 page forwards such a figure rather than failing on it. */
|
|
16
|
-
export declare function isV3Source(source?: string | null): boolean;
|
|
@@ -1,27 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* page's address (2026-09-24). A new figure starts in V3: new V2 figures would only add to what the cutover has to
|
|
6
|
-
* convert (ADR-0087). A figure is opened in V3 only when the server says it is V3 — an unknown format goes to the
|
|
7
|
-
* V2 page, which reports what it could not read.
|
|
2
|
+
* The one modeller. Every figure is V3 since ADR-0087 step 5 (2026-09-24, user decision: V2 is not kept), so the
|
|
3
|
+
* catalogue, a new figure and an old address all open the same page. `figure-v3-modeller` stays as an alias so a
|
|
4
|
+
* link written before the switch still lands.
|
|
8
5
|
*/
|
|
9
|
-
export const
|
|
10
|
-
export const V2_MODELLER = 'figure-modeller';
|
|
6
|
+
export const MODELLER = 'figure-modeller';
|
|
11
7
|
export function modellerPathOf(figure) {
|
|
12
|
-
|
|
13
|
-
return V3_MODELLER;
|
|
14
|
-
return figure.format === 'v3' ? `${V3_MODELLER}/${figure.id}` : `${V2_MODELLER}/${figure.id}`;
|
|
15
|
-
}
|
|
16
|
-
/** The version a V3 asset stamps on itself. The V2 page forwards such a figure rather than failing on it. */
|
|
17
|
-
export function isV3Source(source) {
|
|
18
|
-
if (!source)
|
|
19
|
-
return false;
|
|
20
|
-
try {
|
|
21
|
-
return JSON.parse(source)?.version === 'figure-v3-asset-1';
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
8
|
+
return figure?.id ? `${MODELLER}/${figure.id}` : MODELLER;
|
|
26
9
|
}
|
|
27
10
|
//# sourceMappingURL=modeller-route.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modeller-route.js","sourceRoot":"","sources":["../../client/modeller/modeller-route.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"modeller-route.js","sourceRoot":"","sources":["../../client/modeller/modeller-route.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,iBAAiB,CAAA;AAEzC,MAAM,UAAU,cAAc,CAAC,MAAwB;IACrD,OAAO,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAA;AAC3D,CAAC","sourcesContent":["/**\n * The one modeller. Every figure is V3 since ADR-0087 step 5 (2026-09-24, user decision: V2 is not kept), so the\n * catalogue, a new figure and an old address all open the same page. `figure-v3-modeller` stays as an alias so a\n * link written before the switch still lands.\n */\nexport const MODELLER = 'figure-modeller'\n\nexport function modellerPathOf(figure?: { id?: string }): string {\n return figure?.id ? `${MODELLER}/${figure.id}` : MODELLER\n}\n"]}
|
|
@@ -3,6 +3,7 @@ import type { V3ProductSession } from './v3-product-session.js';
|
|
|
3
3
|
import './v3-canvas.js';
|
|
4
4
|
import './figure-v3-parts.js';
|
|
5
5
|
import './figure-v3-material.js';
|
|
6
|
+
import './figure-v3-links.js';
|
|
6
7
|
/** Product editor surface. The injected session is shared by page persistence and AI commands. */
|
|
7
8
|
export declare class FigureV3Editor extends LitElement {
|
|
8
9
|
static styles: import("lit").CSSResult;
|
|
@@ -43,6 +44,10 @@ export declare class FigureV3Editor extends LitElement {
|
|
|
43
44
|
* (figure-model's rename-part), as one step of the history.
|
|
44
45
|
*/
|
|
45
46
|
private renamePart;
|
|
47
|
+
/** Size response, fastening and motion for the selected part (parity ④ ⑤ ⑥), as authoring commands. */
|
|
48
|
+
private renderLinks;
|
|
49
|
+
/** One command, one step of the history. A refusal a person can meet here is said in their words. */
|
|
50
|
+
private linkCommand;
|
|
46
51
|
private changeField;
|
|
47
52
|
render(): import("lit-html").TemplateResult<1>;
|
|
48
53
|
}
|
|
@@ -7,8 +7,9 @@ import { drawableV3Parts } from './v3-renderer.js';
|
|
|
7
7
|
import './v3-canvas.js';
|
|
8
8
|
import './figure-v3-parts.js';
|
|
9
9
|
import './figure-v3-material.js';
|
|
10
|
+
import './figure-v3-links.js';
|
|
10
11
|
import { gizmoChanges, gizmoReachOf } from './v3-gizmo.js';
|
|
11
|
-
import { alignChanges, canMirror, mirrorChanges } from './v3-align.js';
|
|
12
|
+
import { alignChanges, boxOf, canMirror, mirrorChanges } from './v3-align.js';
|
|
12
13
|
const names = {
|
|
13
14
|
position: '위치',
|
|
14
15
|
rotation: '회전',
|
|
@@ -434,6 +435,50 @@ let FigureV3Editor = class FigureV3Editor extends LitElement {
|
|
|
434
435
|
: String(error);
|
|
435
436
|
}
|
|
436
437
|
}
|
|
438
|
+
/** Size response, fastening and motion for the selected part (parity ④ ⑤ ⑥), as authoring commands. */
|
|
439
|
+
renderLinks(unavailable) {
|
|
440
|
+
let asset;
|
|
441
|
+
try {
|
|
442
|
+
asset = JSON.parse(this.session.source());
|
|
443
|
+
}
|
|
444
|
+
catch {
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
let dims;
|
|
448
|
+
try {
|
|
449
|
+
dims = boxOf(asset, this.selected)?.dims;
|
|
450
|
+
}
|
|
451
|
+
catch {
|
|
452
|
+
dims = undefined;
|
|
453
|
+
}
|
|
454
|
+
return html `<figure-v3-links
|
|
455
|
+
.asset=${asset}
|
|
456
|
+
.partId=${this.selected}
|
|
457
|
+
.dims=${dims}
|
|
458
|
+
?locked=${unavailable}
|
|
459
|
+
@v3-command=${(e) => this.linkCommand(e.detail.action)}
|
|
460
|
+
@v3-part-edit=${(e) => this.run(() => this.session.edit(e.detail.edit))}
|
|
461
|
+
></figure-v3-links>`;
|
|
462
|
+
}
|
|
463
|
+
/** One command, one step of the history. A refusal a person can meet here is said in their words. */
|
|
464
|
+
linkCommand(action) {
|
|
465
|
+
try {
|
|
466
|
+
this.session.command(action);
|
|
467
|
+
this.error = '';
|
|
468
|
+
this.changed();
|
|
469
|
+
}
|
|
470
|
+
catch (error) {
|
|
471
|
+
const code = error?.code;
|
|
472
|
+
this.error =
|
|
473
|
+
code === 'DIMENSION_CYCLE'
|
|
474
|
+
? i18next.t('figure.text.follow-would-loop')
|
|
475
|
+
: code === 'FASTEN_CYCLE' || code === 'ATTACH_CYCLE'
|
|
476
|
+
? i18next.t('figure.text.fasten-would-loop')
|
|
477
|
+
: error instanceof Error
|
|
478
|
+
? error.message
|
|
479
|
+
: String(error);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
437
482
|
changeField(field, event) {
|
|
438
483
|
const input = event.target, value = input.valueAsNumber;
|
|
439
484
|
this.run(() => this.session.apply([
|
|
@@ -516,7 +561,7 @@ let FigureV3Editor = class FigureV3Editor extends LitElement {
|
|
|
516
561
|
${this.renderTools(unavailable)}
|
|
517
562
|
${fields.map(field => html `<label><span>${fieldLabel(field.id)} (${field.unit})${field.role === 'state' ? ' · 동작' : ''}</span><input aria-label=${field.id} type="number" step="any" .value=${String(field.value)} ?disabled=${unavailable} @change=${(e) => this.changeField(field, e)} /></label>`)}
|
|
518
563
|
${part
|
|
519
|
-
? html
|
|
564
|
+
? html `${this.renderLinks(unavailable)}<figure-v3-material
|
|
520
565
|
.body=${part}
|
|
521
566
|
.palette=${view.palette ?? {}}
|
|
522
567
|
?locked=${unavailable}
|
|
@@ -524,8 +569,8 @@ let FigureV3Editor = class FigureV3Editor extends LitElement {
|
|
|
524
569
|
></figure-v3-material>`
|
|
525
570
|
: null}
|
|
526
571
|
${view.bindings.length
|
|
527
|
-
? html `<h3
|
|
528
|
-
${view.bindings.map(b => html `<p>${b.label} · ${b.role}</p>`)}`
|
|
572
|
+
? html `<h3>${i18next.t('figure.label.places')}</h3>
|
|
573
|
+
${view.bindings.map(b => html `<p>${b.label} · ${i18next.t('figure.label.place-' + b.role)}</p>`)}`
|
|
529
574
|
: null}
|
|
530
575
|
</aside>
|
|
531
576
|
</main>`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v3-editor.js","sourceRoot":"","sources":["../../client/modeller/v3-editor.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css, type PropertyValues } from 'lit'\nimport { i18next } from '@operato/i18n'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport type { V3InputChange, V3PrimitiveCreation } from '@hatiolab/figure-model'\nimport type { V3ProductSession } from './v3-product-session.js'\nimport { captureV3Thumbnail } from './v3-thumbnail.js'\nimport { drawableV3Parts } from './v3-renderer.js'\nimport './v3-canvas.js'\nimport './figure-v3-parts.js'\nimport './figure-v3-material.js'\nimport { gizmoChanges, gizmoReachOf, type GizmoReach, type GizmoResult } from './v3-gizmo.js'\nimport { alignChanges, canMirror, mirrorChanges, type AlignTool } from './v3-align.js'\nimport type { V3PartRow } from './figure-v3-parts.js'\nimport type { FigureV3Canvas } from './v3-canvas.js'\n\nconst names: Record<string, string> = {\n position: '위치',\n rotation: '회전',\n size: '크기',\n dimension: '치수',\n width: '너비',\n height: '높이',\n depth: '깊이',\n radius: '반지름',\n length: '길이',\n round: '모서리 반경',\n left: '왼쪽',\n right: '오른쪽',\n bottom: '아랫면',\n top: '윗면',\n openingLeft: '개구부 왼쪽',\n openingRight: '개구부 오른쪽',\n openingTop: '개구부 윗면'\n}\nfunction fieldLabel(id: string) {\n return id\n .split('.')\n .map(p => names[p] ?? p.toUpperCase())\n .join(' · ')\n}\n\n/** Product editor surface. The injected session is shared by page persistence and AI commands. */\n@customElement('figure-v3-editor')\nexport class FigureV3Editor extends LitElement {\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n min-height: 0;\n height: 100%;\n /*\n The editor folds by the width it is given, not the window's. The rail (208 open, 56 closed) and the page's\n 320 side take their share first, so a window rule was wrong whenever either was there: at 945 with the rail\n open the editor had 417 and still drew its 660 of columns, over the side (UX ruling, 2026-09-24).\n */\n container-type: inline-size;\n font: 13px sans-serif;\n color: var(--md-sys-color-on-surface, #22343f);\n }\n header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n flex-wrap: wrap;\n }\n main {\n flex: 1;\n min-height: 0;\n display: grid;\n grid-template-columns: 180px minmax(180px, 1fr) 300px;\n }\n aside {\n padding: 12px;\n overflow: auto;\n background: var(--md-sys-color-surface, #fff);\n }\n figure-v3-parts {\n min-height: 0;\n }\n aside:last-child {\n border-left: 1px solid var(--md-sys-color-outline-variant);\n }\n h3 {\n font-size: var(--ui-t-body, 13px);\n margin: 22px 0 10px;\n }\n h3:first-child {\n margin-top: 0;\n }\n button,\n input,\n select {\n font: inherit;\n box-sizing: border-box;\n height: 34px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n background: var(--md-sys-color-surface, #fff);\n color: inherit;\n padding: 0 8px;\n min-width: 0;\n }\n button {\n cursor: pointer;\n }\n button:disabled {\n opacity: 0.45;\n cursor: default;\n }\n button[aria-pressed='true'] {\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n border-color: var(--md-sys-color-primary);\n }\n label[name-field] {\n margin: 0 0 8px;\n }\n label[name-field] input {\n font-weight: 600;\n }\n div[tools] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin: 0 0 8px;\n }\n div[tools] button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 34px;\n padding: 0;\n }\n div[tools] md-icon {\n font-size: 18px;\n width: 18px;\n height: 18px;\n }\n .parts {\n display: grid;\n gap: 6px;\n }\n .recipes {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 6px;\n }\n label {\n display: grid;\n grid-template-columns: 112px minmax(0, 1fr);\n align-items: center;\n gap: 8px;\n margin: 8px 0;\n }\n label span {\n overflow-wrap: anywhere;\n }\n .error {\n padding: 10px;\n background: var(--md-sys-color-error-container);\n color: var(--md-sys-color-on-error-container);\n white-space: pre-wrap;\n }\n .status {\n margin-left: auto;\n }\n .hint {\n color: var(--md-sys-color-on-surface-variant);\n line-height: 1.5;\n }\n /* 660 and over: parts | canvas | inputs. Below that the sum of the columns' least widths no longer fits. */\n @container (max-width: 659px) {\n main {\n grid-template-columns: 140px minmax(160px, 1fr);\n }\n aside:last-child {\n grid-column: 1/-1;\n max-height: 260px;\n border-left: none;\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n }\n /* Under 420: one column. The canvas first — seeing what is being made comes before the lists — and main scrolls. */\n @container (max-width: 419px) {\n main {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: minmax(240px, 45%);\n grid-auto-rows: auto;\n overflow-y: auto;\n }\n figure-v3-canvas {\n order: -1;\n }\n figure-v3-parts {\n border-right: none;\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n aside:last-child {\n max-height: none;\n }\n }\n `\n @property({ attribute: false }) session?: V3ProductSession\n @property({ type: Number }) revision = 0\n @state() private selected = ''\n @state() private error = ''\n /**\n * Parts hidden on the workbench — the author's view while working, not the asset's visibility. Not saved, as in\n * the V2 modeller: a part hidden here is still in the figure, still checked, still drawn on a board.\n */\n @state() private hiddenParts = new Set<string>()\n private lastContext: string | null = null\n protected willUpdate(_changed: PropertyValues) {\n const view = this.session?.read()\n if (view?.context !== this.lastContext) {\n this.lastContext = view?.context ?? null\n this.selected = ''\n this.error = ''\n this.hiddenParts = new Set()\n }\n if (view && !view.geometry.some(g => g.id === this.selected)) this.selected = ''\n }\n private run(action: () => unknown) {\n try {\n action()\n this.error = ''\n this.changed()\n } catch (error) {\n this.error = error instanceof Error ? error.message : String(error)\n }\n }\n private changed() {\n this.requestUpdate()\n this.dispatchEvent(new CustomEvent('v3-changed', { bubbles: true, composed: true }))\n }\n private async save() {\n if (!this.session) return\n try {\n /*\n The card's picture is taken before the save starts, from a canvas of its own at the card's size —\n not from the one on screen, which stands wherever the author left it turned. A picture that cannot\n be taken is not an error: the save goes on without it (see `v3-thumbnail.ts`).\n */\n const view = this.session.read()\n const thumbnail = await captureV3Thumbnail(drawableV3Parts(view.geometry ?? []), view.palette ?? {})\n const promise = this.session.save({ thumbnail })\n this.changed()\n await promise\n this.error = ''\n } catch (error) {\n this.error = error instanceof Error ? error.message : String(error)\n } finally {\n this.changed()\n }\n }\n private add(kind: V3PrimitiveCreation['kind']) {\n if (!this.session) return\n this.run(() => {\n const ids = new Set(this.session!.read().geometry.map(g => g.id))\n let n = 1\n while (ids.has(`${kind}-${n}`)) n++\n const common = { id: `${kind}-${n}`, position: { x: 0, y: 50, z: 0 } }\n const part: V3PrimitiveCreation =\n kind === 'box'\n ? { ...common, kind, dimensions: { width: 100, height: 100, depth: 100 } }\n : kind === 'cylinder'\n ? { ...common, kind, dimensions: { radius: 50, length: 100 } }\n : kind === 'rounded-box'\n ? { ...common, kind, dimensions: { width: 100, height: 100, depth: 100, round: 10 } }\n : {\n ...common,\n position: { x: 0, y: 0, z: 0 },\n kind: 'portal',\n dimensions: {\n left: -100,\n right: 100,\n bottom: 0,\n top: 200,\n openingLeft: -70,\n openingRight: 70,\n openingTop: 170,\n depth: 30\n }\n }\n this.session!.add(part)\n this.selected = part.id\n })\n }\n /**\n * The list's own operations, as V3 part edits — each one step of the session's history. The copy and the moved\n * part stay selected, as they do in the V2 list.\n */\n private duplicatePart(id: string) {\n this.run(() => {\n const before = new Set(this.session!.read().geometry.map(g => g.id))\n this.session!.edit({ kind: 'duplicate-part', target: id })\n this.selected = this.session!.read().geometry.find(g => !before.has(g.id))?.id ?? id\n })\n }\n private movePart(id: string, to: number) {\n this.run(() => this.session!.edit({ kind: 'move-part', target: id, to }))\n }\n private removePart(id: string) {\n try {\n this.session!.edit({ kind: 'remove-part', target: id })\n this.error = ''\n if (this.selected === id) this.selected = ''\n this.changed()\n } catch (error) {\n /* The refusal a person meets most: another part stands on this one or follows its size. Said in their words. */\n this.error =\n (error as { code?: string })?.code === 'PART_REFERENCED'\n ? i18next.t('figure.text.part-is-referenced', { part: id })\n : error instanceof Error\n ? error.message\n : String(error)\n }\n }\n private toggleHiddenPart(id: string) {\n const next = new Set(this.hiddenParts)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n this.hiddenParts = next\n }\n /** What the gizmo may write for the selected part — read off the asset being edited. */\n private reachOf(id: string): GizmoReach {\n const none = { translate: false, rotate: false, scale: false }\n if (!id || !this.session) return none\n try {\n return gizmoReachOf(JSON.parse(this.session.source()), id)\n } catch {\n return none\n }\n }\n /** A drag, written back as the part's own inputs — one step of the history, like typing the numbers. */\n private transformed(id: string, result: GizmoResult) {\n const view = this.session!.read()\n const sizes = Object.fromEntries(view.fields.map(field => [field.id, field.value as number]))\n const changes = gizmoChanges(id, this.reachOf(id), result, sizes)\n if (changes.length) this.run(() => this.session!.apply(changes))\n else this.requestUpdate()\n }\n /** 맞추기 — one tool, one step of the history, through the same inputs as the gizmo. */\n private align(tool: AlignTool) {\n this.run(() => {\n const asset = JSON.parse(this.session!.source())\n const changes = alignChanges(asset, this.selected, this.reachOf(this.selected), tool)\n if (changes.length) this.session!.apply(changes)\n })\n }\n /** A mirrored copy: duplicate, then place the copy on the other side — two steps, as the V2 list makes it. */\n private mirror(axis: 'x' | 'z') {\n this.run(() => {\n const id = this.selected\n const before = new Set(this.session!.read().geometry.map(g => g.id))\n this.session!.edit({ kind: 'duplicate-part', target: id })\n const copy = this.session!.read().geometry.find(g => !before.has(g.id))?.id\n if (!copy) return\n this.session!.apply(mirrorChanges(JSON.parse(this.session!.source()), id, copy, axis))\n this.selected = copy\n })\n }\n private renderTools(unavailable: boolean) {\n const reach = this.reachOf(this.selected)\n if (!this.selected || !reach.translate) return null\n let asset: unknown\n try {\n asset = JSON.parse(this.session!.source())\n } catch {\n return null\n }\n const tool = (name: AlignTool, icon: string, label: string, title: string) =>\n html`<button ?disabled=${unavailable} aria-label=${i18next.t(label)} title=${i18next.t(title)} @click=${() => this.align(name)}>\n <md-icon>${icon}</md-icon>\n </button>`\n return html`<div tools title=${i18next.t('figure.text.tools-explained')}>\n ${tool('centre-x', 'horizontal_distribute', 'figure.button.center-x', 'figure.text.center-on-x')}\n ${tool('centre-z', 'vertical_align_center', 'figure.button.center-z', 'figure.text.center-on-z')}\n ${tool('floor', 'vertical_align_bottom', 'figure.button.to-floor', 'figure.text.put-on-floor')}\n ${(['x', 'z'] as const).map(axis => {\n const able = canMirror(asset as never, this.selected, axis, reach)\n return html`<button\n ?disabled=${unavailable || !able}\n aria-label=${i18next.t('figure.button.mirror-' + axis)}\n title=${i18next.t(able ? 'figure.text.mirror-explained' : 'figure.text.mirror-would-overlap')}\n @click=${() => this.mirror(axis)}\n >\n <md-icon>${axis === 'x' ? 'flip' : 'flip_camera_android'}</md-icon>\n </button>`\n })}\n ${tool('snap', 'grid_on', 'figure.button.snap', 'figure.text.snap-explained')}\n </div>`\n }\n /**\n * A part's name — the V2 part name field. It renames every value the part owns, and what refers to them follows\n * (figure-model's rename-part), as one step of the history.\n */\n private renamePart(input: HTMLInputElement) {\n const name = input.value.trim()\n const from = this.selected\n if (!name || name === from) {\n input.value = from\n return\n }\n try {\n this.session!.edit({ kind: 'rename-part', target: from, name })\n this.selected = name\n this.error = ''\n this.changed()\n } catch (error) {\n input.value = from\n const code = (error as { code?: string })?.code\n this.error =\n code === 'PART_ID'\n ? i18next.t(/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name) ? 'figure.text.part-name-taken' : 'figure.text.part-name-invalid', { name })\n : error instanceof Error\n ? error.message\n : String(error)\n }\n }\n private changeField(field: { id: string; unit: V3InputChange['unit']; role?: string }, event: Event) {\n const input = event.target as HTMLInputElement,\n value = input.valueAsNumber\n this.run(() =>\n this.session!.apply([\n { kind: field.role === 'state' ? 'set-state' : 'set-design', input: field.id, unit: field.unit, value }\n ])\n )\n // Rejected edits must also restore the displayed numeric value.\n input.value = String(this.session!.read().fields.find(i => i.id === field.id)!.value)\n }\n render() {\n const view = this.session?.read()\n if (!view) return html`<p>모델을 여는 중입니다.</p>`\n const unavailable = view.loading || !!view.error || view.saving || !view.context\n const part = view.geometry.find(g => g.id === this.selected)\n // Shared/root parameters remain available even when a part is selected.\n const own = view.fields.filter(i => this.selected && i.id.startsWith(this.selected + '.'))\n const common = view.fields.filter(i => !view.geometry.some(g => i.id.startsWith(g.id + '.')))\n const fields = this.selected ? [...own, ...common] : view.fields\n return html` <header>\n <strong>V3 모델링</strong>\n <button ?disabled=${unavailable || !view.canUndo} @click=${() => this.run(() => this.session!.undo())}>\n 실행 취소\n </button>\n <button ?disabled=${unavailable || !view.canRedo} @click=${() => this.run(() => this.session!.redo())}>\n 다시 실행\n </button>\n <button @click=${() => this.renderRoot.querySelector<FigureV3Canvas>('figure-v3-canvas')?.fit()}>\n 전체 보기\n </button>\n <span class=\"status\" role=\"status\"\n >${view.loading ? '불러오는 중' : view.saving ? '저장 중' : view.dirty || !view.id ? '저장 안 됨' : '저장됨'}</span\n >\n <button ?disabled=${unavailable || (!view.dirty && !!view.id)} @click=${this.save}>저장</button>\n </header>\n ${this.error || view.error ? html`<div role=\"alert\" class=\"error\">${this.error || view.error}</div>` : null}\n <main>\n <figure-v3-parts\n .parts=${view.geometry.map(\n (g): V3PartRow => ({\n id: g.id,\n provider: (g as { shape?: { provider?: string } }).shape?.provider ?? '',\n hidden: this.hiddenParts.has(g.id),\n invisible: (g as { visible?: boolean }).visible === false\n })\n )}\n .selected=${this.selected}\n ?locked=${unavailable}\n @add-part=${(e: CustomEvent) => this.add(e.detail.kind)}\n @select-part=${(e: CustomEvent) => (this.selected = e.detail.id)}\n @toggle-part-hidden=${(e: CustomEvent) => this.toggleHiddenPart(e.detail.id)}\n @set-all-parts-hidden=${(e: CustomEvent) =>\n (this.hiddenParts = e.detail.hidden ? new Set(view.geometry.map(g => g.id)) : new Set())}\n @move-part-up=${(e: CustomEvent) => this.movePart(e.detail.id, e.detail.to)}\n @move-part-down=${(e: CustomEvent) => this.movePart(e.detail.id, e.detail.to)}\n @duplicate-part=${(e: CustomEvent) => this.duplicatePart(e.detail.id)}\n @remove-part=${(e: CustomEvent) => this.removePart(e.detail.id)}\n ></figure-v3-parts>\n <figure-v3-canvas\n .parts=${drawableV3Parts(view.geometry ?? []).filter(body => !this.hiddenParts.has((body as { id: string }).id))}\n .palette=${view.palette ?? {}}\n .context=${view.context ?? ''}\n .selected=${this.selected}\n .reach=${unavailable ? { translate: false, rotate: false, scale: false } : this.reachOf(this.selected)}\n @part-transformed=${(e: CustomEvent) => this.transformed(e.detail.id, e.detail.result)}\n @part-selected=${(e: CustomEvent<string>) => {\n this.selected = e.detail\n }}\n @render-error=${(e: CustomEvent<Error>) => {\n this.error = e.detail.message\n }}\n ></figure-v3-canvas>\n <aside>\n ${this.selected && part\n ? html`<label name-field\n ><span>${i18next.t('figure.label.name')}</span\n ><input\n aria-label=${i18next.t('figure.label.name')}\n .value=${this.selected}\n ?disabled=${unavailable}\n @change=${(e: Event) => this.renamePart(e.target as HTMLInputElement)}\n /></label>`\n : html`<h3>${this.selected || '모델 입력'}</h3>`}\n ${this.renderTools(unavailable)}\n ${fields.map(field => html`<label><span>${fieldLabel(field.id)} (${field.unit})${field.role === 'state' ? ' · 동작' : ''}</span><input aria-label=${field.id} type=\"number\" step=\"any\" .value=${String(field.value)} ?disabled=${unavailable} @change=${(e: Event) => this.changeField(field, e)} /></label>`)}\n ${\n part\n ? html`<figure-v3-material\n .body=${part}\n .palette=${view.palette ?? {}}\n ?locked=${unavailable}\n @v3-part-edit=${(e: CustomEvent) => this.run(() => this.session!.edit(e.detail.edit))}\n ></figure-v3-material>`\n : null\n }\n ${\n view.bindings.length\n ? html`<h3>배치 연결점</h3>\n ${view.bindings.map(b => html`<p>${b.label} · ${b.role}</p>`)}`\n : null\n }\n </aside>\n </main>`\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"v3-editor.js","sourceRoot":"","sources":["../../client/modeller/v3-editor.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, css, type PropertyValues } from 'lit'\nimport { i18next } from '@operato/i18n'\nimport { customElement, property, state } from 'lit/decorators.js'\nimport type { V3AuthoringAction, V3InputChange, V3PrimitiveCreation } from '@hatiolab/figure-model'\nimport type { V3ProductSession } from './v3-product-session.js'\nimport { captureV3Thumbnail } from './v3-thumbnail.js'\nimport { drawableV3Parts } from './v3-renderer.js'\nimport './v3-canvas.js'\nimport './figure-v3-parts.js'\nimport './figure-v3-material.js'\nimport './figure-v3-links.js'\nimport { gizmoChanges, gizmoReachOf, type GizmoReach, type GizmoResult } from './v3-gizmo.js'\nimport { alignChanges, boxOf, canMirror, mirrorChanges, type AlignTool } from './v3-align.js'\nimport type { V3PartRow } from './figure-v3-parts.js'\nimport type { FigureV3Canvas } from './v3-canvas.js'\n\nconst names: Record<string, string> = {\n position: '위치',\n rotation: '회전',\n size: '크기',\n dimension: '치수',\n width: '너비',\n height: '높이',\n depth: '깊이',\n radius: '반지름',\n length: '길이',\n round: '모서리 반경',\n left: '왼쪽',\n right: '오른쪽',\n bottom: '아랫면',\n top: '윗면',\n openingLeft: '개구부 왼쪽',\n openingRight: '개구부 오른쪽',\n openingTop: '개구부 윗면'\n}\nfunction fieldLabel(id: string) {\n return id\n .split('.')\n .map(p => names[p] ?? p.toUpperCase())\n .join(' · ')\n}\n\n/** Product editor surface. The injected session is shared by page persistence and AI commands. */\n@customElement('figure-v3-editor')\nexport class FigureV3Editor extends LitElement {\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n min-height: 0;\n height: 100%;\n /*\n The editor folds by the width it is given, not the window's. The rail (208 open, 56 closed) and the page's\n 320 side take their share first, so a window rule was wrong whenever either was there: at 945 with the rail\n open the editor had 417 and still drew its 660 of columns, over the side (UX ruling, 2026-09-24).\n */\n container-type: inline-size;\n font: 13px sans-serif;\n color: var(--md-sys-color-on-surface, #22343f);\n }\n header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px;\n border-bottom: 1px solid var(--md-sys-color-outline-variant);\n flex-wrap: wrap;\n }\n main {\n flex: 1;\n min-height: 0;\n display: grid;\n grid-template-columns: 180px minmax(180px, 1fr) 300px;\n }\n aside {\n padding: 12px;\n overflow: auto;\n background: var(--md-sys-color-surface, #fff);\n }\n figure-v3-parts {\n min-height: 0;\n }\n aside:last-child {\n border-left: 1px solid var(--md-sys-color-outline-variant);\n }\n h3 {\n font-size: var(--ui-t-body, 13px);\n margin: 22px 0 10px;\n }\n h3:first-child {\n margin-top: 0;\n }\n button,\n input,\n select {\n font: inherit;\n box-sizing: border-box;\n height: 34px;\n border: 1px solid var(--md-sys-color-outline-variant);\n border-radius: 6px;\n background: var(--md-sys-color-surface, #fff);\n color: inherit;\n padding: 0 8px;\n min-width: 0;\n }\n button {\n cursor: pointer;\n }\n button:disabled {\n opacity: 0.45;\n cursor: default;\n }\n button[aria-pressed='true'] {\n background: var(--md-sys-color-secondary-container);\n color: var(--md-sys-color-on-secondary-container);\n border-color: var(--md-sys-color-primary);\n }\n label[name-field] {\n margin: 0 0 8px;\n }\n label[name-field] input {\n font-weight: 600;\n }\n div[tools] {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin: 0 0 8px;\n }\n div[tools] button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 34px;\n padding: 0;\n }\n div[tools] md-icon {\n font-size: 18px;\n width: 18px;\n height: 18px;\n }\n .parts {\n display: grid;\n gap: 6px;\n }\n .recipes {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 6px;\n }\n label {\n display: grid;\n grid-template-columns: 112px minmax(0, 1fr);\n align-items: center;\n gap: 8px;\n margin: 8px 0;\n }\n label span {\n overflow-wrap: anywhere;\n }\n .error {\n padding: 10px;\n background: var(--md-sys-color-error-container);\n color: var(--md-sys-color-on-error-container);\n white-space: pre-wrap;\n }\n .status {\n margin-left: auto;\n }\n .hint {\n color: var(--md-sys-color-on-surface-variant);\n line-height: 1.5;\n }\n /* 660 and over: parts | canvas | inputs. Below that the sum of the columns' least widths no longer fits. */\n @container (max-width: 659px) {\n main {\n grid-template-columns: 140px minmax(160px, 1fr);\n }\n aside:last-child {\n grid-column: 1/-1;\n max-height: 260px;\n border-left: none;\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n }\n /* Under 420: one column. The canvas first — seeing what is being made comes before the lists — and main scrolls. */\n @container (max-width: 419px) {\n main {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: minmax(240px, 45%);\n grid-auto-rows: auto;\n overflow-y: auto;\n }\n figure-v3-canvas {\n order: -1;\n }\n figure-v3-parts {\n border-right: none;\n border-top: 1px solid var(--md-sys-color-outline-variant);\n }\n aside:last-child {\n max-height: none;\n }\n }\n `\n @property({ attribute: false }) session?: V3ProductSession\n @property({ type: Number }) revision = 0\n @state() private selected = ''\n @state() private error = ''\n /**\n * Parts hidden on the workbench — the author's view while working, not the asset's visibility. Not saved, as in\n * the V2 modeller: a part hidden here is still in the figure, still checked, still drawn on a board.\n */\n @state() private hiddenParts = new Set<string>()\n private lastContext: string | null = null\n protected willUpdate(_changed: PropertyValues) {\n const view = this.session?.read()\n if (view?.context !== this.lastContext) {\n this.lastContext = view?.context ?? null\n this.selected = ''\n this.error = ''\n this.hiddenParts = new Set()\n }\n if (view && !view.geometry.some(g => g.id === this.selected)) this.selected = ''\n }\n private run(action: () => unknown) {\n try {\n action()\n this.error = ''\n this.changed()\n } catch (error) {\n this.error = error instanceof Error ? error.message : String(error)\n }\n }\n private changed() {\n this.requestUpdate()\n this.dispatchEvent(new CustomEvent('v3-changed', { bubbles: true, composed: true }))\n }\n private async save() {\n if (!this.session) return\n try {\n /*\n The card's picture is taken before the save starts, from a canvas of its own at the card's size —\n not from the one on screen, which stands wherever the author left it turned. A picture that cannot\n be taken is not an error: the save goes on without it (see `v3-thumbnail.ts`).\n */\n const view = this.session.read()\n const thumbnail = await captureV3Thumbnail(drawableV3Parts(view.geometry ?? []), view.palette ?? {})\n const promise = this.session.save({ thumbnail })\n this.changed()\n await promise\n this.error = ''\n } catch (error) {\n this.error = error instanceof Error ? error.message : String(error)\n } finally {\n this.changed()\n }\n }\n private add(kind: V3PrimitiveCreation['kind']) {\n if (!this.session) return\n this.run(() => {\n const ids = new Set(this.session!.read().geometry.map(g => g.id))\n let n = 1\n while (ids.has(`${kind}-${n}`)) n++\n const common = { id: `${kind}-${n}`, position: { x: 0, y: 50, z: 0 } }\n const part: V3PrimitiveCreation =\n kind === 'box'\n ? { ...common, kind, dimensions: { width: 100, height: 100, depth: 100 } }\n : kind === 'cylinder'\n ? { ...common, kind, dimensions: { radius: 50, length: 100 } }\n : kind === 'rounded-box'\n ? { ...common, kind, dimensions: { width: 100, height: 100, depth: 100, round: 10 } }\n : {\n ...common,\n position: { x: 0, y: 0, z: 0 },\n kind: 'portal',\n dimensions: {\n left: -100,\n right: 100,\n bottom: 0,\n top: 200,\n openingLeft: -70,\n openingRight: 70,\n openingTop: 170,\n depth: 30\n }\n }\n this.session!.add(part)\n this.selected = part.id\n })\n }\n /**\n * The list's own operations, as V3 part edits — each one step of the session's history. The copy and the moved\n * part stay selected, as they do in the V2 list.\n */\n private duplicatePart(id: string) {\n this.run(() => {\n const before = new Set(this.session!.read().geometry.map(g => g.id))\n this.session!.edit({ kind: 'duplicate-part', target: id })\n this.selected = this.session!.read().geometry.find(g => !before.has(g.id))?.id ?? id\n })\n }\n private movePart(id: string, to: number) {\n this.run(() => this.session!.edit({ kind: 'move-part', target: id, to }))\n }\n private removePart(id: string) {\n try {\n this.session!.edit({ kind: 'remove-part', target: id })\n this.error = ''\n if (this.selected === id) this.selected = ''\n this.changed()\n } catch (error) {\n /* The refusal a person meets most: another part stands on this one or follows its size. Said in their words. */\n this.error =\n (error as { code?: string })?.code === 'PART_REFERENCED'\n ? i18next.t('figure.text.part-is-referenced', { part: id })\n : error instanceof Error\n ? error.message\n : String(error)\n }\n }\n private toggleHiddenPart(id: string) {\n const next = new Set(this.hiddenParts)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n this.hiddenParts = next\n }\n /** What the gizmo may write for the selected part — read off the asset being edited. */\n private reachOf(id: string): GizmoReach {\n const none = { translate: false, rotate: false, scale: false }\n if (!id || !this.session) return none\n try {\n return gizmoReachOf(JSON.parse(this.session.source()), id)\n } catch {\n return none\n }\n }\n /** A drag, written back as the part's own inputs — one step of the history, like typing the numbers. */\n private transformed(id: string, result: GizmoResult) {\n const view = this.session!.read()\n const sizes = Object.fromEntries(view.fields.map(field => [field.id, field.value as number]))\n const changes = gizmoChanges(id, this.reachOf(id), result, sizes)\n if (changes.length) this.run(() => this.session!.apply(changes))\n else this.requestUpdate()\n }\n /** 맞추기 — one tool, one step of the history, through the same inputs as the gizmo. */\n private align(tool: AlignTool) {\n this.run(() => {\n const asset = JSON.parse(this.session!.source())\n const changes = alignChanges(asset, this.selected, this.reachOf(this.selected), tool)\n if (changes.length) this.session!.apply(changes)\n })\n }\n /** A mirrored copy: duplicate, then place the copy on the other side — two steps, as the V2 list makes it. */\n private mirror(axis: 'x' | 'z') {\n this.run(() => {\n const id = this.selected\n const before = new Set(this.session!.read().geometry.map(g => g.id))\n this.session!.edit({ kind: 'duplicate-part', target: id })\n const copy = this.session!.read().geometry.find(g => !before.has(g.id))?.id\n if (!copy) return\n this.session!.apply(mirrorChanges(JSON.parse(this.session!.source()), id, copy, axis))\n this.selected = copy\n })\n }\n private renderTools(unavailable: boolean) {\n const reach = this.reachOf(this.selected)\n if (!this.selected || !reach.translate) return null\n let asset: unknown\n try {\n asset = JSON.parse(this.session!.source())\n } catch {\n return null\n }\n const tool = (name: AlignTool, icon: string, label: string, title: string) =>\n html`<button ?disabled=${unavailable} aria-label=${i18next.t(label)} title=${i18next.t(title)} @click=${() => this.align(name)}>\n <md-icon>${icon}</md-icon>\n </button>`\n return html`<div tools title=${i18next.t('figure.text.tools-explained')}>\n ${tool('centre-x', 'horizontal_distribute', 'figure.button.center-x', 'figure.text.center-on-x')}\n ${tool('centre-z', 'vertical_align_center', 'figure.button.center-z', 'figure.text.center-on-z')}\n ${tool('floor', 'vertical_align_bottom', 'figure.button.to-floor', 'figure.text.put-on-floor')}\n ${(['x', 'z'] as const).map(axis => {\n const able = canMirror(asset as never, this.selected, axis, reach)\n return html`<button\n ?disabled=${unavailable || !able}\n aria-label=${i18next.t('figure.button.mirror-' + axis)}\n title=${i18next.t(able ? 'figure.text.mirror-explained' : 'figure.text.mirror-would-overlap')}\n @click=${() => this.mirror(axis)}\n >\n <md-icon>${axis === 'x' ? 'flip' : 'flip_camera_android'}</md-icon>\n </button>`\n })}\n ${tool('snap', 'grid_on', 'figure.button.snap', 'figure.text.snap-explained')}\n </div>`\n }\n /**\n * A part's name — the V2 part name field. It renames every value the part owns, and what refers to them follows\n * (figure-model's rename-part), as one step of the history.\n */\n private renamePart(input: HTMLInputElement) {\n const name = input.value.trim()\n const from = this.selected\n if (!name || name === from) {\n input.value = from\n return\n }\n try {\n this.session!.edit({ kind: 'rename-part', target: from, name })\n this.selected = name\n this.error = ''\n this.changed()\n } catch (error) {\n input.value = from\n const code = (error as { code?: string })?.code\n this.error =\n code === 'PART_ID'\n ? i18next.t(/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name) ? 'figure.text.part-name-taken' : 'figure.text.part-name-invalid', { name })\n : error instanceof Error\n ? error.message\n : String(error)\n }\n }\n /** Size response, fastening and motion for the selected part (parity ④ ⑤ ⑥), as authoring commands. */\n private renderLinks(unavailable: boolean) {\n let asset\n try {\n asset = JSON.parse(this.session!.source())\n } catch {\n return null\n }\n let dims: [number, number, number] | undefined\n try {\n dims = boxOf(asset, this.selected)?.dims\n } catch {\n dims = undefined\n }\n return html`<figure-v3-links\n .asset=${asset}\n .partId=${this.selected}\n .dims=${dims}\n ?locked=${unavailable}\n @v3-command=${(e: CustomEvent) => this.linkCommand(e.detail.action)}\n @v3-part-edit=${(e: CustomEvent) => this.run(() => this.session!.edit(e.detail.edit))}\n ></figure-v3-links>`\n }\n /** One command, one step of the history. A refusal a person can meet here is said in their words. */\n private linkCommand(action: V3AuthoringAction) {\n try {\n this.session!.command(action)\n this.error = ''\n this.changed()\n } catch (error) {\n const code = (error as { code?: string })?.code\n this.error =\n code === 'DIMENSION_CYCLE'\n ? i18next.t('figure.text.follow-would-loop')\n : code === 'FASTEN_CYCLE' || code === 'ATTACH_CYCLE'\n ? i18next.t('figure.text.fasten-would-loop')\n : error instanceof Error\n ? error.message\n : String(error)\n }\n }\n private changeField(field: { id: string; unit: V3InputChange['unit']; role?: string }, event: Event) {\n const input = event.target as HTMLInputElement,\n value = input.valueAsNumber\n this.run(() =>\n this.session!.apply([\n { kind: field.role === 'state' ? 'set-state' : 'set-design', input: field.id, unit: field.unit, value }\n ])\n )\n // Rejected edits must also restore the displayed numeric value.\n input.value = String(this.session!.read().fields.find(i => i.id === field.id)!.value)\n }\n render() {\n const view = this.session?.read()\n if (!view) return html`<p>모델을 여는 중입니다.</p>`\n const unavailable = view.loading || !!view.error || view.saving || !view.context\n const part = view.geometry.find(g => g.id === this.selected)\n // Shared/root parameters remain available even when a part is selected.\n const own = view.fields.filter(i => this.selected && i.id.startsWith(this.selected + '.'))\n const common = view.fields.filter(i => !view.geometry.some(g => i.id.startsWith(g.id + '.')))\n const fields = this.selected ? [...own, ...common] : view.fields\n return html` <header>\n <strong>V3 모델링</strong>\n <button ?disabled=${unavailable || !view.canUndo} @click=${() => this.run(() => this.session!.undo())}>\n 실행 취소\n </button>\n <button ?disabled=${unavailable || !view.canRedo} @click=${() => this.run(() => this.session!.redo())}>\n 다시 실행\n </button>\n <button @click=${() => this.renderRoot.querySelector<FigureV3Canvas>('figure-v3-canvas')?.fit()}>\n 전체 보기\n </button>\n <span class=\"status\" role=\"status\"\n >${view.loading ? '불러오는 중' : view.saving ? '저장 중' : view.dirty || !view.id ? '저장 안 됨' : '저장됨'}</span\n >\n <button ?disabled=${unavailable || (!view.dirty && !!view.id)} @click=${this.save}>저장</button>\n </header>\n ${this.error || view.error ? html`<div role=\"alert\" class=\"error\">${this.error || view.error}</div>` : null}\n <main>\n <figure-v3-parts\n .parts=${view.geometry.map(\n (g): V3PartRow => ({\n id: g.id,\n provider: (g as { shape?: { provider?: string } }).shape?.provider ?? '',\n hidden: this.hiddenParts.has(g.id),\n invisible: (g as { visible?: boolean }).visible === false\n })\n )}\n .selected=${this.selected}\n ?locked=${unavailable}\n @add-part=${(e: CustomEvent) => this.add(e.detail.kind)}\n @select-part=${(e: CustomEvent) => (this.selected = e.detail.id)}\n @toggle-part-hidden=${(e: CustomEvent) => this.toggleHiddenPart(e.detail.id)}\n @set-all-parts-hidden=${(e: CustomEvent) =>\n (this.hiddenParts = e.detail.hidden ? new Set(view.geometry.map(g => g.id)) : new Set())}\n @move-part-up=${(e: CustomEvent) => this.movePart(e.detail.id, e.detail.to)}\n @move-part-down=${(e: CustomEvent) => this.movePart(e.detail.id, e.detail.to)}\n @duplicate-part=${(e: CustomEvent) => this.duplicatePart(e.detail.id)}\n @remove-part=${(e: CustomEvent) => this.removePart(e.detail.id)}\n ></figure-v3-parts>\n <figure-v3-canvas\n .parts=${drawableV3Parts(view.geometry ?? []).filter(body => !this.hiddenParts.has((body as { id: string }).id))}\n .palette=${view.palette ?? {}}\n .context=${view.context ?? ''}\n .selected=${this.selected}\n .reach=${unavailable ? { translate: false, rotate: false, scale: false } : this.reachOf(this.selected)}\n @part-transformed=${(e: CustomEvent) => this.transformed(e.detail.id, e.detail.result)}\n @part-selected=${(e: CustomEvent<string>) => {\n this.selected = e.detail\n }}\n @render-error=${(e: CustomEvent<Error>) => {\n this.error = e.detail.message\n }}\n ></figure-v3-canvas>\n <aside>\n ${this.selected && part\n ? html`<label name-field\n ><span>${i18next.t('figure.label.name')}</span\n ><input\n aria-label=${i18next.t('figure.label.name')}\n .value=${this.selected}\n ?disabled=${unavailable}\n @change=${(e: Event) => this.renamePart(e.target as HTMLInputElement)}\n /></label>`\n : html`<h3>${this.selected || '모델 입력'}</h3>`}\n ${this.renderTools(unavailable)}\n ${fields.map(field => html`<label><span>${fieldLabel(field.id)} (${field.unit})${field.role === 'state' ? ' · 동작' : ''}</span><input aria-label=${field.id} type=\"number\" step=\"any\" .value=${String(field.value)} ?disabled=${unavailable} @change=${(e: Event) => this.changeField(field, e)} /></label>`)}\n ${\n part\n ? html`${this.renderLinks(unavailable)}<figure-v3-material\n .body=${part}\n .palette=${view.palette ?? {}}\n ?locked=${unavailable}\n @v3-part-edit=${(e: CustomEvent) => this.run(() => this.session!.edit(e.detail.edit))}\n ></figure-v3-material>`\n : null\n }\n ${\n view.bindings.length\n ? html`<h3>${i18next.t('figure.label.places')}</h3>\n ${view.bindings.map(b => html`<p>${b.label} · ${i18next.t('figure.label.place-' + b.role)}</p>`)}`\n : null\n }\n </aside>\n </main>`\n }\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { v3AttachmentsOf } from '@hatiolab/figure-model';
|
|
1
2
|
/** Shapes whose first three arguments are the extent along X, Y and Z. */
|
|
2
3
|
const BOXES = new Set(['box-shape@1', 'rounded-box@1']);
|
|
3
4
|
const AXES = ['x', 'y', 'z'];
|
|
@@ -8,7 +9,16 @@ export function gizmoReachOf(asset, part) {
|
|
|
8
9
|
const allDesign = (ids) => ids.every(id => design.has(id));
|
|
9
10
|
const pose = nodes.find(node => node.id === `${part}.pose`);
|
|
10
11
|
const placed = nodes.find(node => node.id === part && node.op === 'place@1');
|
|
11
|
-
const
|
|
12
|
+
const direct = !!pose && pose.op === 'rigid@1' && pose.params?.to === 'asset' && placed?.args[1] === `${part}.poseValue`;
|
|
13
|
+
/*
|
|
14
|
+
A part taken off another (detach) stands on a seat into the asset frame with its own position numbers back. It
|
|
15
|
+
can be moved like a part never fastened — unless it moves by itself, when where it is drawn is not its position.
|
|
16
|
+
*/
|
|
17
|
+
const reseated = !!pose &&
|
|
18
|
+
pose.op === 'rigid@1' &&
|
|
19
|
+
!nodes.some(node => node.id === `${part}.motion`) &&
|
|
20
|
+
v3AttachmentsOf(asset)[part] === null;
|
|
21
|
+
const posed = direct || reseated;
|
|
12
22
|
const shape = nodes.find(node => node.id === `${part}.shape`);
|
|
13
23
|
const extent = shape && BOXES.has(shape.op) ? shape.args.slice(0, 3) : [];
|
|
14
24
|
const sizes = extent.length === 3 && extent.every(id => id.startsWith(`${part}.`) && design.has(id)) ? extent : undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v3-gizmo.js","sourceRoot":"","sources":["../../client/modeller/v3-gizmo.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"v3-gizmo.js","sourceRoot":"","sources":["../../client/modeller/v3-gizmo.ts"],"names":[],"mappings":"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","sourcesContent":["import { v3AttachmentsOf } from '@hatiolab/figure-model'\nimport type { V3Asset, V3InputChange } from '@hatiolab/figure-model'\n\n/**\n * What the gizmo may write for a part — the V2 gizmo's move · turn · size, on a V3 asset (parity row ③).\n *\n * A drag can only be written back where the part is placed by its own numbers. A part the create commands made is:\n * its pose is `rigid@1` into the asset frame from `<part>.position.*` and `<part>.rotation.*`, and a box's shape\n * (`box-shape@1` or `rounded-box@1`) takes its width, height and depth from inputs of its own — `<part>.size.*` from\n * `addV3Box`, `<part>.dimension.*` from the editor's shape palette. A part fastened to another, following an instance size or made by the\n * converter from expressions has no such numbers; the gizmo does not offer what it could not write back, rather\n * than move something the next evaluation would put back.\n */\nexport interface GizmoReach {\n translate: boolean\n rotate: boolean\n scale: boolean\n /** The inputs sizing the part along X, Y and Z, when it can be sized. */\n sizes?: [string, string, string]\n}\n\n/** Shapes whose first three arguments are the extent along X, Y and Z. */\nconst BOXES = new Set(['box-shape@1', 'rounded-box@1'])\n\ninterface Node {\n id: string\n op: string\n args: string[]\n params?: Record<string, unknown>\n}\ninterface AssetLike {\n document: { model: { nodes: Node[]; inputs: Array<{ id: string; role?: string }> } }\n}\n\nconst AXES = ['x', 'y', 'z'] as const\n\nexport function gizmoReachOf(asset: AssetLike, part: string): GizmoReach {\n const { nodes, inputs } = asset.document.model\n const design = new Set(inputs.filter(input => input.role === 'design').map(input => input.id))\n const own = (name: string) => AXES.map(axis => `${part}.${name}.${axis}`)\n const allDesign = (ids: string[]) => ids.every(id => design.has(id))\n const pose = nodes.find(node => node.id === `${part}.pose`)\n const placed = nodes.find(node => node.id === part && node.op === 'place@1')\n const direct = !!pose && pose.op === 'rigid@1' && pose.params?.to === 'asset' && placed?.args[1] === `${part}.poseValue`\n /*\n A part taken off another (detach) stands on a seat into the asset frame with its own position numbers back. It\n can be moved like a part never fastened — unless it moves by itself, when where it is drawn is not its position.\n */\n const reseated =\n !!pose &&\n pose.op === 'rigid@1' &&\n !nodes.some(node => node.id === `${part}.motion`) &&\n v3AttachmentsOf(asset as unknown as V3Asset)[part] === null\n const posed = direct || reseated\n const shape = nodes.find(node => node.id === `${part}.shape`)\n const extent = shape && BOXES.has(shape.op) ? shape.args.slice(0, 3) : []\n const sizes =\n extent.length === 3 && extent.every(id => id.startsWith(`${part}.`) && design.has(id)) ? (extent as [string, string, string]) : undefined\n return {\n translate: posed && allDesign(own('position')) && own('position').every((id, i) => pose!.args[i] === id),\n rotate: posed && allDesign(own('rotation')) && own('rotation').every((id, i) => pose!.args[3 + i] === id),\n scale: !!sizes,\n ...(sizes ? { sizes } : {})\n }\n}\n\n/** Where a drag left the part, in the asset frame: millimetres, degrees and per-axis scale. */\nexport interface GizmoResult {\n position?: [number, number, number]\n rotation?: [number, number, number]\n scale?: [number, number, number]\n}\n\n/**\n * The input changes a drag makes — one list, applied as one step. Millimetres to the millimetre and degrees to a\n * tenth, as the V2 gizmo rounds (a drag otherwise stores 722.4180046035418 mm). A size never goes below 1 mm.\n */\nexport function gizmoChanges(part: string, reach: GizmoReach, result: GizmoResult, sizes: Record<string, number>): V3InputChange[] {\n const changes: V3InputChange[] = []\n const put = (input: string, unit: V3InputChange['unit'], value: number) =>\n changes.push({ kind: 'set-design', input, unit, value } as V3InputChange)\n if (result.position && reach.translate)\n AXES.forEach((axis, i) => put(`${part}.position.${axis}`, 'mm', Math.round(result.position![i]!)))\n if (result.rotation && reach.rotate)\n AXES.forEach((axis, i) => put(`${part}.rotation.${axis}`, 'deg', Math.round(result.rotation![i]! * 10) / 10))\n if (result.scale && reach.scale && reach.sizes)\n reach.sizes.forEach((id, i) => {\n if (sizes[id] !== undefined) put(id, 'mm', Math.max(1, Math.round(sizes[id]! * result.scale![i]!)))\n })\n return changes\n}\n"]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { V3Asset, V3BindingPlace, V3Face } from '@hatiolab/figure-model';
|
|
2
|
+
export type Axis = 'x' | 'y' | 'z';
|
|
3
|
+
export declare const AXES: readonly Axis[];
|
|
4
|
+
/** What one dimension of a part is worked out from. */
|
|
5
|
+
export type Follow = {
|
|
6
|
+
of: 'own';
|
|
7
|
+
} | {
|
|
8
|
+
of: 'instance';
|
|
9
|
+
axis: Axis;
|
|
10
|
+
} | {
|
|
11
|
+
of: 'part';
|
|
12
|
+
part: string;
|
|
13
|
+
axis: Axis;
|
|
14
|
+
} | {
|
|
15
|
+
of: 'input';
|
|
16
|
+
input: string;
|
|
17
|
+
}
|
|
18
|
+
/** Worked out some other way (the converter writes expressions) — shown, not offered as a choice. */
|
|
19
|
+
| {
|
|
20
|
+
of: 'expression';
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* `link-dimension` routes a part's dimension through `<part>.dimension.<axis>` and points its first argument at the
|
|
24
|
+
* source, directly or through the nodes that scale it. Walking back through those nodes finds the source: the
|
|
25
|
+
* instance size (`size.<axis>`), another part's dimension (`<part>.dimension.<axis>.value`) or a declared input.
|
|
26
|
+
*/
|
|
27
|
+
export declare function followOf(asset: V3Asset, part: string, axis: Axis): Follow;
|
|
28
|
+
/** Whether the asset declares an instance size on an axis — only then can a dimension follow it. */
|
|
29
|
+
export declare const hasInstanceSize: (asset: V3Asset, axis: Axis) => boolean;
|
|
30
|
+
/** The part this one is fastened to, or `null`. The mounting plane counts as fastened (the model names no part). */
|
|
31
|
+
export declare function fastenedTo(asset: V3Asset, part: string): string | null;
|
|
32
|
+
/** Whether a dimension of this part can follow something — box-shaped, whose three sizes are X, Y and Z. */
|
|
33
|
+
export declare function canFollow(asset: V3Asset, part: string): boolean;
|
|
34
|
+
/** Whether `attach` can take this part: a box, or a cylinder (figure-model measures its faces since 0.1.47). */
|
|
35
|
+
export declare function canFasten(asset: V3Asset, part: string): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* The axes on which the part's position is worked out from other values rather than being its own number — the
|
|
38
|
+
* converter writes V2's anchor rules that way. `fix-position` makes one its own number where it is now.
|
|
39
|
+
*/
|
|
40
|
+
export declare function positionsWorkedOut(asset: V3Asset, part: string): Axis[];
|
|
41
|
+
/** How a part moves, if it does: slide or turn, along which axis, driven by which control. */
|
|
42
|
+
export interface Motion {
|
|
43
|
+
kind: 'slide' | 'turn';
|
|
44
|
+
axis: Axis | '?';
|
|
45
|
+
control?: {
|
|
46
|
+
id: string;
|
|
47
|
+
unit?: string;
|
|
48
|
+
min?: number;
|
|
49
|
+
max?: number;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export declare function motionOf(asset: V3Asset, part: string): Motion | undefined;
|
|
53
|
+
/** The select's value for what a dimension follows now. */
|
|
54
|
+
export declare function choiceOf(follow: Follow): string;
|
|
55
|
+
/** The faces a place can sit on for this part: a box's six, a rounded box's top and bottom, none for a round body. */
|
|
56
|
+
export declare function placeFacesOf(asset: V3Asset, part: string): V3Face[];
|
|
57
|
+
/** The places things are held that sit on this part. */
|
|
58
|
+
export declare function placesOn(asset: V3Asset, part: string): V3BindingPlace[];
|
|
59
|
+
/** An id for a new place on this part, not yet taken: `<part>-<role>`, then `-2`, `-3`. */
|
|
60
|
+
export declare function placeIdFor(asset: V3Asset, part: string, role: 'seat' | 'grip'): string;
|
|
61
|
+
/**
|
|
62
|
+
* Whether a board will hand this figure anything: a place is a slot only on a figure that declares it holds things
|
|
63
|
+
* (`Capacity`, or `FlowNode`, which includes it). Without it the places are declared and nothing arrives.
|
|
64
|
+
*/
|
|
65
|
+
export declare const holdsThings: (asset: V3Asset) => boolean;
|
|
66
|
+
/** What `accepts` a person typed: names split on commas, trimmed, blanks and repeats dropped. */
|
|
67
|
+
export declare const acceptsOf: (typed: string) => string[];
|