jupiter-dynamic-forms 1.22.4 → 1.22.6

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
@@ -1808,6 +1808,7 @@ const field$1 = {
1808
1808
  selectUnit: "Select Unit",
1809
1809
  leaveBlankForInf: "Leave blank for INF",
1810
1810
  prefilledLocked: "Pre-filled — cannot be changed here",
1811
+ notApplicablePriorYear: "Not required for the previous year",
1811
1812
  invalidNumber: `Can't read "{{value}}" as a number`,
1812
1813
  noDecimalsAllowed: "This field doesn't accept decimals",
1813
1814
  negativeNotAllowed: "A negative value isn't allowed here",
@@ -1865,7 +1866,9 @@ const duplicateFactWarning$1 = {
1865
1866
  message: "The same concept, period and dimensions were found with different values entered in different roles. Only one value can be correct — click a fact below to review and fix it.",
1866
1867
  role: "Role:",
1867
1868
  value: "Value:",
1868
- clickToFocus: "Click to go to this fact"
1869
+ clickToFocus: "Click to go to this fact",
1870
+ cellTooltip: "This value differs from the same fact entered elsewhere — click to review",
1871
+ close: "Close"
1869
1872
  };
1870
1873
  const calculationWarning$1 = {
1871
1874
  title: "Calculation warning",
@@ -2068,6 +2071,7 @@ const field = {
2068
2071
  selectUnit: "Selecteer eenheid",
2069
2072
  leaveBlankForInf: "Leeg laten voor INF",
2070
2073
  prefilledLocked: "Vooraf ingevuld — kan hier niet worden gewijzigd",
2074
+ notApplicablePriorYear: "Niet vereist voor het voorgaande jaar",
2071
2075
  invalidNumber: "Kan '{{value}}' niet lezen als getal",
2072
2076
  noDecimalsAllowed: "Dit veld accepteert geen decimalen",
2073
2077
  negativeNotAllowed: "Een negatieve waarde is hier niet toegestaan",
@@ -2125,7 +2129,9 @@ const duplicateFactWarning = {
2125
2129
  message: "Hetzelfde concept, dezelfde periode en dimensies zijn gevonden met verschillende waarden in verschillende rollen. Slechts één waarde kan juist zijn — klik op een feit hieronder om het te controleren en te corrigeren.",
2126
2130
  role: "Rol:",
2127
2131
  value: "Waarde:",
2128
- clickToFocus: "Klik om naar dit feit te gaan"
2132
+ clickToFocus: "Klik om naar dit feit te gaan",
2133
+ cellTooltip: "Deze waarde wijkt af van hetzelfde feit dat elders is ingevoerd — klik om te controleren",
2134
+ close: "Sluiten"
2129
2135
  };
2130
2136
  const calculationWarning = {
2131
2137
  title: "Berekeningswaarschuwing",
@@ -2888,6 +2894,7 @@ function collectAllCandidates(formData) {
2888
2894
  return candidates;
2889
2895
  }
2890
2896
  function indexConceptTree(concept, conceptByQName, conceptById, conceptIdByQName, conceptIdByQNameHasChildren, childrenIndex) {
2897
+ var _a;
2891
2898
  const info = {
2892
2899
  conceptId: concept.id,
2893
2900
  qname: concept.name,
@@ -2898,8 +2905,11 @@ function indexConceptTree(concept, conceptByQName, conceptById, conceptIdByQName
2898
2905
  (conceptByQName.get(concept.name) ?? conceptByQName.set(concept.name, []).get(concept.name)).push(info);
2899
2906
  const children = concept.children || [];
2900
2907
  const hasOwnChildren = children.length > 0;
2908
+ const existingConceptId = conceptIdByQName.get(concept.name);
2901
2909
  const alreadyHasChildren = conceptIdByQNameHasChildren.get(concept.name) === true;
2902
- if (!conceptIdByQName.has(concept.name) || hasOwnChildren && !alreadyHasChildren) {
2910
+ const existingEffectivePeriodRole = existingConceptId ? (_a = conceptById.get(existingConceptId)) == null ? void 0 : _a.effectivePeriodRole : void 0;
2911
+ const shouldPreferPeriodEnd = hasOwnChildren && alreadyHasChildren && concept.effectivePeriodRole === "periodEndLabel" && existingEffectivePeriodRole === "periodStartLabel";
2912
+ if (!conceptIdByQName.has(concept.name) || hasOwnChildren && !alreadyHasChildren || shouldPreferPeriodEnd) {
2903
2913
  conceptIdByQName.set(concept.name, concept.id);
2904
2914
  conceptIdByQNameHasChildren.set(concept.name, hasOwnChildren);
2905
2915
  }
@@ -3354,6 +3364,42 @@ function uncoveredExplicitDimensionAxisIds(variable, ctx) {
3354
3364
  }
3355
3365
  return axisIds;
3356
3366
  }
3367
+ function coveredExplicitDimensionAxisIds(variable, ctx) {
3368
+ const axisIds = /* @__PURE__ */ new Set();
3369
+ for (const filter2 of variable.filters) {
3370
+ if (filter2.type !== "EXPLICIT_DIMENSION" || !filter2.cover)
3371
+ continue;
3372
+ const axisId = ctx.dimensionQNameToId.get(filter2.attributes["dimension.qname"] ?? "");
3373
+ if (axisId)
3374
+ axisIds.add(axisId);
3375
+ }
3376
+ return axisIds;
3377
+ }
3378
+ function axisIdsOnCandidates(candidates, ctx) {
3379
+ const axisIds = /* @__PURE__ */ new Set();
3380
+ candidates.forEach((candidate) => {
3381
+ var _a;
3382
+ const dimensionData = (_a = getColumn(ctx, candidate)) == null ? void 0 : _a.dimensionData;
3383
+ if (!dimensionData)
3384
+ return;
3385
+ if (dimensionData.axisId)
3386
+ axisIds.add(dimensionData.axisId);
3387
+ (dimensionData.combinations || []).forEach((combo) => {
3388
+ if (combo.axisId)
3389
+ axisIds.add(combo.axisId);
3390
+ });
3391
+ });
3392
+ return axisIds;
3393
+ }
3394
+ function impliedUncoveredAxisIds(variable, candidates, ctx) {
3395
+ const axisIds = uncoveredExplicitDimensionAxisIds(variable, ctx);
3396
+ const covered = coveredExplicitDimensionAxisIds(variable, ctx);
3397
+ axisIdsOnCandidates(candidates, ctx).forEach((axisId) => {
3398
+ if (!covered.has(axisId))
3399
+ axisIds.add(axisId);
3400
+ });
3401
+ return axisIds;
3402
+ }
3357
3403
  function candidateMemberIdForAxis(ctx, candidate, axisId) {
3358
3404
  var _a;
3359
3405
  const column2 = getColumn(ctx, candidate);
@@ -3363,21 +3409,39 @@ function candidateMemberIdForAxis(ctx, candidate, axisId) {
3363
3409
  return column2.dimensionData.memberId;
3364
3410
  return (_a = (column2.dimensionData.combinations || []).find((combo) => combo.axisId === axisId)) == null ? void 0 : _a.memberId;
3365
3411
  }
3412
+ function coveredMemberIdForAxis(variable, axisId, ctx) {
3413
+ for (const filter2 of variable.filters) {
3414
+ if (filter2.type !== "EXPLICIT_DIMENSION" || !filter2.cover || filter2.complement)
3415
+ continue;
3416
+ if (filter2.attributes["member.axis"])
3417
+ continue;
3418
+ if (ctx.dimensionQNameToId.get(filter2.attributes["dimension.qname"] ?? "") !== axisId)
3419
+ continue;
3420
+ const memberId = ctx.memberQNameToId.get(filter2.attributes["member.qname"] ?? "");
3421
+ if (memberId)
3422
+ return memberId;
3423
+ }
3424
+ return void 0;
3425
+ }
3366
3426
  function findUncoveredAxisAnchor(variables, axisId, candidatesByName, ctx) {
3367
3427
  for (const variable of variables) {
3368
3428
  if (variable.bindAsSequence)
3369
3429
  continue;
3370
- if (!uncoveredExplicitDimensionAxisIds(variable, ctx).has(axisId))
3371
- continue;
3372
3430
  const candidates = candidatesByName.get(variable.name) || [];
3373
- const memberIds = new Set(
3374
- candidates.map((candidate) => candidateMemberIdForAxis(ctx, candidate, axisId)).filter((id) => id !== void 0)
3375
- );
3376
- if (memberIds.size === 1)
3377
- return { memberId: [...memberIds][0], variableName: variable.name, ambiguous: false };
3378
- const rootMembers = [...memberIds].filter((id) => !ctx.memberIdsWithParent.has(id));
3379
- if (rootMembers.length === 1)
3380
- return { memberId: rootMembers[0], variableName: variable.name, ambiguous: true };
3431
+ if (impliedUncoveredAxisIds(variable, candidates, ctx).has(axisId)) {
3432
+ const memberIds = new Set(
3433
+ candidates.map((candidate) => candidateMemberIdForAxis(ctx, candidate, axisId)).filter((id) => id !== void 0)
3434
+ );
3435
+ if (memberIds.size === 1)
3436
+ return { memberId: [...memberIds][0], variableName: variable.name, ambiguous: false };
3437
+ const rootMembers = [...memberIds].filter((id) => !ctx.memberIdsWithParent.has(id));
3438
+ if (rootMembers.length === 1)
3439
+ return { memberId: rootMembers[0], variableName: variable.name, ambiguous: true };
3440
+ continue;
3441
+ }
3442
+ const pinnedMemberId = coveredMemberIdForAxis(variable, axisId, ctx);
3443
+ if (pinnedMemberId)
3444
+ return { memberId: pinnedMemberId, variableName: variable.name, ambiguous: false };
3381
3445
  }
3382
3446
  return void 0;
3383
3447
  }
@@ -3386,13 +3450,15 @@ function computeAssertionNarrowedCandidatesByName(variables, ctx, implicitFilter
3386
3450
  variables.forEach((variable) => candidatesByName.set(variable.name, resolveNarrowedCandidates(variable, ctx, roleURI)));
3387
3451
  if (implicitFiltering) {
3388
3452
  const axisIds = /* @__PURE__ */ new Set();
3389
- variables.forEach((variable) => uncoveredExplicitDimensionAxisIds(variable, ctx).forEach((axisId) => axisIds.add(axisId)));
3453
+ variables.forEach(
3454
+ (variable) => impliedUncoveredAxisIds(variable, candidatesByName.get(variable.name) || [], ctx).forEach((axisId) => axisIds.add(axisId))
3455
+ );
3390
3456
  axisIds.forEach((axisId) => {
3391
3457
  const anchor = findUncoveredAxisAnchor(variables, axisId, candidatesByName, ctx);
3392
3458
  if (!anchor)
3393
3459
  return;
3394
3460
  variables.forEach((variable) => {
3395
- const isNarrowableSequence = variable.bindAsSequence && uncoveredExplicitDimensionAxisIds(variable, ctx).has(axisId);
3461
+ const isNarrowableSequence = variable.bindAsSequence && impliedUncoveredAxisIds(variable, candidatesByName.get(variable.name) || [], ctx).has(axisId);
3396
3462
  const isAmbiguousAnchorItself = anchor.ambiguous && variable.name === anchor.variableName;
3397
3463
  if (!isNarrowableSequence && !isAmbiguousAnchorItself)
3398
3464
  return;
@@ -5005,13 +5071,22 @@ let JupiterFormField = class extends LitElement {
5005
5071
  this._availableUnits = [];
5006
5072
  this._numericDraftValue = null;
5007
5073
  this._focused = false;
5074
+ this._boundHandlePeriodPopupKeydown = this._handlePeriodPopupKeydown.bind(this);
5075
+ }
5076
+ connectedCallback() {
5077
+ super.connectedCallback();
5078
+ window.addEventListener("keydown", this._boundHandlePeriodPopupKeydown);
5079
+ }
5080
+ disconnectedCallback() {
5081
+ window.removeEventListener("keydown", this._boundHandlePeriodPopupKeydown);
5082
+ super.disconnectedCallback();
5008
5083
  }
5009
5084
  willUpdate(changedProperties) {
5010
5085
  var _a;
5011
5086
  if (changedProperties.has("value") || changedProperties.has("field")) {
5012
5087
  this._validateField();
5013
5088
  }
5014
- if (changedProperties.has("unit") && this.unit) {
5089
+ if (changedProperties.has("unit") && this.unit && this.hasUpdated) {
5015
5090
  console.log(`🏷️ [FormField willUpdate] Unit property changed to: ${this.unit}, conceptId: ${this.conceptId}, columnId: ${this.columnId}`);
5016
5091
  this.dispatchEvent(new CustomEvent("unit-change", {
5017
5092
  detail: {
@@ -5046,6 +5121,14 @@ let JupiterFormField = class extends LitElement {
5046
5121
  _isRoundingLevelConcept() {
5047
5122
  return !!this.conceptId && this.conceptId.includes("DocumentIntendedRoundingLevel");
5048
5123
  }
5124
+ // jenv-bw2-i:BalanceSheetBeforeAfterAppropriationResults records the profit-appropriation
5125
+ // decision for the current balance sheet only — the NL taxonomy's validation rules warn when
5126
+ // it's also reported for the comparative year, so the prior-year column doesn't accept it.
5127
+ // `columnId` carries the `_prev` marker `generatePreviousYearColumns` (xbrl-form-builder.ts)
5128
+ // gives every comparative-year column, whether dimensioned (`${id}_prev`) or not (`duration_prev_N`).
5129
+ _isDisabledForPriorYear() {
5130
+ return !!this.conceptId && !!this.columnId && this.conceptId.includes("BalanceSheetBeforeAfterAppropriationResults") && this.columnId.includes("_prev");
5131
+ }
5049
5132
  /**
5050
5133
  * JDF-110: lock icon (SVG, not emoji) shown on a masterData-prefilled or rounding-level-locked
5051
5134
  * cell, so a locked value reads as "filled and protected" rather than empty placeholder text.
@@ -5689,7 +5772,7 @@ let JupiterFormField = class extends LitElement {
5689
5772
  const isMonetary = this._isMonetaryType();
5690
5773
  return html`<span class="readonly-value ${isEmpty ? "empty" : ""} ${isMonetary ? "monetary" : ""}">${isEmpty ? "—" : displayValue}</span>`;
5691
5774
  }
5692
- _renderInput(effectiveValue = this.value, effectiveDisabled = this.disabled, isLocked = false) {
5775
+ _renderInput(effectiveValue = this.value, effectiveDisabled = this.disabled, isLocked = false, disabledTooltip) {
5693
5776
  if (this.mode === "readonly") {
5694
5777
  return this._renderReadonlyValue(effectiveValue);
5695
5778
  }
@@ -5715,6 +5798,7 @@ let JupiterFormField = class extends LitElement {
5715
5798
  class="${cssClass}"
5716
5799
  .value="${effectiveValue ?? ""}"
5717
5800
  ?disabled="${effectiveDisabled || this.field.disabled}"
5801
+ title="${disabledTooltip || ""}"
5718
5802
  @change="${this._handleInput}"
5719
5803
  @focus="${this._handleFocus}"
5720
5804
  @blur="${this._handleBlur}"
@@ -5921,18 +6005,14 @@ let JupiterFormField = class extends LitElement {
5921
6005
  }
5922
6006
  return html``;
5923
6007
  }
5924
- // JDF-118: the period popup is a plain Lit overlay, not a native <dialog>, so it doesn't get
5925
- // Escape-to-close for free the way the info/text dialogs do. Keydown on the overlay catches it
5926
- // as it bubbles up from whichever control inside the popup has focus.
5927
6008
  _handlePeriodPopupKeydown(e2) {
5928
- if (e2.key === "Escape") {
5929
- e2.stopPropagation();
6009
+ if (this._showPeriodPopup && e2.key === "Escape") {
5930
6010
  this._closePeriodPopup();
5931
6011
  }
5932
6012
  }
5933
6013
  _renderPeriodPopup() {
5934
6014
  return html`
5935
- <div class="period-popup-overlay" @click="${this._handlePopupOverlayClick}" @keydown="${this._handlePeriodPopupKeydown}">
6015
+ <div class="period-popup-overlay" @click="${this._handlePopupOverlayClick}">
5936
6016
  <div class="period-popup" @click="${(e2) => e2.stopPropagation()}">
5937
6017
  <div class="period-popup-header">
5938
6018
  <div class="period-popup-title">${I18n.t("field.editPeriod")}</div>
@@ -6066,6 +6146,7 @@ let JupiterFormField = class extends LitElement {
6066
6146
  const baseConceptId = this._extractBaseConceptId(this.conceptId);
6067
6147
  const isPredefinedValue = this.mode !== "admin" && this.masterData && baseConceptId in this.masterData;
6068
6148
  const isRoundingLevelLocked = this._isRoundingLevelConcept();
6149
+ const isDisabledForPriorYear = this._isDisabledForPriorYear();
6069
6150
  let factValue = null;
6070
6151
  if (this.facts && this.facts.length > 0 && !isPredefinedValue) {
6071
6152
  const cellContext = {
@@ -6119,8 +6200,8 @@ let JupiterFormField = class extends LitElement {
6119
6200
  }
6120
6201
  }
6121
6202
  const hasUserValue = this.value !== null && this.value !== void 0;
6122
- const effectiveValue = isPredefinedValue ? this.masterData[baseConceptId] : hasUserValue ? this.value : factValue;
6123
- const effectiveDisabled = isPredefinedValue || isRoundingLevelLocked || this.disabled || this.mode === "readonly";
6203
+ const effectiveValue = isDisabledForPriorYear ? null : isPredefinedValue ? this.masterData[baseConceptId] : hasUserValue ? this.value : factValue;
6204
+ const effectiveDisabled = isPredefinedValue || isRoundingLevelLocked || isDisabledForPriorYear || this.disabled || this.mode === "readonly";
6124
6205
  const isLocked = (isPredefinedValue || isRoundingLevelLocked) && this.mode !== "readonly";
6125
6206
  const typeConfigForLock = getInputTypeForConceptType(this.conceptType, this.datatypes);
6126
6207
  const effectiveFieldTypeForLock = typeConfigForLock.fieldType || this.field.type || "text";
@@ -6134,7 +6215,7 @@ let JupiterFormField = class extends LitElement {
6134
6215
  ` : ""}
6135
6216
 
6136
6217
  <div class="field-wrapper">
6137
- ${this._renderInput(effectiveValue, effectiveDisabled, isLocked)}
6218
+ ${this._renderInput(effectiveValue, effectiveDisabled, isLocked, isDisabledForPriorYear ? I18n.t("field.notApplicablePriorYear") : void 0)}
6138
6219
 
6139
6220
  ${isLocked && !isTextareaField || hasPeriodControl && this.mode !== "readonly" && !isRoundingLevelLocked ? html`
6140
6221
  <div class="field-trailing-icons">
@@ -7061,6 +7142,19 @@ let JupiterConceptTree = class extends LitElement {
7061
7142
  `;
7062
7143
  document.head.appendChild(style);
7063
7144
  }
7145
+ /**
7146
+ * Dispatches the clicked cell's duplicate-fact mismatch up to `jupiter-dynamic-form`, which owns
7147
+ * the click-to-navigate machinery (role/column reveal, side-panel switch, highlight) already
7148
+ * built for the Validate pre-flight popup — reused here to show this one mismatch's facts.
7149
+ */
7150
+ _handleDuplicateFactWarningBadgeClick(e2, mismatch) {
7151
+ e2.stopPropagation();
7152
+ this.dispatchEvent(new CustomEvent("duplicate-fact-warning-click", {
7153
+ detail: { mismatch },
7154
+ bubbles: true,
7155
+ composed: true
7156
+ }));
7157
+ }
7064
7158
  _openCalculationWarningDialog(e2, mismatch) {
7065
7159
  var _a;
7066
7160
  e2.stopPropagation();
@@ -7135,7 +7229,7 @@ let JupiterConceptTree = class extends LitElement {
7135
7229
 
7136
7230
  <!-- Input Field Cells (Period Columns) - Only for non-abstract concepts -->
7137
7231
  ${this.columns.map((column2) => {
7138
- var _a, _b, _c, _d, _e;
7232
+ var _a, _b, _c, _d, _e, _f;
7139
7233
  if (column2.hidden) {
7140
7234
  return html`<td class="field-cell hidden-column"></td>`;
7141
7235
  }
@@ -7144,8 +7238,9 @@ let JupiterConceptTree = class extends LitElement {
7144
7238
  const storedUnit = (_b = (_a = this.unitData) == null ? void 0 : _a[this.concept.id]) == null ? void 0 : _b[column2.id];
7145
7239
  const storedDecimals = (_d = (_c = this.decimalsData) == null ? void 0 : _c[this.concept.id]) == null ? void 0 : _d[column2.id];
7146
7240
  const calcMismatch = this.mode !== "readonly" ? (_e = this.calculationMismatches) == null ? void 0 : _e.get(`${this.concept.id}__${column2.id}`) : void 0;
7241
+ const dupWarning = this.mode !== "readonly" ? (_f = this.duplicateFactWarnings) == null ? void 0 : _f.get(`${this.concept.id}__${column2.id}`) : void 0;
7147
7242
  return html`
7148
- <td class="field-cell ${!shouldShowField ? "empty" : ""} ${isAbstract ? "abstract-row" : ""} ${isTotal ? "total-row" : ""} ${this.highlightType && column2.id === this.highlightColumnId ? "highlight-" + this.highlightType : ""} ${calcMismatch ? "calc-warning" : ""} ${this.rowFocused ? "row-focused" : ""}">
7243
+ <td class="field-cell ${!shouldShowField ? "empty" : ""} ${isAbstract ? "abstract-row" : ""} ${isTotal ? "total-row" : ""} ${this.highlightType && column2.id === this.highlightColumnId ? "highlight-" + this.highlightType : ""} ${calcMismatch ? "calc-warning" : ""} ${dupWarning ? "duplicate-fact-warning" : ""} ${this.rowFocused ? "row-focused" : ""}">
7149
7244
  ${calcMismatch ? html`
7150
7245
  <button
7151
7246
  class="calc-warning-badge"
@@ -7155,6 +7250,15 @@ let JupiterConceptTree = class extends LitElement {
7155
7250
  @click="${(e2) => this._openCalculationWarningDialog(e2, calcMismatch)}"
7156
7251
  >!</button>
7157
7252
  ` : ""}
7253
+ ${dupWarning ? html`
7254
+ <button
7255
+ class="duplicate-warning-badge"
7256
+ type="button"
7257
+ tabindex="-1"
7258
+ title="${I18n.t("duplicateFactWarning.cellTooltip")}"
7259
+ @click="${(e2) => this._handleDuplicateFactWarningBadgeClick(e2, dupWarning)}"
7260
+ >≠</button>
7261
+ ` : ""}
7158
7262
  ${shouldShowField ? html`
7159
7263
  <jupiter-form-field
7160
7264
  .field="${field2}"
@@ -7407,6 +7511,38 @@ JupiterConceptTree.styles = css`
7407
7511
  background: #e65100;
7408
7512
  }
7409
7513
 
7514
+ /* Live counterpart to the Validate pre-flight's duplicate-fact-value check — deliberately a
7515
+ distinct color from calc-warning's amber so the two non-blocking warnings never look like
7516
+ the same issue when both land on the same cell. */
7517
+ .field-cell.duplicate-fact-warning {
7518
+ box-shadow: inset 0 0 0 2px var(--jupiter-duplicate-warning-color, #8e24aa);
7519
+ }
7520
+
7521
+ .duplicate-warning-badge {
7522
+ position: absolute;
7523
+ top: 2px;
7524
+ left: 2px;
7525
+ width: 16px;
7526
+ height: 16px;
7527
+ border-radius: 50%;
7528
+ border: none;
7529
+ background: var(--jupiter-duplicate-warning-color, #8e24aa);
7530
+ color: #fff;
7531
+ font-size: 10px;
7532
+ font-weight: 700;
7533
+ line-height: 1;
7534
+ padding: 0;
7535
+ display: flex;
7536
+ align-items: center;
7537
+ justify-content: center;
7538
+ cursor: pointer;
7539
+ z-index: 3;
7540
+ }
7541
+
7542
+ .duplicate-warning-badge:hover {
7543
+ background: #6a1b9a;
7544
+ }
7545
+
7410
7546
  /* Row-level highlight while a field in this row has focus. Applied to every
7411
7547
  cell so the row stays identifiable even after the user scrolls the table
7412
7548
  horizontally away from the focused input. */
@@ -7560,6 +7696,9 @@ __decorateClass$7([
7560
7696
  __decorateClass$7([
7561
7697
  n2({ type: Object })
7562
7698
  ], JupiterConceptTree.prototype, "calculationMismatches", 2);
7699
+ __decorateClass$7([
7700
+ n2({ type: Object })
7701
+ ], JupiterConceptTree.prototype, "duplicateFactWarnings", 2);
7563
7702
  __decorateClass$7([
7564
7703
  n2({ type: String })
7565
7704
  ], JupiterConceptTree.prototype, "language", 2);
@@ -7597,6 +7736,7 @@ let JupiterAddColumnDialog = class extends LitElement {
7597
7736
  this._selectedType = "duration";
7598
7737
  this._selectedDimensions = /* @__PURE__ */ new Map();
7599
7738
  this._typedValueErrors = {};
7739
+ this._boundHandleKeydown = this._handleKeydown.bind(this);
7600
7740
  }
7601
7741
  updated(changedProperties) {
7602
7742
  if (changedProperties.has("open") && this.open) {
@@ -7608,6 +7748,11 @@ let JupiterAddColumnDialog = class extends LitElement {
7608
7748
  connectedCallback() {
7609
7749
  super.connectedCallback();
7610
7750
  this._resetForm();
7751
+ window.addEventListener("keydown", this._boundHandleKeydown);
7752
+ }
7753
+ disconnectedCallback() {
7754
+ window.removeEventListener("keydown", this._boundHandleKeydown);
7755
+ super.disconnectedCallback();
7611
7756
  }
7612
7757
  willUpdate(changedProperties) {
7613
7758
  super.willUpdate(changedProperties);
@@ -7615,6 +7760,11 @@ let JupiterAddColumnDialog = class extends LitElement {
7615
7760
  this._resetForm();
7616
7761
  }
7617
7762
  }
7763
+ _handleKeydown(event) {
7764
+ if (this.open && event.key === "Escape") {
7765
+ this._handleCancel();
7766
+ }
7767
+ }
7618
7768
  _handleCancel() {
7619
7769
  this.open = false;
7620
7770
  this.dispatchEvent(new CustomEvent("dialog-cancel", { bubbles: true }));
@@ -9347,6 +9497,7 @@ let JupiterFormSection = class extends LitElement {
9347
9497
  .highlightColumnId="${(_b = this._highlightMap.get(instanceConcept.id)) == null ? void 0 : _b.columnId}"
9348
9498
  .rowFocused="${this._focusedConceptId === instanceConcept.id}"
9349
9499
  .calculationMismatches="${this._calculationMismatches}"
9500
+ .duplicateFactWarnings="${this.duplicateFactWarnings}"
9350
9501
  @field-change="${this._handleFieldChange}"
9351
9502
  @field-focus="${this._handleFieldFocusForHighlight}"
9352
9503
  @period-change="${this._handlePeriodChange}"
@@ -9982,6 +10133,9 @@ __decorateClass$5([
9982
10133
  __decorateClass$5([
9983
10134
  n2({ type: Object })
9984
10135
  ], JupiterFormSection.prototype, "totalManuallyEditedData", 2);
10136
+ __decorateClass$5([
10137
+ n2({ type: Object })
10138
+ ], JupiterFormSection.prototype, "duplicateFactWarnings", 2);
9985
10139
  __decorateClass$5([
9986
10140
  r()
9987
10141
  ], JupiterFormSection.prototype, "_expanded", 2);
@@ -10187,6 +10341,7 @@ let JupiterAdvancedFilter = class extends LitElement {
10187
10341
  return;
10188
10342
  }
10189
10343
  if (e2.key === "Escape") {
10344
+ e2.stopPropagation();
10190
10345
  this._showSuggestions = false;
10191
10346
  this._activeSuggestionIndex = -1;
10192
10347
  return;
@@ -10501,11 +10656,22 @@ let JupiterFilterRolesDialog = class extends LitElement {
10501
10656
  this._showFactsOnly = false;
10502
10657
  this._conceptSearchText = "";
10503
10658
  this._collapsedRoles = /* @__PURE__ */ new Set();
10659
+ this._boundHandleKeydown = this._handleKeydown.bind(this);
10504
10660
  }
10505
10661
  connectedCallback() {
10506
10662
  super.connectedCallback();
10507
10663
  this._initializeTempSelection();
10508
10664
  this._initializePeriodPreferences();
10665
+ window.addEventListener("keydown", this._boundHandleKeydown);
10666
+ }
10667
+ disconnectedCallback() {
10668
+ window.removeEventListener("keydown", this._boundHandleKeydown);
10669
+ super.disconnectedCallback();
10670
+ }
10671
+ _handleKeydown(event) {
10672
+ if (this.open && event.key === "Escape") {
10673
+ this._handleCancel();
10674
+ }
10509
10675
  }
10510
10676
  updated(changedProperties) {
10511
10677
  if (changedProperties.has("selectedRoleIds") || changedProperties.has("open")) {
@@ -12939,6 +13105,8 @@ let JupiterDynamicForm = class extends LitElement {
12939
13105
  this._showValidateWarningPopup = false;
12940
13106
  this._typedDimensionWarningFacts = [];
12941
13107
  this._duplicateFactMismatches = [];
13108
+ this._duplicateFactWarnings = /* @__PURE__ */ new Map();
13109
+ this._duplicateWarningPopupMode = "validate";
12942
13110
  this._submitDisabled = false;
12943
13111
  this._allSections = [];
12944
13112
  this._selectedRoleIds = [];
@@ -12947,6 +13115,7 @@ let JupiterDynamicForm = class extends LitElement {
12947
13115
  this._showFactsOnly = false;
12948
13116
  this._conceptSearchText = "";
12949
13117
  this._lastFocusedFieldIdentity = null;
13118
+ this._dimensionColumnDriftDiagnostics = [];
12950
13119
  this._periodPreferences = {};
12951
13120
  this._activeSidePanelRoleId = null;
12952
13121
  this._sidePanelSearchQuery = "";
@@ -12996,6 +13165,15 @@ let JupiterDynamicForm = class extends LitElement {
12996
13165
  this.addEventListener("calculation-mismatch-changed", (e2) => {
12997
13166
  this._handleCalculationMismatchChanged(e2);
12998
13167
  });
13168
+ this.addEventListener("duplicate-fact-warning-click", (e2) => {
13169
+ const { mismatch } = e2.detail || {};
13170
+ if (!mismatch)
13171
+ return;
13172
+ this._typedDimensionWarningFacts = [];
13173
+ this._duplicateFactMismatches = [mismatch];
13174
+ this._duplicateWarningPopupMode = "cellInfo";
13175
+ this._showValidateWarningPopup = true;
13176
+ });
12999
13177
  this.addEventListener("total-manually-edited", (e2) => {
13000
13178
  const { conceptId, columnId } = e2.detail;
13001
13179
  const updated = { ...this._totalManuallyEditedData };
@@ -13209,6 +13387,7 @@ let JupiterDynamicForm = class extends LitElement {
13209
13387
  if ((_a = this.xbrlInput) == null ? void 0 : _a.initialData) {
13210
13388
  this._formData = { ...this._formData, ...this.xbrlInput.initialData };
13211
13389
  }
13390
+ this._formData = this._stripPriorYearExcludedFacts(this._formData);
13212
13391
  this._initializeGlobalDecimalsFromRoundingData();
13213
13392
  this._extractTypedMembersFromFacts();
13214
13393
  if (!this._skipDraftLoading) {
@@ -13889,8 +14068,15 @@ let JupiterDynamicForm = class extends LitElement {
13889
14068
  // which reads as "still cut off" when its row height isn't an exact multiple of the container.
13890
14069
  _scrollActiveRoleIntoView() {
13891
14070
  var _a;
13892
- const activeItem = (_a = this.shadowRoot) == null ? void 0 : _a.querySelector(".side-panel-roles-list .side-panel-role-item.active");
13893
- activeItem == null ? void 0 : activeItem.scrollIntoView({ block: "center" });
14071
+ const rolesList = (_a = this.shadowRoot) == null ? void 0 : _a.querySelector(".side-panel-roles-list");
14072
+ const activeItem = rolesList == null ? void 0 : rolesList.querySelector(".side-panel-role-item.active");
14073
+ if (!rolesList || !activeItem)
14074
+ return;
14075
+ const listRect = rolesList.getBoundingClientRect();
14076
+ const itemRect = activeItem.getBoundingClientRect();
14077
+ const itemCenter = itemRect.top + itemRect.height / 2;
14078
+ const listCenter = listRect.top + listRect.height / 2;
14079
+ rolesList.scrollTop += itemCenter - listCenter;
13894
14080
  }
13895
14081
  // Re-locates the fact input identified by _lastFocusedFieldIdentity after a rebuild and restores
13896
14082
  // focus to it, mirroring the shadow-DOM traversal scrollToConcept/_handleErrorFieldClick use.
@@ -14115,6 +14301,29 @@ let JupiterDynamicForm = class extends LitElement {
14115
14301
  this._calculationWarnings = next;
14116
14302
  this._validateForm();
14117
14303
  }
14304
+ // jenv-bw2-i:BalanceSheetBeforeAfterAppropriationResults isn't applicable to the previous-year
14305
+ // column — mirrors `_isDisabledForPriorYear` in form-field.ts (which disables the input itself);
14306
+ // this is the `_formData`/submission-side counterpart so a value already sitting in a draft,
14307
+ // `initialData`, or preserved (hidden-role) data from before that UI restriction existed gets
14308
+ // scrubbed on load and can never resurface in a later draft save or submission.
14309
+ _isPriorYearExcludedFact(conceptId, columnId) {
14310
+ return !!conceptId && !!columnId && conceptId.includes("BalanceSheetBeforeAfterAppropriationResults") && columnId.includes("_prev");
14311
+ }
14312
+ /** Strips any prior-year-excluded concept/column entries from a `FormData` map (immutable). */
14313
+ _stripPriorYearExcludedFacts(data) {
14314
+ const cleaned = {};
14315
+ Object.keys(data).forEach((conceptId) => {
14316
+ const columns = data[conceptId] || {};
14317
+ const keptColumns = {};
14318
+ Object.keys(columns).forEach((columnId) => {
14319
+ if (!this._isPriorYearExcludedFact(conceptId, columnId)) {
14320
+ keptColumns[columnId] = columns[columnId];
14321
+ }
14322
+ });
14323
+ cleaned[conceptId] = keptColumns;
14324
+ });
14325
+ return cleaned;
14326
+ }
14118
14327
  /**
14119
14328
  * JDF-058: single source of truth for writing a value into `_formData` with the immutable-update
14120
14329
  * pattern Lit reactivity needs — shared by a real user keystroke (`_handleFieldChange`) and the
@@ -14122,6 +14331,10 @@ let JupiterDynamicForm = class extends LitElement {
14122
14331
  * duplicated. Returns the value that was previously stored, for event `oldValue` fields.
14123
14332
  */
14124
14333
  _writeFormDataValue(conceptId, columnId, value) {
14334
+ var _a;
14335
+ if (this._isPriorYearExcludedFact(conceptId, columnId)) {
14336
+ return (_a = this._formData[conceptId]) == null ? void 0 : _a[columnId];
14337
+ }
14125
14338
  const updatedFormData = { ...this._formData };
14126
14339
  if (!updatedFormData[conceptId]) {
14127
14340
  updatedFormData[conceptId] = {};
@@ -14174,13 +14387,17 @@ let JupiterDynamicForm = class extends LitElement {
14174
14387
  this.requestUpdate();
14175
14388
  }
14176
14389
  _handleUnitChange(event) {
14390
+ var _a;
14177
14391
  console.log(`🏷️ [DynamicForm] _handleUnitChange called with event:`, event);
14178
14392
  console.log(`🏷️ [DynamicForm] Event detail:`, event.detail);
14179
14393
  const { conceptId, columnId, unit } = event.detail;
14180
14394
  console.log(`🏷️ Unit change received: conceptId=${conceptId}, columnId=${columnId}, unit=${unit}`);
14395
+ const isUnchanged = ((_a = this._unitData[conceptId]) == null ? void 0 : _a[columnId]) === unit;
14181
14396
  this._storeUnit(conceptId, columnId, unit);
14182
- this._dirty = true;
14183
- this.hasUnsavedChanges = true;
14397
+ if (!isUnchanged) {
14398
+ this._dirty = true;
14399
+ this.hasUnsavedChanges = true;
14400
+ }
14184
14401
  this.requestUpdate();
14185
14402
  }
14186
14403
  _storeUnit(conceptId, columnId, unit) {
@@ -14488,6 +14705,7 @@ let JupiterDynamicForm = class extends LitElement {
14488
14705
  console.log(`🟧 [DynamicForm] Removed ${beforeLength - this._xbrlFormErrors.length} errors`);
14489
14706
  }
14490
14707
  console.log(`🔍 [Validation] Total errors: ${this._xbrlFormErrors.length}`, this._xbrlFormErrors);
14708
+ this._updateDuplicateFactWarnings(conceptId, columnId);
14491
14709
  }
14492
14710
  _getSectionTitle(sectionId) {
14493
14711
  console.log(`🔍 [_getSectionTitle] Looking for sectionId: "${sectionId}"`);
@@ -15325,6 +15543,33 @@ let JupiterDynamicForm = class extends LitElement {
15325
15543
  }
15326
15544
  return String(value);
15327
15545
  }
15546
+ /**
15547
+ * Live, blur-triggered counterpart to `_findDuplicateFactMismatches`. Re-runs the full duplicate
15548
+ * check (cheap — the same pass Validate already does) and rebuilds `_duplicateFactWarnings` from
15549
+ * scratch, so a resolved conflict clears itself and a newly created one appears without any
15550
+ * extra bookkeeping. Every fact in every current mismatch group gets flagged, not just the field
15551
+ * that was just blurred, so the user sees all the cells involved in a conflict — including one
15552
+ * they filled in earlier — the moment either side changes, rather than having to revisit them
15553
+ * one by one after Validate. Skipped when the blurred cell has no value and wasn't already
15554
+ * flagged, since a blank cell can never be part of a mismatch (`_collectDuplicateFactCandidates`
15555
+ * ignores blanks) — this keeps tabbing through empty cells cheap.
15556
+ */
15557
+ _updateDuplicateFactWarnings(conceptId, columnId) {
15558
+ var _a;
15559
+ const value = (_a = this._formData[conceptId]) == null ? void 0 : _a[columnId];
15560
+ const hasMeaningfulValue = value !== void 0 && value !== null && String(value).trim() !== "";
15561
+ const key = `${conceptId}__${columnId}`;
15562
+ if (!hasMeaningfulValue && !this._duplicateFactWarnings.has(key))
15563
+ return;
15564
+ const mismatches = this._findDuplicateFactMismatches();
15565
+ const updated = /* @__PURE__ */ new Map();
15566
+ for (const mismatch of mismatches) {
15567
+ for (const fact of mismatch.facts) {
15568
+ updated.set(`${fact.conceptId}__${fact.columnId}`, mismatch);
15569
+ }
15570
+ }
15571
+ this._duplicateFactWarnings = updated;
15572
+ }
15328
15573
  /** Popup header for the Validate pre-flight warning: specific when only one check found something, generic when both did. */
15329
15574
  _validateWarningPopupTitle() {
15330
15575
  const hasTypedDimensionWarning = this._typedDimensionWarningFacts.length > 0;
@@ -15352,6 +15597,7 @@ let JupiterDynamicForm = class extends LitElement {
15352
15597
  console.log("⚠️ [Submit] Duplicate facts with mismatched values:", duplicateFactMismatches);
15353
15598
  this._typedDimensionWarningFacts = missingTypedDimensionFacts;
15354
15599
  this._duplicateFactMismatches = duplicateFactMismatches;
15600
+ this._duplicateWarningPopupMode = "validate";
15355
15601
  this._showValidateWarningPopup = true;
15356
15602
  this._submitDisabled = false;
15357
15603
  this.requestUpdate();
@@ -15722,6 +15968,10 @@ let JupiterDynamicForm = class extends LitElement {
15722
15968
  return;
15723
15969
  }
15724
15970
  }
15971
+ if (this._isPriorYearExcludedFact(conceptId, columnId)) {
15972
+ console.log(`⏭️ Dropping legacy draft value for ${conceptId}/${columnId} — not applicable to the previous year`);
15973
+ return;
15974
+ }
15725
15975
  const instanceKey = draftInstanceId || conceptId;
15726
15976
  const baseConceptId = instanceKey.includes("__repeat_") ? instanceKey.split("__repeat_")[0] : instanceKey;
15727
15977
  const actualBaseId = this._findActualConceptId(baseConceptId);
@@ -15758,6 +16008,7 @@ let JupiterDynamicForm = class extends LitElement {
15758
16008
  });
15759
16009
  this._formData = { ...this._formData, ...restoredFormData };
15760
16010
  console.log(`🔄 Restored ${Object.keys(restoredFormData).length} concepts with data`);
16011
+ this._diagnoseDimensionColumnDrift(formData);
15761
16012
  this._seedLegacyManuallyEditedTotals(restoredFormData);
15762
16013
  this._initializeGlobalDecimalsFromRoundingData();
15763
16014
  this._periodData = {
@@ -16254,6 +16505,70 @@ let JupiterDynamicForm = class extends LitElement {
16254
16505
  }
16255
16506
  return null;
16256
16507
  }
16508
+ /**
16509
+ * JDF-133 Phase 0: diagnostics-only. Walks the raw draft `formData` array `_restoreFromDraft`
16510
+ * was given — not `restoredFormData`, which has already dropped each entry's own `dimension`
16511
+ * string by the time this runs — and flags any entry whose saved `dimension` tag disagrees with
16512
+ * what its `columnId` resolves to in the schema just rebuilt for this session. Read-only:
16513
+ * populates `_dimensionColumnDriftDiagnostics` and logs, never writes to `_formData` or any
16514
+ * other state a render or a later save could observe. Builds a one-time conceptId->section index
16515
+ * (`_allSections` can run to hundreds of sections/thousands of concepts) rather than repeating
16516
+ * `_findSectionForConcept`'s linear scan once per fact, so this stays cheap enough to run
16517
+ * unconditionally on every restore without being itself a measurable behavior change.
16518
+ */
16519
+ _diagnoseDimensionColumnDrift(formData) {
16520
+ var _a, _b, _c;
16521
+ const sectionByConceptId = /* @__PURE__ */ new Map();
16522
+ const indexConcepts = (concepts, section2) => {
16523
+ concepts.forEach((concept) => {
16524
+ var _a2;
16525
+ sectionByConceptId.set(concept.id, section2);
16526
+ if ((_a2 = concept.children) == null ? void 0 : _a2.length)
16527
+ indexConcepts(concept.children, section2);
16528
+ });
16529
+ };
16530
+ this._allSections.forEach((section2) => indexConcepts(section2.concepts, section2));
16531
+ const drifted = [];
16532
+ for (const entry of formData) {
16533
+ const savedDimension = entry == null ? void 0 : entry.dimension;
16534
+ if (!savedDimension || typeof savedDimension !== "string")
16535
+ continue;
16536
+ const section2 = sectionByConceptId.get(entry.conceptId);
16537
+ const column2 = (_a = section2 == null ? void 0 : section2.columns) == null ? void 0 : _a.find((c2) => c2.id === entry.columnId);
16538
+ const currentColumnDimension = (_b = column2 == null ? void 0 : column2.dimensionData) == null ? void 0 : _b.dimensionIdKey;
16539
+ if (!currentColumnDimension)
16540
+ continue;
16541
+ if (!this._dimensionKeysMatch(savedDimension, currentColumnDimension)) {
16542
+ drifted.push({
16543
+ conceptId: entry.conceptId,
16544
+ columnId: entry.columnId,
16545
+ roleURI: ((_c = section2 == null ? void 0 : section2.metadata) == null ? void 0 : _c.roleURI) || (section2 == null ? void 0 : section2.id) || "unknown",
16546
+ value: entry.value,
16547
+ savedDimension,
16548
+ currentColumnDimension
16549
+ });
16550
+ }
16551
+ }
16552
+ this._dimensionColumnDriftDiagnostics = drifted;
16553
+ if (drifted.length > 0) {
16554
+ console.warn(
16555
+ `⚠️ [JDF-133] Detected ${drifted.length} fact(s) whose saved dimension tag no longer matches their column's current dimension — see form._dimensionColumnDriftDiagnostics. Diagnostics-only: nothing was changed or corrected.`
16556
+ );
16557
+ console.table(drifted);
16558
+ }
16559
+ }
16560
+ /** Order-independent comparison of two `axisId|memberId::axisId|memberId...` dimensionIdKey-shaped strings. */
16561
+ _dimensionKeysMatch(a2, b2) {
16562
+ const setA = new Set(a2.split("::").filter(Boolean));
16563
+ const setB = new Set(b2.split("::").filter(Boolean));
16564
+ if (setA.size !== setB.size)
16565
+ return false;
16566
+ for (const item of setA) {
16567
+ if (!setB.has(item))
16568
+ return false;
16569
+ }
16570
+ return true;
16571
+ }
16257
16572
  _findSectionForConcept(conceptId) {
16258
16573
  for (const section2 of this._allSections) {
16259
16574
  const concept = this._findConceptInSection(section2.concepts, conceptId);
@@ -16265,6 +16580,8 @@ let JupiterDynamicForm = class extends LitElement {
16265
16580
  }
16266
16581
  _addConceptDataToSubmission(concept, columnId, value, submissionData, section2) {
16267
16582
  var _a, _b, _c, _d, _e;
16583
+ if (this._isPriorYearExcludedFact(concept.id, columnId))
16584
+ return;
16268
16585
  const field2 = concept.fields.find((f2) => f2.columnId === columnId);
16269
16586
  if (!field2)
16270
16587
  return;
@@ -16437,26 +16754,25 @@ let JupiterDynamicForm = class extends LitElement {
16437
16754
  }
16438
16755
  if (concept.fields && concept.fields.length > 0) {
16439
16756
  concept.fields.forEach((field2) => {
16440
- var _a, _b, _c, _d, _e, _f, _g, _h;
16757
+ var _a, _b, _c, _d, _e, _f, _g;
16758
+ if (this._isPriorYearExcludedFact(concept.id, field2.columnId)) {
16759
+ return;
16760
+ }
16441
16761
  const conceptData = this._formData[concept.id];
16442
- let fieldValue = conceptData == null ? void 0 : conceptData[field2.columnId];
16443
16762
  const baseConceptId = field2.conceptId || concept.id.split("__").slice(0, -1).join("__") || concept.id;
16444
- if ((fieldValue === void 0 || fieldValue === null || fieldValue === "") && this._isRoundingLevelConcept(baseConceptId) && !this._hasValidGlobalDecimals()) {
16763
+ const masterDataWins = this.mode !== "admin" && !!this._effectiveMasterData && baseConceptId in this._effectiveMasterData;
16764
+ let fieldValue = masterDataWins ? this._effectiveMasterData[baseConceptId] : conceptData == null ? void 0 : conceptData[field2.columnId];
16765
+ if (masterDataWins) {
16766
+ console.log(` 📦 [Submission] Using masterData for: ${baseConceptId} [${field2.columnId}] = ${JSON.stringify(fieldValue)}`);
16767
+ } else if ((fieldValue === void 0 || fieldValue === null || fieldValue === "") && this._isRoundingLevelConcept(baseConceptId) && !this._hasValidGlobalDecimals()) {
16445
16768
  const factValue = this._findFactValueForField(concept, field2, section2);
16446
16769
  if (factValue !== void 0 && factValue !== null && factValue !== "") {
16447
16770
  fieldValue = factValue;
16448
16771
  }
16449
16772
  }
16450
- if ((fieldValue === void 0 || fieldValue === null || fieldValue === "") && this._effectiveMasterData) {
16451
- const masterValue = (_a = this._effectiveMasterData) == null ? void 0 : _a[baseConceptId];
16452
- if (masterValue !== void 0 && masterValue !== null && masterValue !== "") {
16453
- fieldValue = masterValue;
16454
- console.log(` 📦 [Submission] Using masterData for: ${baseConceptId} [${field2.columnId}] = ${JSON.stringify(fieldValue)}`);
16455
- }
16456
- }
16457
16773
  if (fieldValue !== void 0 && fieldValue !== null && fieldValue !== "") {
16458
16774
  const column2 = this._findColumnByIdInSection(field2.columnId, section2);
16459
- const fieldPeriodData = (_b = this._periodData[concept.id]) == null ? void 0 : _b[field2.columnId];
16775
+ const fieldPeriodData = (_a = this._periodData[concept.id]) == null ? void 0 : _a[field2.columnId];
16460
16776
  const submissionEntry = {
16461
16777
  conceptId: concept.id,
16462
16778
  draftInstanceId: concept.id,
@@ -16478,21 +16794,21 @@ let JupiterDynamicForm = class extends LitElement {
16478
16794
  submissionEntry.period.endDate = endDate;
16479
16795
  }
16480
16796
  console.log(`🔍 [Submission] Concept: ${concept.id}, Column: ${field2.columnId}, Field Period: ${fieldPeriodData ? JSON.stringify(fieldPeriodData) : "none"}, Column Period: ${(column2 == null ? void 0 : column2.periodStartDate) || "none"} - ${(column2 == null ? void 0 : column2.periodEndDate) || "none"}, Used Period: ${submissionEntry.period.type === "instant" ? submissionEntry.period.date : `${submissionEntry.period.startDate} - ${submissionEntry.period.endDate}`}`);
16481
- const fieldUnit = (_c = this._unitData[concept.id]) == null ? void 0 : _c[field2.columnId];
16797
+ const fieldUnit = (_b = this._unitData[concept.id]) == null ? void 0 : _b[field2.columnId];
16482
16798
  if (fieldUnit) {
16483
16799
  submissionEntry.unit = fieldUnit;
16484
16800
  console.log(`✅ [Submission] Adding unit to entry: ${fieldUnit} for ${concept.id}/${field2.columnId}`);
16485
16801
  } else {
16486
16802
  console.log(`⚠️ [Submission] No unit found in _unitData for ${concept.id}/${field2.columnId}. _unitData state:`, JSON.stringify(this._unitData, null, 2));
16487
16803
  }
16488
- const isMonetary = (_d = concept.type) == null ? void 0 : _d.toLowerCase().includes("monetary");
16489
- const fieldDecimals = (_e = this._decimalsData[concept.id]) == null ? void 0 : _e[field2.columnId];
16804
+ const isMonetary = (_c = concept.type) == null ? void 0 : _c.toLowerCase().includes("monetary");
16805
+ const fieldDecimals = (_d = this._decimalsData[concept.id]) == null ? void 0 : _d[field2.columnId];
16490
16806
  const decimalsValue = fieldDecimals || (this.decimals !== "INF" ? this.decimals : void 0);
16491
16807
  if (isMonetary && decimalsValue) {
16492
16808
  const parsed = parseFloat(decimalsValue);
16493
16809
  submissionEntry.decimals = isNaN(parsed) ? decimalsValue : String(-Math.abs(parsed));
16494
16810
  }
16495
- if ((column2 == null ? void 0 : column2.type) === "dimension" && ((_f = column2.dimensionData) == null ? void 0 : _f.dimensionIdKey)) {
16811
+ if ((column2 == null ? void 0 : column2.type) === "dimension" && ((_e = column2.dimensionData) == null ? void 0 : _e.dimensionIdKey)) {
16496
16812
  submissionEntry.dimension = column2.dimensionData.dimensionIdKey;
16497
16813
  console.log(`🔍 [DynamicForm] Using dimension key from field's column (${field2.columnId}):`, column2.dimensionData.dimensionIdKey);
16498
16814
  } else {
@@ -16531,12 +16847,12 @@ let JupiterDynamicForm = class extends LitElement {
16531
16847
  console.log(`🔍 [DynamicForm] Column details:`, {
16532
16848
  id: column2.id,
16533
16849
  type: column2.type,
16534
- hasTypedMembers: (_g = column2.dimensionData) == null ? void 0 : _g.hasTypedMembers,
16850
+ hasTypedMembers: (_f = column2.dimensionData) == null ? void 0 : _f.hasTypedMembers,
16535
16851
  dimensionData: column2.dimensionData
16536
16852
  });
16537
16853
  }
16538
16854
  }
16539
- if (!submissionEntry.typedMembers && ((_h = field2.crossRoleTypedMembers) == null ? void 0 : _h.length)) {
16855
+ if (!submissionEntry.typedMembers && ((_g = field2.crossRoleTypedMembers) == null ? void 0 : _g.length)) {
16540
16856
  const crossRoleKey = `${concept.id}__${field2.columnId}`;
16541
16857
  const crossRoleValues = this._typedMemberData[crossRoleKey];
16542
16858
  if (crossRoleValues) {
@@ -16627,7 +16943,7 @@ let JupiterDynamicForm = class extends LitElement {
16627
16943
  });
16628
16944
  }
16629
16945
  _handleReset() {
16630
- this._formData = { ...this.initialData };
16946
+ this._formData = this._stripPriorYearExcludedFacts(this.initialData);
16631
16947
  this._touched.clear();
16632
16948
  this._dirty = false;
16633
16949
  this.hasUnsavedChanges = false;
@@ -17394,6 +17710,7 @@ let JupiterDynamicForm = class extends LitElement {
17394
17710
  .periodEndDate="${this.periodEndDate}"
17395
17711
  .calculationEnabled="${this.calculationEnabled}"
17396
17712
  .totalManuallyEditedData="${this._totalManuallyEditedData}"
17713
+ .duplicateFactWarnings="${this._duplicateFactWarnings}"
17397
17714
  @field-change="${this._handleFieldChange}"
17398
17715
  @period-change="${this._handlePeriodChange}"
17399
17716
  @typed-member-change="${this._handleTypedMemberChange}"
@@ -17601,6 +17918,7 @@ let JupiterDynamicForm = class extends LitElement {
17601
17918
  .periodEndDate="${this.periodEndDate}"
17602
17919
  .calculationEnabled="${this.calculationEnabled}"
17603
17920
  .totalManuallyEditedData="${this._totalManuallyEditedData}"
17921
+ .duplicateFactWarnings="${this._duplicateFactWarnings}"
17604
17922
  @field-change="${this._handleFieldChange}"
17605
17923
  @typed-member-change="${this._handleTypedMemberChange}"
17606
17924
  @add-concept-repeat="${this._handleAddConceptRepeat}"
@@ -17653,7 +17971,7 @@ let JupiterDynamicForm = class extends LitElement {
17653
17971
  return { ...this._formData };
17654
17972
  }
17655
17973
  setData(data) {
17656
- this._formData = { ...data };
17974
+ this._formData = this._stripPriorYearExcludedFacts(data);
17657
17975
  this._dirty = true;
17658
17976
  this.hasUnsavedChanges = true;
17659
17977
  this._validateForm();
@@ -18464,14 +18782,21 @@ let JupiterDynamicForm = class extends LitElement {
18464
18782
  ` : ""}
18465
18783
  </div>
18466
18784
  <div class="error-popup-footer">
18467
- <button class="btn-secondary" @click="${() => {
18785
+ ${this._duplicateWarningPopupMode === "validate" ? html`
18786
+ <button class="btn-secondary" @click="${() => {
18468
18787
  this._showValidateWarningPopup = false;
18469
18788
  this.requestUpdate();
18470
18789
  }}">${I18n.t("typedDimensionWarning.cancel")}</button>
18471
- <button class="btn-primary" @click="${() => {
18790
+ <button class="btn-primary" @click="${() => {
18472
18791
  this._showValidateWarningPopup = false;
18473
18792
  this._continueSubmit();
18474
18793
  }}">${I18n.t("typedDimensionWarning.continue")}</button>
18794
+ ` : html`
18795
+ <button class="btn-primary" @click="${() => {
18796
+ this._showValidateWarningPopup = false;
18797
+ this.requestUpdate();
18798
+ }}">${I18n.t("duplicateFactWarning.close")}</button>
18799
+ `}
18475
18800
  </div>
18476
18801
  </div>
18477
18802
  </div>
@@ -19605,6 +19930,12 @@ __decorateClass([
19605
19930
  __decorateClass([
19606
19931
  r()
19607
19932
  ], JupiterDynamicForm.prototype, "_duplicateFactMismatches", 2);
19933
+ __decorateClass([
19934
+ r()
19935
+ ], JupiterDynamicForm.prototype, "_duplicateFactWarnings", 2);
19936
+ __decorateClass([
19937
+ r()
19938
+ ], JupiterDynamicForm.prototype, "_duplicateWarningPopupMode", 2);
19608
19939
  __decorateClass([
19609
19940
  r()
19610
19941
  ], JupiterDynamicForm.prototype, "_submitDisabled", 2);