jupiter-dynamic-forms 1.15.1 → 1.15.3

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
@@ -3073,18 +3073,29 @@ let JupiterFormField = class extends LitElement {
3073
3073
  if (availableUnits.length === 0) {
3074
3074
  return;
3075
3075
  }
3076
- if (!this.unit) {
3077
- this._xbrlErrors = [
3078
- ...this._xbrlErrors,
3079
- {
3080
- type: "unit",
3081
- message: I18n.t("validation.unitRequired"),
3082
- expectedValue: availableUnits.map((u2) => u2.label).join(", "),
3083
- actualValue: ""
3084
- }
3085
- ];
3086
- console.log(`❌ [FormField] Unit validation failed for ${this.conceptId}: unit is required but not selected`);
3076
+ if (this.unit)
3077
+ return;
3078
+ const defaultUnit = availableUnits.find((u2) => u2.isDefault === true) ?? (availableUnits.length === 1 ? availableUnits[0] : null);
3079
+ if (defaultUnit) {
3080
+ this.unit = defaultUnit.id;
3081
+ this.dispatchEvent(new CustomEvent("unit-change", {
3082
+ detail: { fieldId: this.field.id, conceptId: this.conceptId, columnId: this.columnId, unit: this.unit },
3083
+ bubbles: true,
3084
+ composed: true
3085
+ }));
3086
+ console.log(`🎯 [FormField] Auto-selected default unit on blur: ${this.unit} for ${this.conceptId}`);
3087
+ return;
3087
3088
  }
3089
+ this._xbrlErrors = [
3090
+ ...this._xbrlErrors,
3091
+ {
3092
+ type: "unit",
3093
+ message: I18n.t("validation.unitRequired"),
3094
+ expectedValue: availableUnits.map((u2) => u2.label).join(", "),
3095
+ actualValue: ""
3096
+ }
3097
+ ];
3098
+ console.log(`❌ [FormField] Unit validation failed for ${this.conceptId}: unit is required but not selected`);
3088
3099
  }
3089
3100
  _handlePeriodIconClick() {
3090
3101
  this._availableUnits = this._collectUnitsForConceptType();
@@ -3512,7 +3523,7 @@ let JupiterFormField = class extends LitElement {
3512
3523
  }
3513
3524
  const hasUserValue = this.value !== null && this.value !== void 0;
3514
3525
  const effectiveValue = isPredefinedValue ? this.masterData[baseConceptId] : hasUserValue ? this.value : factValue;
3515
- const effectiveDisabled = isPredefinedValue || this.disabled;
3526
+ const effectiveDisabled = isPredefinedValue || this.disabled || this.mode === "readonly";
3516
3527
  return html`
3517
3528
  <div class="field-container">
3518
3529
  ${showLabel ? html`
@@ -3524,9 +3535,9 @@ let JupiterFormField = class extends LitElement {
3524
3535
  <div class="field-wrapper">
3525
3536
  ${this._renderInput(effectiveValue, effectiveDisabled)}
3526
3537
 
3527
- ${hasPeriodControl ? html`
3528
- <button
3529
- class="period-icon-btn"
3538
+ ${hasPeriodControl && this.mode !== "readonly" ? html`
3539
+ <button
3540
+ class="period-icon-btn"
3530
3541
  type="button"
3531
3542
  @click="${this._handlePeriodIconClick}"
3532
3543
  title="Edit period"
@@ -4978,6 +4989,20 @@ let JupiterFormSection = class extends LitElement {
4978
4989
  }
4979
4990
  return result;
4980
4991
  }
4992
+ /**
4993
+ * Returns true when every column cell for a concept has no value.
4994
+ * Used in readonly mode to hide fully-blank rows.
4995
+ */
4996
+ _isConceptRowBlank(concept) {
4997
+ var _a;
4998
+ for (const column2 of this.columns) {
4999
+ const value = (_a = this.formData[concept.id]) == null ? void 0 : _a[column2.id];
5000
+ if (value !== null && value !== void 0 && value !== "") {
5001
+ return false;
5002
+ }
5003
+ }
5004
+ return true;
5005
+ }
4981
5006
  _getAllConceptIds(concepts) {
4982
5007
  const result = [];
4983
5008
  for (const concept of concepts) {
@@ -5109,24 +5134,25 @@ let JupiterFormSection = class extends LitElement {
5109
5134
  ` : ""}
5110
5135
  </div>
5111
5136
 
5112
- <!-- Column menu icon (3 vertical dots) -->
5113
- <div
5137
+ <!-- Column menu icon (hidden in readonly mode) -->
5138
+ ${this.mode !== "readonly" ? html`
5139
+ <div
5114
5140
  class="column-menu-icon"
5115
5141
  @click="${(e2) => this._toggleColumnMenu(column2.id, e2)}"
5116
5142
  title="${I18n.t("column.columnOptions")}"
5117
5143
  >⋮</div>
5118
-
5144
+
5119
5145
  <!-- Context menu -->
5120
5146
  ${this._openMenuColumnId === column2.id ? html`
5121
5147
  <div class="column-context-menu">
5122
- <button
5148
+ <button
5123
5149
  class="column-context-menu-item"
5124
5150
  @click="${(e2) => this._handleAddColumnFromMenu(column2.id, e2)}"
5125
5151
  >
5126
5152
  ${I18n.t("column.addColumn")}
5127
5153
  </button>
5128
5154
  ${column2.removable ? html`
5129
- <button
5155
+ <button
5130
5156
  class="column-context-menu-item remove"
5131
5157
  @click="${(e2) => {
5132
5158
  e2.stopPropagation();
@@ -5138,13 +5164,14 @@ let JupiterFormSection = class extends LitElement {
5138
5164
  ` : ""}
5139
5165
  </div>
5140
5166
  ` : ""}
5167
+ ` : ""}
5141
5168
  </th>
5142
5169
  `;
5143
5170
  })}
5144
5171
  </tr>
5145
5172
  </thead>
5146
5173
  <tbody class="table-body">
5147
- ${this._flattenConcepts(this.section.concepts, this._expandedConcepts).map((concept) => html`
5174
+ ${this._flattenConcepts(this.section.concepts, this._expandedConcepts).filter((concept) => this.mode !== "readonly" || !this._isConceptRowBlank(concept)).map((concept) => html`
5148
5175
  <tr>
5149
5176
  <jupiter-concept-tree
5150
5177
  .concept="${concept}"
@@ -8527,6 +8554,12 @@ let JupiterDynamicForm = class extends LitElement {
8527
8554
  }
8528
8555
  console.log(`✅ [Submit] No validation errors, proceeding with submission...`);
8529
8556
  this._validateForm();
8557
+ if (!this._valid) {
8558
+ console.log("❌ [Submit] Cannot submit - form validation errors present:", this._errors);
8559
+ this._showErrorPopup = true;
8560
+ this.requestUpdate();
8561
+ return;
8562
+ }
8530
8563
  const submissionData = this._generateSubmissionData();
8531
8564
  console.log("📊 Form Submission Data:", JSON.stringify(submissionData, null, 2));
8532
8565
  console.log("📊 Submission Data Summary:");
@@ -9716,6 +9749,32 @@ let JupiterDynamicForm = class extends LitElement {
9716
9749
  _toggleSidePanelCollapse() {
9717
9750
  this._sidePanelCollapsed = !this._sidePanelCollapsed;
9718
9751
  }
9752
+ /**
9753
+ * Returns true when every non-abstract concept row in the section has no value
9754
+ * in any column. Used in readonly mode to hide fully-blank sections.
9755
+ */
9756
+ _isSectionBlank(section2) {
9757
+ const columns = section2.columns || this._columns;
9758
+ const hasValue = (concepts) => {
9759
+ var _a;
9760
+ for (const concept of concepts) {
9761
+ if (!concept.abstract) {
9762
+ for (const column2 of columns) {
9763
+ const value = (_a = this._formData[concept.id]) == null ? void 0 : _a[column2.id];
9764
+ if (value !== null && value !== void 0 && value !== "") {
9765
+ return true;
9766
+ }
9767
+ }
9768
+ }
9769
+ if (concept.children && concept.children.length > 0) {
9770
+ if (hasValue(concept.children))
9771
+ return true;
9772
+ }
9773
+ }
9774
+ return false;
9775
+ };
9776
+ return !hasValue(section2.concepts);
9777
+ }
9719
9778
  _filterSidePanelSections(sections) {
9720
9779
  if (!this._sidePanelSearchQuery.trim()) {
9721
9780
  return sections;
@@ -10108,7 +10167,7 @@ let JupiterDynamicForm = class extends LitElement {
10108
10167
  <p>${I18n.t("filter.selectRoles")}</p>
10109
10168
  <p>${I18n.t("filter.roles")}: ${this._allSections.length}</p>
10110
10169
  </div>
10111
- ` : schema.sections.map((section2, index) => {
10170
+ ` : (this.mode === "readonly" ? schema.sections.filter((s2) => !this._isSectionBlank(s2)) : schema.sections).map((section2, index) => {
10112
10171
  var _a;
10113
10172
  return html`
10114
10173
  <jupiter-form-section
@@ -10145,7 +10204,7 @@ let JupiterDynamicForm = class extends LitElement {
10145
10204
  }
10146
10205
  _renderSidePanelLayout(schema, config, showValidationSummary, errorCount) {
10147
10206
  var _a;
10148
- const visibleSections = schema.sections;
10207
+ const visibleSections = this.mode === "readonly" ? schema.sections.filter((s2) => !this._isSectionBlank(s2)) : schema.sections;
10149
10208
  const filteredSections = this._filterSidePanelSections(visibleSections);
10150
10209
  if (!this._activeSidePanelRoleId || !filteredSections.find((s2) => s2.id === this._activeSidePanelRoleId)) {
10151
10210
  this._activeSidePanelRoleId = filteredSections.length > 0 ? filteredSections[0].id : null;
@@ -10322,7 +10381,8 @@ let JupiterDynamicForm = class extends LitElement {
10322
10381
  <!-- Form Content -->
10323
10382
  ${this.display === "sidePanel" ? this._renderSidePanelLayout(schema, config, showValidationSummary, errorCount) : this._renderAccordionLayout(schema, config, showValidationSummary, errorCount)}
10324
10383
 
10325
- <!-- Form Actions - Fixed Footer -->
10384
+ <!-- Form Actions - Fixed Footer (hidden in readonly mode) -->
10385
+ ${this.mode !== "readonly" ? html`
10326
10386
  <div class="form-actions">
10327
10387
  <!-- Filter Roles Button (shown when more than 10 roles) -->
10328
10388
  ${this._shouldShowFilterButton() ? html`
@@ -10357,8 +10417,8 @@ let JupiterDynamicForm = class extends LitElement {
10357
10417
  ${this.submitButtonLabel || I18n.t("form.submit")}
10358
10418
  </button>
10359
10419
 
10360
-
10361
10420
  </div>
10421
+ ` : ""}
10362
10422
 
10363
10423
  <!-- Filter Roles Dialog -->
10364
10424
  ${this._showFilterDialog ? html`