jupiter-dynamic-forms 1.17.8 → 1.18.0

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
@@ -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);
758
758
  let columnId;
759
759
  if (forcedColumnId) {
760
760
  columnId = forcedColumnId;
@@ -1635,6 +1635,7 @@ const conceptInfo$1 = {
1635
1635
  close: "Close"
1636
1636
  };
1637
1637
  const form$1 = {
1638
+ markAsComplete: "Mark as Complete",
1638
1639
  loading: "Loading form...",
1639
1640
  submit: "Validate",
1640
1641
  save: "Save",
@@ -1742,7 +1743,12 @@ const field$1 = {
1742
1743
  phonePlaceholder: "+1 (555) 000-0000",
1743
1744
  enterValue: "Enter value",
1744
1745
  enterDetailedInformation: "Enter detailed information...",
1745
- scale: "Scale"
1746
+ scale: "Scale",
1747
+ addText: "Add text",
1748
+ editText: "Edit",
1749
+ save: "Save",
1750
+ cancel: "Cancel",
1751
+ characters: "characters"
1746
1752
  };
1747
1753
  const admin$1 = {
1748
1754
  title: "Configure Roles",
@@ -1802,6 +1808,7 @@ const conceptInfo = {
1802
1808
  close: "Sluiten"
1803
1809
  };
1804
1810
  const form = {
1811
+ markAsComplete: "Markeren als volledig behandeld",
1805
1812
  loading: "Formulier laden...",
1806
1813
  submit: "Valideren",
1807
1814
  save: "Opslaan",
@@ -1909,7 +1916,12 @@ const field = {
1909
1916
  phonePlaceholder: "+31 (0)20 123 4567",
1910
1917
  enterValue: "Voer waarde in",
1911
1918
  enterDetailedInformation: "Voer gedetailleerde informatie in...",
1912
- scale: "Schaal"
1919
+ scale: "Schaal",
1920
+ addText: "Tekst toevoegen",
1921
+ editText: "Bewerken",
1922
+ save: "Opslaan",
1923
+ cancel: "Annuleren",
1924
+ characters: "tekens"
1913
1925
  };
1914
1926
  const admin = {
1915
1927
  title: "Rollen configureren",
@@ -3397,6 +3409,170 @@ let JupiterFormField = class extends LitElement {
3397
3409
  this._closePeriodPopup();
3398
3410
  }
3399
3411
  }
3412
+ _ensureTextDialogStyles() {
3413
+ if (document.getElementById("jdf-text-dialog-styles"))
3414
+ return;
3415
+ const style = document.createElement("style");
3416
+ style.id = "jdf-text-dialog-styles";
3417
+ style.textContent = `
3418
+ dialog.jdf-text-entry-dialog {
3419
+ border: none; border-radius: 8px; padding: 0;
3420
+ max-width: 600px; width: 90vw;
3421
+ box-shadow: 0 8px 32px rgba(0,0,0,0.2); overflow: hidden;
3422
+ font-family: inherit;
3423
+ }
3424
+ dialog.jdf-text-entry-dialog::backdrop { background: rgba(0,0,0,0.35); }
3425
+ .jdf-text-dialog-header {
3426
+ background: #f0f2f5; padding: 14px 20px;
3427
+ display: flex; align-items: center; justify-content: space-between;
3428
+ border-bottom: 1px solid #ddd;
3429
+ }
3430
+ .jdf-text-dialog-title {
3431
+ font-size: 15px; font-weight: 600; color: #333; margin: 0;
3432
+ font-family: inherit; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
3433
+ }
3434
+ .jdf-text-dialog-close {
3435
+ flex-shrink: 0; width: 28px; height: 28px; border: none; background: transparent;
3436
+ font-size: 20px; line-height: 1; cursor: pointer; color: #666;
3437
+ border-radius: 4px; display: flex; align-items: center; justify-content: center;
3438
+ padding: 0; font-family: inherit; margin-left: 8px;
3439
+ }
3440
+ .jdf-text-dialog-close:hover { background: #ddd; color: #333; }
3441
+ .jdf-text-dialog-body { padding: 20px 20px 12px; }
3442
+ .jdf-text-dialog-textarea {
3443
+ width: 100%; min-height: 200px; max-height: 50vh;
3444
+ padding: 10px 12px; font-size: 14px; font-family: inherit;
3445
+ border: 1px solid #ddd; border-radius: 4px;
3446
+ box-sizing: border-box; resize: vertical; line-height: 1.5;
3447
+ color: #333; background: #fff;
3448
+ }
3449
+ .jdf-text-dialog-textarea:focus {
3450
+ outline: none; border-color: #1976d2;
3451
+ box-shadow: 0 0 0 2px rgba(25,118,210,0.2);
3452
+ }
3453
+ .jdf-text-dialog-char-count {
3454
+ margin-top: 4px; font-size: 12px; color: #888; text-align: right;
3455
+ font-family: inherit;
3456
+ }
3457
+ .jdf-text-dialog-actions {
3458
+ display: flex; justify-content: flex-end; gap: 8px;
3459
+ padding: 12px 20px 16px; border-top: 1px solid #eee;
3460
+ }
3461
+ .jdf-text-dialog-cancel {
3462
+ padding: 7px 18px; border: 1px solid #ddd; border-radius: 4px;
3463
+ background: transparent; color: #555; font-size: 14px;
3464
+ cursor: pointer; font-family: inherit;
3465
+ }
3466
+ .jdf-text-dialog-cancel:hover { background: #f5f5f5; }
3467
+ .jdf-text-dialog-save {
3468
+ padding: 7px 18px; border: none; border-radius: 4px;
3469
+ background: #1976d2; color: #fff; font-size: 14px;
3470
+ cursor: pointer; font-family: inherit; font-weight: 500;
3471
+ }
3472
+ .jdf-text-dialog-save:hover { background: #1565c0; }
3473
+ `;
3474
+ document.head.appendChild(style);
3475
+ }
3476
+ _openTextDialog(currentValue, fieldLabel) {
3477
+ var _a;
3478
+ this._ensureTextDialogStyles();
3479
+ (_a = document.getElementById("jdf-text-entry-dialog")) == null ? void 0 : _a.remove();
3480
+ const dialog = document.createElement("dialog");
3481
+ dialog.id = "jdf-text-entry-dialog";
3482
+ dialog.className = "jdf-text-entry-dialog";
3483
+ dialog.setAttribute("role", "dialog");
3484
+ dialog.setAttribute("aria-modal", "true");
3485
+ dialog.setAttribute("aria-labelledby", "jdf-text-dialog-title");
3486
+ dialog.innerHTML = `
3487
+ <div class="jdf-text-dialog-header">
3488
+ <h3 class="jdf-text-dialog-title" id="jdf-text-dialog-title"></h3>
3489
+ <button class="jdf-text-dialog-close" type="button" aria-label="Close">×</button>
3490
+ </div>
3491
+ <div class="jdf-text-dialog-body">
3492
+ <textarea class="jdf-text-dialog-textarea" spellcheck="true"></textarea>
3493
+ <div class="jdf-text-dialog-char-count"></div>
3494
+ </div>
3495
+ <div class="jdf-text-dialog-actions">
3496
+ <button class="jdf-text-dialog-cancel" type="button"></button>
3497
+ <button class="jdf-text-dialog-save" type="button"></button>
3498
+ </div>
3499
+ `;
3500
+ const cleanTitle = fieldLabel;
3501
+ dialog.querySelector(".jdf-text-dialog-title").textContent = cleanTitle || fieldLabel;
3502
+ dialog.querySelector(".jdf-text-dialog-cancel").textContent = I18n.t("field.cancel");
3503
+ dialog.querySelector(".jdf-text-dialog-save").textContent = I18n.t("field.save");
3504
+ const textarea = dialog.querySelector(".jdf-text-dialog-textarea");
3505
+ const charCount = dialog.querySelector(".jdf-text-dialog-char-count");
3506
+ textarea.value = currentValue;
3507
+ charCount.textContent = `${currentValue.length} ${I18n.t("field.characters")}`;
3508
+ textarea.addEventListener("input", () => {
3509
+ charCount.textContent = `${textarea.value.length} ${I18n.t("field.characters")}`;
3510
+ });
3511
+ dialog.querySelector(".jdf-text-dialog-close").addEventListener("click", () => dialog.close());
3512
+ dialog.querySelector(".jdf-text-dialog-cancel").addEventListener("click", () => dialog.close());
3513
+ dialog.querySelector(".jdf-text-dialog-save").addEventListener("click", () => {
3514
+ const newValue = textarea.value;
3515
+ const oldValue = this.value;
3516
+ this.value = newValue;
3517
+ this._touched = true;
3518
+ this.dispatchEvent(new CustomEvent("field-change", {
3519
+ detail: { fieldId: this.field.id, conceptId: this.conceptId, columnId: this.columnId, value: newValue, oldValue },
3520
+ bubbles: true
3521
+ }));
3522
+ dialog.close();
3523
+ });
3524
+ dialog.addEventListener("click", (ev) => {
3525
+ const rect = dialog.getBoundingClientRect();
3526
+ if (ev.clientX < rect.left || ev.clientX > rect.right || ev.clientY < rect.top || ev.clientY > rect.bottom) {
3527
+ dialog.close();
3528
+ }
3529
+ });
3530
+ dialog.addEventListener("close", () => dialog.remove());
3531
+ document.body.appendChild(dialog);
3532
+ dialog.showModal();
3533
+ textarea.focus();
3534
+ }
3535
+ _renderTextDialogTrigger(effectiveValue, effectiveDisabled) {
3536
+ const hasValue = effectiveValue !== null && effectiveValue !== void 0 && String(effectiveValue).trim() !== "";
3537
+ const displayText = hasValue ? String(effectiveValue) : "";
3538
+ if (effectiveDisabled) {
3539
+ return html`
3540
+ <span class="text-readonly-label ${hasValue ? "" : "empty"}"
3541
+ title="${displayText}">${hasValue ? displayText : "—"}</span>
3542
+ `;
3543
+ }
3544
+ if (!hasValue) {
3545
+ return html`
3546
+ <button class="text-trigger-btn" type="button"
3547
+ aria-label="${I18n.t("field.addText")}"
3548
+ @click="${() => {
3549
+ var _a;
3550
+ return this._openTextDialog("", ((_a = this.field) == null ? void 0 : _a.label) || "");
3551
+ }}">
3552
+ + ${I18n.t("field.addText")}
3553
+ </button>
3554
+ `;
3555
+ }
3556
+ return html`
3557
+ <div class="text-filled">
3558
+ <span class="text-filled-label" title="${displayText}"
3559
+ @click="${() => {
3560
+ var _a;
3561
+ return this._openTextDialog(displayText, ((_a = this.field) == null ? void 0 : _a.label) || "");
3562
+ }}">
3563
+ ${displayText}
3564
+ </span>
3565
+ <button class="text-edit-btn" type="button"
3566
+ aria-label="${I18n.t("field.editText")}"
3567
+ @click="${() => {
3568
+ var _a;
3569
+ return this._openTextDialog(displayText, ((_a = this.field) == null ? void 0 : _a.label) || "");
3570
+ }}">
3571
+ ✎ ${I18n.t("field.editText")}
3572
+ </button>
3573
+ </div>
3574
+ `;
3575
+ }
3400
3576
  _handlePeriodChange(event, type) {
3401
3577
  const target = event.target;
3402
3578
  const value = target.value;
@@ -3481,19 +3657,7 @@ let JupiterFormField = class extends LitElement {
3481
3657
  ;
3482
3658
  const effectiveFieldType = typeConfig.fieldType || this.field.type || "text";
3483
3659
  if (effectiveFieldType === "textarea" || isTextareaType(effectiveFieldType)) {
3484
- return html`
3485
- <textarea
3486
- id="${fieldId}"
3487
- name="${fieldName}"
3488
- class="${cssClass}"
3489
- .value="${effectiveValue || ""}"
3490
- ?disabled="${effectiveDisabled || this.field.disabled}"
3491
- placeholder="${typeConfig.placeholder || this.field.placeholder || ""}"
3492
- @input="${this._handleInput}"
3493
- @focus="${this._handleFocus}"
3494
- @blur="${this._handleBlur}"
3495
- ></textarea>
3496
- `;
3660
+ return this._renderTextDialogTrigger(effectiveValue, effectiveDisabled || this.field.disabled || false);
3497
3661
  }
3498
3662
  if (effectiveFieldType === "select" || this.field.type === "select") {
3499
3663
  const selectOptions = typeConfig.enumerations || this.field.options || [];
@@ -3892,6 +4056,8 @@ JupiterFormField.styles = css`
3892
4056
  :host {
3893
4057
  display: block;
3894
4058
  margin-bottom: 0px; /* Remove bottom margin for table layout */
4059
+ overflow: hidden;
4060
+ min-width: 0;
3895
4061
  }
3896
4062
 
3897
4063
  :host([hideLabel]) {
@@ -3919,6 +4085,8 @@ JupiterFormField.styles = css`
3919
4085
  display: flex;
3920
4086
  align-items: center;
3921
4087
  gap: 8px;
4088
+ min-width: 0;
4089
+ overflow: hidden;
3922
4090
  }
3923
4091
 
3924
4092
  .period-icon-btn {
@@ -4237,6 +4405,89 @@ JupiterFormField.styles = css`
4237
4405
  outline: none;
4238
4406
  border-color: var(--jupiter-primary-color, #1976d2);
4239
4407
  }
4408
+
4409
+ /* Text dialog trigger — empty state */
4410
+ .text-trigger-btn {
4411
+ flex: 1;
4412
+ min-width: 0;
4413
+ padding: 5px 8px;
4414
+ border: 1px dashed var(--jupiter-border-color, #bbb);
4415
+ border-radius: 4px;
4416
+ background: transparent;
4417
+ color: var(--jupiter-text-secondary, #888);
4418
+ font-size: 12px;
4419
+ cursor: pointer;
4420
+ text-align: center;
4421
+ font-family: inherit;
4422
+ box-sizing: border-box;
4423
+ }
4424
+
4425
+ .text-trigger-btn:hover {
4426
+ border-color: var(--jupiter-primary-color, #1976d2);
4427
+ color: var(--jupiter-primary-color, #1976d2);
4428
+ background: rgba(25, 118, 210, 0.04);
4429
+ }
4430
+
4431
+ /* Text dialog trigger — filled state */
4432
+ .text-filled {
4433
+ display: flex;
4434
+ align-items: center;
4435
+ gap: 4px;
4436
+ flex: 1;
4437
+ min-width: 0;
4438
+ overflow: hidden;
4439
+ }
4440
+
4441
+ .text-filled-label {
4442
+ flex: 1;
4443
+ font-size: 13px;
4444
+ color: var(--jupiter-text-primary, #333);
4445
+ overflow: hidden;
4446
+ text-overflow: ellipsis;
4447
+ white-space: nowrap;
4448
+ cursor: pointer;
4449
+ min-width: 0;
4450
+ }
4451
+
4452
+ .text-filled-label:hover {
4453
+ color: var(--jupiter-primary-color, #1976d2);
4454
+ }
4455
+
4456
+ .text-edit-btn {
4457
+ flex-shrink: 0;
4458
+ padding: 2px 7px;
4459
+ border: 1px solid var(--jupiter-border-color, #ddd);
4460
+ border-radius: 3px;
4461
+ background: transparent;
4462
+ color: var(--jupiter-text-secondary, #666);
4463
+ font-size: 11px;
4464
+ cursor: pointer;
4465
+ font-family: inherit;
4466
+ white-space: nowrap;
4467
+ }
4468
+
4469
+ .text-edit-btn:hover {
4470
+ border-color: var(--jupiter-primary-color, #1976d2);
4471
+ color: var(--jupiter-primary-color, #1976d2);
4472
+ background: rgba(25, 118, 210, 0.04);
4473
+ }
4474
+
4475
+ /* Read-only filled text (disabled/inputForm) */
4476
+ .text-readonly-label {
4477
+ display: block;
4478
+ font-size: 13px;
4479
+ color: var(--jupiter-text-primary, #333);
4480
+ overflow: hidden;
4481
+ text-overflow: ellipsis;
4482
+ white-space: nowrap;
4483
+ flex: 1;
4484
+ min-width: 0;
4485
+ }
4486
+
4487
+ .text-readonly-label.empty {
4488
+ color: var(--jupiter-text-secondary, #999);
4489
+ font-style: italic;
4490
+ }
4240
4491
  `;
4241
4492
  __decorateClass$6([
4242
4493
  n2({ type: Object })
@@ -6230,6 +6481,7 @@ JupiterFormSection.styles = css`
6230
6481
 
6231
6482
  .form-table {
6232
6483
  width: 100%;
6484
+ table-layout: fixed;
6233
6485
  border-collapse: separate;
6234
6486
  border-spacing: 0;
6235
6487
  background: var(--jupiter-table-background, #fff);
@@ -12078,7 +12330,7 @@ let JupiterDynamicForm = class extends LitElement {
12078
12330
  .checked="${this._roleCompletedStates.get(activeSection.id) === true}"
12079
12331
  @change="${(e2) => this._handleRoleCompletedChange(activeSection.id, e2.target.checked)}"
12080
12332
  >
12081
- <label for="role-complete-${activeSection.id}">Mark as completed</label>
12333
+ <label for="role-complete-${activeSection.id}">${I18n.t("form.markAsComplete")}</label>
12082
12334
  </div>
12083
12335
  ` : html`
12084
12336
  <div class="no-roles-message">