@things-factory/figure-ui 10.1.26 → 10.1.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/client/graphql/index.ts +23 -0
  2. package/client/modeller/base-box.ts +104 -0
  3. package/client/modeller/figure-animations.ts +253 -32
  4. package/client/modeller/figure-canvas.ts +18 -3
  5. package/client/modeller/figure-inspector.ts +292 -3
  6. package/client/modeller/figure-preview.ts +57 -2
  7. package/client/modeller/figure-report.ts +9 -4
  8. package/client/modeller/figure-side.ts +9 -1
  9. package/client/modeller/figure-source.ts +24 -4
  10. package/client/modeller/figure-view.ts +20 -0
  11. package/client/modeller/joint-edits.ts +262 -0
  12. package/client/modeller/joint-gizmo.ts +118 -0
  13. package/client/modeller/pose-defaults.ts +67 -0
  14. package/client/modeller/proposal.ts +9 -3
  15. package/client/modeller/scene-budget.ts +31 -40
  16. package/client/pages/figure-list-page.ts +4 -9
  17. package/client/pages/figure-modeller-page.ts +124 -41
  18. package/dist-client/graphql/index.d.ts +7 -0
  19. package/dist-client/graphql/index.js +21 -0
  20. package/dist-client/graphql/index.js.map +1 -1
  21. package/dist-client/modeller/base-box.d.ts +47 -0
  22. package/dist-client/modeller/base-box.js +52 -0
  23. package/dist-client/modeller/base-box.js.map +1 -0
  24. package/dist-client/modeller/figure-animations.d.ts +29 -0
  25. package/dist-client/modeller/figure-animations.js +228 -25
  26. package/dist-client/modeller/figure-animations.js.map +1 -1
  27. package/dist-client/modeller/figure-canvas.d.ts +9 -0
  28. package/dist-client/modeller/figure-canvas.js +14 -3
  29. package/dist-client/modeller/figure-canvas.js.map +1 -1
  30. package/dist-client/modeller/figure-inspector.d.ts +37 -0
  31. package/dist-client/modeller/figure-inspector.js +253 -2
  32. package/dist-client/modeller/figure-inspector.js.map +1 -1
  33. package/dist-client/modeller/figure-preview.d.ts +15 -0
  34. package/dist-client/modeller/figure-preview.js +48 -2
  35. package/dist-client/modeller/figure-preview.js.map +1 -1
  36. package/dist-client/modeller/figure-report.d.ts +3 -2
  37. package/dist-client/modeller/figure-report.js +9 -4
  38. package/dist-client/modeller/figure-report.js.map +1 -1
  39. package/dist-client/modeller/figure-side.d.ts +5 -1
  40. package/dist-client/modeller/figure-side.js +12 -0
  41. package/dist-client/modeller/figure-side.js.map +1 -1
  42. package/dist-client/modeller/figure-source.d.ts +15 -0
  43. package/dist-client/modeller/figure-source.js +8 -4
  44. package/dist-client/modeller/figure-source.js.map +1 -1
  45. package/dist-client/modeller/figure-view.d.ts +16 -0
  46. package/dist-client/modeller/figure-view.js +15 -0
  47. package/dist-client/modeller/figure-view.js.map +1 -1
  48. package/dist-client/modeller/joint-edits.d.ts +49 -0
  49. package/dist-client/modeller/joint-edits.js +223 -0
  50. package/dist-client/modeller/joint-edits.js.map +1 -0
  51. package/dist-client/modeller/joint-gizmo.d.ts +31 -0
  52. package/dist-client/modeller/joint-gizmo.js +104 -0
  53. package/dist-client/modeller/joint-gizmo.js.map +1 -0
  54. package/dist-client/modeller/pose-defaults.d.ts +9 -0
  55. package/dist-client/modeller/pose-defaults.js +35 -0
  56. package/dist-client/modeller/pose-defaults.js.map +1 -0
  57. package/dist-client/modeller/proposal.d.ts +1 -1
  58. package/dist-client/modeller/proposal.js +8 -3
  59. package/dist-client/modeller/proposal.js.map +1 -1
  60. package/dist-client/modeller/scene-budget.d.ts +31 -34
  61. package/dist-client/modeller/scene-budget.js +28 -37
  62. package/dist-client/modeller/scene-budget.js.map +1 -1
  63. package/dist-client/pages/figure-list-page.js +4 -9
  64. package/dist-client/pages/figure-list-page.js.map +1 -1
  65. package/dist-client/pages/figure-modeller-page.d.ts +43 -0
  66. package/dist-client/pages/figure-modeller-page.js +121 -40
  67. package/dist-client/pages/figure-modeller-page.js.map +1 -1
  68. package/dist-client/tsconfig.tsbuildinfo +1 -1
  69. package/dist-server/tsconfig.tsbuildinfo +1 -1
  70. package/package.json +3 -3
  71. package/test/ai-proposal-contract.test.ts +16 -11
  72. package/test/base-box.test.ts +154 -0
  73. package/test/figure-source.test.ts +32 -0
  74. package/test/joint-edits.test.ts +165 -0
  75. package/test/joint-gizmo.test.ts +174 -0
  76. package/test/pose-defaults.test.ts +71 -0
  77. package/test/preview-board-depth.test.ts +27 -0
  78. package/test/scene-budget.test.ts +53 -0
  79. package/translations/en.json +37 -2
  80. package/translations/ja.json +37 -2
  81. package/translations/ko.json +37 -2
  82. package/translations/ms.json +37 -2
  83. package/translations/zh.json +37 -2
