jupiter-dynamic-forms 1.17.7 → 1.17.9

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
@@ -569,6 +569,14 @@ class XBRLFormBuilder {
569
569
  }
570
570
  return Math.abs(hash).toString(36).substr(0, 6);
571
571
  }
572
+ static _extractDocumentationLabels(labels) {
573
+ const result = {};
574
+ const docRole = "http://www.xbrl.org/2003/role/documentation";
575
+ labels.filter((l2) => l2.role === docRole).forEach((l2) => {
576
+ result[l2.lang] = l2.label;
577
+ });
578
+ return result;
579
+ }
572
580
  /**
573
581
  * Build form schema from XBRL input data
574
582
  * Creates accordion sections for each presentation role
@@ -707,6 +715,14 @@ class XBRLFormBuilder {
707
715
  conceptId = `${conceptId}__occ${count + 1}`;
708
716
  }
709
717
  }
718
+ const conceptMetadata = {
719
+ conceptName: concept.conceptName,
720
+ type: concept.type,
721
+ substitutionGroup: concept.substitutionGroup,
722
+ periodType: concept.periodType,
723
+ balance: concept.balance,
724
+ documentationLabels: this._extractDocumentationLabels(concept.labels)
725
+ };
710
726
  return {
711
727
  id: conceptId,
712
728
  originalConceptId: concept.id,
@@ -719,6 +735,7 @@ class XBRLFormBuilder {
719
735
  level,
720
736
  children,
721
737
  fields,
738
+ conceptMetadata,
722
739
  facts: concept.facts || [],
723
740
  // Pass facts array from presentation concept for pre-population
724
741
  collapsed: level > 0,
@@ -1605,6 +1622,18 @@ class XBRLFormBuilder {
1605
1622
  }];
1606
1623
  }
1607
1624
  }
1625
+ const conceptInfo$1 = {
1626
+ title: "Concept Information",
1627
+ conceptName: "Concept name",
1628
+ type: "Type",
1629
+ substitutionGroup: "Substitution group",
1630
+ periodType: "Period type",
1631
+ balance: "Balance",
1632
+ documentation: "Documentation",
1633
+ instant: "Instant",
1634
+ duration: "Duration",
1635
+ close: "Close"
1636
+ };
1608
1637
  const form$1 = {
1609
1638
  loading: "Loading form...",
1610
1639
  submit: "Validate",
@@ -1713,7 +1742,12 @@ const field$1 = {
1713
1742
  phonePlaceholder: "+1 (555) 000-0000",
1714
1743
  enterValue: "Enter value",
1715
1744
  enterDetailedInformation: "Enter detailed information...",
1716
- scale: "Scale"
1745
+ scale: "Scale",
1746
+ addText: "Add text",
1747
+ editText: "Edit",
1748
+ save: "Save",
1749
+ cancel: "Cancel",
1750
+ characters: "characters"
1717
1751
  };
1718
1752
  const admin$1 = {
1719
1753
  title: "Configure Roles",
@@ -1749,6 +1783,7 @@ const error$1 = {
1749
1783
  }
1750
1784
  };
1751
1785
  const enTranslations = {
1786
+ conceptInfo: conceptInfo$1,
1752
1787
  form: form$1,
1753
1788
  filter: filter$1,
1754
1789
  column: column$1,
@@ -1759,6 +1794,18 @@ const enTranslations = {
1759
1794
  xbrlValidation: xbrlValidation$1,
1760
1795
  error: error$1
1761
1796
  };
1797
+ const conceptInfo = {
1798
+ title: "Conceptinformatie",
1799
+ conceptName: "Conceptnaam",
1800
+ type: "Type",
1801
+ substitutionGroup: "Substitutiegroep",
1802
+ periodType: "Periodetype",
1803
+ balance: "Saldo",
1804
+ documentation: "Documentatie",
1805
+ instant: "Moment",
1806
+ duration: "Periode",
1807
+ close: "Sluiten"
1808
+ };
1762
1809
  const form = {
1763
1810
  loading: "Formulier laden...",
1764
1811
  submit: "Valideren",
@@ -1867,7 +1914,12 @@ const field = {
1867
1914
  phonePlaceholder: "+31 (0)20 123 4567",
1868
1915
  enterValue: "Voer waarde in",
1869
1916
  enterDetailedInformation: "Voer gedetailleerde informatie in...",
1870
- scale: "Schaal"
1917
+ scale: "Schaal",
1918
+ addText: "Tekst toevoegen",
1919
+ editText: "Bewerken",
1920
+ save: "Opslaan",
1921
+ cancel: "Annuleren",
1922
+ characters: "tekens"
1871
1923
  };
1872
1924
  const admin = {
1873
1925
  title: "Rollen configureren",
@@ -1903,6 +1955,7 @@ const error = {
1903
1955
  }
1904
1956
  };
1905
1957
  const nlTranslations = {
1958
+ conceptInfo,
1906
1959
  form,
1907
1960
  filter,
1908
1961
  column,
@@ -3354,6 +3407,169 @@ let JupiterFormField = class extends LitElement {
3354
3407
  this._closePeriodPopup();
3355
3408
  }
3356
3409
  }
3410
+ _ensureTextDialogStyles() {
3411
+ if (document.getElementById("jdf-text-dialog-styles"))
3412
+ return;
3413
+ const style = document.createElement("style");
3414
+ style.id = "jdf-text-dialog-styles";
3415
+ style.textContent = `
3416
+ dialog.jdf-text-entry-dialog {
3417
+ border: none; border-radius: 8px; padding: 0;
3418
+ max-width: 600px; width: 90vw;
3419
+ box-shadow: 0 8px 32px rgba(0,0,0,0.2); overflow: hidden;
3420
+ font-family: inherit;
3421
+ }
3422
+ dialog.jdf-text-entry-dialog::backdrop { background: rgba(0,0,0,0.35); }
3423
+ .jdf-text-dialog-header {
3424
+ background: #f0f2f5; padding: 14px 20px;
3425
+ display: flex; align-items: center; justify-content: space-between;
3426
+ border-bottom: 1px solid #ddd;
3427
+ }
3428
+ .jdf-text-dialog-title {
3429
+ font-size: 15px; font-weight: 600; color: #333; margin: 0;
3430
+ font-family: inherit; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
3431
+ }
3432
+ .jdf-text-dialog-close {
3433
+ flex-shrink: 0; width: 28px; height: 28px; border: none; background: transparent;
3434
+ font-size: 20px; line-height: 1; cursor: pointer; color: #666;
3435
+ border-radius: 4px; display: flex; align-items: center; justify-content: center;
3436
+ padding: 0; font-family: inherit; margin-left: 8px;
3437
+ }
3438
+ .jdf-text-dialog-close:hover { background: #ddd; color: #333; }
3439
+ .jdf-text-dialog-body { padding: 20px 20px 12px; }
3440
+ .jdf-text-dialog-textarea {
3441
+ width: 100%; min-height: 200px; max-height: 50vh;
3442
+ padding: 10px 12px; font-size: 14px; font-family: inherit;
3443
+ border: 1px solid #ddd; border-radius: 4px;
3444
+ box-sizing: border-box; resize: vertical; line-height: 1.5;
3445
+ color: #333; background: #fff;
3446
+ }
3447
+ .jdf-text-dialog-textarea:focus {
3448
+ outline: none; border-color: #1976d2;
3449
+ box-shadow: 0 0 0 2px rgba(25,118,210,0.2);
3450
+ }
3451
+ .jdf-text-dialog-char-count {
3452
+ margin-top: 4px; font-size: 12px; color: #888; text-align: right;
3453
+ font-family: inherit;
3454
+ }
3455
+ .jdf-text-dialog-actions {
3456
+ display: flex; justify-content: flex-end; gap: 8px;
3457
+ padding: 12px 20px 16px; border-top: 1px solid #eee;
3458
+ }
3459
+ .jdf-text-dialog-cancel {
3460
+ padding: 7px 18px; border: 1px solid #ddd; border-radius: 4px;
3461
+ background: transparent; color: #555; font-size: 14px;
3462
+ cursor: pointer; font-family: inherit;
3463
+ }
3464
+ .jdf-text-dialog-cancel:hover { background: #f5f5f5; }
3465
+ .jdf-text-dialog-save {
3466
+ padding: 7px 18px; border: none; border-radius: 4px;
3467
+ background: #1976d2; color: #fff; font-size: 14px;
3468
+ cursor: pointer; font-family: inherit; font-weight: 500;
3469
+ }
3470
+ .jdf-text-dialog-save:hover { background: #1565c0; }
3471
+ `;
3472
+ document.head.appendChild(style);
3473
+ }
3474
+ _openTextDialog(currentValue, fieldLabel) {
3475
+ var _a;
3476
+ this._ensureTextDialogStyles();
3477
+ (_a = document.getElementById("jdf-text-entry-dialog")) == null ? void 0 : _a.remove();
3478
+ const dialog = document.createElement("dialog");
3479
+ dialog.id = "jdf-text-entry-dialog";
3480
+ dialog.className = "jdf-text-entry-dialog";
3481
+ dialog.setAttribute("role", "dialog");
3482
+ dialog.setAttribute("aria-modal", "true");
3483
+ dialog.setAttribute("aria-labelledby", "jdf-text-dialog-title");
3484
+ dialog.innerHTML = `
3485
+ <div class="jdf-text-dialog-header">
3486
+ <h3 class="jdf-text-dialog-title" id="jdf-text-dialog-title"></h3>
3487
+ <button class="jdf-text-dialog-close" type="button" aria-label="Close">×</button>
3488
+ </div>
3489
+ <div class="jdf-text-dialog-body">
3490
+ <textarea class="jdf-text-dialog-textarea" spellcheck="true"></textarea>
3491
+ <div class="jdf-text-dialog-char-count"></div>
3492
+ </div>
3493
+ <div class="jdf-text-dialog-actions">
3494
+ <button class="jdf-text-dialog-cancel" type="button"></button>
3495
+ <button class="jdf-text-dialog-save" type="button"></button>
3496
+ </div>
3497
+ `;
3498
+ dialog.querySelector(".jdf-text-dialog-title").textContent = fieldLabel;
3499
+ dialog.querySelector(".jdf-text-dialog-cancel").textContent = I18n.t("field.cancel");
3500
+ dialog.querySelector(".jdf-text-dialog-save").textContent = I18n.t("field.save");
3501
+ const textarea = dialog.querySelector(".jdf-text-dialog-textarea");
3502
+ const charCount = dialog.querySelector(".jdf-text-dialog-char-count");
3503
+ textarea.value = currentValue;
3504
+ charCount.textContent = `${currentValue.length} ${I18n.t("field.characters")}`;
3505
+ textarea.addEventListener("input", () => {
3506
+ charCount.textContent = `${textarea.value.length} ${I18n.t("field.characters")}`;
3507
+ });
3508
+ dialog.querySelector(".jdf-text-dialog-close").addEventListener("click", () => dialog.close());
3509
+ dialog.querySelector(".jdf-text-dialog-cancel").addEventListener("click", () => dialog.close());
3510
+ dialog.querySelector(".jdf-text-dialog-save").addEventListener("click", () => {
3511
+ const newValue = textarea.value;
3512
+ const oldValue = this.value;
3513
+ this.value = newValue;
3514
+ this._touched = true;
3515
+ this.dispatchEvent(new CustomEvent("field-change", {
3516
+ detail: { fieldId: this.field.id, conceptId: this.conceptId, columnId: this.columnId, value: newValue, oldValue },
3517
+ bubbles: true
3518
+ }));
3519
+ dialog.close();
3520
+ });
3521
+ dialog.addEventListener("click", (ev) => {
3522
+ const rect = dialog.getBoundingClientRect();
3523
+ if (ev.clientX < rect.left || ev.clientX > rect.right || ev.clientY < rect.top || ev.clientY > rect.bottom) {
3524
+ dialog.close();
3525
+ }
3526
+ });
3527
+ dialog.addEventListener("close", () => dialog.remove());
3528
+ document.body.appendChild(dialog);
3529
+ dialog.showModal();
3530
+ textarea.focus();
3531
+ }
3532
+ _renderTextDialogTrigger(effectiveValue, effectiveDisabled) {
3533
+ const hasValue = effectiveValue !== null && effectiveValue !== void 0 && String(effectiveValue).trim() !== "";
3534
+ const displayText = hasValue ? String(effectiveValue) : "";
3535
+ if (effectiveDisabled) {
3536
+ return html`
3537
+ <span class="text-readonly-label ${hasValue ? "" : "empty"}"
3538
+ title="${displayText}">${hasValue ? displayText : "—"}</span>
3539
+ `;
3540
+ }
3541
+ if (!hasValue) {
3542
+ return html`
3543
+ <button class="text-trigger-btn" type="button"
3544
+ aria-label="${I18n.t("field.addText")}"
3545
+ @click="${() => {
3546
+ var _a;
3547
+ return this._openTextDialog("", ((_a = this.field) == null ? void 0 : _a.label) || "");
3548
+ }}">
3549
+ + ${I18n.t("field.addText")}
3550
+ </button>
3551
+ `;
3552
+ }
3553
+ return html`
3554
+ <div class="text-filled">
3555
+ <span class="text-filled-label" title="${displayText}"
3556
+ @click="${() => {
3557
+ var _a;
3558
+ return this._openTextDialog(displayText, ((_a = this.field) == null ? void 0 : _a.label) || "");
3559
+ }}">
3560
+ ${displayText}
3561
+ </span>
3562
+ <button class="text-edit-btn" type="button"
3563
+ aria-label="${I18n.t("field.editText")}"
3564
+ @click="${() => {
3565
+ var _a;
3566
+ return this._openTextDialog(displayText, ((_a = this.field) == null ? void 0 : _a.label) || "");
3567
+ }}">
3568
+ ✎ ${I18n.t("field.editText")}
3569
+ </button>
3570
+ </div>
3571
+ `;
3572
+ }
3357
3573
  _handlePeriodChange(event, type) {
3358
3574
  const target = event.target;
3359
3575
  const value = target.value;
@@ -3438,19 +3654,7 @@ let JupiterFormField = class extends LitElement {
3438
3654
  ;
3439
3655
  const effectiveFieldType = typeConfig.fieldType || this.field.type || "text";
3440
3656
  if (effectiveFieldType === "textarea" || isTextareaType(effectiveFieldType)) {
3441
- return html`
3442
- <textarea
3443
- id="${fieldId}"
3444
- name="${fieldName}"
3445
- class="${cssClass}"
3446
- .value="${effectiveValue || ""}"
3447
- ?disabled="${effectiveDisabled || this.field.disabled}"
3448
- placeholder="${typeConfig.placeholder || this.field.placeholder || ""}"
3449
- @input="${this._handleInput}"
3450
- @focus="${this._handleFocus}"
3451
- @blur="${this._handleBlur}"
3452
- ></textarea>
3453
- `;
3657
+ return this._renderTextDialogTrigger(effectiveValue, effectiveDisabled || this.field.disabled || false);
3454
3658
  }
3455
3659
  if (effectiveFieldType === "select" || this.field.type === "select") {
3456
3660
  const selectOptions = typeConfig.enumerations || this.field.options || [];
@@ -3849,6 +4053,8 @@ JupiterFormField.styles = css`
3849
4053
  :host {
3850
4054
  display: block;
3851
4055
  margin-bottom: 0px; /* Remove bottom margin for table layout */
