jupiter-dynamic-forms 1.17.9 → 1.18.1

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
@@ -674,7 +674,7 @@ class XBRLFormBuilder {
674
674
  */
675
675
  static buildConceptTree(concept, level, periodStartDate, periodEndDate, roleInfo, sectionId, language = "en", conceptIdOccurrences, ancestorPeriodHint) {
676
676
  var _a, _b;
677
- const label = this.getPreferredLabel(concept.labels, language);
677
+ const label = this.getPreferredLabel(concept.labels, language, concept.preferredLabel);
678
678
  const childPeriodHint = ((_a = concept.preferredLabel) == null ? void 0 : _a.includes("periodStartLabel")) ? "start" : ((_b = concept.preferredLabel) == null ? void 0 : _b.includes("periodEndLabel")) ? "end" : ancestorPeriodHint;
679
679
  const fields = [];
680
680
  if (!concept.elementAbstract) {
@@ -689,7 +689,7 @@ class XBRLFormBuilder {
689
689
  const column2 = (_a2 = roleInfo == null ? void 0 : roleInfo.availableColumns) == null ? void 0 : _a2.find((c2) => c2.id === columnId);
690
690
  const colStartDate = (column2 == null ? void 0 : column2.periodStartDate) || periodStartDate;
691
691
  const colEndDate = (column2 == null ? void 0 : column2.periodEndDate) || periodEndDate;
692
- const field2 = this.createFieldFromConcept(concept, colStartDate, colEndDate, columnId, ancestorPeriodHint);
692
+ const field2 = this.createFieldFromConcept(concept, colStartDate, colEndDate, columnId, ancestorPeriodHint, language);
693
693
  if (field2)
694
694
  fields.push(field2);
695
695
  });
@@ -751,10 +751,10 @@ class XBRLFormBuilder {
751
751
  /**
752
752
  * Create form field from XBRL concept
753
753
  */
754
- static createFieldFromConcept(concept, periodStartDate, periodEndDate, forcedColumnId, ancestorPeriodHint) {
754
+ static createFieldFromConcept(concept, periodStartDate, periodEndDate, forcedColumnId, ancestorPeriodHint, language = "en") {
755
755
  var _a;
756
756
  const fieldType = this.mapXBRLTypeToFieldType(concept.type);
757
- const label = this.getPreferredLabel(concept.labels);
757
+ const label = this.getPreferredLabel(concept.labels, language, concept.preferredLabel);
758
758
  let columnId;
759
759
  if (forcedColumnId) {
760
760
  columnId = forcedColumnId;
@@ -806,11 +806,19 @@ class XBRLFormBuilder {
806
806
  * @param labels - Array of XBRL labels
807
807
  * @param language - ISO language code (e.g., 'en', 'nl', 'de')
808
808
  */
809
- static getPreferredLabel(labels, language = "en") {
809
+ static getPreferredLabel(labels, language = "en", preferredRole) {
810
810
  if (!labels || labels.length === 0)
811
811
  return "Unnamed Concept";
812
812
  const languageLabels = labels.filter((l2) => l2.lang === language);
813
813
  const labelsToSearch = languageLabels.length > 0 ? languageLabels : labels;
814
+ if (preferredRole) {
815
+ const roleSpecificInLanguage = languageLabels.find((l2) => l2.role === preferredRole);
816
+ if (roleSpecificInLanguage)
817
+ return roleSpecificInLanguage.label;
818
+ const roleSpecificAnyLanguage = labels.find((l2) => l2.role === preferredRole);
819
+ if (roleSpecificAnyLanguage)
820
+ return roleSpecificAnyLanguage.label;
821
+ }
814
822
  const preferred = labelsToSearch.find((l2) => l2.preferredLabel);
815
823
  if (preferred)
816
824
  return preferred.label;
@@ -1635,6 +1643,7 @@ const conceptInfo$1 = {
1635
1643
  close: "Close"
1636
1644
  };
1637
1645
  const form$1 = {
1646
+ markAsComplete: "Mark as Complete",
1638
1647
  loading: "Loading form...",
1639
1648
  submit: "Validate",
1640
1649
  save: "Save",
@@ -1807,6 +1816,7 @@ const conceptInfo = {
1807
1816
  close: "Sluiten"
1808
1817
  };
1809
1818
  const form = {
1819
+ markAsComplete: "Markeren als volledig behandeld",
1810
1820
  loading: "Formulier laden...",
1811
1821
  submit: "Valideren",
1812
1822
  save: "Opslaan",
@@ -3090,6 +3100,7 @@ let JupiterFormField = class extends LitElement {
3090
3100
  this._touched = false;
3091
3101
  this._showPeriodPopup = false;
3092
3102
  this._availableUnits = [];
3103
+ this._numericDraftValue = null;
3093
3104
  }
3094
3105
  willUpdate(changedProperties) {
3095
3106
  var _a;
@@ -3131,13 +3142,33 @@ let JupiterFormField = class extends LitElement {
3131
3142
  _isRoundingLevelConcept() {
3132
3143
  return !!this.conceptId && this.conceptId.includes("DocumentIntendedRoundingLevel");
3133
3144
  }
3145
+ _isNumericField() {
3146
+ var _a;
3147
+ const typeConfig = getInputTypeForConceptType(this.conceptType, this.datatypes);
3148
+ const effectiveFieldType = typeConfig.fieldType || ((_a = this.field) == null ? void 0 : _a.type) || "text";
3149
+ return isNumericType(effectiveFieldType) || this._getInputType() === "number";
3150
+ }
3151
+ _isIntermediateNumericValue(raw) {
3152
+ return raw === "-" || raw === "." || raw === "-.";
3153
+ }
3134
3154
  _handleInput(event) {
3135
3155
  const target = event.target;
3156
+ const oldValue = this.value;
3136
3157
  let value = target.value;
3137
- if (this.field.type === "number" || this.field.type === "decimal") {
3138
- value = value === "" ? null : Number(value);
3158
+ if (this._isNumericField()) {
3159
+ const rawValue = target.value;
3160
+ this._numericDraftValue = rawValue;
3161
+ if (rawValue === "" || this._isIntermediateNumericValue(rawValue)) {
3162
+ value = null;
3163
+ } else {
3164
+ const parsed = Number(rawValue);
3165
+ value = Number.isNaN(parsed) ? null : parsed;
3166
+ }
3139
3167
  } else if (this.field.type === "boolean") {
3140
3168
  value = target.checked;
3169
+ this._numericDraftValue = null;
3170
+ } else {
3171
+ this._numericDraftValue = null;
3141
3172
  }
3142
3173
  this.value = value;
3143
3174
  this._touched = true;
@@ -3147,7 +3178,7 @@ let JupiterFormField = class extends LitElement {
3147
3178
  conceptId: this.conceptId,
3148
3179
  columnId: this.columnId,
3149
3180
  value,
3150
- oldValue: this.value
3181
+ oldValue
3151
3182
  },
3152
3183
  bubbles: true
3153
3184
  }));
@@ -3163,6 +3194,16 @@ let JupiterFormField = class extends LitElement {
3163
3194
  }));
3164
3195
  }
3165
3196
  _handleBlur() {
3197
+ if (this._isNumericField() && this._numericDraftValue !== null) {
3198
+ const raw = this._numericDraftValue;
3199
+ if (raw === "" || this._isIntermediateNumericValue(raw)) {
3200
+ this.value = null;
3201
+ } else {
3202
+ const parsed = Number(raw);
3203
+ this.value = Number.isNaN(parsed) ? null : parsed;
3204
+ }
3205
+ this._numericDraftValue = null;
3206
+ }
3166
3207
  this._touched = true;
3167
3208
  this._validateXBRLDatatype();
3168
3209
  this._validateUnitSelection();
@@ -3225,7 +3266,7 @@ let JupiterFormField = class extends LitElement {
3225
3266
  if (event.ctrlKey || event.metaKey) {
3226
3267
  return;
3227
3268
  }
3228
- if (event.key === "-" && target.selectionStart === 0 && !target.value.includes("-")) {
3269
+ if (event.key === "-" && !target.value.includes("-") && (target.selectionStart === 0 || target.selectionStart === null || target.value.length === 0)) {
3229
3270
  return;
3230
3271
  }
3231
3272
  if (event.key === "." && !target.value.includes(".")) {
@@ -3495,7 +3536,8 @@ let JupiterFormField = class extends LitElement {
3495
3536
  <button class="jdf-text-dialog-save" type="button"></button>
3496
3537
  </div>
3497
3538
  `;
3498
- dialog.querySelector(".jdf-text-dialog-title").textContent = fieldLabel;
3539
+ const cleanTitle = fieldLabel;
3540
+ dialog.querySelector(".jdf-text-dialog-title").textContent = cleanTitle || fieldLabel;
3499
3541
  dialog.querySelector(".jdf-text-dialog-cancel").textContent = I18n.t("field.cancel");
3500
3542
  dialog.querySelector(".jdf-text-dialog-save").textContent = I18n.t("field.save");
3501
3543
  const textarea = dialog.querySelector(".jdf-text-dialog-textarea");
@@ -3663,7 +3705,7 @@ let JupiterFormField = class extends LitElement {
3663
3705
  id="${fieldId}"
3664
3706
  name="${fieldName}"
3665
3707
  class="${cssClass}"
3666
- .value="${effectiveValue || ""}"
3708
+ .value="${effectiveValue ?? ""}"
3667
3709
  ?disabled="${effectiveDisabled || this.field.disabled}"
3668
3710
  @change="${this._handleInput}"
3669
3711
  @focus="${this._handleFocus}"
@@ -3709,13 +3751,14 @@ let JupiterFormField = class extends LitElement {
3709
3751
  const step = typeConfig.step !== void 0 ? typeConfig.step : isNumericType(effectiveFieldType) ? "any" : void 0;
3710
3752
  const min = typeConfig.min;
3711
3753
  const max = typeConfig.max;
3754
+ const renderedInputValue = this._isNumericField() && this._numericDraftValue !== null ? this._numericDraftValue : effectiveValue ?? "";
3712
3755
  return html`
3713
3756
  <input
3714
3757
  id="${fieldId}"
3715
3758
  name="${fieldName}"
3716
3759
  type="${inputType}"
3717
3760
  class="${cssClass}"
3718
- .value="${effectiveValue || ""}"
3761
+ .value="${renderedInputValue}"
3719
3762
  ?disabled="${effectiveDisabled || this.field.disabled}"
3720
3763
  placeholder="${typeConfig.placeholder || this.field.placeholder || ""}"
3721
3764
  step="${step !== void 0 ? step : ""}"
@@ -4564,6 +4607,9 @@ __decorateClass$6([
4564
4607
  __decorateClass$6([
4565
4608
  r()
4566
4609
  ], JupiterFormField.prototype, "_availableUnits", 2);
4610
+ __decorateClass$6([
4611
+ r()
4612
+ ], JupiterFormField.prototype, "_numericDraftValue", 2);
4567
4613
  JupiterFormField = __decorateClass$6([
4568
4614
  t$1("jupiter-form-field")
4569
4615
  ], JupiterFormField);
@@ -5017,25 +5063,30 @@ JupiterConceptTree.styles = css`
5017
5063
 
5018
5064
  .concept-info-btn {
5019
5065
  flex-shrink: 0;
5020
- width: 18px;
5021
- height: 18px;
5066
+ width: 22px;
5067
+ height: 22px;
5022
5068
  border-radius: 50%;
5023
- border: 1px solid transparent;
5024
- background: transparent;
5025
- color: var(--jupiter-text-secondary, #888);
5026
- font-size: 12px;
5069
+ border: 1px solid var(--jupiter-border-color, #cfd8dc);
5070
+ background: var(--jupiter-card-background, #fff);
5071
+ color: var(--jupiter-primary-color, #1976d2);
5072
+ font-size: 13px;
5073
+ font-weight: 700;
5027
5074
  cursor: pointer;
5028
5075
  display: flex;
5029
5076
  align-items: center;
5030
5077
  justify-content: center;
5031
5078
  opacity: 0;
5032
- transition: opacity 0.15s, background 0.15s, color 0.15s;
5079
+ transition: opacity 0.15s, background 0.15s, color 0.15s, border-color 0.15s, box-shadow 0.15s;
5033
5080
  padding: 0;
5034
5081
  margin-left: 4px;
5035
5082
  line-height: 1;
5083
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
5084
+ pointer-events: auto;
5036
5085
  }
5037
5086
 
5038
- .concept-content:hover .concept-info-btn {
5087
+ .concept-content:hover .concept-info-btn,
5088
+ .concept-info-btn:hover,
5089
+ .concept-info-btn:focus-visible {
5039
5090
  opacity: 1;
5040
5091
  }
5041
5092
 
@@ -5043,6 +5094,14 @@ JupiterConceptTree.styles = css`
5043
5094
  background: var(--jupiter-primary-color, #1976d2);
5044
5095
  color: #fff;
5045
5096
  border-color: var(--jupiter-primary-color, #1976d2);
5097
+ box-shadow: 0 2px 6px rgba(25, 118, 210, 0.25);
5098
+ }
5099
+
5100
+ .concept-info-btn:focus-visible {
5101
+ outline: none;
5102
+ border-color: var(--jupiter-primary-color, #1976d2);
5103
+ box-shadow: 0 0 0 2px rgba(25, 118, 210, 0.25);
5104
+ opacity: 1;
5046
5105
  }
5047
5106
 
5048
5107
  `;
@@ -6639,6 +6698,7 @@ JupiterFormSection.styles = css`
6639
6698
  border-radius: 3px;
6640
6699
  font-size: 12px;
6641
6700
  background: var(--jupiter-input-background, #fff);
6701
+ color:#000;
6642
6702
  }
6643
6703
 
6644
6704
  .typed-member-header-field:focus {
@@ -10912,7 +10972,7 @@ let JupiterDynamicForm = class extends LitElement {
10912
10972
  if (concept.abstract)
10913
10973
  return;
10914
10974
  const isCustomColumn = column2.id.startsWith("col-");
10915
- const isDimensionColumn = column2.id.startsWith("duration_") || column2.id.startsWith("instant_");
10975
+ const isDimensionColumn = column2.id.startsWith("duration_") || column2.id.startsWith("instant_") || column2.id.startsWith("typed-");
10916
10976
  const isMixedSection = section2.showPeriodControl === true;
10917
10977
  const shouldSkipPeriodCheck = !columnPeriodType || column2.id === "duration" || column2.id === "default" || isCustomColumn && isMixedSection || isDimensionColumn;
10918
10978
  if (!shouldSkipPeriodCheck && conceptPeriodType && columnPeriodType) {
@@ -12327,7 +12387,7 @@ let JupiterDynamicForm = class extends LitElement {
12327
12387
  .checked="${this._roleCompletedStates.get(activeSection.id) === true}"
12328
12388
  @change="${(e2) => this._handleRoleCompletedChange(activeSection.id, e2.target.checked)}"
12329
12389
  >
12330
- <label for="role-complete-${activeSection.id}">Mark as completed</label>
12390
+ <label for="role-complete-${activeSection.id}">${I18n.t("form.markAsComplete")}</label>
12331
12391
  </div>
12332
12392
  ` : html`
12333
12393
  <div class="no-roles-message">
@@ -12947,35 +13007,35 @@ JupiterDynamicForm.styles = css`
12947
13007
  }
12948
13008
 
12949
13009
  .side-panel-role-item.has-errors {
12950
- border-left: 2px solid var(--jupiter-error-color, #d32f2f);
13010
+ border-left: 4px solid var(--jupiter-error-color, #d32f2f);
12951
13011
  }
12952
13012
 
12953
13013
  .side-panel-role-item.has-errors.active {
12954
- border-left: 2px solid var(--jupiter-error-color, #d32f2f);
13014
+ border-left: 4px solid var(--jupiter-error-color, #d32f2f);
12955
13015
  }
12956
13016
 
12957
13017
  .side-panel-role-item.has-no-data {
12958
- border-left: 2px solid var(--jupiter-untouched-color, #757575);
13018
+ border-left: 4px solid var(--jupiter-untouched-color, #757575);
12959
13019
  }
12960
13020
 
12961
13021
  .side-panel-role-item.has-no-data.active {
12962
- border-left: 2px solid var(--jupiter-untouched-color, #757575);
13022
+ border-left: 4px solid var(--jupiter-untouched-color, #757575);
12963
13023
  }
12964
13024
 
12965
13025
  .side-panel-role-item.has-empty-fields {
12966
- border-left: 2px solid var(--jupiter-warning-color, #ff9800);
13026
+ border-left: 4px solid var(--jupiter-warning-color, #ff9800);
12967
13027
  }
12968
13028
 
12969
13029
  .side-panel-role-item.has-empty-fields.active {
12970
- border-left: 2px solid var(--jupiter-warning-color, #ff9800);
13030
+ border-left: 4px solid var(--jupiter-warning-color, #ff9800);
12971
13031
  }
12972
13032
 
12973
13033
  .side-panel-role-item.has-complete-data {
12974
- border-left: 2px solid var(--jupiter-success-color, #4caf50);
13034
+ border-left: 4px solid var(--jupiter-success-color, #4caf50);
12975
13035
  }
12976
13036
 
12977
13037
  .side-panel-role-item.has-complete-data.active {
12978
- border-left: 2px solid var(--jupiter-success-color, #4caf50);
13038
+ border-left: 4px solid var(--jupiter-success-color, #4caf50);
12979
13039
  }
12980
13040
 
12981
13041
  .role-completion-row {