@@ -5,6 +5,10 @@ import { live } from 'lit/directives/live.js';
5
5
  import { i18next, localize } from '@operato/i18n';
6
6
  import { ScrollbarStyles } from '@operato/styles';
7
7
  import { AXES, CHANNEL_PATHS, INTERPOLATIONS, LIMITS } from '@hatiolab/figure-model';
8
+ /** A channel that drives a joint names the joint and carries one number per key (ADR-0066). */
9
+ function isJointChannel(channel) {
10
+ return channel.path === undefined;
11
+ }
8
12
  /*
9
13
  레시피의 `end` 가 곧 그 범위의 끝 자세다 — 리프트가 100mm 올라가는 곡선이면 범위도
10
14
  0~100mm 다. 둘이 어긋나면 저작자가 1200 을 주고도 100 만 올라가는 것을 보게 된다.
@@ -65,6 +69,16 @@ function freeName(taken, stem) {
65
69
  if (!used.has(`${stem}-${n}`))
66
70
  return `${stem}-${n}`;
67
71
  }
72
+ /**
73
+ * 파라미터 범위에 적히는 단위 — **권하는 것이지 가두는 것이 아니다.**
74
+ *
75
+ * 관절이 만드는 파라미터가 `deg` 와 `mm` 을 쓰고(회전과 직선), 그리퍼·문 같은 값은 `%` 를 쓴다.
76
+ * 속도는 `mm/s` 와 `rpm`, 시간은 `s` 다. 이 여섯이 지금 쓰이는 전부이고, 목록에 없는 말을 적는
77
+ * 길은 그대로 열려 있다.
78
+ */
79
+ const PARAMETER_UNITS = ['deg', 'mm', '%', 'mm/s', 'rpm', 's'];
80
+ /** 목록 대신 손으로 적겠다는 표. `select` 의 값으로 쓴다. */
81
+ const UNIT_TYPE_IT = '__type-it';
68
82
  let FigureAnimations = class FigureAnimations extends localize(i18next)(LitElement) {
69
83
  constructor() {
70
84
  super(...arguments);
@@ -76,6 +90,8 @@ let FigureAnimations = class FigureAnimations extends localize(i18next)(LitEleme
76
90
  */
77
91
  this.open = '';
78
92
  this.recipeTarget = '';
93
+ /** 단위를 손으로 적는 중인 파라미터. 목록에 없는 말을 적으려고 연 칸이다. */
94
+ this.typingUnit = new Set();
79
95
  }
80
96
  static { this.styles = [
81
97
  ScrollbarStyles,
@@ -170,6 +186,21 @@ let FigureAnimations = class FigureAnimations extends localize(i18next)(LitEleme
170
186
  min-width: 3.2em;
171
187
  color: var(--md-sys-color-on-surface-variant);
172
188
  }
189
+ /*
190
+ 칸이 줄어들 줄 알아야 한다. 숫자 입력칸은 제 기본 너비(20자 남짓)를 갖고 있고 flex 는
191
+ 기본 크기 아래로는 안 줄이므로, 범위처럼 한 줄에 셋이 서는 줄은 패널 밖으로 밀려
192
+ 오른쪽 칸이 잘렸다.
193
+ */
194
+ div[row] > input {
195
+ flex: 1 1 0;
196
+ min-width: 0;
197
+ }
198
+ /* 단위는 「mm」 정도의 짧은 말이라 숫자 칸보다 좁게 둔다. 고르는 칸도 같은 폭이다. */
199
+ div[row] > input[unit],
200
+ div[row] > select[unit] {
201
+ flex: 0 1 5.5em;
202
+ min-width: 0;
203
+ }
173
204
 
174
205
  /* ── keyframe ─────────────────────────────────────────────────── */
175
206
 
@@ -291,6 +322,10 @@ let FigureAnimations = class FigureAnimations extends localize(i18next)(LitEleme
291
322
  get partNames() {
292
323
  return this.parts.map(part => part.name).filter(name => !!name);
293
324
  }
325
+ /** Joints a channel can drive instead of a part (ADR-0066). */
326
+ get joints() {
327
+ return this.draft?.joints ?? [];
328
+ }
294
329
  /**
295
330
  * 몇 부품이 움직이나 — 채널이 가리키는 **서로 다른 부품**의 수.
296
331
  *
@@ -460,14 +495,7 @@ let FigureAnimations = class FigureAnimations extends localize(i18next)(LitEleme
460
495
  aria-label="max"
461
496
  @change=${(e) => this.setRange(at, { max: Number(e.target.value) || 0 })}
462
497
  />
463
- <input
464
- unit
465
- .value=${live(range.unit ?? '')}
466
- placeholder="mm"
467
- aria-label="unit"
468
- title=${i18next.t('figure.text.unit-is-a-word-not-a-rule')}
469
- @change=${(e) => this.setRange(at, { unit: e.target.value.trim() })}
470
- />
498
+ ${this.renderUnit(at, range.unit ?? '')}
471
499
  </div>
472
500
  ${backwards ? html `<p warn>${i18next.t('figure.text.range-needs-room')}</p>` : nothing}
473
501
 
@@ -520,23 +548,45 @@ let FigureAnimations = class FigureAnimations extends localize(i18next)(LitEleme
520
548
  * 검증은 저장할 때 말하고 여기서는 **그 자리에서** 보여 준다.
521
549
  */
522
550
  renderChannel(kind, channel, at, j) {
523
- const orphan = !this.partNames.includes(channel.target);
551
+ const joint = this.joints.find(one => one.name === channel.target);
552
+ const orphan = !this.partNames.includes(channel.target) && !joint;
553
+ const target = html `
554
+ <div row>
555
+ <label>${i18next.t('figure.label.channel-target')}</label>
556
+ <select
557
+ .value=${live(channel.target ?? '')}
558
+ @change=${(e) => this.retarget(kind, at, j, e.target.value)}
559
+ >
560
+ ${orphan ? html `<option value=${channel.target}>${channel.target}</option>` : nothing}
561
+ <optgroup label=${i18next.t('figure.label.channel-target-parts')}>
562
+ ${this.partNames.map(name => html `<option value=${name}>${name}</option>`)}
563
+ </optgroup>
564
+ ${this.joints.length > 0
565
+ ? html `<optgroup label=${i18next.t('figure.label.channel-target-joints')}>
566
+ ${this.joints.map(one => html `<option value=${one.name}>${one.name}</option>`)}
567
+ </optgroup>`
568
+ : nothing}
569
+ </select>
570
+ <button plain @click=${() => this.removeChannel(kind, at, j)} title=${i18next.t('figure.button.remove')}>
571
+ <md-icon>close</md-icon>
572
+ </button>
573
+ </div>
574
+ `;
575
+ /* A joint channel has no path or pivot: the joint says what moves. Each key is the joint coordinate. */
576
+ if (isJointChannel(channel)) {
577
+ const unit = joint?.type === 'prismatic' ? 'mm' : 'deg';
578
+ return html `
579
+ <div channel ?orphan=${orphan}>
580
+ ${target} ${orphan ? html `<p warn>${i18next.t('figure.text.channel-target-is-gone')}</p>` : nothing}
581
+ <p quiet>${i18next.t('figure.text.joint-channel-value-' + unit)}</p>
582
+ ${this.renderJointKeys(kind, channel, at, j, joint?.limits)}
583
+ </div>
584
+ `;
585
+ }
524
586
  const turning = channel.path === 'rotation';
525
587
  return html `
526
588
  <div channel ?orphan=${orphan}>
527
- <div row>
528
- <label>${i18next.t('figure.label.channel-target')}</label>
529
- <select
530
- .value=${live(channel.target ?? '')}
531
- @change=${(e) => this.setChannel(kind, at, j, { target: e.target.value })}
532
- >
533
- ${orphan ? html `<option value=${channel.target}>${channel.target}</option>` : nothing}
534
- ${this.partNames.map(name => html `<option value=${name}>${name}</option>`)}
535
- </select>
536
- <button plain @click=${() => this.removeChannel(kind, at, j)} title=${i18next.t('figure.button.remove')}>
537
- <md-icon>close</md-icon>
538
- </button>
539
- </div>
589
+ ${target}
540
590
 
541
591
  ${orphan ? html `<p warn>${i18next.t('figure.text.channel-target-is-gone')}</p>` : nothing}
542
592
 
@@ -607,6 +657,66 @@ let FigureAnimations = class FigureAnimations extends localize(i18next)(LitEleme
607
657
  * 시각이 오름차순이어야 하는 것도 형식의 규칙이다. 여기서는 어긋난 줄을 붉게 내고 값을
608
658
  * 고치지는 않는다 — 저작자가 3 을 1 로 고치던 중일 수 있다.
609
659
  */
660
+ /**
661
+ * Keys of a joint channel: a position and one joint coordinate each. A value outside the joint's limits
662
+ * is marked and left as typed; the format refuses it on save.
663
+ */
664
+ renderJointKeys(kind, channel, at, j, limits) {
665
+ const keys = channel.keys ?? [];
666
+ const onValues = kind === 'parameter';
667
+ const beyond = (key) => !!limits && (key.value < limits.min || key.value > limits.max);
668
+ return html `
669
+ <table keys>
670
+ <tr>
671
+ <th>${i18next.t(onValues ? 'figure.label.key-at-value' : 'figure.label.key-at')}</th>
672
+ <th>${i18next.t('figure.label.joint-value')}</th>
673
+ <th></th>
674
+ </tr>
675
+ ${keys.map((key, k) => {
676
+ const backwards = k > 0 && key.at <= (keys[k - 1].at ?? 0);
677
+ return html `
678
+ <tr>
679
+ <td>
680
+ <input
681
+ type="number"
682
+ step=${onValues ? '0.05' : '0.1'}
683
+ min="0"
684
+ max=${onValues ? '1' : nothing}
685
+ ?bad=${backwards || key.at < 0 || (onValues && key.at > 1)}
686
+ .value=${live(String(key.at))}
687
+ @change=${(e) => this.setJointKey(kind, at, j, k, { at: Math.max(0, Number(e.target.value) || 0) })}
688
+ />
689
+ </td>
690
+ <td>
691
+ <input
692
+ type="number"
693
+ step="1"
694
+ ?bad=${beyond(key)}
695
+ .value=${live(String(key.value))}
696
+ title=${beyond(key) ? i18next.t('figure.text.joint-value-beyond-limits') : ''}
697
+ @change=${(e) => this.setJointKey(kind, at, j, k, { value: Number(e.target.value) || 0 })}
698
+ />
699
+ </td>
700
+ <td drop>
701
+ <button
702
+ plain
703
+ ?disabled=${keys.length <= 2}
704
+ title=${keys.length <= 2 ? i18next.t('figure.text.two-keys-at-least') : i18next.t('figure.button.remove')}
705
+ @click=${() => this.removeKey(kind, at, j, k)}
706
+ >
707
+ <md-icon>close</md-icon>
708
+ </button>
709
+ </td>
710
+ </tr>
711
+ `;
712
+ })}
713
+ </table>
714
+ ${keys.some(beyond) ? html `<p warn>${i18next.t('figure.text.joint-value-beyond-limits')}</p>` : nothing}
715
+ <button @click=${() => this.addKey(kind, at, j)}>
716
+ <md-icon>add</md-icon>${i18next.t('figure.button.add-key')}
717
+ </button>
718
+ `;
719
+ }
610
720
  renderKeys(kind, channel, at, j) {
611
721
  const keys = channel.keys ?? [];
612
722
  /*
@@ -797,6 +907,51 @@ let FigureAnimations = class FigureAnimations extends localize(i18next)(LitEleme
797
907
  renameParameter(at, name) {
798
908
  this.patchParameter(at, { name: name.trim() });
799
909
  }
910
+ /**
911
+ * 단위 칸 — **목록이 보이는 채로, 적는 길도 열어 둔다.**
912
+ *
913
+ * 처음에는 `datalist` 를 붙였다. 그것은 브라우저가 쥐고 있는 기능이라 **눌러 보기 전에는 목록이
914
+ * 있는지조차 안 보인다** — 화살표도 없고, 어디에 어떻게 뜨는지도 브라우저가 정한다. 고를 수
915
+ * 있다는 것을 알리는 것이 이 칸의 목적이므로 `select` 로 바꿨다.
916
+ *
917
+ * 형식은 단위를 규칙으로 쓰지 않으므로(표시용 말이다) 목록에 가두지 않는다. 마지막 줄이
918
+ * 「직접 적기」이고, 목록에 없는 말이 이미 적혀 있으면 처음부터 적는 칸으로 연다.
919
+ */
920
+ renderUnit(at, unit) {
921
+ const listed = PARAMETER_UNITS.includes(unit);
922
+ const typing = this.typingUnit.has(at) || (unit !== '' && !listed);
923
+ if (typing) {
924
+ return html `<input
925
+ unit
926
+ .value=${live(unit)}
927
+ placeholder="mm"
928
+ aria-label="unit"
929
+ title=${i18next.t('figure.text.unit-is-a-word-not-a-rule')}
930
+ @change=${(e) => this.setRange(at, { unit: e.target.value.trim() })}
931
+ />`;
932
+ }
933
+ return html `<select
934
+ unit
935
+ aria-label="unit"
936
+ title=${i18next.t('figure.text.unit-is-a-word-not-a-rule')}
937
+ @change=${(e) => this.chooseUnit(at, e.target.value)}
938
+ >
939
+ <option value="" ?selected=${unit === ''}>${i18next.t('figure.label.unit-none')}</option>
940
+ ${PARAMETER_UNITS.map(one => html `<option value=${one} ?selected=${one === unit}>${one}</option>`)}
941
+ <option value=${UNIT_TYPE_IT}>${i18next.t('figure.label.unit-type-it')}</option>
942
+ </select>`;
943
+ }
944
+ /** 고른 것을 넣는다. 「직접 적기」는 값이 아니라 **칸을 바꾸는 것**이다. */
945
+ chooseUnit(at, value) {
946
+ if (value === UNIT_TYPE_IT) {
947
+ this.typingUnit = new Set([...this.typingUnit, at]);
948
+ return;
949
+ }
950
+ const next = new Set(this.typingUnit);
951
+ next.delete(at);
952
+ this.typingUnit = next;
953
+ this.setRange(at, { unit: value });
954
+ }
800
955
  setRange(at, patch) {
801
956
  const parameter = this.parameters[at];
802
957
  if (!parameter)
@@ -836,10 +991,36 @@ let FigureAnimations = class FigureAnimations extends localize(i18next)(LitEleme
836
991
  { target, path: 'translation', keys: keysFor('translation') }
837
992
  ]);
838
993
  }
839
- setChannel(kind, at, j, patch) {
994
+ /**
995
+ * Points a channel at another part or joint. Crossing between the two changes the channel's shape: a
996
+ * joint channel has no path and one number per key, a part channel a path and a vector. The key positions
997
+ * are kept, since they are the author's timing; values restart at the rest pose.
998
+ */
999
+ retarget(kind, at, j, target) {
840
1000
  const channel = this.channelsOf(kind, at)[j];
841
1001
  if (!channel)
842
1002
  return;
1003
+ const toJoint = this.joints.some(one => one.name === target);
1004
+ if (toJoint && !isJointChannel(channel)) {
1005
+ const next = { target, keys: channel.keys.map(key => ({ at: key.at, value: 0 })) };
1006
+ if (channel.interpolation !== undefined)
1007
+ next.interpolation = channel.interpolation;
1008
+ this.patchChannel(kind, at, j, next);
1009
+ return;
1010
+ }
1011
+ if (!toJoint && isJointChannel(channel)) {
1012
+ const next = { target, path: 'translation', keys: channel.keys.map(key => ({ at: key.at, value: startValue('translation') })) };
1013
+ if (channel.interpolation !== undefined)
1014
+ next.interpolation = channel.interpolation;
1015
+ this.patchChannel(kind, at, j, next);
1016
+ return;
1017
+ }
1018
+ this.patchChannel(kind, at, j, { ...channel, target });
1019
+ }
1020
+ setChannel(kind, at, j, patch) {
1021
+ const channel = this.channelsOf(kind, at)[j];
1022
+ if (!channel || isJointChannel(channel))
1023
+ return;
843
1024
  const next = { ...channel, ...patch };
844
1025
  /* `undefined` 를 얹는 것은 지우는 뜻이다. 남겨 두면 저장 형식에 빈 칸이 실린다. */
845
1026
  if ('pivot' in patch && patch.pivot === undefined)
@@ -855,7 +1036,7 @@ let FigureAnimations = class FigureAnimations extends localize(i18next)(LitEleme
855
1036
  */
856
1037
  setPath(kind, at, j, path) {
857
1038
  const channel = this.channelsOf(kind, at)[j];
858
- if (!channel)
1039
+ if (!channel || isJointChannel(channel))
859
1040
  return;
860
1041
  const crossing = (channel.path === 'scale') !== (path === 'scale');
861
1042
  const next = {
@@ -876,6 +1057,18 @@ let FigureAnimations = class FigureAnimations extends localize(i18next)(LitEleme
876
1057
  const channel = this.channelsOf(kind, at)[j];
877
1058
  if (!channel)
878
1059
  return;
1060
+ if (isJointChannel(channel)) {
1061
+ const keys = channel.keys;
1062
+ const end = keys[keys.length - 1];
1063
+ if (kind === 'parameter' && keys.length >= 2) {
1064
+ const before = keys[keys.length - 2];
1065
+ const middle = { at: (before.at + end.at) / 2, value: before.value };
1066
+ this.patchChannel(kind, at, j, { ...channel, keys: [...keys.slice(0, -1), middle, end] });
1067
+ return;
1068
+ }
1069
+ this.patchChannel(kind, at, j, { ...channel, keys: [...keys, { at: (end?.at ?? 0) + 1, value: end?.value ?? 0 }] });
1070
+ return;
1071
+ }
879
1072
  const last = channel.keys[channel.keys.length - 1];
880
1073
  /*
881
1074
  A parameter curve ends at 1, so appending a key would make it unreachable. Insert it between the last two keys.
@@ -889,9 +1082,15 @@ let FigureAnimations = class FigureAnimations extends localize(i18next)(LitEleme
889
1082
  const key = { at: (last?.at ?? 0) + 1, value: { ...(last?.value ?? startValue(channel.path)) } };
890
1083
  this.patchChannel(kind, at, j, { ...channel, keys: [...channel.keys, key] });
891
1084
  }
1085
+ setJointKey(kind, at, j, k, patch) {
1086
+ const channel = this.channelsOf(kind, at)[j];
1087
+ if (!channel || !isJointChannel(channel))
1088
+ return;
1089
+ this.patchChannel(kind, at, j, { ...channel, keys: channel.keys.map((key, i) => (i === k ? { ...key, ...patch } : key)) });
1090
+ }
892
1091
  setKey(kind, at, j, k, patch) {
893
1092
  const channel = this.channelsOf(kind, at)[j];
894
- if (!channel)
1093
+ if (!channel || isJointChannel(channel))
895
1094
  return;
896
1095
  this.patchChannel(kind, at, j, {
897
1096
  ...channel,
@@ -922,6 +1121,10 @@ __decorate([
922
1121
  state(),
923
1122
  __metadata("design:type", Object)
924
1123
  ], FigureAnimations.prototype, "recipeTarget", void 0);
1124
+ __decorate([
1125
+ state(),
1126
+ __metadata("design:type", Object)
1127
+ ], FigureAnimations.prototype, "typingUnit", void 0);
925
1128
  FigureAnimations = __decorate([
926
1129
  customElement('figure-animations')
927
1130
  ], FigureAnimations);