4056
+ overflow: hidden;
4057
+ min-width: 0;
3852
4058
  }
3853
4059
 
3854
4060
  :host([hideLabel]) {
@@ -3876,6 +4082,8 @@ JupiterFormField.styles = css`
3876
4082
  display: flex;
3877
4083
  align-items: center;
3878
4084
  gap: 8px;
4085
+ min-width: 0;
4086
+ overflow: hidden;
3879
4087
  }
3880
4088
 
3881
4089
  .period-icon-btn {
@@ -4194,6 +4402,89 @@ JupiterFormField.styles = css`
4194
4402
  outline: none;
4195
4403
  border-color: var(--jupiter-primary-color, #1976d2);
4196
4404
  }
4405
+
4406
+ /* Text dialog trigger — empty state */
4407
+ .text-trigger-btn {
4408
+ flex: 1;
4409
+ min-width: 0;
4410
+ padding: 5px 8px;
4411
+ border: 1px dashed var(--jupiter-border-color, #bbb);
4412
+ border-radius: 4px;
4413
+ background: transparent;
4414
+ color: var(--jupiter-text-secondary, #888);
4415
+ font-size: 12px;
4416
+ cursor: pointer;
4417
+ text-align: center;
4418
+ font-family: inherit;
4419
+ box-sizing: border-box;
4420
+ }
4421
+
4422
+ .text-trigger-btn:hover {
4423
+ border-color: var(--jupiter-primary-color, #1976d2);
4424
+ color: var(--jupiter-primary-color, #1976d2);
4425
+ background: rgba(25, 118, 210, 0.04);
4426
+ }
4427
+
4428
+ /* Text dialog trigger — filled state */
4429
+ .text-filled {
4430
+ display: flex;
4431
+ align-items: center;
4432
+ gap: 4px;
4433
+ flex: 1;
4434
+ min-width: 0;
4435
+ overflow: hidden;
4436
+ }
4437
+
4438
+ .text-filled-label {
4439
+ flex: 1;
4440
+ font-size: 13px;
4441
+ color: var(--jupiter-text-primary, #333);
4442
+ overflow: hidden;
4443
+ text-overflow: ellipsis;
4444
+ white-space: nowrap;
4445
+ cursor: pointer;
4446
+ min-width: 0;
4447
+ }
4448
+
4449
+ .text-filled-label:hover {
4450
+ color: var(--jupiter-primary-color, #1976d2);
4451
+ }
4452
+
4453
+ .text-edit-btn {
4454
+ flex-shrink: 0;
4455
+ padding: 2px 7px;
4456
+ border: 1px solid var(--jupiter-border-color, #ddd);
4457
+ border-radius: 3px;
4458
+ background: transparent;
4459
+ color: var(--jupiter-text-secondary, #666);
4460
+ font-size: 11px;
4461
+ cursor: pointer;
4462
+ font-family: inherit;
4463
+ white-space: nowrap;
4464
+ }
4465
+
4466
+ .text-edit-btn:hover {
4467
+ border-color: var(--jupiter-primary-color, #1976d2);
4468
+ color: var(--jupiter-primary-color, #1976d2);
4469
+ background: rgba(25, 118, 210, 0.04);
4470
+ }
4471
+
4472
+ /* Read-only filled text (disabled/inputForm) */
4473
+ .text-readonly-label {
4474
+ display: block;
4475
+ font-size: 13px;
4476
+ color: var(--jupiter-text-primary, #333);
4477
+ overflow: hidden;
4478
+ text-overflow: ellipsis;
4479
+ white-space: nowrap;
4480
+ flex: 1;
4481
+ min-width: 0;
4482
+ }
4483
+
4484
+ .text-readonly-label.empty {
4485
+ color: var(--jupiter-text-secondary, #999);
4486
+ font-style: italic;
4487
+ }
4197
4488
  `;
4198
4489
  __decorateClass$6([
4199
4490
  n2({ type: Object })
@@ -4304,6 +4595,7 @@ let JupiterConceptTree = class extends LitElement {
4304
4595
  this.typedMemberData = {};
4305
4596
  this.showAddButton = false;
4306
4597
  this.showRemoveButton = false;
4598
+ this.language = "en";
4307
4599
  this._expanded = true;
4308
4600
  }
4309
4601
  connectedCallback() {
@@ -4373,6 +4665,108 @@ let JupiterConceptTree = class extends LitElement {
4373
4665
  }));
4374
4666
  console.log(`🌲 [ConceptTree] Forwarded period-change event to form-section`);
4375
4667
  }
4668
+ _getDocLabel() {
4669
+ const meta = this.concept.conceptMetadata;
4670
+ if (!meta)
4671
+ return "";
4672
+ const lang = this.language || this.locale.split("-")[0];
4673
+ return meta.documentationLabels[lang] || meta.documentationLabels["en"] || meta.documentationLabels["nl"] || "";
4674
+ }
4675
+ _escapeHtml(str) {
4676
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
4677
+ }
4678
+ _ensureDialogStyles() {
4679
+ if (document.getElementById("jdf-concept-info-dialog-styles"))
4680
+ return;
4681
+ const style = document.createElement("style");
4682
+ style.id = "jdf-concept-info-dialog-styles";
4683
+ style.textContent = `
4684
+ dialog.jdf-concept-info-dialog {
4685
+ border: none; border-radius: 8px; padding: 0;
4686
+ max-width: 480px; width: 90vw;
4687
+ box-shadow: 0 8px 32px rgba(0,0,0,0.2); overflow: hidden;
4688
+ }
4689
+ dialog.jdf-concept-info-dialog::backdrop { background: rgba(0,0,0,0.35); }
4690
+ .jdf-dialog-header {
4691
+ background: #f0f2f5; padding: 14px 20px;
4692
+ display: flex; align-items: center; justify-content: space-between;
4693
+ border-bottom: 1px solid #ddd;
4694
+ }
4695
+ .jdf-dialog-title { font-size: 15px; font-weight: 600; color: #333; margin: 0; font-family: inherit; }
4696
+ .jdf-dialog-close-btn {
4697
+ width: 28px; height: 28px; border: none; background: transparent;
4698
+ font-size: 20px; line-height: 1; cursor: pointer; color: #666;
4699
+ border-radius: 4px; display: flex; align-items: center; justify-content: center;
4700
+ padding: 0; font-family: inherit;
4701
+ }
4702
+ .jdf-dialog-close-btn:hover { background: #ddd; color: #333; }
4703
+ .jdf-dialog-body { padding: 20px; }
4704
+ .jdf-info-table { width: 100%; border-collapse: collapse; font-size: 14px; font-family: inherit; }
4705
+ .jdf-info-table tr:not(:last-child) td { border-bottom: 1px solid #f0f0f0; }
4706
+ .jdf-info-table td { padding: 9px 4px; vertical-align: top; }
4707
+ .jdf-info-label { font-weight: 600; color: #666; width: 40%; white-space: nowrap; padding-right: 16px; }
4708
+ .jdf-info-value { color: #333; word-break: break-all; }
4709
+ .jdf-info-value.doc-text { font-style: italic; color: #555; line-height: 1.5; word-break: normal; }
4710
+ .jdf-period-pill { display: inline-block; padding: 2px 8px; border-radius: 10px; font-size: 12px; font-weight: 600; }
4711
+ .jdf-period-pill.instant { background: rgba(25,118,210,0.1); color: #1565c0; border: 1px solid rgba(25,118,210,0.3); }
4712
+ .jdf-period-pill.duration { background: rgba(56,142,60,0.1); color: #2e7d32; border: 1px solid rgba(56,142,60,0.3); }
4713
+ .jdf-balance-pill { display: inline-block; padding: 2px 8px; border-radius: 10px; font-size: 12px; font-weight: 600; text-transform: capitalize; }
4714
+ .jdf-balance-pill.debit { background: rgba(211,47,47,0.1); color: #c62828; border: 1px solid rgba(211,47,47,0.3); }
4715
+ .jdf-balance-pill.credit { background: rgba(56,142,60,0.1); color: #2e7d32; border: 1px solid rgba(56,142,60,0.3); }
4716
+ `;
4717
+ document.head.appendChild(style);
4718
+ }
4719
+ _openInfoDialog(e2) {
4720
+ var _a;
4721
+ e2.stopPropagation();
4722
+ this._ensureDialogStyles();
4723
+ const meta = this.concept.conceptMetadata;
4724
+ const docLabel = this._getDocLabel();
4725
+ const periodType = (meta == null ? void 0 : meta.periodType) || this.concept.periodType;
4726
+ const balance = (meta == null ? void 0 : meta.balance) || this.concept.balance;
4727
+ const periodLabel = periodType === "instant" ? I18n.t("conceptInfo.instant") : I18n.t("conceptInfo.duration");
4728
+ const rows = [
4729
+ { label: I18n.t("conceptInfo.conceptName"), valueHtml: this._escapeHtml((meta == null ? void 0 : meta.conceptName) || this.concept.name) },
4730
+ { label: I18n.t("conceptInfo.type"), valueHtml: this._escapeHtml((meta == null ? void 0 : meta.type) || this.concept.type || "—") }
4731
+ ];
4732
+ if (meta == null ? void 0 : meta.substitutionGroup) {
4733
+ rows.push({ label: I18n.t("conceptInfo.substitutionGroup"), valueHtml: this._escapeHtml(meta.substitutionGroup) });
4734
+ }
4735
+ rows.push({ label: I18n.t("conceptInfo.periodType"), valueHtml: `<span class="jdf-period-pill ${periodType}">${this._escapeHtml(periodLabel)}</span>` });
4736
+ if (balance) {
4737
+ rows.push({ label: I18n.t("conceptInfo.balance"), valueHtml: `<span class="jdf-balance-pill ${balance}">${this._escapeHtml(balance)}</span>` });
4738
+ }
4739
+ if (docLabel) {
4740
+ rows.push({ label: I18n.t("conceptInfo.documentation"), valueHtml: this._escapeHtml(docLabel), isDoc: true });
4741
+ }
4742
+ const rowsHtml = rows.map((r2) => `
4743
+ <tr>
4744
+ <td class="jdf-info-label">${this._escapeHtml(r2.label)}</td>
4745
+ <td class="jdf-info-value${r2.isDoc ? " doc-text" : ""}">${r2.valueHtml}</td>
4746
+ </tr>
4747
+ `).join("");
4748
+ const dialog = document.createElement("dialog");
4749
+ dialog.className = "jdf-concept-info-dialog";
4750
+ dialog.innerHTML = `
4751
+ <div class="jdf-dialog-header">
4752
+ <h3 class="jdf-dialog-title">${this._escapeHtml(I18n.t("conceptInfo.title"))}</h3>
4753
+ <button class="jdf-dialog-close-btn" type="button" aria-label="${this._escapeHtml(I18n.t("conceptInfo.close"))}">×</button>
4754
+ </div>
4755
+ <div class="jdf-dialog-body">
4756
+ <table class="jdf-info-table">${rowsHtml}</table>
4757
+ </div>
4758
+ `;
4759
+ document.body.appendChild(dialog);
4760
+ (_a = dialog.querySelector(".jdf-dialog-close-btn")) == null ? void 0 : _a.addEventListener("click", () => dialog.close());
4761
+ dialog.addEventListener("click", (ev) => {
4762
+ const rect = dialog.getBoundingClientRect();
4763
+ if (ev.clientX < rect.left || ev.clientX > rect.right || ev.clientY < rect.top || ev.clientY > rect.bottom) {
4764
+ dialog.close();
4765
+ }
4766
+ });
4767
+ dialog.addEventListener("close", () => document.body.removeChild(dialog));
4768
+ dialog.showModal();
4769
+ }
4376
4770
  render() {
4377
4771
  const hasChildren = this.concept.children && this.concept.children.length > 0;
4378
4772
  const level = this.concept.level || 0;
@@ -4394,6 +4788,8 @@ let JupiterConceptTree = class extends LitElement {
4394
4788
  ${this.concept.balance ? html`
4395
4789
  <div class="concept-balance ${this.concept.balance}">${this.concept.balance}</div>
4396
4790
  ` : ""}
4791
+ <button class="concept-info-btn" type="button" title="${I18n.t("conceptInfo.title")}"
4792
+ @click="${this._openInfoDialog}">ℹ</button>
4397
4793
  ${this.showAddButton ? html`
4398
4794
  <button class="repeat-btn" type="button" title="Add row"
4399
4795
  @click="${this._handleAddRepeat}">+</button>
@@ -4445,6 +4841,7 @@ let JupiterConceptTree = class extends LitElement {
4445
4841
  </td>
4446
4842
  `;
4447
4843
  })}
4844
+
4448
4845
  `;
4449
4846
  }
4450
4847
  };
@@ -4618,6 +5015,36 @@ JupiterConceptTree.styles = css`
4618
5015
  box-shadow: inset 0 0 0 2px var(--jupiter-error-color, #d32f2f);
4619
5016
  }
4620
5017
 
5018
+ .concept-info-btn {
5019
+ flex-shrink: 0;
5020
+ width: 18px;
5021
+ height: 18px;
5022
+ border-radius: 50%;
5023
+ border: 1px solid transparent;
5024
+ background: transparent;
5025
+ color: var(--jupiter-text-secondary, #888);
5026
+ font-size: 12px;
5027
+ cursor: pointer;
5028
+ display: flex;
5029
+ align-items: center;
5030
+ justify-content: center;
5031
+ opacity: 0;
5032
+ transition: opacity 0.15s, background 0.15s, color 0.15s;
5033
+ padding: 0;
5034
+ margin-left: 4px;
5035
+ line-height: 1;
5036
+ }
5037
+
5038
+ .concept-content:hover .concept-info-btn {
5039
+ opacity: 1;
5040
+ }
5041
+
5042
+ .concept-info-btn:hover {
5043
+ background: var(--jupiter-primary-color, #1976d2);
5044
+ color: #fff;
5045
+ border-color: var(--jupiter-primary-color, #1976d2);
5046
+ }
5047
+
4621
5048
  `;
4622
5049
  __decorateClass$5([
4623
5050
  n2({ type: Object })
@@ -4682,6 +5109,9 @@ __decorateClass$5([
4682
5109
  __decorateClass$5([
4683
5110
  n2({ type: Object })
4684
5111
  ], JupiterConceptTree.prototype, "calculationErrorKeys", 2);
5112
+ __decorateClass$5([
5113
+ n2({ type: String })
5114
+ ], JupiterConceptTree.prototype, "language", 2);
4685
5115
  __decorateClass$5([
4686
5116
  r()
4687
5117
  ], JupiterConceptTree.prototype, "_expanded", 2);
@@ -5351,6 +5781,7 @@ let JupiterFormSection = class extends LitElement {
5351
5781
  this.showFactsOnly = false;
5352
5782
  this.periodStartDate = "";
5353
5783
  this.periodEndDate = "";
5784
+ this.language = "en";
5354
5785
  this._expanded = true;
5355
5786
  this._showAddColumnDialog = false;
5356
5787
  this._sectionPeriodType = "duration";
@@ -5778,6 +6209,7 @@ let JupiterFormSection = class extends LitElement {
5778
6209
  .defaultUnits="${this.defaultUnits}"
5779
6210
  .disabled="${this.disabled}"
5780
6211
  .locale="${this.locale}"
6212
+ .language="${this.language}"
5781
6213
  .expandedConcepts="${this._expandedConcepts}"
5782
6214
  .mode="${this.mode}"
5783
6215
  .masterData="${this.masterData}"
@@ -6046,6 +6478,7 @@ JupiterFormSection.styles = css`
6046
6478
 
6047
6479
  .form-table {
6048
6480
  width: 100%;
6481
+ table-layout: fixed;
6049
6482
  border-collapse: separate;
6050
6483
  border-spacing: 0;
6051
6484
  background: var(--jupiter-table-background, #fff);
@@ -6295,6 +6728,9 @@ __decorateClass$3([
6295
6728
  __decorateClass$3([
6296
6729
  n2({ type: String })
6297
6730
  ], JupiterFormSection.prototype, "periodEndDate", 2);
6731
+ __decorateClass$3([
6732
+ n2({ type: String })
6733
+ ], JupiterFormSection.prototype, "language", 2);
6298
6734
  __decorateClass$3([
6299
6735
  r()
6300
6736
  ], JupiterFormSection.prototype, "_expanded", 2);
@@ -11721,6 +12157,7 @@ let JupiterDynamicForm = class extends LitElement {
11721
12157
  .disabled="${this.disabled || this.readonly}"
11722
12158
  .collapsible="${config.collapsibleSections !== false}"
11723
12159
  .locale="${config.locale || "en-US"}"
12160
+ .language="${this.language}"
11724
12161
  .isFirstSection="${index === 0}"
11725
12162
  .availableDimensions="${this._getAvailableDimensionsForSection(section2.id)}"
11726
12163
  .mode="${this.mode}"
@@ -11865,6 +12302,7 @@ let JupiterDynamicForm = class extends LitElement {
11865
12302
  .collapsible="${false}"
11866
12303
  .hideHeader="${true}"
11867
12304
  .locale="${config.locale || "en-US"}"
12305
+ .language="${this.language}"
11868
12306
  .isFirstSection="${true}"
11869
12307
  .availableDimensions="${this._getAvailableDimensionsForSection(activeSection.id)}"
11870
12308
  .mode="${this.mode}"