jupiter-dynamic-forms 1.20.1 → 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/core/dynamic-form.d.ts +1 -0
- package/dist/core/dynamic-form.d.ts.map +1 -1
- package/dist/core/form-section.d.ts +46 -1
- package/dist/core/form-section.d.ts.map +1 -1
- package/dist/index.js +10 -8
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +120 -15
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -6154,6 +6154,7 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6154
6154
|
this.periodStartDate = "";
|
|
6155
6155
|
this.periodEndDate = "";
|
|
6156
6156
|
this.language = "en";
|
|
6157
|
+
this.calculationEnabled = false;
|
|
6157
6158
|
this._expanded = true;
|
|
6158
6159
|
this._showAddColumnDialog = false;
|
|
6159
6160
|
this._sectionPeriodType = "duration";
|
|
@@ -6162,7 +6163,7 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6162
6163
|
this._boundFieldBlur = (e2) => {
|
|
6163
6164
|
this._clearHighlights();
|
|
6164
6165
|
this._focusedConceptId = null;
|
|
6165
|
-
if (this.mode === "readonly")
|
|
6166
|
+
if (this.mode === "readonly" || !this.calculationEnabled)
|
|
6166
6167
|
return;
|
|
6167
6168
|
const detail = e2.detail;
|
|
6168
6169
|
if ((detail == null ? void 0 : detail.conceptId) && (detail == null ? void 0 : detail.columnId)) {
|
|
@@ -6198,8 +6199,12 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6198
6199
|
if (changedProperties.has("isFirstSection") || changedProperties.has("section")) {
|
|
6199
6200
|
this._checkAndExpandFirstSection();
|
|
6200
6201
|
}
|
|
6201
|
-
if (changedProperties.has("section")
|
|
6202
|
-
this.
|
|
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
|
+
}
|
|
6203
6208
|
}
|
|
6204
6209
|
}
|
|
6205
6210
|
_checkAndExpandFirstSection() {
|
|
@@ -6435,6 +6440,21 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6435
6440
|
this._totalChildConceptsMap.clear();
|
|
6436
6441
|
this._traverseTotalGroups(concepts);
|
|
6437
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
|
+
}
|
|
6438
6458
|
/**
|
|
6439
6459
|
* JDF-038: XBRL uses more than one preferredLabel role to mark a "total" row — the plain
|
|
6440
6460
|
* `.../role/totalLabel` and the sign-flipped `.../role/negatedTotalLabel` (used for subtotals of
|
|
@@ -6445,6 +6465,15 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6445
6465
|
static _isTotalLabel(preferredLabel) {
|
|
6446
6466
|
return !!(preferredLabel == null ? void 0 : preferredLabel.toLowerCase().includes("totallabel"));
|
|
6447
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
|
+
}
|
|
6448
6477
|
/**
|
|
6449
6478
|
* A member of a total's sibling/child group can itself be a presentation-only abstract wrapper
|
|
6450
6479
|
* (e.g. "Group equity" wrapping Equity + Third party share + "Total of group equity") rather than
|
|
@@ -6475,6 +6504,47 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6475
6504
|
this._memberParentMap.set(memberId, totalConcept.id);
|
|
6476
6505
|
}
|
|
6477
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
|
+
}
|
|
6478
6548
|
_traverseTotalGroups(concepts) {
|
|
6479
6549
|
var _a, _b;
|
|
6480
6550
|
for (let i2 = 0; i2 < concepts.length; i2++) {
|
|
@@ -6491,10 +6561,9 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6491
6561
|
}
|
|
6492
6562
|
}
|
|
6493
6563
|
const siblings = concepts.slice(lastTotalIdx + 1, i2);
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
this._registerTotalGroup(concept, [concepts[lastTotalIdx]]);
|
|
6564
|
+
const members = this._resolveTotalGroupMembers(concepts, i2, lastTotalIdx, siblings);
|
|
6565
|
+
if (members.length > 0) {
|
|
6566
|
+
this._registerTotalGroup(concept, members);
|
|
6498
6567
|
}
|
|
6499
6568
|
}
|
|
6500
6569
|
}
|
|
@@ -6529,7 +6598,7 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6529
6598
|
return;
|
|
6530
6599
|
}
|
|
6531
6600
|
const children = this._totalChildConceptsMap.get(totalConceptId) || [];
|
|
6532
|
-
const { calculatedSum, hasAnyValue, breakdown } =
|
|
6601
|
+
const { calculatedSum, hasAnyValue, breakdown } = this._buildCalculationBreakdown(
|
|
6533
6602
|
children,
|
|
6534
6603
|
this.formData,
|
|
6535
6604
|
columnId,
|
|
@@ -6576,19 +6645,46 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6576
6645
|
static _resolveWeight(totalBalance, childBalance) {
|
|
6577
6646
|
return !totalBalance || !childBalance || totalBalance === childBalance ? 1 : -1;
|
|
6578
6647
|
}
|
|
6579
|
-
|
|
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) {
|
|
6580
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) {
|
|
6581
6677
|
let calculatedSum = 0;
|
|
6582
6678
|
let hasAnyValue = false;
|
|
6583
6679
|
const breakdown = [];
|
|
6584
6680
|
for (const child of children) {
|
|
6585
|
-
const val = parseFloat((_a = formData[child.id]) == null ? void 0 : _a[columnId]);
|
|
6586
|
-
if (isNaN(val))
|
|
6587
|
-
continue;
|
|
6588
|
-
hasAnyValue = true;
|
|
6589
6681
|
const weight = JupiterFormSection._resolveWeight(totalBalance, child.balance);
|
|
6590
|
-
|
|
6591
|
-
|
|
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
|
+
}
|
|
6592
6688
|
}
|
|
6593
6689
|
return { calculatedSum, hasAnyValue, breakdown };
|
|
6594
6690
|
}
|
|
@@ -7251,6 +7347,9 @@ __decorateClass$3([
|
|
|
7251
7347
|
__decorateClass$3([
|
|
7252
7348
|
n2({ type: String })
|
|
7253
7349
|
], JupiterFormSection.prototype, "language", 2);
|
|
7350
|
+
__decorateClass$3([
|
|
7351
|
+
n2({ type: Boolean })
|
|
7352
|
+
], JupiterFormSection.prototype, "calculationEnabled", 2);
|
|
7254
7353
|
__decorateClass$3([
|
|
7255
7354
|
r()
|
|
7256
7355
|
], JupiterFormSection.prototype, "_expanded", 2);
|
|
@@ -9292,6 +9391,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
9292
9391
|
this.initialData = {};
|
|
9293
9392
|
this.disabled = false;
|
|
9294
9393
|
this.readonly = false;
|
|
9394
|
+
this.calculationEnabled = false;
|
|
9295
9395
|
this.periodStartDate = "2025-01-01";
|
|
9296
9396
|
this.periodEndDate = "2025-12-31";
|
|
9297
9397
|
this.language = "en";
|
|
@@ -13035,6 +13135,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
13035
13135
|
.masterData="${this._effectiveMasterData}"
|
|
13036
13136
|
.periodStartDate="${this.periodStartDate}"
|
|
13037
13137
|
.periodEndDate="${this.periodEndDate}"
|
|
13138
|
+
.calculationEnabled="${this.calculationEnabled}"
|
|
13038
13139
|
@field-change="${this._handleFieldChange}"
|
|
13039
13140
|
@period-change="${this._handlePeriodChange}"
|
|
13040
13141
|
@typed-member-change="${this._handleTypedMemberChange}"
|
|
@@ -13182,6 +13283,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
13182
13283
|
.masterData="${this._effectiveMasterData}"
|
|
13183
13284
|
.periodStartDate="${this.periodStartDate}"
|
|
13184
13285
|
.periodEndDate="${this.periodEndDate}"
|
|
13286
|
+
.calculationEnabled="${this.calculationEnabled}"
|
|
13185
13287
|
@field-change="${this._handleFieldChange}"
|
|
13186
13288
|
@typed-member-change="${this._handleTypedMemberChange}"
|
|
13187
13289
|
@add-concept-repeat="${this._handleAddConceptRepeat}"
|
|
@@ -14518,6 +14620,9 @@ __decorateClass([
|
|
|
14518
14620
|
__decorateClass([
|
|
14519
14621
|
n2({ type: Boolean })
|
|
14520
14622
|
], JupiterDynamicForm.prototype, "readonly", 2);
|
|
14623
|
+
__decorateClass([
|
|
14624
|
+
n2({ type: Boolean, attribute: "calculation-enabled" })
|
|
14625
|
+
], JupiterDynamicForm.prototype, "calculationEnabled", 2);
|
|
14521
14626
|
__decorateClass([
|
|
14522
14627
|
n2({ type: String })
|
|
14523
14628
|
], JupiterDynamicForm.prototype, "periodStartDate", 2);
|