jupiter-dynamic-forms 1.20.0 → 1.20.2

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/dist/index.mjs CHANGED
@@ -683,6 +683,7 @@ class XBRLFormBuilder {
683
683
  var _a, _b;
684
684
  const label = this.getPreferredLabel(concept.labels, language, concept.preferredLabel);
685
685
  const childPeriodHint = ((_a = concept.preferredLabel) == null ? void 0 : _a.includes("periodStartLabel")) ? "start" : ((_b = concept.preferredLabel) == null ? void 0 : _b.includes("periodEndLabel")) ? "end" : ancestorPeriodHint;
686
+ const effectivePeriodRole = childPeriodHint === "start" ? "periodStartLabel" : childPeriodHint === "end" ? "periodEndLabel" : void 0;
686
687
  const fields = [];
687
688
  if (!concept.elementAbstract) {
688
689
  let columnIds = [];
@@ -751,8 +752,10 @@ class XBRLFormBuilder {
751
752
  periodType: concept.periodType,
752
753
  balance: concept.balance,
753
754
  // Pass through balance attribute from XBRL data
754
- preferredLabel: concept.preferredLabel
755
+ preferredLabel: concept.preferredLabel,
755
756
  // Pass through for period date calculation in manual columns
757
+ effectivePeriodRole
758
+ // JDF-039: own-or-inherited periodStartLabel/periodEndLabel role
756
759
  };
757
760
  }
758
761
  /**
@@ -6151,6 +6154,7 @@ let JupiterFormSection = class extends LitElement {
6151
6154
  this.periodStartDate = "";
6152
6155
  this.periodEndDate = "";
6153
6156
  this.language = "en";
6157
+ this.calculationEnabled = false;
6154
6158
  this._expanded = true;
6155
6159
  this._showAddColumnDialog = false;
6156
6160
  this._sectionPeriodType = "duration";
@@ -6159,7 +6163,7 @@ let JupiterFormSection = class extends LitElement {
6159
6163
  this._boundFieldBlur = (e2) => {
6160
6164
  this._clearHighlights();
6161
6165
  this._focusedConceptId = null;
6162
- if (this.mode === "readonly")
6166
+ if (this.mode === "readonly" || !this.calculationEnabled)
6163
6167
  return;
6164
6168
  const detail = e2.detail;
6165
6169
  if ((detail == null ? void 0 : detail.conceptId) && (detail == null ? void 0 : detail.columnId)) {
@@ -6195,8 +6199,12 @@ let JupiterFormSection = class extends LitElement {
6195
6199
  if (changedProperties.has("isFirstSection") || changedProperties.has("section")) {
6196
6200
  this._checkAndExpandFirstSection();
6197
6201
  }
6198
- if (changedProperties.has("section") && ((_a = this.section) == null ? void 0 : _a.concepts)) {
6199
- this._buildTotalMaps(this.section.concepts);
6202
+ if (changedProperties.has("section") || changedProperties.has("calculationEnabled")) {
6203
+ if (this.calculationEnabled && ((_a = this.section) == null ? void 0 : _a.concepts)) {
6204
+ this._buildTotalMaps(this.section.concepts);
6205
+ } else {
6206
+ this._clearCalculationState();
6207
+ }
6200
6208
  }
6201
6209
  }
6202
6210
  _checkAndExpandFirstSection() {
@@ -6432,6 +6440,21 @@ let JupiterFormSection = class extends LitElement {
6432
6440
  this._totalChildConceptsMap.clear();
6433
6441
  this._traverseTotalGroups(concepts);
6434
6442
  }
6443
+ /**
6444
+ * JDF-041: drops all calculation-warning state — used when the feature is disabled/toggled off.
6445
+ * Clears each existing mismatch through `_clearCalculationMismatch` (rather than resetting the
6446
+ * map directly) so the parent's validation summary, which tracks mismatches via the dispatched
6447
+ * `calculation-mismatch-changed` events, is told about each removal instead of being left stale.
6448
+ */
6449
+ _clearCalculationState() {
6450
+ this._totalChildrenMap.clear();
6451
+ this._memberParentMap.clear();
6452
+ this._totalConceptMap.clear();
6453
+ this._totalChildConceptsMap.clear();
6454
+ for (const key of Array.from(this._calculationMismatches.keys())) {
6455
+ this._clearCalculationMismatch(key);
6456
+ }
6457
+ }
6435
6458
  /**
6436
6459
  * JDF-038: XBRL uses more than one preferredLabel role to mark a "total" row — the plain
6437
6460
  * `.../role/totalLabel` and the sign-flipped `.../role/negatedTotalLabel` (used for subtotals of
@@ -6442,6 +6465,15 @@ let JupiterFormSection = class extends LitElement {
6442
6465
  static _isTotalLabel(preferredLabel) {
6443
6466
  return !!(preferredLabel == null ? void 0 : preferredLabel.toLowerCase().includes("totallabel"));
6444
6467
  }
6468
+ /**
6469
+ * JDF-041: distinguishes a self-contained "deduction block" subtotal (negatedTotalLabel, e.g.
6470
+ * "Total of sum of expenses") from a plain cascading/running total. Only the latter is treated as
6471
+ * additively built on the total before it — a negatedTotalLabel row summarizes just the raw items
6472
+ * directly before it and must not also absorb an unrelated earlier total into its own check.
6473
+ */
6474
+ static _isNegatedTotalLabel(preferredLabel) {
6475
+ return !!(preferredLabel == null ? void 0 : preferredLabel.toLowerCase().includes("negatedtotallabel"));
6476
+ }
6445
6477
  /**
6446
6478
  * A member of a total's sibling/child group can itself be a presentation-only abstract wrapper
6447
6479
  * (e.g. "Group equity" wrapping Equity + Third party share + "Total of group equity") rather than
@@ -6472,6 +6504,47 @@ let JupiterFormSection = class extends LitElement {
6472
6504
  this._memberParentMap.set(memberId, totalConcept.id);
6473
6505
  }
6474
6506
  }
6507
+ /**
6508
+ * JDF-041: computes the JDF-030 sibling-fallback member set for a total at `concepts[i]`, given the
6509
+ * nearest preceding total's index (`lastTotalIdx`, -1 if none) and the raw siblings between them.
6510
+ *
6511
+ * - No preceding total → members are just the raw siblings (unchanged, e.g. the very first total
6512
+ * in the role).
6513
+ * - This total is itself a negatedTotalLabel (a self-contained deduction-block subtotal, e.g.
6514
+ * "Total of sum of expenses") → the preceding total stays a scan boundary only, never a member —
6515
+ * it summarizes just its own raw siblings, same as before JDF-041.
6516
+ * - Otherwise (a plain totalLabel, cascading/running total) with raw siblings before it → the
6517
+ * preceding total is included as a real member alongside them, since this total is built
6518
+ * additively on top of it.
6519
+ * - Otherwise (a plain totalLabel adjacent to the preceding total, zero raw siblings between them):
6520
+ * if that preceding total is itself a negatedTotalLabel subtotal, it doesn't carry the running
6521
+ * total from before it forward (per the rule above) — reach one more hop back to also include the
6522
+ * total the subtotal was deducted from (e.g. "Net operating result" needs both "Gross operating
6523
+ * result" and "Total of sum of expenses", not just the latter). Otherwise, the single preceding
6524
+ * total is the member, as it was for JDF-038's original adjacent-boundary case.
6525
+ */
6526
+ _resolveTotalGroupMembers(concepts, i2, lastTotalIdx, siblings) {
6527
+ if (lastTotalIdx < 0)
6528
+ return siblings;
6529
+ const concept = concepts[i2];
6530
+ if (JupiterFormSection._isNegatedTotalLabel(concept.preferredLabel)) {
6531
+ return siblings.length > 0 ? siblings : [concepts[lastTotalIdx]];
6532
+ }
6533
+ if (siblings.length > 0) {
6534
+ return [concepts[lastTotalIdx], ...siblings];
6535
+ }
6536
+ if (JupiterFormSection._isNegatedTotalLabel(concepts[lastTotalIdx].preferredLabel)) {
6537
+ let grandTotalIdx = -1;
6538
+ for (let k = lastTotalIdx - 1; k >= 0; k--) {
6539
+ if (JupiterFormSection._isTotalLabel(concepts[k].preferredLabel)) {
6540
+ grandTotalIdx = k;
6541
+ break;
6542
+ }
6543
+ }
6544
+ return grandTotalIdx >= 0 ? [concepts[grandTotalIdx], concepts[lastTotalIdx]] : [concepts[lastTotalIdx]];
6545
+ }
6546
+ return [concepts[lastTotalIdx]];
6547
+ }
6475
6548
  _traverseTotalGroups(concepts) {
6476
6549
  var _a, _b;
6477
6550
  for (let i2 = 0; i2 < concepts.length; i2++) {
@@ -6488,10 +6561,9 @@ let JupiterFormSection = class extends LitElement {
6488
6561
  }
6489
6562
  }
6490
6563
  const siblings = concepts.slice(lastTotalIdx + 1, i2);
6491
- if (siblings.length > 0) {
6492
- this._registerTotalGroup(concept, siblings);
6493
- } else if (lastTotalIdx >= 0) {
6494
- this._registerTotalGroup(concept, [concepts[lastTotalIdx]]);
6564
+ const members = this._resolveTotalGroupMembers(concepts, i2, lastTotalIdx, siblings);
6565
+ if (members.length > 0) {
6566
+ this._registerTotalGroup(concept, members);
6495
6567
  }
6496
6568
  }
6497
6569
  }
@@ -6526,7 +6598,7 @@ let JupiterFormSection = class extends LitElement {
6526
6598
  return;
6527
6599
  }
6528
6600
  const children = this._totalChildConceptsMap.get(totalConceptId) || [];
6529
- const { calculatedSum, hasAnyValue, breakdown } = JupiterFormSection._buildCalculationBreakdown(
6601
+ const { calculatedSum, hasAnyValue, breakdown } = this._buildCalculationBreakdown(
6530
6602
  children,
6531
6603
  this.formData,
6532
6604
  columnId,
@@ -6573,19 +6645,46 @@ let JupiterFormSection = class extends LitElement {
6573
6645
  static _resolveWeight(totalBalance, childBalance) {
6574
6646
  return !totalBalance || !childBalance || totalBalance === childBalance ? 1 : -1;
6575
6647
  }
6576
- static _buildCalculationBreakdown(children, formData, columnId, totalBalance) {
6648
+ /**
6649
+ * JDF-041: a group member can itself be a registered cascading total with no entered value (e.g. a
6650
+ * customer who fills in "Operating income" directly without ever populating the "Net operating
6651
+ * result" running-subtotal row it's built on). Treating a blank member as a zero contribution
6652
+ * silently drops whatever it's actually built from and produces a false-positive mismatch. Instead,
6653
+ * look through a blank total member into its own registered members, recursively, so the check
6654
+ * reaches the real entered values wherever they are in the chain. `visited`/`depth` guard against
6655
+ * cycles and unbounded recursion (mirrors `_resolveValueConcept`'s depth cutoff).
6656
+ */
6657
+ _resolveMemberContributions(member, weight, formData, columnId, visited, depth = 0) {
6577
6658
  var _a;
6659
+ const val = parseFloat((_a = formData[member.id]) == null ? void 0 : _a[columnId]);
6660
+ if (!isNaN(val)) {
6661
+ return [{ conceptId: member.id, label: member.label, value: val, balance: member.balance, weight }];
6662
+ }
6663
+ if (depth >= 5 || visited.has(member.id))
6664
+ return [];
6665
+ const nestedMembers = this._totalChildConceptsMap.get(member.id);
6666
+ if (!nestedMembers)
6667
+ return [];
6668
+ const nextVisited = new Set(visited).add(member.id);
6669
+ const contributions = [];
6670
+ for (const nested of nestedMembers) {
6671
+ const nestedWeight = weight * JupiterFormSection._resolveWeight(member.balance, nested.balance);
6672
+ contributions.push(...this._resolveMemberContributions(nested, nestedWeight, formData, columnId, nextVisited, depth + 1));
6673
+ }
6674
+ return contributions;
6675
+ }
6676
+ _buildCalculationBreakdown(children, formData, columnId, totalBalance) {
6578
6677
  let calculatedSum = 0;
6579
6678
  let hasAnyValue = false;
6580
6679
  const breakdown = [];
6581
6680
  for (const child of children) {
6582
- const val = parseFloat((_a = formData[child.id]) == null ? void 0 : _a[columnId]);
6583
- if (isNaN(val))
6584
- continue;
6585
- hasAnyValue = true;
6586
6681
  const weight = JupiterFormSection._resolveWeight(totalBalance, child.balance);
6587
- calculatedSum += weight * val;
6588
- breakdown.push({ conceptId: child.id, label: child.label, value: val, balance: child.balance, weight });
6682
+ const contributions = this._resolveMemberContributions(child, weight, formData, columnId, /* @__PURE__ */ new Set());
6683
+ for (const contribution of contributions) {
6684
+ calculatedSum += contribution.weight * contribution.value;
6685
+ hasAnyValue = true;
6686
+ breakdown.push(contribution);
6687
+ }
6589
6688
  }
6590
6689
  return { calculatedSum, hasAnyValue, breakdown };
6591
6690
  }
@@ -7248,6 +7347,9 @@ __decorateClass$3([
7248
7347
  __decorateClass$3([
7249
7348
  n2({ type: String })
7250
7349
  ], JupiterFormSection.prototype, "language", 2);
7350
+ __decorateClass$3([
7351
+ n2({ type: Boolean })
7352
+ ], JupiterFormSection.prototype, "calculationEnabled", 2);
7251
7353
  __decorateClass$3([
7252
7354
  r()
7253
7355
  ], JupiterFormSection.prototype, "_expanded", 2);
@@ -9289,6 +9391,7 @@ let JupiterDynamicForm = class extends LitElement {
9289
9391
  this.initialData = {};
9290
9392
  this.disabled = false;
9291
9393
  this.readonly = false;
9394
+ this.calculationEnabled = false;
9292
9395
  this.periodStartDate = "2025-01-01";
9293
9396
  this.periodEndDate = "2025-12-31";
9294
9397
  this.language = "en";
@@ -10781,6 +10884,38 @@ let JupiterDynamicForm = class extends LitElement {
10781
10884
  }
10782
10885
  return `${startDate} / ${endDate}`;
10783
10886
  }
10887
+ /**
10888
+ * JDF-040: Resolves the instant date for a submission entry (Save Draft/Submit).
10889
+ * periodStartLabel-effective concepts (own-labelled or inherited, JDF-039) always
10890
+ * resolve via _resolveInstantDate — the same call the self-heal itself makes — instead
10891
+ * of trusting whatever happens to be cached in _periodData/field.periodInstantDate.
10892
+ * This matters because self-heal only ever corrects an EXISTING _periodData override
10893
+ * (it never fabricates one), so a cell that was never manually period-edited would
10894
+ * otherwise fall through to column.periodEndDate here and silently re-emit the wrong
10895
+ * date on every Save Draft/Submit even though field.periodInstantDate was healed.
10896
+ * Everything else keeps the previous fallback chain, but with field.periodInstantDate
10897
+ * now outranking column.periodEndDate, matching the already-correct sibling
10898
+ * implementations in _findFactValueForField and _addConceptDataToSubmission.
10899
+ */
10900
+ _resolveSubmissionInstantDate(concept, field2, fieldPeriodData, column2) {
10901
+ const effectiveRole = this._getEffectivePeriodRole(concept);
10902
+ if (effectiveRole == null ? void 0 : effectiveRole.includes("periodStartLabel")) {
10903
+ const periodStartDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.startDate) || (column2 == null ? void 0 : column2.periodStartDate) || field2.periodStartDate || this.periodStartDate;
10904
+ const periodEndDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) || field2.periodEndDate || this.periodEndDate;
10905
+ return this._resolveInstantDate(effectiveRole, void 0, periodStartDate, periodEndDate);
10906
+ }
10907
+ return (fieldPeriodData == null ? void 0 : fieldPeriodData.instantDate) || (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || field2.periodInstantDate || (column2 == null ? void 0 : column2.periodEndDate) || field2.periodEndDate || field2.periodStartDate || this.periodStartDate;
10908
+ }
10909
+ /**
10910
+ * JDF-039: The label value to use for periodStartLabel/periodEndLabel checks — the
10911
+ * concept's own preferredLabel if it carries one of those roles, otherwise the role
10912
+ * inherited from the nearest ancestor that does (stamped by XBRLFormBuilder as
10913
+ * effectivePeriodRole). Falls back to preferredLabel for any concept built before this
10914
+ * fix (or otherwise missing the field).
10915
+ */
10916
+ _getEffectivePeriodRole(concept) {
10917
+ return concept.effectivePeriodRole ?? concept.preferredLabel;
10918
+ }
10784
10919
  _resolveInstantDate(preferredLabel, instantDate, startDate, endDate) {
10785
10920
  if (preferredLabel == null ? void 0 : preferredLabel.includes("periodStartLabel")) {
10786
10921
  const base = startDate || "2025-01-01";
@@ -10810,7 +10945,7 @@ let JupiterDynamicForm = class extends LitElement {
10810
10945
  _correctPeriodStartInstantDatesInConcepts(concepts, section2) {
10811
10946
  concepts.forEach((concept) => {
10812
10947
  var _a, _b;
10813
- if (((_a = concept.preferredLabel) == null ? void 0 : _a.includes("periodStartLabel")) && concept.periodType === "instant" && ((_b = concept.fields) == null ? void 0 : _b.length)) {
10948
+ if (((_a = this._getEffectivePeriodRole(concept)) == null ? void 0 : _a.includes("periodStartLabel")) && concept.periodType === "instant" && ((_b = concept.fields) == null ? void 0 : _b.length)) {
10814
10949
  concept.fields.forEach((field2) => {
10815
10950
  this._correctFieldPeriodStartInstantDate(concept, field2, concept.id, section2);
10816
10951
  const repeatCount = this._repeatCounts[concept.id] || 0;
@@ -10830,7 +10965,7 @@ let JupiterDynamicForm = class extends LitElement {
10830
10965
  const fieldPeriodData = (_a = this._periodData[periodDataKey]) == null ? void 0 : _a[field2.columnId];
10831
10966
  const periodStartDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.startDate) || (column2 == null ? void 0 : column2.periodStartDate) || field2.periodStartDate || this.periodStartDate;
10832
10967
  const periodEndDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) || field2.periodEndDate || this.periodEndDate;
10833
- const correctedInstantDate = this._resolveInstantDate(concept.preferredLabel, void 0, periodStartDate, periodEndDate);
10968
+ const correctedInstantDate = this._resolveInstantDate(this._getEffectivePeriodRole(concept), void 0, periodStartDate, periodEndDate);
10834
10969
  if (fieldPeriodData && fieldPeriodData.instantDate !== correctedInstantDate) {
10835
10970
  console.log(`🩹 [Legacy Period Correction] ${periodDataKey}/${field2.columnId}: instantDate ${fieldPeriodData.instantDate} → ${correctedInstantDate}`);
10836
10971
  fieldPeriodData.instantDate = correctedInstantDate;
@@ -11040,7 +11175,7 @@ let JupiterDynamicForm = class extends LitElement {
11040
11175
  let field2;
11041
11176
  const colStartDate = request.periodType === "instant" ? request.instantDate : request.startDate;
11042
11177
  const colEndDate = request.periodType === "instant" ? request.instantDate : request.endDate;
11043
- const instantDate = this._resolveInstantDate(concept.preferredLabel, request.instantDate, colStartDate, colEndDate);
11178
+ const instantDate = this._resolveInstantDate(this._getEffectivePeriodRole(concept), request.instantDate, colStartDate, colEndDate);
11044
11179
  if (existingField) {
11045
11180
  field2 = {
11046
11181
  id: `${concept.id}_${columnId}`,
@@ -11756,7 +11891,7 @@ let JupiterDynamicForm = class extends LitElement {
11756
11891
  // CRITICAL: Include conceptType for XBRL validation
11757
11892
  periodStartDate: column2.periodStartDate,
11758
11893
  periodEndDate: column2.periodEndDate,
11759
- periodInstantDate: conceptPeriodType === "instant" ? column2.periodEndDate || column2.periodStartDate : void 0
11894
+ periodInstantDate: conceptPeriodType === "instant" ? this._resolveInstantDate(this._getEffectivePeriodRole(concept), void 0, column2.periodStartDate, column2.periodEndDate) : void 0
11760
11895
  };
11761
11896
  if ((_a = this._periodData[concept.id]) == null ? void 0 : _a[column2.id]) {
11762
11897
  const customPeriod = this._periodData[concept.id][column2.id];
@@ -12088,7 +12223,7 @@ let JupiterDynamicForm = class extends LitElement {
12088
12223
  }
12089
12224
  };
12090
12225
  if (concept.periodType === "instant") {
12091
- const instantDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.instantDate) || (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) || field2.periodInstantDate || field2.periodEndDate || field2.periodStartDate || this.periodStartDate;
12226
+ const instantDate = this._resolveSubmissionInstantDate(concept, field2, fieldPeriodData, column2);
12092
12227
  submissionEntry.period.date = instantDate;
12093
12228
  } else {
12094
12229
  const startDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.startDate) || (column2 == null ? void 0 : column2.periodStartDate) || field2.periodStartDate || this.periodStartDate;
@@ -12204,7 +12339,7 @@ let JupiterDynamicForm = class extends LitElement {
12204
12339
  }
12205
12340
  };
12206
12341
  if (concept.periodType === "instant") {
12207
- instanceEntry.period.date = (fieldPeriodData == null ? void 0 : fieldPeriodData.instantDate) || (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) || field2.periodInstantDate || field2.periodEndDate || field2.periodStartDate || this.periodStartDate;
12342
+ instanceEntry.period.date = this._resolveSubmissionInstantDate(concept, field2, fieldPeriodData, column2);
12208
12343
  } else {
12209
12344
  instanceEntry.period.startDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.startDate) || (column2 == null ? void 0 : column2.periodStartDate) || field2.periodStartDate || this.periodStartDate;
12210
12345
  instanceEntry.period.endDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) || field2.periodEndDate || this.periodEndDate;
@@ -13000,6 +13135,7 @@ let JupiterDynamicForm = class extends LitElement {
13000
13135
  .masterData="${this._effectiveMasterData}"
13001
13136
  .periodStartDate="${this.periodStartDate}"
13002
13137
  .periodEndDate="${this.periodEndDate}"
13138
+ .calculationEnabled="${this.calculationEnabled}"
13003
13139
  @field-change="${this._handleFieldChange}"
13004
13140
  @period-change="${this._handlePeriodChange}"
13005
13141
  @typed-member-change="${this._handleTypedMemberChange}"
@@ -13147,6 +13283,7 @@ let JupiterDynamicForm = class extends LitElement {
13147
13283
  .masterData="${this._effectiveMasterData}"
13148
13284
  .periodStartDate="${this.periodStartDate}"
13149
13285
  .periodEndDate="${this.periodEndDate}"
13286
+ .calculationEnabled="${this.calculationEnabled}"
13150
13287
  @field-change="${this._handleFieldChange}"
13151
13288
  @typed-member-change="${this._handleTypedMemberChange}"
13152
13289
  @add-concept-repeat="${this._handleAddConceptRepeat}"
@@ -14483,6 +14620,9 @@ __decorateClass([
14483
14620
  __decorateClass([
14484
14621
  n2({ type: Boolean })
14485
14622
  ], JupiterDynamicForm.prototype, "readonly", 2);
14623
+ __decorateClass([
14624
+ n2({ type: Boolean, attribute: "calculation-enabled" })
14625
+ ], JupiterDynamicForm.prototype, "calculationEnabled", 2);
14486
14626
  __decorateClass([
14487
14627
  n2({ type: String })
14488
14628
  ], JupiterDynamicForm.prototype, "periodStartDate", 2);