jupiter-dynamic-forms 1.14.6 → 1.14.7

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
@@ -699,6 +699,8 @@ class XBRLFormBuilder {
699
699
  level,
700
700
  children,
701
701
  fields,
702
+ facts: concept.facts || [],
703
+ // Pass facts array from presentation concept for pre-population
702
704
  collapsed: level > 0,
703
705
  // Collapse nested levels by default
704
706
  abstract: concept.elementAbstract,
@@ -2597,6 +2599,241 @@ function determineInputTypeFromBaseChain(baseTypeChain, datatypes) {
2597
2599
  placeholder: I18n.t("field.enterValue")
2598
2600
  };
2599
2601
  }
2602
+ class FactMatcher {
2603
+ /**
2604
+ * Find a matching fact for a given cell context
2605
+ */
2606
+ static findMatchingFact(facts, context) {
2607
+ if (!facts || facts.length === 0) {
2608
+ return null;
2609
+ }
2610
+ const periodMatchedFacts = facts.filter(
2611
+ (fact) => this.matchesPeriod(fact, context)
2612
+ );
2613
+ if (periodMatchedFacts.length === 0) {
2614
+ return null;
2615
+ }
2616
+ const dimensionMatchedFacts = periodMatchedFacts.filter(
2617
+ (fact) => this.matchesDimensions(fact, context)
2618
+ );
2619
+ if (dimensionMatchedFacts.length === 0) {
2620
+ return null;
2621
+ }
2622
+ if (dimensionMatchedFacts.length > 1 && context.unit) {
2623
+ const unitMatchedFact = dimensionMatchedFacts.find(
2624
+ (fact) => this.matchesUnit(fact, context)
2625
+ );
2626
+ if (unitMatchedFact) {
2627
+ return unitMatchedFact;
2628
+ }
2629
+ }
2630
+ return dimensionMatchedFacts[0];
2631
+ }
2632
+ /**
2633
+ * Check if fact period matches cell period
2634
+ */
2635
+ static matchesPeriod(fact, context) {
2636
+ const factPeriod = this.parsePeriod(fact.period);
2637
+ if (context.periodType === "instant" && context.periodInstantDate) {
2638
+ return factPeriod.isInstant && factPeriod.instantDate === context.periodInstantDate;
2639
+ }
2640
+ if (context.periodType === "duration" && context.periodStartDate && context.periodEndDate) {
2641
+ return !factPeriod.isInstant && factPeriod.startDate === context.periodStartDate && factPeriod.endDate === context.periodEndDate;
2642
+ }
2643
+ if (context.periodInstantDate) {
2644
+ return factPeriod.isInstant && factPeriod.instantDate === context.periodInstantDate;
2645
+ }
2646
+ if (context.periodStartDate && context.periodEndDate) {
2647
+ return !factPeriod.isInstant && factPeriod.startDate === context.periodStartDate && factPeriod.endDate === context.periodEndDate;
2648
+ }
2649
+ return true;
2650
+ }
2651
+ /**
2652
+ * Check if fact dimensions match cell dimensions
2653
+ */
2654
+ static matchesDimensions(fact, context) {
2655
+ const factDimensions = fact.dimensions || [];
2656
+ const cellDimensions = this.extractDimensionsFromContext(context);
2657
+ if (cellDimensions.length === 0) {
2658
+ return factDimensions.length === 0;
2659
+ }
2660
+ if (factDimensions.length === 0 && cellDimensions.length > 0) {
2661
+ return false;
2662
+ }
2663
+ if (factDimensions.length !== cellDimensions.length) {
2664
+ return false;
2665
+ }
2666
+ const allMatch = cellDimensions.every((cellDim) => {
2667
+ return factDimensions.some((factDim) => {
2668
+ const axisMatch = this.normalizeAxisId(factDim.dimension) === this.normalizeAxisId(cellDim.axisId);
2669
+ if (!axisMatch) {
2670
+ return false;
2671
+ }
2672
+ if (factDim.dimensionType === "explicit" && cellDim.memberId) {
2673
+ const memberMatch = this.normalizeMemberId(factDim.member || "") === this.normalizeMemberId(cellDim.memberId);
2674
+ return memberMatch;
2675
+ }
2676
+ if (factDim.dimensionType === "typed" && cellDim.isTyped) {
2677
+ return true;
2678
+ }
2679
+ return false;
2680
+ });
2681
+ });
2682
+ return allMatch;
2683
+ }
2684
+ /**
2685
+ * Check if fact unit matches cell unit
2686
+ */
2687
+ static matchesUnit(fact, context) {
2688
+ if (!context.unit || !fact.unitMeasure) {
2689
+ return true;
2690
+ }
2691
+ const factUnit = this.normalizeUnit(fact.unitMeasure);
2692
+ const cellUnit = this.normalizeUnit(context.unit);
2693
+ return factUnit === cellUnit;
2694
+ }
2695
+ /**
2696
+ * Parse period string into structured format
2697
+ */
2698
+ static parsePeriod(period) {
2699
+ if (period.includes(" / ")) {
2700
+ const [startDate, endDate] = period.split(" / ").map((d2) => d2.trim());
2701
+ return {
2702
+ isInstant: false,
2703
+ startDate,
2704
+ endDate
2705
+ };
2706
+ }
2707
+ return {
2708
+ isInstant: true,
2709
+ instantDate: period.trim()
2710
+ };
2711
+ }
2712
+ /**
2713
+ * Extract dimensions from cell context
2714
+ */
2715
+ static extractDimensionsFromContext(context) {
2716
+ if (!context.dimensionData) {
2717
+ return [];
2718
+ }
2719
+ const dimensions = [];
2720
+ if (context.dimensionData.combinations && context.dimensionData.combinations.length > 0) {
2721
+ context.dimensionData.combinations.forEach((combo) => {
2722
+ dimensions.push({
2723
+ axisId: combo.axisId,
2724
+ memberId: combo.memberId
2725
+ });
2726
+ });
2727
+ }
2728
+ if (context.dimensionData.typedMembers && context.dimensionData.typedMembers.length > 0) {
2729
+ context.dimensionData.typedMembers.forEach((typed) => {
2730
+ dimensions.push({
2731
+ axisId: typed.axisId,
2732
+ memberId: "[typed]",
2733
+ isTyped: true
2734
+ });
2735
+ });
2736
+ }
2737
+ return dimensions;
2738
+ }
2739
+ /**
2740
+ * Normalize axis ID for comparison
2741
+ * Handles both formats: "jenv-bw2-dim:BasisOfPreparationAxis" and "jenv-bw2-dim_BasisOfPreparationAxis"
2742
+ * Returns: "BasisOfPreparationAxis"
2743
+ */
2744
+ static normalizeAxisId(axisId) {
2745
+ if (!axisId)
2746
+ return "";
2747
+ if (axisId.includes(":")) {
2748
+ const parts = axisId.split(":");
2749
+ return parts[1] || parts[0];
2750
+ }
2751
+ if (axisId.includes("_")) {
2752
+ axisId.split("_");
2753
+ const lastUnderscoreIndex = axisId.lastIndexOf("_");
2754
+ if (lastUnderscoreIndex > 0) {
2755
+ return axisId.substring(lastUnderscoreIndex + 1);
2756
+ }
2757
+ }
2758
+ return axisId;
2759
+ }
2760
+ /**
2761
+ * Normalize member ID for comparison
2762
+ * Handles both formats: "jenv-bw2-dm:CommercialMember" and "jenv-bw2-dm_CommercialMember"
2763
+ * Returns: "CommercialMember"
2764
+ */
2765
+ static normalizeMemberId(memberId) {
2766
+ if (!memberId)
2767
+ return "";
2768
+ if (memberId.includes(":")) {
2769
+ const parts = memberId.split(":");
2770
+ return parts[1] || parts[0];
2771
+ }
2772
+ if (memberId.includes("_")) {
2773
+ const lastUnderscoreIndex = memberId.lastIndexOf("_");
2774
+ if (lastUnderscoreIndex > 0) {
2775
+ return memberId.substring(lastUnderscoreIndex + 1);
2776
+ }
2777
+ }
2778
+ return memberId;
2779
+ }
2780
+ /**
2781
+ * Normalize unit for comparison
2782
+ * Converts "iso4217:EUR" to "EUR"
2783
+ */
2784
+ static normalizeUnit(unit) {
2785
+ if (!unit)
2786
+ return "";
2787
+ const parts = unit.split(":");
2788
+ return parts.length > 1 ? parts[1] : parts[0];
2789
+ }
2790
+ /**
2791
+ * Extract typed dimension values from facts
2792
+ * Returns a map of axis IDs to typed values
2793
+ */
2794
+ static extractTypedValues(facts, context) {
2795
+ const typedValues = {};
2796
+ if (!facts || facts.length === 0) {
2797
+ return typedValues;
2798
+ }
2799
+ const matchedFacts = facts.filter(
2800
+ (fact) => this.matchesPeriod(fact, context) && this.matchesDimensions(fact, context)
2801
+ );
2802
+ matchedFacts.forEach((fact) => {
2803
+ if (fact.dimensions) {
2804
+ fact.dimensions.forEach((dim) => {
2805
+ if (dim.dimensionType === "typed" && dim.typedMemberValue) {
2806
+ const axisId = this.normalizeAxisId(dim.dimension);
2807
+ typedValues[axisId] = dim.typedMemberValue;
2808
+ }
2809
+ });
2810
+ }
2811
+ });
2812
+ return typedValues;
2813
+ }
2814
+ /**
2815
+ * Debug helper: Log matching process
2816
+ */
2817
+ static debugMatch(facts, context) {
2818
+ console.log("🔍 [FactMatcher] Debug Match");
2819
+ console.log(" Context:", {
2820
+ conceptId: context.conceptId,
2821
+ columnId: context.columnId,
2822
+ period: context.periodType === "instant" ? context.periodInstantDate : `${context.periodStartDate} / ${context.periodEndDate}`,
2823
+ dimensions: this.extractDimensionsFromContext(context)
2824
+ });
2825
+ console.log(" Facts:", facts.map((f2) => {
2826
+ var _a;
2827
+ return {
2828
+ value: f2.value,
2829
+ period: f2.period,
2830
+ dimensions: (_a = f2.dimensions) == null ? void 0 : _a.map((d2) => `${d2.dimension}:${d2.member}`)
2831
+ };
2832
+ }));
2833
+ const match = this.findMatchingFact(facts, context);
2834
+ console.log(" Match Result:", match ? match.value : "No match");
2835
+ }
2836
+ }
2600
2837
  var __defProp$5 = Object.defineProperty;
