jupiter-dynamic-forms 1.16.6 → 1.16.8

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
@@ -4215,6 +4215,13 @@ let JupiterConceptTree = class extends LitElement {
4215
4215
  composed: true
4216
4216
  }));
4217
4217
  }
4218
+ _handleFieldFocus(event) {
4219
+ event.stopPropagation();
4220
+ this.dispatchEvent(new CustomEvent("field-focus", {
4221
+ detail: event.detail,
4222
+ bubbles: true
4223
+ }));
4224
+ }
4218
4225
  _handlePeriodChange(event) {
4219
4226
  console.log(`🌲 [ConceptTree] Received period-change event:`, event.detail);
4220
4227
  event.stopPropagation();
@@ -4260,12 +4267,12 @@ let JupiterConceptTree = class extends LitElement {
4260
4267
 
4261
4268
  <!-- Input Field Cells (Period Columns) - Only for non-abstract concepts -->
4262
4269
  ${this.columns.map((column2) => {
4263
- var _a, _b;
4270
+ var _a, _b, _c;
4264
4271
  const field2 = this._getFieldForColumn(column2.id);
4265
4272
  const shouldShowField = !isAbstract && field2;
4266
4273
  const storedUnit = (_b = (_a = this.unitData) == null ? void 0 : _a[this.concept.id]) == null ? void 0 : _b[column2.id];
4267
4274
  return html`
4268
- <td class="field-cell ${!shouldShowField ? "empty" : ""} ${isAbstract ? "abstract-row" : ""}">
4275
+ <td class="field-cell ${!shouldShowField ? "empty" : ""} ${isAbstract ? "abstract-row" : ""} ${this.highlightType && column2.id === this.highlightColumnId ? "highlight-" + this.highlightType : ""} ${((_c = this.calculationErrorKeys) == null ? void 0 : _c.has(`${this.concept.id}__${column2.id}`)) ? "calc-error" : ""}">
4269
4276
  ${shouldShowField ? html`
4270
4277
  <jupiter-form-field
4271
4278
  .field="${field2}"
@@ -4288,6 +4295,7 @@ let JupiterConceptTree = class extends LitElement {
4288
4295
  .column="${column2}"
4289
4296
  .typedMemberValues="${this.typedMemberData[`${this.concept.id}__${column2.id}`] || {}}"
4290
4297
  @field-change="${this._handleFieldChange}"
4298
+ @field-focus="${this._handleFieldFocus}"
4291
4299
  @period-change="${this._handlePeriodChange}"
4292
4300
  ></jupiter-form-field>
4293
4301
  ` : ""}
@@ -4455,6 +4463,18 @@ JupiterConceptTree.styles = css`
4455
4463
  color: #fff;
4456
4464
  }
4457
4465
 
4466
+ .field-cell.highlight-total {
4467
+ background: rgba(25, 118, 210, 0.15);
4468
+ }
4469
+
4470
+ .field-cell.highlight-member {
4471
+ background: rgba(25, 118, 210, 0.07);
4472
+ }
4473
+
4474
+ .field-cell.calc-error {
4475
+ box-shadow: inset 0 0 0 2px var(--jupiter-error-color, #d32f2f);
4476
+ }
4477
+
4458
4478
  `;
4459
4479
  __decorateClass$4([
4460
4480
  n2({ type: Object })
@@ -4504,6 +4524,15 @@ __decorateClass$4([
4504
4524
  __decorateClass$4([
4505
4525
  n2({ type: Boolean })
4506
4526
  ], JupiterConceptTree.prototype, "showRemoveButton", 2);
4527
+ __decorateClass$4([
4528
+ n2({ type: String })
4529
+ ], JupiterConceptTree.prototype, "highlightType", 2);
4530
+ __decorateClass$4([
4531
+ n2({ type: String })
4532
+ ], JupiterConceptTree.prototype, "highlightColumnId", 2);
4533
+ __decorateClass$4([
4534
+ n2({ type: Object })
4535
+ ], JupiterConceptTree.prototype, "calculationErrorKeys", 2);
4507
4536
  __decorateClass$4([
4508
4537
  r()
4509
4538
  ], JupiterConceptTree.prototype, "_expanded", 2);
@@ -5131,8 +5160,20 @@ let JupiterFormSection = class extends LitElement {
5131
5160
  this._sectionPeriodType = "duration";
5132
5161
  this._openMenuColumnId = null;
5133
5162
  this._insertAfterColumnId = null;
5163
+ this._boundFieldBlur = (e2) => {
5164
+ this._clearHighlights();
5165
+ const { conceptId, columnId } = e2.detail || {};
5166
+ if (conceptId && columnId)
5167
+ this._runCalculationCheck(conceptId, columnId);
5168
+ };
5134
5169
  this._expandedConcepts = /* @__PURE__ */ new Set();
5135
5170
  this._allTreeExpanded = false;
5171
+ this._highlightMap = /* @__PURE__ */ new Map();
5172
+ this._calculationErrorKeys = /* @__PURE__ */ new Set();
5173
+ this._totalChildrenMap = /* @__PURE__ */ new Map();
5174
+ this._memberParentMap = /* @__PURE__ */ new Map();
5175
+ this._totalConceptMap = /* @__PURE__ */ new Map();
5176
+ this._totalChildConceptsMap = /* @__PURE__ */ new Map();
5136
5177
  }
5137
5178
  connectedCallback() {
5138
5179
  super.connectedCallback();
@@ -5140,16 +5181,22 @@ let JupiterFormSection = class extends LitElement {
5140
5181
  this._determinePeriodType();
5141
5182
  this._checkAndExpandFirstSection();
5142
5183
  document.addEventListener("click", () => this._closeColumnMenu());
5184
+ this.addEventListener("field-blur", this._boundFieldBlur);
5143
5185
  }
5144
5186
  disconnectedCallback() {
5145
5187
  super.disconnectedCallback();
5146
5188
  document.removeEventListener("click", () => this._closeColumnMenu());
5189
+ this.removeEventListener("field-blur", this._boundFieldBlur);
5147
5190
  }
5148
5191
  updated(changedProperties) {
5192
+ var _a;
5149
5193
  super.updated(changedProperties);
5150
5194
  if (changedProperties.has("isFirstSection") || changedProperties.has("section")) {
5151
5195
  this._checkAndExpandFirstSection();
5152
5196
  }
5197
+ if (changedProperties.has("section") && ((_a = this.section) == null ? void 0 : _a.concepts)) {
5198
+ this._buildTotalMaps(this.section.concepts);
5199
+ }
5153
5200
  }
5154
5201
  _checkAndExpandFirstSection() {
5155
5202
  if (this.isFirstSection && this.section && this.section.concepts) {
@@ -5334,31 +5381,135 @@ let JupiterFormSection = class extends LitElement {
5334
5381
  }
5335
5382
  _expandAllTrees() {
5336
5383
  const allConceptIds = this._getAllConceptIds(this.section.concepts || []);
5337
- allConceptIds.forEach((id) => this._expandedConcepts.add(id));
5384
+ this._expandedConcepts = /* @__PURE__ */ new Set([...this._expandedConcepts, ...allConceptIds]);
5338
5385
  this._allTreeExpanded = true;
5339
- this.requestUpdate();
5340
5386
  }
5341
5387
  _collapseAllTrees() {
5342
- this._expandedConcepts.clear();
5388
+ this._expandedConcepts = /* @__PURE__ */ new Set();
5343
5389
  this._allTreeExpanded = false;
5344
- this.requestUpdate();
5345
5390
  }
5346
5391
  _handleConceptExpand(event) {
5347
5392
  event.stopPropagation();
5348
5393
  const { conceptId, expanded } = event.detail;
5394
+ const next = new Set(this._expandedConcepts);
5349
5395
  if (expanded) {
5350
- this._expandedConcepts.add(conceptId);
5396
+ next.add(conceptId);
5351
5397
  } else {
5352
- this._expandedConcepts.delete(conceptId);
5398
+ next.delete(conceptId);
5353
5399
  }
5400
+ this._expandedConcepts = next;
5354
5401
  const allConceptIds = this._getAllConceptIds(this.section.concepts || []);
5355
- this._allTreeExpanded = allConceptIds.length > 0 && allConceptIds.every((id) => this._expandedConcepts.has(id));
5356
- this.requestUpdate();
5402
+ this._allTreeExpanded = allConceptIds.length > 0 && allConceptIds.every((id) => next.has(id));
5357
5403
  this.dispatchEvent(new CustomEvent("concept-expand", {
5358
5404
  detail: event.detail,
5359
5405
  bubbles: true
5360
5406
  }));
5361
5407
  }
5408
+ _buildTotalMaps(concepts) {
5409
+ this._totalChildrenMap.clear();
5410
+ this._memberParentMap.clear();
5411
+ this._totalConceptMap.clear();
5412
+ this._totalChildConceptsMap.clear();
5413
+ this._traverseTotalGroups(concepts);
5414
+ }
5415
+ _traverseTotalGroups(concepts) {
5416
+ var _a, _b, _c;
5417
+ for (const concept of concepts) {
5418
+ if (((_a = concept.preferredLabel) == null ? void 0 : _a.includes("totalLabel")) && ((_b = concept.children) == null ? void 0 : _b.length)) {
5419
+ const childIds = concept.children.map((c2) => c2.id);
5420
+ this._totalChildrenMap.set(concept.id, childIds);
5421
+ this._totalConceptMap.set(concept.id, concept);
5422
+ this._totalChildConceptsMap.set(concept.id, concept.children);
5423
+ for (const childId of childIds) {
5424
+ this._memberParentMap.set(childId, concept.id);
5425
+ }
5426
+ }
5427
+ if ((_c = concept.children) == null ? void 0 : _c.length) {
5428
+ this._traverseTotalGroups(concept.children);
5429
+ }
5430
+ }
5431
+ }
5432
+ _runCalculationCheck(conceptId, columnId) {
5433
+ var _a;
5434
+ const isSelfTotal = this._totalConceptMap.has(conceptId);
5435
+ const totalConceptId = isSelfTotal ? conceptId : this._memberParentMap.get(conceptId);
5436
+ if (!totalConceptId)
5437
+ return;
5438
+ const totalConcept = this._totalConceptMap.get(totalConceptId);
5439
+ const totalRaw = (_a = this.formData[totalConceptId]) == null ? void 0 : _a[columnId];
5440
+ const errorKey = `${totalConceptId}__${columnId}`;
5441
+ if (totalRaw === null || totalRaw === void 0 || totalRaw === "") {
5442
+ if (this._calculationErrorKeys.has(errorKey)) {
5443
+ const next2 = new Set(this._calculationErrorKeys);
5444
+ next2.delete(errorKey);
5445
+ this._calculationErrorKeys = next2;
5446
+ }
5447
+ return;
5448
+ }
5449
+ const totalValue = parseFloat(totalRaw);
5450
+ if (isNaN(totalValue))
5451
+ return;
5452
+ const children = this._totalChildConceptsMap.get(totalConceptId) || [];
5453
+ const childData = children.map((child) => {
5454
+ var _a2;
5455
+ return {
5456
+ value: (_a2 = this.formData[child.id]) == null ? void 0 : _a2[columnId],
5457
+ balance: child.balance
5458
+ };
5459
+ });
5460
+ const isValid = JupiterFormSection._checkTotal(totalValue, childData, totalConcept.balance);
5461
+ const next = new Set(this._calculationErrorKeys);
5462
+ if (!isValid) {
5463
+ next.add(errorKey);
5464
+ } else {
5465
+ next.delete(errorKey);
5466
+ }
5467
+ this._calculationErrorKeys = next;
5468
+ }
5469
+ static _checkTotal(totalValue, children, totalBalance) {
5470
+ let calculatedSum = 0;
5471
+ let hasAnyValue = false;
5472
+ for (const child of children) {
5473
+ const val = parseFloat(child.value);
5474
+ if (isNaN(val))
5475
+ continue;
5476
+ hasAnyValue = true;
5477
+ const weight = !totalBalance || !child.balance || totalBalance === child.balance ? 1 : -1;
5478
+ calculatedSum += weight * val;
5479
+ }
5480
+ if (!hasAnyValue)
5481
+ return true;
5482
+ return Math.abs(calculatedSum - totalValue) < 0.01;
5483
+ }
5484
+ _handleFieldFocusForHighlight(event) {
5485
+ var _a, _b;
5486
+ const conceptId = (_a = event.detail) == null ? void 0 : _a.conceptId;
5487
+ const columnId = (_b = event.detail) == null ? void 0 : _b.columnId;
5488
+ if (!conceptId || !columnId)
5489
+ return;
5490
+ const newMap = /* @__PURE__ */ new Map();
5491
+ const isSelfTotal = this._totalChildrenMap.has(conceptId);
5492
+ if (isSelfTotal) {
5493
+ newMap.set(conceptId, { type: "total", columnId });
5494
+ for (const childId of this._totalChildrenMap.get(conceptId)) {
5495
+ newMap.set(childId, { type: "member", columnId });
5496
+ }
5497
+ } else {
5498
+ const parentId = this._memberParentMap.get(conceptId);
5499
+ if (parentId) {
5500
+ newMap.set(parentId, { type: "total", columnId });
5501
+ for (const siblingId of this._totalChildrenMap.get(parentId)) {
5502
+ newMap.set(siblingId, { type: "member", columnId });
5503
+ }
5504
+ }
5505
+ }
5506
+ this._highlightMap = newMap;
5507
+ }
5508
+ _clearHighlights() {
5509
+ if (this._highlightMap.size > 0) {
5510
+ this._highlightMap = /* @__PURE__ */ new Map();
5511
+ }
5512
+ }
5362
5513
  _getTypedMemberHeaderValue(columnId, axisId) {
5363
5514
  var _a;
5364
5515
  return ((_a = this.typedMemberData[columnId]) == null ? void 0 : _a[axisId]) || "";
@@ -5398,7 +5549,9 @@ let JupiterFormSection = class extends LitElement {
5398
5549
  return ((_a2 = f2.crossRoleTypedMembers) == null ? void 0 : _a2.length) > 0;
5399
5550
  }));
5400
5551
  const repeatCount = isRepeatable ? this.repeatCounts[concept.id] || 0 : 0;
5401
- const sharedProps = (instanceConcept, opts) => html`
5552
+ const sharedProps = (instanceConcept, opts) => {
5553
+ var _a2, _b;
5554
+ return html`
5402
5555
  <jupiter-concept-tree
5403
5556
  .concept="${instanceConcept}"
5404
5557
  .columns="${this.columns}"
@@ -5416,13 +5569,18 @@ let JupiterFormSection = class extends LitElement {
5416
5569
  .typedMemberData="${this.typedMemberData}"
5417
5570
  .showAddButton="${opts.showAdd || false}"
5418
5571
  .showRemoveButton="${opts.showRemove || false}"
5572
+ .highlightType="${(_a2 = this._highlightMap.get(instanceConcept.id)) == null ? void 0 : _a2.type}"
5573
+ .highlightColumnId="${(_b = this._highlightMap.get(instanceConcept.id)) == null ? void 0 : _b.columnId}"
5574
+ .calculationErrorKeys="${this._calculationErrorKeys}"
5419
5575
  @field-change="${this._handleFieldChange}"
5576
+ @field-focus="${this._handleFieldFocusForHighlight}"
5420
5577
  @period-change="${this._handlePeriodChange}"
5421
5578
  @concept-expand="${this._handleConceptExpand}"
5422
5579
  @add-concept-repeat="${this._handleAddRepeat}"
5423
5580
  @remove-concept-repeat="${this._handleRemoveRepeat}"
5424
5581
  ></jupiter-concept-tree>
5425
5582
  `;
5583
+ };
5426
5584
  const rows = [html`
5427
5585
  <tr>${sharedProps(concept, { showAdd: isRepeatable })}</tr>
5428
5586
  `];
@@ -5923,6 +6081,12 @@ __decorateClass$2([
5923
6081
  __decorateClass$2([
5924
6082
  r()
5925
6083
  ], JupiterFormSection.prototype, "_allTreeExpanded", 2);
6084
+ __decorateClass$2([
6085
+ r()
6086
+ ], JupiterFormSection.prototype, "_highlightMap", 2);
6087
+ __decorateClass$2([
6088
+ r()
6089
+ ], JupiterFormSection.prototype, "_calculationErrorKeys", 2);
5926
6090
  JupiterFormSection = __decorateClass$2([
5927
6091
  t$1("jupiter-form-section")
5928
6092
  ], JupiterFormSection);
@@ -7049,10 +7213,10 @@ JupiterFilterRolesDialog.styles = css`
7049
7213
  transition: all 0.2s ease;
7050
7214
  }
7051
7215
 
7052
- .selection-control:hover {
7053
- background: var(--menuBgColorLighter, var(--jupiter-primary-color, #1976d2));
7054
- color: white;
7055
- }
7216
+ // .selection-control:hover {
7217
+ // background: var(--menuBgColorLighter, var(--jupiter-primary-color, #1976d2));
7218
+ // color: white;
7219
+ // }
7056
7220
 
7057
7221
  .roles-list {
7058
7222
  display: flex;
@@ -11034,7 +11198,7 @@ let JupiterDynamicForm = class extends LitElement {
11034
11198
 
11035
11199
  ${this._validationStatus === "complete" || this.showLastValidationResultBtn ? html`
11036
11200
  <button
11037
- class="btn-last-results"
11201
+ class="btn-secondary btn-last-results"
11038
11202
  @click="${() => this.dispatchEvent(new CustomEvent("show-validation-results", { bubbles: true, composed: true }))}"
11039
11203
  ?disabled="${this.disabled || this.readonly}"
11040
11204
  >
@@ -11290,14 +11454,6 @@ JupiterDynamicForm.styles = css`
11290
11454
  background: var(--jupiter-primary-color-dark, #1565c0);
11291
11455
  }
11292
11456
 
11293
- .btn-last-results {
11294
- background: var(--jupiter-primary-color, #1976d2);
11295
- color: white;
11296
- }
11297
- .btn-last-results:hover:not(:disabled) {
11298
- background: var(--jupiter-primary-color, #1976d2);
11299
- color: white;
11300
- }
11301
11457
 
11302
11458
  .validation-spinner {
11303
11459
  display: inline-block;
@@ -11367,15 +11523,15 @@ JupiterDynamicForm.styles = css`
11367
11523
  .no-roles-message {
11368
11524
  padding: 40px;
11369
11525
  text-align: center;
11370
- color: var(--jupiter-text-secondary, #666);
11371
- background: var(--jupiter-background-light, #f8f9fa);
11526
+ color: var(--primaryTextColor, var(--jupiter-text-secondary, #666));
11527
+ background: var(--bg-color-2, var(--jupiter-background-light, #f8f9fa));
11372
11528
  border-radius: 8px;
11373
11529
  margin: 20px 0;
11374
11530
  }
11375
11531
 
11376
11532
  .no-roles-message h3 {
11377
11533
  margin: 0 0 16px 0;
11378
- color: var(--jupiter-text-primary, #333);
11534
+ color: var(--primaryTextColor, var(--jupiter-text-primary, #333));
11379
11535
  }
11380
11536
 
11381
11537
  .no-roles-message p {
@@ -11510,11 +11666,12 @@ JupiterDynamicForm.styles = css`
11510
11666
 
11511
11667
  .side-panel-search-results-info {
11512
11668
  font-size: 12px;
11513
- color: var(--jupiter-text-secondary, #666);
11514
11669
  padding: 8px 16px;
11515
11670
  text-align: center;
11516
11671
  border-bottom: 1px solid var(--jupiter-border-color, #e0e0e0);
11517
- background: var(--jupiter-background-light, #f8f9fa);
11672
+
11673
+ color: var(--primaryTextColor, var(--jupiter-text-secondary, #666));
11674
+ background: var(--bg-color-2, var(--jupiter-background-light, #f8f9fa));
11518
11675
  }
11519
11676
 
11520
11677
  .side-panel-no-results {
@@ -11573,6 +11730,7 @@ JupiterDynamicForm.styles = css`
11573
11730
  flex: 1;
11574
11731
  overflow-y: auto;
11575
11732
  padding: 0;
11733
+ background: var(--bg-color-2, var(--jupiter-background, #fff));
11576
11734
  }
11577
11735
 
11578
11736
  .side-panel-content .form-sections {