2601
2838
  var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
2602
2839
  var __decorateClass$5 = (decorators, target, key, kind) => {
@@ -2616,6 +2853,7 @@ let JupiterFormField = class extends LitElement {
2616
2853
  this.disabled = false;
2617
2854
  this.locale = "en-US";
2618
2855
  this.hideLabel = false;
2856
+ this.mode = "inputForm";
2619
2857
  this._errors = [];
2620
2858
  this._xbrlErrors = [];
2621
2859
  this._touched = false;
@@ -2916,7 +3154,7 @@ let JupiterFormField = class extends LitElement {
2916
3154
  periodType: this.field.periodType
2917
3155
  });
2918
3156
  }
2919
- _renderInput() {
3157
+ _renderInput(effectiveValue = this.value, effectiveDisabled = this.disabled) {
2920
3158
  const hasErrors = this._errors.some((e2) => e2.severity === "error");
2921
3159
  const hasWarnings = this._errors.some((e2) => e2.severity === "warning");
2922
3160
  const isMonetary = this._isMonetaryType();
@@ -2933,8 +3171,8 @@ let JupiterFormField = class extends LitElement {
2933
3171
  id="${fieldId}"
2934
3172
  name="${fieldName}"
2935
3173
  class="${cssClass}"
2936
- .value="${this.value || ""}"
2937
- ?disabled="${this.disabled || this.field.disabled}"
3174
+ .value="${effectiveValue || ""}"
3175
+ ?disabled="${effectiveDisabled || this.field.disabled}"
2938
3176
  placeholder="${typeConfig.placeholder || this.field.placeholder || ""}"
2939
3177
  @input="${this._handleInput}"
2940
3178
  @focus="${this._handleFocus}"
@@ -2949,8 +3187,8 @@ let JupiterFormField = class extends LitElement {
2949
3187
  id="${fieldId}"
2950
3188
  name="${fieldName}"
2951
3189
  class="${cssClass}"
2952
- .value="${this.value || ""}"
2953
- ?disabled="${this.disabled || this.field.disabled}"
3190
+ .value="${effectiveValue || ""}"
3191
+ ?disabled="${effectiveDisabled || this.field.disabled}"
2954
3192
  @change="${this._handleInput}"
2955
3193
  @focus="${this._handleFocus}"
2956
3194
  @blur="${this._handleBlur}"
@@ -2964,7 +3202,7 @@ let JupiterFormField = class extends LitElement {
2964
3202
  <option
2965
3203
  value="${optionValue}"
2966
3204
  ?disabled="${isDisabled}"
2967
- ?selected="${this.value === optionValue}"
3205
+ ?selected="${effectiveValue === optionValue}"
2968
3206
  >
2969
3207
  ${optionLabel}
2970
3208
  </option>
@@ -2981,8 +3219,8 @@ let JupiterFormField = class extends LitElement {
2981
3219
  name="${fieldName}"
2982
3220
  type="checkbox"
2983
3221
  class="field-input"
2984
- .checked="${Boolean(this.value)}"
2985
- ?disabled="${this.disabled || this.field.disabled}"
3222
+ .checked="${Boolean(effectiveValue)}"
3223
+ ?disabled="${effectiveDisabled || this.field.disabled}"
2986
3224
  @change="${this._handleInput}"
2987
3225
  @focus="${this._handleFocus}"
2988
3226
  @blur="${this._handleBlur}"
@@ -3001,8 +3239,8 @@ let JupiterFormField = class extends LitElement {
3001
3239
  name="${fieldName}"
3002
3240
  type="${inputType}"
3003
3241
  class="${cssClass}"
3004
- .value="${this.value || ""}"
3005
- ?disabled="${this.disabled || this.field.disabled}"
3242
+ .value="${effectiveValue || ""}"
3243
+ ?disabled="${effectiveDisabled || this.field.disabled}"
3006
3244
  placeholder="${typeConfig.placeholder || this.field.placeholder || ""}"
3007
3245
  step="${step !== void 0 ? step : ""}"
3008
3246
  min="${min !== void 0 ? min : ""}"
@@ -3035,6 +3273,17 @@ let JupiterFormField = class extends LitElement {
3035
3273
  return "text";
3036
3274
  }
3037
3275
  }
3276
+ /**
3277
+ * Extract base concept ID by removing column suffix
3278
+ * Example: "nl-cd_LegalEntityName__4qukyf" -> "nl-cd_LegalEntityName"
3279
+ */
3280
+ _extractBaseConceptId(conceptId) {
3281
+ const parts = conceptId.split("__");
3282
+ if (parts.length > 1) {
3283
+ return parts.slice(0, -1).join("__");
3284
+ }
3285
+ return conceptId;
3286
+ }
3038
3287
  _renderPeriodControls() {
3039
3288
  if (this.conceptId === "nl-cd_DescriptionLocationNL__a64trl") {
3040
3289
  console.log(`🔍 [FormField Render] Concept: ${this.conceptId}, ColumnId: ${this.columnId}, Field periodType: ${this.field.periodType}, Field periodStartDate: ${this.field.periodStartDate}, Field periodEndDate: ${this.field.periodEndDate}`);
@@ -3143,8 +3392,69 @@ let JupiterFormField = class extends LitElement {
3143
3392
  `;
3144
3393
  }
3145
3394
  render() {
3395
+ var _a, _b;
3396
+ if (!this.field) {
3397
+ console.error("[FormField] No field provided!", { conceptId: this.conceptId, columnId: this.columnId });
3398
+ return html`<div>Error: No field data</div>`;
3399
+ }
3146
3400
  const showLabel = !this.hideLabel && this.field.type !== "boolean";
3147
3401
  const hasPeriodControl = this.field.periodType && (this.field.periodType === "instant" || this.field.periodType === "duration");
3402
+ const baseConceptId = this._extractBaseConceptId(this.conceptId);
3403
+ const isPredefinedValue = this.mode !== "admin" && this.masterData && baseConceptId in this.masterData;
3404
+ let factValue = null;
3405
+ if (this.facts && this.facts.length > 0 && !isPredefinedValue) {
3406
+ const cellContext = {
3407
+ conceptId: baseConceptId,
3408
+ columnId: this.columnId,
3409
+ periodStartDate: this.periodStartDate || this.field.periodStartDate,
3410
+ periodEndDate: this.periodEndDate || this.field.periodEndDate,
3411
+ periodInstantDate: this.periodInstantDate || this.field.periodInstantDate,
3412
+ periodType: this.field.periodType,
3413
+ unit: this.unit,
3414
+ dimensionData: (_a = this.column) == null ? void 0 : _a.dimensionData
3415
+ };
3416
+ const shouldDebugDimensions = baseConceptId.includes("BalanceSheet") || baseConceptId.includes("CostsIncorporation") || baseConceptId.includes("Assets");
3417
+ if (shouldDebugDimensions && this.facts.length > 0) {
3418
+ console.log("🔍 [FormField] Attempting fact match for concept with dimensions:", {
3419
+ conceptId: baseConceptId,
3420
+ columnId: this.columnId,
3421
+ factsCount: this.facts.length,
3422
+ cellContext: {
3423
+ period: cellContext.periodType === "instant" ? cellContext.periodInstantDate : `${cellContext.periodStartDate} / ${cellContext.periodEndDate}`,
3424
+ dimensionData: cellContext.dimensionData
3425
+ },
3426
+ facts: this.facts.map((f2) => {
3427
+ var _a2;
3428
+ return {
3429
+ value: f2.value,
3430
+ period: f2.period,
3431
+ dimensions: (_a2 = f2.dimensions) == null ? void 0 : _a2.map((d2) => `${d2.dimension}:${d2.member}`)
3432
+ };
3433
+ })
3434
+ });
3435
+ }
3436
+ const matchedFact = FactMatcher.findMatchingFact(this.facts, cellContext);
3437
+ if (matchedFact) {
3438
+ factValue = matchedFact.value;
3439
+ if (shouldDebugDimensions || baseConceptId.includes("StreetName")) {
3440
+ console.log("✅ [FormField] Fact matched:", {
3441
+ conceptId: baseConceptId,
3442
+ columnId: this.columnId,
3443
+ factValue: matchedFact.value,
3444
+ period: matchedFact.period,
3445
+ dimensions: (_b = matchedFact.dimensions) == null ? void 0 : _b.map((d2) => `${d2.dimension}:${d2.member}`)
3446
+ });
3447
+ }
3448
+ } else if (shouldDebugDimensions && this.facts.length > 0) {
3449
+ console.log("❌ [FormField] No fact match found for:", {
3450
+ conceptId: baseConceptId,
3451
+ columnId: this.columnId,
3452
+ factsAvailable: this.facts.length
3453
+ });
3454
+ }
3455
+ }
3456
+ const effectiveValue = isPredefinedValue ? this.masterData[baseConceptId] : factValue !== null ? factValue : this.value;
3457
+ const effectiveDisabled = isPredefinedValue || this.disabled;
3148
3458
  return html`
3149
3459
  <div class="field-container">
3150
3460
  ${showLabel ? html`
@@ -3154,7 +3464,7 @@ let JupiterFormField = class extends LitElement {
3154
3464
  ` : ""}
3155
3465
 
3156
3466
  <div class="field-wrapper">
3157
- ${this._renderInput()}
3467
+ ${this._renderInput(effectiveValue, effectiveDisabled)}
3158
3468
 
3159
3469
  ${hasPeriodControl ? html`
3160
3470
  <button
@@ -3496,6 +3806,18 @@ __decorateClass$5([
3496
3806
  __decorateClass$5([
3497
3807
  n2({ type: Boolean })
3498
3808
  ], JupiterFormField.prototype, "hideLabel", 2);
3809
+ __decorateClass$5([
3810
+ n2({ type: String })
3811
+ ], JupiterFormField.prototype, "mode", 2);
3812
+ __decorateClass$5([
3813
+ n2({ type: Object })
3814
+ ], JupiterFormField.prototype, "masterData", 2);
3815
+ __decorateClass$5([
3816
+ n2({ type: Array })
3817
+ ], JupiterFormField.prototype, "facts", 2);
3818
+ __decorateClass$5([
3819
+ n2({ type: Object })
3820
+ ], JupiterFormField.prototype, "column", 2);
3499
3821
  __decorateClass$5([
3500
3822
  n2({ type: String })
3501
3823
  ], JupiterFormField.prototype, "periodStartDate", 2);
@@ -3548,6 +3870,7 @@ let JupiterConceptTree = class extends LitElement {
3548
3870
  this.disabled = false;
3549
3871
  this.locale = "en-US";
3550
3872
  this.expandedConcepts = /* @__PURE__ */ new Set();
3873
+ this.mode = "inputForm";
3551
3874
  this._expanded = true;
3552
3875
  }
3553
3876
  connectedCallback() {
@@ -3641,6 +3964,10 @@ let JupiterConceptTree = class extends LitElement {
3641
3964
  .disabled="${this.disabled}"
3642
3965
  .locale="${this.locale}"
3643
3966
  .hideLabel="${true}"
3967
+ .mode="${this.mode}"
3968
+ .masterData="${this.masterData}"
3969
+ .facts="${this.facts}"
3970
+ .column="${column2}"
3644
3971
  @field-change="${this._handleFieldChange}"
3645
3972
  @period-change="${this._handlePeriodChange}"
3646
3973
  ></jupiter-form-field>
@@ -3784,6 +4111,15 @@ __decorateClass$4([
3784
4111
  __decorateClass$4([
3785
4112
  n2({ type: Array })
3786
4113
  ], JupiterConceptTree.prototype, "datatypes", 2);
4114
+ __decorateClass$4([
4115
+ n2({ type: String })
4116
+ ], JupiterConceptTree.prototype, "mode", 2);
4117
+ __decorateClass$4([
4118
+ n2({ type: Object })
4119
+ ], JupiterConceptTree.prototype, "masterData", 2);
4120
+ __decorateClass$4([
4121
+ n2({ type: Array })
4122
+ ], JupiterConceptTree.prototype, "facts", 2);
3787
4123
  __decorateClass$4([
3788
4124
  r()
3789
4125
  ], JupiterConceptTree.prototype, "_expanded", 2);
@@ -4392,6 +4728,7 @@ let JupiterFormSection = class extends LitElement {
4392
4728
  this.isFirstSection = false;
4393
4729
  this.availableDimensions = [];
4394
4730
  this.hideHeader = false;
4731
+ this.mode = "inputForm";
4395
4732
  this._expanded = true;
4396
4733
  this._showAddColumnDialog = false;
4397
4734
  this._sectionPeriodType = "duration";
@@ -4753,6 +5090,9 @@ let JupiterFormSection = class extends LitElement {
4753
5090
  .disabled="${this.disabled}"
4754
5091
  .locale="${this.locale}"
4755
5092
  .expandedConcepts="${this._expandedConcepts}"
5093
+ .mode="${this.mode}"
5094
+ .masterData="${this.masterData}"
5095
+ .facts="${concept.facts}"
4756
5096
  @field-change="${this._handleFieldChange}"
4757
5097
  @period-change="${this._handlePeriodChange}"
4758
5098
  @concept-expand="${this._handleConceptExpand}"
@@ -5076,6 +5416,12 @@ __decorateClass$2([
5076
5416
  __decorateClass$2([
5077
5417
  n2({ type: Boolean })
5078
5418
  ], JupiterFormSection.prototype, "hideHeader", 2);
5419
+ __decorateClass$2([
5420
+ n2({ type: String })
5421
+ ], JupiterFormSection.prototype, "mode", 2);
5422
+ __decorateClass$2([
5423
+ n2({ type: Object })
5424
+ ], JupiterFormSection.prototype, "masterData", 2);
5079
5425
  __decorateClass$2([
5080
5426
  r()
5081
5427
  ], JupiterFormSection.prototype, "_expanded", 2);
@@ -5344,6 +5690,13 @@ let JupiterFilterRolesDialog = class extends LitElement {
5344
5690
  }));
5345
5691
  }
5346
5692
  _handleApply() {
5693
+ const currentlySelected = Array.from(this._tempSelectedRoles);
5694
+ const orderedByOriginal = currentlySelected.sort((a2, b2) => {
5695
+ const indexA = this.availableRoles.findIndex((r2) => r2.id === a2);
5696
+ const indexB = this.availableRoles.findIndex((r2) => r2.id === b2);
5697
+ return indexA - indexB;
5698
+ });
5699
+ this._chosenRoleOrder = orderedByOriginal;
5347
5700
  const orderedRolesWithMetadata = this._chosenRoleOrder.map((roleId, index) => {
5348
5701
  var _a;
5349
5702
  const role = this.availableRoles.find((r2) => r2.id === roleId);
@@ -6675,6 +7028,11 @@ let JupiterDynamicForm = class extends LitElement {
6675
7028
  this._sidePanelSearchQuery = "";
6676
7029
  this._sidePanelCollapsed = false;
6677
7030
  this._adminRoleConfigs = {};
7031
+ this._roleBorderStatuses = /* @__PURE__ */ new Map();
7032
+ this._showRoleContextMenu = false;
7033
+ this._contextMenuX = 0;
7034
+ this._contextMenuY = 0;
7035
+ this._contextMenuRoleId = null;
6678
7036
  this._skipDraftLoading = false;
6679
7037
  this._skipPeriodPreferencesRestore = false;
6680
7038
  }
@@ -6697,6 +7055,12 @@ let JupiterDynamicForm = class extends LitElement {
6697
7055
  const customEvent = e2;
6698
7056
  this._handleFieldBlur(customEvent);
6699
7057
  });
7058
+ document.addEventListener("click", () => {
7059
+ if (this._showRoleContextMenu) {
7060
+ this._showRoleContextMenu = false;
7061
+ this.requestUpdate();
7062
+ }
7063
+ });
6700
7064
  this._initializeForm();
6701
7065
  }
6702
7066
  updated(changedProperties) {
@@ -6824,13 +7188,185 @@ let JupiterDynamicForm = class extends LitElement {
6824
7188
  if ((_a = this.xbrlInput) == null ? void 0 : _a.initialData) {
6825
7189
  this._formData = { ...this._formData, ...this.xbrlInput.initialData };
6826
7190
  }
7191
+ this._extractTypedMembersFromFacts();
6827
7192
  if (!this._skipDraftLoading) {
6828
- this._loadDraftIfExists();
7193
+ this._loadDraftIfExists().then(() => {
7194
+ this._analyzeAllVisibleRoles();
7195
+ }).catch(() => {
7196
+ this._analyzeAllVisibleRoles();
7197
+ });
6829
7198
  } else {
6830
7199
  console.log("⏭️ Skipping draft loading during preference update");
7200
+ this._analyzeAllVisibleRoles();
6831
7201
  }
6832
7202
  this._validateForm();
6833
7203
  }
7204
+ /**
7205
+ * Extract typed dimension values from facts and pre-populate typedMemberData
7206
+ * This scans all facts for typed dimensions and sets their values in column headers
7207
+ */
7208
+ _extractTypedMembersFromFacts() {
7209
+ var _a;
7210
+ if (!((_a = this._currentSchema) == null ? void 0 : _a.sections)) {
7211
+ return;
7212
+ }
7213
+ console.log("🔍 [DynamicForm] Extracting typed member values from facts");
7214
+ this._currentSchema.sections.forEach((section2) => {
7215
+ this._extractTypedMembersFromConcepts(section2.concepts || [], section2);
7216
+ });
7217
+ console.log("✅ [DynamicForm] Typed member data populated:", this._typedMemberData);
7218
+ }
7219
+ /**
7220
+ * Recursively extract typed member values from concept tree
7221
+ */
7222
+ _extractTypedMembersFromConcepts(concepts, section2) {
7223
+ concepts.forEach((concept) => {
7224
+ if (concept.facts && concept.facts.length > 0) {
7225
+ console.log(`🔍 [DynamicForm] Checking concept ${concept.id} with ${concept.facts.length} facts`);
7226
+ concept.facts.forEach((fact) => {
7227
+ if (fact.dimensions && Array.isArray(fact.dimensions)) {
7228
+ const typedDimensions = fact.dimensions.filter((d2) => d2.dimensionType === "typed" && d2.typedMemberValue);
7229
+ if (typedDimensions.length > 0) {
7230
+ console.log(`📝 [DynamicForm] Found ${typedDimensions.length} typed dimensions in fact:`, {
7231
+ factName: fact.name,
7232
+ typedDimensions: typedDimensions.map((d2) => ({
7233
+ dimension: d2.dimension,
7234
+ typedMemberValue: d2.typedMemberValue
7235
+ }))
7236
+ });
7237
+ const matchingColumn = this._findColumnWithTypedMembers(fact, concept, section2);
7238
+ if (matchingColumn) {
7239
+ console.log(`✅ [DynamicForm] Found matching column: ${matchingColumn.id}`);
7240
+ typedDimensions.forEach((dim) => {
7241
+ var _a, _b;
7242
+ const normalizedAxisId = this._normalizeAxisId(dim.dimension);
7243
+ const typedMember = (_b = (_a = matchingColumn.dimensionData) == null ? void 0 : _a.typedMembers) == null ? void 0 : _b.find(
7244
+ (tm) => tm.axisId === normalizedAxisId || this._normalizeAxisId(tm.axisId) === normalizedAxisId
7245
+ );
7246
+ if (typedMember) {
7247
+ if (!this._typedMemberData[matchingColumn.id]) {
7248
+ this._typedMemberData[matchingColumn.id] = {};
7249
+ }
7250
+ const axisKey = typedMember.axisId;
7251
+ this._typedMemberData[matchingColumn.id][axisKey] = dim.typedMemberValue;
7252
+ console.log(`✅ [DynamicForm] Set typed member value:`, {
7253
+ sectionId: section2.id,
7254
+ conceptId: concept.id,
7255
+ columnId: matchingColumn.id,
7256
+ axisKey,
7257
+ typedMemberValue: dim.typedMemberValue
7258
+ });
7259
+ } else {
7260
+ console.warn(`⚠️ [DynamicForm] Typed member not found for axis: ${normalizedAxisId}`);
7261
+ }
7262
+ });
7263
+ } else {
7264
+ console.warn(`⚠️ [DynamicForm] No matching column found for fact with typed dimensions`);
7265
+ }
7266
+ }
7267
+ }
7268
+ });
7269
+ }
7270
+ if (concept.children && concept.children.length > 0) {
7271
+ this._extractTypedMembersFromConcepts(concept.children, section2);
7272
+ }
7273
+ });
7274
+ }
7275
+ /**
7276
+ * Find a column that has typed members and matches the fact's explicit dimensions
7277
+ */
7278
+ _findColumnWithTypedMembers(fact, concept, section2) {
7279
+ var _a;
7280
+ if (!concept.fields || concept.fields.length === 0) {
7281
+ return null;
7282
+ }
7283
+ const sectionColumns = section2.columns || [];
7284
+ if (sectionColumns.length === 0) {
7285
+ return null;
7286
+ }
7287
+ for (const field2 of concept.fields) {
7288
+ const column2 = sectionColumns.find((col) => col.id === field2.columnId);
7289
+ if (column2 && ((_a = column2.dimensionData) == null ? void 0 : _a.hasTypedMembers)) {
7290
+ const factExplicitDims = (fact.dimensions || []).filter((d2) => d2.dimensionType === "explicit");
7291
+ const columnExplicitDims = column2.dimensionData.combinations || [];
7292
+ if (factExplicitDims.length === 0 || factExplicitDims.length === columnExplicitDims.length && factExplicitDims.every(
7293
+ (factDim) => columnExplicitDims.some(
7294
+ (colDim) => this._normalizeAxisId(factDim.dimension) === this._normalizeAxisId(colDim.axisId) && this._normalizeMemberId(factDim.member) === this._normalizeMemberId(colDim.memberId)
7295
+ )
7296
+ )) {
7297
+ return column2;
7298
+ }
7299
+ }
7300
+ }
7301
+ return null;
7302
+ }
7303
+ /**
7304
+ * Find the column that matches the fact's dimensions
7305
+ */
7306
+ _findColumnForFactDimensions(fact, concept, section2) {
7307
+ if (!concept.fields || concept.fields.length === 0) {
7308
+ console.log(`⚠️ [DynamicForm] No fields for concept: ${concept.id}`);
7309
+ return null;
7310
+ }
7311
+ const sectionColumns = section2.columns || [];
7312
+ if (sectionColumns.length === 0) {
7313
+ console.log(`⚠️ [DynamicForm] No columns in section: ${section2.id}`);
7314
+ return null;
7315
+ }
7316
+ for (const field2 of concept.fields) {
7317
+ const column2 = sectionColumns.find((col) => col.id === field2.columnId);
7318
+ if (column2 && column2.dimensionData) {
7319
+ const factDimensions = fact.dimensions || [];
7320
+ const columnDimensions = column2.dimensionData.combinations || [];
7321
+ console.log(`🔍 [DynamicForm] Checking column ${column2.id}:`, {
7322
+ factDimensions: factDimensions.map((d2) => ({ axis: d2.dimension, member: d2.member, type: d2.dimensionType })),
7323
+ columnDimensions: columnDimensions.map((d2) => ({ axis: d2.axisId, member: d2.memberId }))
7324
+ });
7325
+ const allMatch = columnDimensions.every((colDim) => {
7326
+ return factDimensions.some((factDim) => {
7327
+ const axisMatch = this._normalizeAxisId(factDim.dimension) === this._normalizeAxisId(colDim.axisId);
7328
+ if (factDim.dimensionType === "explicit") {
7329
+ const memberMatch = this._normalizeMemberId(factDim.member) === this._normalizeMemberId(colDim.memberId);
7330
+ return axisMatch && memberMatch;
7331
+ } else if (factDim.dimensionType === "typed") {
7332
+ return axisMatch;
7333
+ }
7334
+ return false;
7335
+ });
7336
+ });
7337
+ if (allMatch) {
7338
+ return column2;
7339
+ }
7340
+ }
7341
+ }
7342
+ return null;
7343
+ }
7344
+ /**
7345
+ * Normalize axis ID by extracting the local name
7346
+ */
7347
+ _normalizeAxisId(axisId) {
7348
+ if (!axisId)
7349
+ return "";
7350
+ if (axisId.includes(":")) {
7351
+ return axisId.split(":").pop() || axisId;
7352
+ } else if (axisId.includes("_")) {
7353
+ return axisId.split("_").pop() || axisId;
7354
+ }
7355
+ return axisId;
7356
+ }
7357
+ /**
7358
+ * Normalize member ID by extracting the local name
7359
+ */
7360
+ _normalizeMemberId(memberId) {
7361
+ if (!memberId)
7362
+ return "";
7363
+ if (memberId.includes(":")) {
7364
+ return memberId.split(":").pop() || memberId;
7365
+ } else if (memberId.includes("_")) {
7366
+ return memberId.split("_").pop() || memberId;
7367
+ }
7368
+ return memberId;
7369
+ }
6834
7370
  _getDefaultSchema() {
6835
7371
  return {
6836
7372
  version: "1.0",
@@ -7078,10 +7614,14 @@ let JupiterDynamicForm = class extends LitElement {
7078
7614
  console.log(`🚫 Filter dialog cancelled. Current selection: ${roleCount}/${this._allSections.length}`);
7079
7615
  }
7080
7616
  _handleRoleFilterApply(event) {
7617
+ var _a, _b;
7081
7618
  const { selectedRoleIds, periodPreferences } = event.detail;
7619
+ console.log("🎯 Filter apply triggered");
7620
+ console.log("📊 Old _selectedRoleIds:", this._selectedRoleIds);
7621
+ console.log("📊 New selectedRoleIds from dialog:", selectedRoleIds);
7082
7622
  this._selectedRoleIds = selectedRoleIds;
7083
7623
  this._periodPreferences = periodPreferences;
7084
- console.log("🎯 Filter apply triggered - always reinitializing form");
7624
+ console.log("📊 Updated _selectedRoleIds:", this._selectedRoleIds);
7085
7625
  console.log("📊 New period preferences (including dimension selections):", this._periodPreferences);
7086
7626
  console.log("💾 Capturing current form data before reinitialization...");
7087
7627
  const currentFormData = this._generateSubmissionData();
@@ -7105,6 +7645,8 @@ let JupiterDynamicForm = class extends LitElement {
7105
7645
  this._initializeForm();
7106
7646
  this._skipDraftLoading = false;
7107
7647
  this._skipPeriodPreferencesRestore = false;
7648
+ console.log("📊 After _initializeForm, _currentSchema.sections.length:", (_a = this._currentSchema) == null ? void 0 : _a.sections.length);
7649
+ console.log("📊 Section IDs:", (_b = this._currentSchema) == null ? void 0 : _b.sections.map((s2) => s2.id));
7108
7650
  console.log("📥 Restoring form data from draft after reinitialization...");
7109
7651
  this._loadDraftIfExists().then(() => {
7110
7652
  console.log("✅ Form data restored successfully after reinitialization");
@@ -7345,6 +7887,9 @@ let JupiterDynamicForm = class extends LitElement {
7345
7887
  console.log(`🔍 [_getSectionTitle] Result: "${result}"`);
7346
7888
  return result;
7347
7889
  }
7890
+ _roleHasErrors(roleId) {
7891
+ return this._xbrlFormErrors.some((error2) => error2.sectionId === roleId);
7892
+ }
7348
7893
  async _handleErrorFieldClick(conceptId, columnId, sectionId) {
7349
7894
  var _a, _b, _c, _d;
7350
7895
  console.log(`🎯 [Error Click] Attempting to focus field: ${conceptId}__${columnId} in section: ${sectionId}`);
@@ -7823,6 +8368,16 @@ let JupiterDynamicForm = class extends LitElement {
7823
8368
  this._handleAdminModeSubmit();
7824
8369
  return;
7825
8370
  }
8371
+ console.log(`🔵 [Submit] Checking for errors...`);
8372
+ console.log(`🔵 [Submit] _xbrlFormErrors.length: ${this._xbrlFormErrors.length}`);
8373
+ console.log(`🔵 [Submit] _xbrlFormErrors:`, this._xbrlFormErrors);
8374
+ if (this._xbrlFormErrors.length > 0) {
8375
+ console.log("❌ [Submit] Cannot submit - validation errors present:", this._xbrlFormErrors);
8376
+ this._showErrorPopup = true;
8377
+ this.requestUpdate();
8378
+ return;
8379
+ }
8380
+ console.log(`✅ [Submit] No validation errors, proceeding with submission...`);
7826
8381
  this._validateForm();
7827
8382
  const submissionData = this._generateSubmissionData();
7828
8383
  console.log("📊 Form Submission Data:", JSON.stringify(submissionData, null, 2));
@@ -8800,9 +9355,181 @@ let JupiterDynamicForm = class extends LitElement {
8800
9355
  submitted: this._submitted
8801
9356
  };
8802
9357
  }
9358
+ /**
9359
+ * Analyze all visible roles on form load to set initial border statuses
9360
+ */
9361
+ _analyzeAllVisibleRoles() {
9362
+ if (!this._currentSchema || !this._currentSchema.sections || this._currentSchema.sections.length === 0) {
9363
+ console.log("⏭️ No sections to analyze for initial border status");
9364
+ return;
9365
+ }
9366
+ console.log(`🔍 Analyzing ${this._currentSchema.sections.length} visible roles for initial border status...`);
9367
+ for (const section2 of this._currentSchema.sections) {
9368
+ this._analyzeAndLogRole(section2.id);
9369
+ }
9370
+ console.log(`✅ Initial border status analysis complete for all visible roles`);
9371
+ }
9372
+ /**
9373
+ * Handle right-click on role item to show context menu
9374
+ */
9375
+ _handleRoleContextMenu(event, roleId, roleTitle) {
9376
+ event.preventDefault();
9377
+ event.stopPropagation();
9378
+ this._contextMenuX = event.clientX;
9379
+ this._contextMenuY = event.clientY;
9380
+ this._contextMenuRoleId = roleId;
9381
+ this._showRoleContextMenu = true;
9382
+ console.log(`🖱️ Context menu opened for role: ${roleTitle} (ID: ${roleId})`);
9383
+ this.requestUpdate();
9384
+ }
9385
+ /**
9386
+ * Close the context menu
9387
+ */
9388
+ _closeRoleContextMenu() {
9389
+ this._showRoleContextMenu = false;
9390
+ this._contextMenuRoleId = null;
9391
+ this.requestUpdate();
9392
+ }
9393
+ /**
9394
+ * Handle remove role action - removes role from side panel
9395
+ */
9396
+ _handleRemoveRole() {
9397
+ if (!this._contextMenuRoleId) {
9398
+ this._closeRoleContextMenu();
9399
+ return;
9400
+ }
9401
+ const role = this._allSections.find((s2) => s2.id === this._contextMenuRoleId);
9402
+ const roleTitle = (role == null ? void 0 : role.title) || "Unknown";
9403
+ console.log(`🗑️ Removing role from side panel:`);
9404
+ console.log(` - Role ID: ${this._contextMenuRoleId}`);
9405
+ console.log(` - Role Title: ${roleTitle}`);
9406
+ if (Array.isArray(this._selectedRoleIds)) {
9407
+ if (this._selectedRoleIds.length > 0 && typeof this._selectedRoleIds[0] === "object") {
9408
+ this._selectedRoleIds = this._selectedRoleIds.filter((r2) => r2.roleId !== this._contextMenuRoleId);
9409
+ } else {
9410
+ this._selectedRoleIds = this._selectedRoleIds.filter((id) => id !== this._contextMenuRoleId);
9411
+ }
9412
+ }
9413
+ console.log(`✅ Role removed from _selectedRoleIds. Remaining roles: ${this._selectedRoleIds.length}`);
9414
+ if (this._activeSidePanelRoleId === this._contextMenuRoleId) {
9415
+ const remainingRoleIds = this._getRoleIdsArray();
9416
+ this._activeSidePanelRoleId = remainingRoleIds.length > 0 ? remainingRoleIds[0] : null;
9417
+ console.log(`📌 Active role changed to: ${this._activeSidePanelRoleId || "None"}`);
9418
+ }
9419
+ this._applyRoleFilter();
9420
+ this.dispatchEvent(new CustomEvent("role-removed", {
9421
+ detail: {
9422
+ roleId: this._contextMenuRoleId,
9423
+ roleTitle,
9424
+ remainingRolesCount: this._selectedRoleIds.length
9425
+ },
9426
+ bubbles: true,
9427
+ composed: true
9428
+ }));
9429
+ console.log(`✅ Role "${roleTitle}" successfully removed from side panel`);
9430
+ console.log(`ℹ️ User can re-add this role using the Filter Roles dialog`);
9431
+ this._closeRoleContextMenu();
9432
+ }
8803
9433
  _handleSidePanelRoleClick(roleId) {
9434
+ if (this._activeSidePanelRoleId && this._activeSidePanelRoleId !== roleId) {
9435
+ this._analyzeAndLogRole(this._activeSidePanelRoleId);
9436
+ }
8804
9437
  this._activeSidePanelRoleId = roleId;
8805
9438
  }
9439
+ _analyzeAndLogRole(roleId) {
9440
+ const section2 = this._allSections.find((s2) => s2.id === roleId);
9441
+ if (!section2) {
9442
+ console.warn(`⚠️ Section not found for roleId: ${roleId}`);
9443
+ return;
9444
+ }
9445
+ console.warn(`
9446
+ ========================================`);
9447
+ console.warn(`🔍 ANALYZING ROLE: "${section2.title}"`);
9448
+ console.warn(`========================================`);
9449
+ if (this.masterData) {
9450
+ console.warn(`📦 masterData keys:`, Object.keys(this.masterData));
9451
+ } else {
9452
+ console.warn(`📦 masterData: NOT PROVIDED`);
9453
+ }
9454
+ const allFields = [];
9455
+ this._collectAllFields(section2.concepts || [], new Set((section2.columns || []).map((col) => col.id)), allFields);
9456
+ console.warn(`📊 Total fields found: ${allFields.length}`);
9457
+ console.warn(`
9458
+ 📋 FIELD DETAILS:`);
9459
+ allFields.forEach((field2, index) => {
9460
+ const status = field2.isEmpty ? "❌ EMPTY" : "✅ FILLED";
9461
+ console.warn(` ${index + 1}. ${field2.conceptId} [${field2.columnId}]: ${status} = ${JSON.stringify(field2.value)}`);
9462
+ });
9463
+ const hasErrors = this._roleHasErrors(roleId);
9464
+ const emptyCount = allFields.filter((f2) => f2.isEmpty).length;
9465
+ const filledCount = allFields.filter((f2) => !f2.isEmpty).length;
9466
+ console.warn(`
9467
+ 📈 SUMMARY:`);
9468
+ console.warn(` Total Fields: ${allFields.length}`);
9469
+ console.warn(` Filled: ${filledCount}`);
9470
+ console.warn(` Empty: ${emptyCount}`);
9471
+ console.warn(` Has Errors: ${hasErrors}`);
9472
+ let result;
9473
+ if (hasErrors) {
9474
+ result = "INVALID";
9475
+ console.warn(`
9476
+ 🔴 RESULT: INVALID (contains validation errors)`);
9477
+ } else if (emptyCount > 0) {
9478
+ result = "INCOMPLETE";
9479
+ console.warn(`
9480
+ 🟠 RESULT: INCOMPLETE (${emptyCount} field(s) blank)`);
9481
+ } else {
9482
+ result = "COMPLETE";
9483
+ console.warn(`
9484
+ 🟢 RESULT: COMPLETE (all fields filled)`);
9485
+ }
9486
+ console.warn(`========================================
9487
+ `);
9488
+ if (result === "INVALID")
9489
+ ;
9490
+ else if (result === "INCOMPLETE") {
9491
+ this._roleBorderStatuses.set(roleId, "incomplete");
9492
+ this._roleBorderStatuses = new Map(this._roleBorderStatuses);
9493
+ } else {
9494
+ this._roleBorderStatuses.set(roleId, "complete");
9495
+ this._roleBorderStatuses = new Map(this._roleBorderStatuses);
9496
+ }
9497
+ }
9498
+ _collectAllFields(concepts, sectionColumnIds, allFields) {
9499
+ var _a;
9500
+ for (const concept of concepts) {
9501
+ if (concept.abstract) {
9502
+ if (concept.children && concept.children.length > 0) {
9503
+ this._collectAllFields(concept.children, sectionColumnIds, allFields);
9504
+ }
9505
+ continue;
9506
+ }
9507
+ if (concept.fields && concept.fields.length > 0) {
9508
+ const relevantFields = concept.fields.filter((field2) => sectionColumnIds.has(field2.columnId));
9509
+ for (const field2 of relevantFields) {
9510
+ const conceptIdForCheck = concept.id;
9511
+ const originalConceptId = concept.id.split("__")[0];
9512
+ const isMasterDataField = this.masterData && (this.masterData[conceptIdForCheck] !== void 0 || this.masterData[originalConceptId] !== void 0);
9513
+ if (isMasterDataField && this.masterData) {
9514
+ const masterValue = this.masterData[conceptIdForCheck] || this.masterData[originalConceptId];
9515
+ console.warn(` ⏭️ SKIPPING masterData field: ${concept.id} [${field2.columnId}] = ${JSON.stringify(masterValue)}`);
9516
+ continue;
9517
+ }
9518
+ const value = (_a = this._formData[concept.id]) == null ? void 0 : _a[field2.columnId];
9519
+ const isEmpty = value === null || value === void 0 || typeof value === "string" && value.trim() === "";
9520
+ allFields.push({
9521
+ conceptId: concept.id,
9522
+ columnId: field2.columnId,
9523
+ value,
9524
+ isEmpty
9525
+ });
9526
+ }
9527
+ }
9528
+ if (concept.children && concept.children.length > 0) {
9529
+ this._collectAllFields(concept.children, sectionColumnIds, allFields);
9530
+ }
9531
+ }
9532
+ }
8806
9533
  _handleSidePanelSearchInput(event) {
8807
9534
  const input = event.target;
8808
9535
  this._sidePanelSearchQuery = input.value;
@@ -9229,6 +9956,8 @@ let JupiterDynamicForm = class extends LitElement {
9229
9956
  .locale="${config.locale || "en-US"}"
9230
9957
  .isFirstSection="${index === 0}"
9231
9958
  .availableDimensions="${this._getAvailableDimensionsForSection(section2.id)}"
9959
+ .mode="${this.mode}"
9960
+ .masterData="${this.masterData}"
9232
9961
  @field-change="${this._handleFieldChange}"
9233
9962
  @period-change="${this._handlePeriodChange}"
9234
9963
  @typed-member-change="${this._handleTypedMemberChange}"
@@ -9300,14 +10029,20 @@ let JupiterDynamicForm = class extends LitElement {
9300
10029
  ${I18n.t("filter.tryDifferentSearch")}
9301
10030
  </div>
9302
10031
  ` : html`
9303
- ${filteredSections.map((section2) => html`
9304
- <div
9305
- class="side-panel-role-item ${section2.id === this._activeSidePanelRoleId ? "active" : ""}"
9306
- @click="${() => this._handleSidePanelRoleClick(section2.id)}"
9307
- >
9308
- ${section2.title}
9309
- </div>
9310
- `)}
10032
+ ${filteredSections.map((section2) => {
10033
+ const hasErrors = this._roleHasErrors(section2.id);
10034
+ const borderStatus = this._roleBorderStatuses.get(section2.id);
10035
+ const statusClass = hasErrors ? "has-errors" : borderStatus === "incomplete" ? "has-empty-fields" : borderStatus === "complete" ? "has-complete-data" : "";
10036
+ return html`
10037
+ <div
10038
+ class="side-panel-role-item ${section2.id === this._activeSidePanelRoleId ? "active" : ""} ${statusClass}"
10039
+ @click="${() => this._handleSidePanelRoleClick(section2.id)}"
10040
+ @contextmenu="${(e2) => this._handleRoleContextMenu(e2, section2.id, section2.title)}"
10041
+ >
10042
+ ${section2.title}
10043
+ </div>
10044
+ `;
10045
+ })}
9311
10046
  `}
9312
10047
  ` : ""}
9313
10048
  </div>
@@ -9349,6 +10084,8 @@ let JupiterDynamicForm = class extends LitElement {
9349
10084
  .locale="${config.locale || "en-US"}"
9350
10085
  .isFirstSection="${true}"
9351
10086
  .availableDimensions="${this._getAvailableDimensionsForSection(activeSection.id)}"
10087
+ .mode="${this.mode}"
10088
+ .masterData="${this.masterData}"
9352
10089
  @field-change="${this._handleFieldChange}"
9353
10090
  @typed-member-change="${this._handleTypedMemberChange}"
9354
10091
  @section-expand="${this._handleSectionExpand}"
@@ -9510,6 +10247,27 @@ let JupiterDynamicForm = class extends LitElement {
9510
10247
  </div>
9511
10248
  </div>
9512
10249
  ` : ""}
10250
+
10251
+ <!-- Role Context Menu -->
10252
+ ${this._showRoleContextMenu ? html`
10253
+ <div
10254
+ class="role-context-menu"
10255
+ style="left: ${this._contextMenuX}px; top: ${this._contextMenuY}px;"
10256
+ @click="${(e2) => {
10257
+ e2.stopPropagation();
10258
+ }}"
10259
+ >
10260
+ <div
10261
+ class="context-menu-item danger"
10262
+ @click="${() => this._handleRemoveRole()}"
10263
+ >
10264
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
10265
+ <path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/>
10266
+ </svg>
10267
+ Remove
10268
+ </div>
10269
+ </div>
10270
+ ` : ""}
9513
10271
  </div>
9514
10272
  `;
9515
10273
  }
@@ -9866,6 +10624,30 @@ JupiterDynamicForm.styles = css`
9866
10624
  font-weight: 500;
9867
10625
  }
9868
10626
 
10627
+ .side-panel-role-item.has-errors {
10628
+ border-left: 2px solid var(--jupiter-error-color, #d32f2f);
10629
+ }
10630
+
10631
+ .side-panel-role-item.has-errors.active {
10632
+ border-left: 2px solid var(--jupiter-error-color, #d32f2f);
10633
+ }
10634
+
10635
+ .side-panel-role-item.has-empty-fields {
10636
+ border-left: 2px solid var(--jupiter-warning-color, #ff9800);
10637
+ }
10638
+
10639
+ .side-panel-role-item.has-empty-fields.active {
10640
+ border-left: 2px solid var(--jupiter-warning-color, #ff9800);
10641
+ }
10642
+
10643
+ .side-panel-role-item.has-complete-data {
10644
+ border-left: 2px solid var(--jupiter-success-color, #4caf50);
10645
+ }
10646
+
10647
+ .side-panel-role-item.has-complete-data.active {
10648
+ border-left: 2px solid var(--jupiter-success-color, #4caf50);
10649
+ }
10650
+
9869
10651
  .side-panel-content {
9870
10652
  flex: 1;
9871
10653
  overflow-y: auto;
@@ -10159,6 +10941,41 @@ JupiterDynamicForm.styles = css`
10159
10941
  color: #0052a3;
10160
10942
  text-decoration: none;
10161
10943
  }
10944
+
10945
+ /* Context Menu Styles */
10946
+ .role-context-menu {
10947
+ position: fixed;
10948
+ background: white;
10949
+ border: 1px solid var(--jupiter-border-color, #ddd);
10950
+ border-radius: 4px;
10951
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
10952
+ z-index: 10001;
10953
+ min-width: 150px;
10954
+ padding: 4px 0;
10955
+ }
10956
+
10957
+ .context-menu-item {
10958
+ padding: 8px 16px;
10959
+ cursor: pointer;
10960
+ font-size: 14px;
10961
+ color: var(--jupiter-text-primary, #333);
10962
+ transition: background-color 0.2s ease;
10963
+ display: flex;
10964
+ align-items: center;
10965
+ gap: 8px;
10966
+ }
10967
+
10968
+ .context-menu-item:hover {
10969
+ background: var(--jupiter-hover-background, #f5f5f5);
10970
+ }
10971
+
10972
+ .context-menu-item.danger {
10973
+ color: var(--jupiter-error-color, #d32f2f);
10974
+ }
10975
+
10976
+ .context-menu-item.danger:hover {
10977
+ background: #ffebee;
10978
+ }
10162
10979
  `;
10163
10980
  __decorateClass([
10164
10981
  n2({ type: Object })
@@ -10202,6 +11019,9 @@ __decorateClass([
10202
11019
  __decorateClass([
10203
11020
  n2({ type: Array })
10204
11021
  ], JupiterDynamicForm.prototype, "defaultUnits", 2);
11022
+ __decorateClass([
11023
+ n2({ type: Object, attribute: "master-data" })
11024
+ ], JupiterDynamicForm.prototype, "masterData", 2);
10205
11025
  __decorateClass([
10206
11026
  n2({ type: Object, attribute: "dynaforms-metadata" })
10207
11027
  ], JupiterDynamicForm.prototype, "dynaformsMetadata", 2);
@@ -10289,11 +11109,27 @@ __decorateClass([
10289
11109
  __decorateClass([
10290
11110
  r()
10291
11111
  ], JupiterDynamicForm.prototype, "_adminRoleConfigs", 2);
11112
+ __decorateClass([
11113
+ r()
11114
+ ], JupiterDynamicForm.prototype, "_roleBorderStatuses", 2);
11115
+ __decorateClass([
11116
+ r()
11117
+ ], JupiterDynamicForm.prototype, "_showRoleContextMenu", 2);
11118
+ __decorateClass([
11119
+ r()
11120
+ ], JupiterDynamicForm.prototype, "_contextMenuX", 2);
11121
+ __decorateClass([
11122
+ r()
11123
+ ], JupiterDynamicForm.prototype, "_contextMenuY", 2);
11124
+ __decorateClass([
11125
+ r()
11126
+ ], JupiterDynamicForm.prototype, "_contextMenuRoleId", 2);
10292
11127
  JupiterDynamicForm = __decorateClass([
10293
11128
  t$1("jupiter-dynamic-form")
10294
11129
  ], JupiterDynamicForm);
10295
11130
  const version = "1.5.0";
10296
11131
  export {
11132
+ FactMatcher,
10297
11133
  FormValidator,
10298
11134
  JupiterAddColumnDialog,
10299
11135
  JupiterConceptTree,