jupiter-dynamic-forms 1.4.0 → 1.6.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
@@ -570,7 +570,16 @@ class XBRLFormBuilder {
570
570
  const periodTypes = new Set(
571
571
  nonAbstractConcepts.filter((concept) => concept.periodType).map((concept) => concept.periodType)
572
572
  );
573
- const roleInfo = { periodTypes };
573
+ const hypercubeRole = hypercubeData == null ? void 0 : hypercubeData.roles.find((hr) => hr.roleId === role.id);
574
+ if (hypercubeRole) {
575
+ console.log(`🏷️ Found matching hypercube role "${role.id}"`);
576
+ } else {
577
+ console.log(`❌ No hypercube role found for "${role.id}"`);
578
+ }
579
+ const columns = this.generateDefaultColumnsForRole(role, periodStartDate || "2025-01-01", periodEndDate || "2025-12-31", hypercubeRole, nonAbstractConcepts, periodTypes);
580
+ const availableColumnIds = columns.map((col) => col.id);
581
+ console.log(`📋 Available column IDs for role "${role.id}":`, availableColumnIds);
582
+ const roleInfo = { periodTypes, availableColumnIds };
574
583
  const conceptTrees = [];
575
584
  if ((_a = role.presentationLinkbase) == null ? void 0 : _a.concepts) {
576
585
  role.presentationLinkbase.concepts.forEach((concept) => {
@@ -580,17 +589,10 @@ class XBRLFormBuilder {
580
589
  }
581
590
  });
582
591
  }
583
- const hypercubeRole = hypercubeData == null ? void 0 : hypercubeData.roles.find((hr) => hr.roleId === role.id);
584
- if (hypercubeRole) {
585
- console.log(`🏷️ Found matching hypercube role "${role.id}"`);
586
- } else {
587
- console.log(`❌ No hypercube role found for "${role.id}"`);
588
- }
589
- const columns = this.generateDefaultColumnsForRole(role, periodStartDate || "2025-01-01", periodEndDate || "2025-12-31", hypercubeRole, nonAbstractConcepts, periodTypes);
590
592
  return {
591
593
  id: role.id,
592
594
  title,
593
- description: `Section for ${title}`,
595
+ description: ``,
594
596
  concepts: conceptTrees,
595
597
  columns,
596
598
  expanded: false
@@ -603,27 +605,42 @@ class XBRLFormBuilder {
603
605
  const label = this.getPreferredLabel(concept.labels);
604
606
  const fields = [];
605
607
  if (!concept.elementAbstract) {
606
- let shouldCreateField = true;
607
- if ((roleInfo == null ? void 0 : roleInfo.periodTypes) && roleInfo.periodTypes.size > 1) {
608
- if (concept.periodType === "instant") {
609
- shouldCreateField = false;
608
+ let columnIds = [];
609
+ if ((roleInfo == null ? void 0 : roleInfo.availableColumnIds) && roleInfo.availableColumnIds.length > 0) {
610
+ columnIds = roleInfo.availableColumnIds.filter((colId) => {
611
+ if (concept.periodType === "instant") {
612
+ return colId.includes("instant") || colId === "instant";
613
+ } else if (concept.periodType === "duration") {
614
+ return colId.includes("duration") || colId === "duration";
615
+ } else {
616
+ return true;
617
+ }
618
+ });
619
+ if (columnIds.length === 0) {
620
+ columnIds = roleInfo.availableColumnIds;
610
621
  }
611
- }
612
- if (shouldCreateField) {
613
- let columnId;
622
+ } else {
614
623
  if (!(roleInfo == null ? void 0 : roleInfo.periodTypes) || roleInfo.periodTypes.size === 0) {
615
- columnId = "default";
624
+ columnIds = ["default"];
616
625
  } else if (roleInfo.periodTypes.size === 1 && roleInfo.periodTypes.has("instant")) {
617
- columnId = "instant";
626
+ columnIds = ["instant"];
618
627
  } else if (roleInfo.periodTypes.size === 1 && roleInfo.periodTypes.has("duration")) {
619
- columnId = "duration";
628
+ columnIds = ["duration"];
620
629
  } else {
621
- columnId = "period";
630
+ if (concept.periodType === "instant") {
631
+ columnIds = ["instant"];
632
+ } else if (concept.periodType === "duration") {
633
+ columnIds = ["duration"];
634
+ } else {
635
+ columnIds = ["duration", "instant"];
636
+ }
622
637
  }
638
+ }
639
+ columnIds.forEach((columnId) => {
623
640
  const field = this.createFieldFromConcept(concept, periodStartDate, periodEndDate, columnId);
624
641
  if (field)
625
642
  fields.push(field);
626
- }
643
+ });
627
644
  }
628
645
  const children = [];
629
646
  if (concept.children && concept.children.length > 0) {
@@ -634,6 +651,10 @@ class XBRLFormBuilder {
634
651
  }
635
652
  });
636
653
  }
654
+ const hasContent = fields.length > 0 || children.length > 0;
655
+ if (!hasContent) {
656
+ return null;
657
+ }
637
658
  return {
638
659
  id: this.createUniqueConceptId(concept),
639
660
  // Use unique ID for form management
@@ -788,7 +809,7 @@ class XBRLFormBuilder {
788
809
  * Generate default columns based on period types of non-abstract concepts in a role
789
810
  */
790
811
  static generateDefaultColumnsForRole(role, periodStartDate, periodEndDate, hypercubeRole, nonAbstractConcepts, rolePeriodTypes) {
791
- var _a, _b, _c, _d, _e;
812
+ var _a, _b, _c;
792
813
  const concepts = nonAbstractConcepts || this.getAllNonAbstractConcepts(role);
793
814
  const periodTypes = rolePeriodTypes || new Set(
794
815
  concepts.filter((concept) => concept.periodType).map((concept) => concept.periodType)
@@ -805,7 +826,7 @@ class XBRLFormBuilder {
805
826
  removable: false
806
827
  }];
807
828
  }
808
- let dimensionInfo = null;
829
+ let dimensionColumns = [];
809
830
  if (((_a = hypercubeRole == null ? void 0 : hypercubeRole.items) == null ? void 0 : _a.length) === 1) {
810
831
  const item = hypercubeRole.items[0];
811
832
  console.log(`🔍 Processing hypercube item for role "${role.role}":`, {
@@ -814,43 +835,191 @@ class XBRLFormBuilder {
814
835
  dimensions: item.dimensions.length
815
836
  });
816
837
  if (item.dimensions.length === 1) {
817
- const dimension = item.dimensions[0];
818
- console.log(`📊 Found single dimension:`, {
819
- id: dimension.id,
820
- conceptName: dimension.conceptName,
821
- membersCount: dimension.members.length
822
- });
823
- if (dimension.members.length > 0) {
824
- const axisLabel = ((_c = dimension.labels.find((l2) => l2.role === "http://www.xbrl.org/2003/role/label")) == null ? void 0 : _c.label) || dimension.conceptName;
825
- const firstMember = dimension.members[0];
826
- const memberLabel = ((_d = firstMember.labels.find((l2) => l2.role === "http://www.xbrl.org/2003/role/label")) == null ? void 0 : _d.label) || firstMember.conceptName;
827
- dimensionInfo = {
828
- axisId: dimension.id,
829
- axisLabel,
830
- memberId: firstMember.id,
831
- memberLabel,
832
- dimensionKey: `${axisLabel} | ${memberLabel}`,
833
- dimensionIdKey: `${dimension.id} | ${firstMember.id}`
834
- };
835
- console.log(`📊 Generated dimension info:`, dimensionInfo);
836
- }
837
- } else {
838
- console.log(`⚠️ Multiple dimensions found (${item.dimensions.length}), skipping for now`);
838
+ dimensionColumns = this.generateSingleDimensionColumns(item.dimensions[0], periodStartDate, periodEndDate, periodTypes);
839
+ } else if (item.dimensions.length > 1) {
840
+ dimensionColumns = this.generateMultiDimensionColumns(item.dimensions, periodStartDate, periodEndDate, periodTypes);
839
841
  }
840
- } else if (((_e = hypercubeRole == null ? void 0 : hypercubeRole.items) == null ? void 0 : _e.length) && hypercubeRole.items.length > 1) {
842
+ } else if (((_c = hypercubeRole == null ? void 0 : hypercubeRole.items) == null ? void 0 : _c.length) && hypercubeRole.items.length > 1) {
841
843
  console.log(`⚠️ Multiple items found (${hypercubeRole.items.length}), skipping for now`);
842
844
  }
843
845
  console.log(`📅 Found period types: ${Array.from(periodTypes).join(", ")}`);
844
846
  const columns = [];
847
+ if (dimensionColumns.length > 0) {
848
+ columns.push(...dimensionColumns);
849
+ } else {
850
+ if (periodTypes.size === 0) {
851
+ console.log("📅 No period types found, using default column");
852
+ columns.push({
853
+ id: "default",
854
+ title: "Value",
855
+ description: "Default value column",
856
+ type: "base",
857
+ order: 0,
858
+ removable: false
859
+ });
860
+ } else if (periodTypes.size === 1 && periodTypes.has("instant")) {
861
+ console.log("📅 All concepts are instant type, creating single column");
862
+ columns.push({
863
+ id: "instant",
864
+ title: `As of ${this.formatDateForDisplay(periodStartDate)}`,
865
+ description: `Values as of ${periodStartDate}`,
866
+ type: "base",
867
+ order: 0,
868
+ removable: false
869
+ });
870
+ } else if (periodTypes.size === 1 && periodTypes.has("duration")) {
871
+ console.log("📅 All concepts are duration type, creating single column with period range");
872
+ columns.push({
873
+ id: "duration",
874
+ title: `${this.formatDateForDisplay(periodStartDate)} / ${this.formatDateForDisplay(periodEndDate)}`,
875
+ description: `Period: ${periodStartDate} to ${periodEndDate}`,
876
+ type: "base",
877
+ order: 0,
878
+ removable: false
879
+ });
880
+ } else {
881
+ console.log("📅 Mixed period types found, creating both duration and instant columns");
882
+ columns.push({
883
+ id: "duration",
884
+ title: `${this.formatDateForDisplay(periodStartDate)} / ${this.formatDateForDisplay(periodEndDate)}`,
885
+ description: `Period: ${periodStartDate} to ${periodEndDate}`,
886
+ type: "base",
887
+ order: 0,
888
+ removable: false
889
+ });
890
+ columns.push({
891
+ id: "instant",
892
+ title: `As of ${this.formatDateForDisplay(periodStartDate)}`,
893
+ description: `Values as of ${periodStartDate}`,
894
+ type: "base",
895
+ order: 1,
896
+ removable: false
897
+ });
898
+ }
899
+ }
900
+ console.log(`📊 Generated ${columns.length} columns for role "${role.role}":`, columns.map((c2) => c2.title));
901
+ return columns;
902
+ }
903
+ /**
904
+ * Generate columns for single dimension scenarios
905
+ */
906
+ static generateSingleDimensionColumns(dimension, periodStartDate, periodEndDate, periodTypes) {
907
+ var _a, _b, _c;
908
+ if (dimension.typedMember) {
909
+ console.log(`📊 Found typed member dimension:`, {
910
+ id: dimension.id,
911
+ conceptName: dimension.conceptName,
912
+ typedMemberId: dimension.typedMember.id
913
+ });
914
+ const axisLabel2 = ((_a = dimension.labels.find((l2) => l2.role === "http://www.xbrl.org/2003/role/label")) == null ? void 0 : _a.label) || dimension.conceptName;
915
+ const typedMemberLabel = dimension.typedMember.id.split("_").pop() || "TypedMember";
916
+ const dimensionInfo2 = {
917
+ axisId: dimension.id,
918
+ axisLabel: axisLabel2,
919
+ memberId: dimension.typedMember.id,
920
+ memberLabel: typedMemberLabel,
921
+ dimensionKey: `${axisLabel2} | ${typedMemberLabel}`,
922
+ dimensionIdKey: `${dimension.id} | ${dimension.typedMember.id}`
923
+ };
924
+ console.log(`📊 Generated typed dimension info:`, dimensionInfo2);
925
+ const columns2 = [];
926
+ if (periodTypes.size === 0) {
927
+ const column = {
928
+ id: "default",
929
+ title: dimensionInfo2.memberLabel,
930
+ description: "Default typed dimension column",
931
+ type: "dimension",
932
+ dimensionData: {
933
+ dimensionId: "default",
934
+ axisId: dimensionInfo2.axisId,
935
+ memberId: dimensionInfo2.memberId,
936
+ memberValue: dimensionInfo2.memberLabel,
937
+ axisLabel: dimensionInfo2.axisLabel,
938
+ memberLabel: dimensionInfo2.memberLabel,
939
+ isTypedMember: true,
940
+ dimensionIdKey: dimensionInfo2.dimensionIdKey
941
+ },
942
+ order: 0,
943
+ removable: false
944
+ };
945
+ console.log(`📊 Generated typed member column:`, column);
946
+ columns2.push(column);
947
+ } else {
948
+ if (periodTypes.has("instant")) {
949
+ columns2.push({
950
+ id: `instant_${dimensionInfo2.axisId}_${dimensionInfo2.memberId}`,
951
+ title: `${dimensionInfo2.memberLabel} (Instant)`,
952
+ description: `${periodStartDate}`,
953
+ type: "dimension",
954
+ dimensionData: {
955
+ dimensionId: `instant_${dimensionInfo2.axisId}_${dimensionInfo2.memberId}`,
956
+ axisId: dimensionInfo2.axisId,
957
+ memberId: dimensionInfo2.memberId,
958
+ memberValue: dimensionInfo2.memberLabel,
959
+ axisLabel: dimensionInfo2.axisLabel,
960
+ memberLabel: dimensionInfo2.memberLabel,
961
+ isTypedMember: true,
962
+ dimensionIdKey: dimensionInfo2.dimensionIdKey
963
+ },
964
+ order: 0,
965
+ removable: false
966
+ });
967
+ }
968
+ if (periodTypes.has("duration")) {
969
+ columns2.push({
970
+ id: `duration_${dimensionInfo2.axisId}_${dimensionInfo2.memberId}`,
971
+ title: `${dimensionInfo2.memberLabel} (Duration)`,
972
+ description: `${periodStartDate} / ${periodEndDate}`,
973
+ type: "dimension",
974
+ dimensionData: {
975
+ dimensionId: `duration_${dimensionInfo2.axisId}_${dimensionInfo2.memberId}`,
976
+ axisId: dimensionInfo2.axisId,
977
+ memberId: dimensionInfo2.memberId,
978
+ memberValue: dimensionInfo2.memberLabel,
979
+ axisLabel: dimensionInfo2.axisLabel,
980
+ memberLabel: dimensionInfo2.memberLabel,
981
+ isTypedMember: true,
982
+ dimensionIdKey: dimensionInfo2.dimensionIdKey
983
+ },
984
+ order: 1,
985
+ removable: false
986
+ });
987
+ }
988
+ }
989
+ return columns2;
990
+ }
991
+ if (!dimension.members || !Array.isArray(dimension.members)) {
992
+ console.log(`⚠️ Dimension ${dimension.id} has no members defined, skipping column generation`);
993
+ return [];
994
+ }
995
+ console.log(`📊 Found single dimension:`, {
996
+ id: dimension.id,
997
+ conceptName: dimension.conceptName,
998
+ membersCount: dimension.members.length
999
+ });
1000
+ if (dimension.members.length === 0) {
1001
+ return [];
1002
+ }
1003
+ const axisLabel = ((_b = dimension.labels.find((l2) => l2.role === "http://www.xbrl.org/2003/role/label")) == null ? void 0 : _b.label) || dimension.conceptName;
1004
+ const firstMember = dimension.members[0];
1005
+ const memberLabel = ((_c = firstMember.labels.find((l2) => l2.role === "http://www.xbrl.org/2003/role/label")) == null ? void 0 : _c.label) || firstMember.conceptName;
1006
+ const dimensionInfo = {
1007
+ axisId: dimension.id,
1008
+ axisLabel,
1009
+ memberId: firstMember.id,
1010
+ memberLabel,
1011
+ dimensionKey: `${axisLabel} | ${memberLabel}`,
1012
+ dimensionIdKey: `${dimension.id} | ${firstMember.id}`
1013
+ };
1014
+ console.log(`📊 Generated dimension info:`, dimensionInfo);
1015
+ const columns = [];
845
1016
  if (periodTypes.size === 0) {
846
- console.log("📅 No period types found, using default column");
847
- const columnTitle = dimensionInfo ? `${dimensionInfo.memberLabel}` : "Value";
848
1017
  columns.push({
849
1018
  id: "default",
850
- title: columnTitle,
1019
+ title: dimensionInfo.memberLabel,
851
1020
  description: "Default value column",
852
- type: dimensionInfo ? "dimension" : "base",
853
- dimensionData: dimensionInfo ? {
1021
+ type: "dimension",
1022
+ dimensionData: {
854
1023
  dimensionId: "default",
855
1024
  axisId: dimensionInfo.axisId,
856
1025
  memberId: dimensionInfo.memberId,
@@ -860,19 +1029,17 @@ class XBRLFormBuilder {
860
1029
  axisLabel: dimensionInfo.axisLabel,
861
1030
  memberKey: dimensionInfo.dimensionKey,
862
1031
  dimensionIdKey: dimensionInfo.dimensionIdKey
863
- } : void 0,
1032
+ },
864
1033
  order: 0,
865
1034
  removable: false
866
1035
  });
867
1036
  } else if (periodTypes.size === 1 && periodTypes.has("instant")) {
868
- console.log("📅 All concepts are instant type, creating single column");
869
- const columnTitle = dimensionInfo ? `${dimensionInfo.memberLabel} (${this.formatDateForDisplay(periodStartDate)})` : `As of ${this.formatDateForDisplay(periodStartDate)}`;
870
1037
  columns.push({
871
1038
  id: "instant",
872
- title: columnTitle,
1039
+ title: `${dimensionInfo.memberLabel} (${this.formatDateForDisplay(periodStartDate)})`,
873
1040
  description: `Values as of ${periodStartDate}`,
874
- type: dimensionInfo ? "dimension" : "base",
875
- dimensionData: dimensionInfo ? {
1041
+ type: "dimension",
1042
+ dimensionData: {
876
1043
  dimensionId: "instant",
877
1044
  axisId: dimensionInfo.axisId,
878
1045
  memberId: dimensionInfo.memberId,
@@ -882,19 +1049,17 @@ class XBRLFormBuilder {
882
1049
  axisLabel: dimensionInfo.axisLabel,
883
1050
  memberKey: dimensionInfo.dimensionKey,
884
1051
  dimensionIdKey: dimensionInfo.dimensionIdKey
885
- } : void 0,
1052
+ },
886
1053
  order: 0,
887
1054
  removable: false
888
1055
  });
889
1056
  } else if (periodTypes.size === 1 && periodTypes.has("duration")) {
890
- console.log("📅 All concepts are duration type, creating single column with period range");
891
- const columnTitle = dimensionInfo ? `${dimensionInfo.memberLabel} (${this.formatDateForDisplay(periodStartDate)} / ${this.formatDateForDisplay(periodEndDate)})` : `${this.formatDateForDisplay(periodStartDate)} / ${this.formatDateForDisplay(periodEndDate)}`;
892
1057
  columns.push({
893
1058
  id: "duration",
894
- title: columnTitle,
1059
+ title: `${dimensionInfo.memberLabel} (${this.formatDateForDisplay(periodStartDate)} / ${this.formatDateForDisplay(periodEndDate)})`,
895
1060
  description: `Period: ${periodStartDate} to ${periodEndDate}`,
896
- type: dimensionInfo ? "dimension" : "base",
897
- dimensionData: dimensionInfo ? {
1061
+ type: "dimension",
1062
+ dimensionData: {
898
1063
  dimensionId: "duration",
899
1064
  axisId: dimensionInfo.axisId,
900
1065
  memberId: dimensionInfo.memberId,
@@ -904,21 +1069,18 @@ class XBRLFormBuilder {
904
1069
  axisLabel: dimensionInfo.axisLabel,
905
1070
  memberKey: dimensionInfo.dimensionKey,
906
1071
  dimensionIdKey: dimensionInfo.dimensionIdKey
907
- } : void 0,
1072
+ },
908
1073
  order: 0,
909
1074
  removable: false
910
1075
  });
911
- console.log("📅 Created duration column:", columns.map((c2) => ({ id: c2.id, title: c2.title })));
912
1076
  } else {
913
- console.log("📅 Mixed period types found, creating single column with period range");
914
- const columnTitle = dimensionInfo ? `${dimensionInfo.memberLabel} (${this.formatDateForDisplay(periodStartDate)} / ${this.formatDateForDisplay(periodEndDate)})` : `${this.formatDateForDisplay(periodStartDate)} / ${this.formatDateForDisplay(periodEndDate)}`;
915
1077
  columns.push({
916
- id: "period",
917
- title: columnTitle,
1078
+ id: "duration",
1079
+ title: `${dimensionInfo.memberLabel} (${this.formatDateForDisplay(periodStartDate)} / ${this.formatDateForDisplay(periodEndDate)})`,
918
1080
  description: `Period: ${periodStartDate} to ${periodEndDate}`,
919
- type: dimensionInfo ? "dimension" : "base",
920
- dimensionData: dimensionInfo ? {
921
- dimensionId: "period",
1081
+ type: "dimension",
1082
+ dimensionData: {
1083
+ dimensionId: "duration",
922
1084
  axisId: dimensionInfo.axisId,
923
1085
  memberId: dimensionInfo.memberId,
924
1086
  memberValue: dimensionInfo.memberLabel,
@@ -927,17 +1089,219 @@ class XBRLFormBuilder {
927
1089
  axisLabel: dimensionInfo.axisLabel,
928
1090
  memberKey: dimensionInfo.dimensionKey,
929
1091
  dimensionIdKey: dimensionInfo.dimensionIdKey
930
- } : void 0,
1092
+ },
931
1093
  order: 0,
932
1094
  removable: false
933
1095
  });
1096
+ columns.push({
1097
+ id: "instant",
1098
+ title: `${dimensionInfo.memberLabel} (${this.formatDateForDisplay(periodStartDate)})`,
1099
+ description: `Values as of ${periodStartDate}`,
1100
+ type: "dimension",
1101
+ dimensionData: {
1102
+ dimensionId: "instant",
1103
+ axisId: dimensionInfo.axisId,
1104
+ memberId: dimensionInfo.memberId,
1105
+ memberValue: dimensionInfo.memberLabel,
1106
+ memberLabel: dimensionInfo.memberLabel,
1107
+ axis: dimensionInfo.axisLabel,
1108
+ axisLabel: dimensionInfo.axisLabel,
1109
+ memberKey: dimensionInfo.dimensionKey,
1110
+ dimensionIdKey: dimensionInfo.dimensionIdKey
1111
+ },
1112
+ order: 1,
1113
+ removable: false
1114
+ });
934
1115
  }
935
- if (dimensionInfo) {
936
- console.log(`📊 Applied dimension to ${columns.length} columns: ${dimensionInfo.dimensionKey}`);
1116
+ return columns;
1117
+ }
1118
+ /**
1119
+ * Generate columns for multi-dimension scenarios - creates combinations of all dimension members
1120
+ */
1121
+ static generateMultiDimensionColumns(dimensions, periodStartDate, periodEndDate, periodTypes) {
1122
+ console.log(`📊 Processing ${dimensions.length} dimensions for multi-dimensional columns`);
1123
+ const validDimensions = dimensions.filter((dimension) => {
1124
+ if (dimension.typedMember) {
1125
+ return true;
1126
+ }
1127
+ if (!dimension.members || !Array.isArray(dimension.members) || dimension.members.length === 0) {
1128
+ console.log(`⚠️ Skipping dimension ${dimension.id} - no members defined`);
1129
+ return false;
1130
+ }
1131
+ return true;
1132
+ });
1133
+ if (validDimensions.length === 0) {
1134
+ console.log(`⚠️ No valid dimensions with members found, skipping multi-dimensional column generation`);
1135
+ return [];
937
1136
  }
938
- console.log(`📊 Generated ${columns.length} columns for role "${role.role}":`, columns.map((c2) => c2.title));
1137
+ const dimensionInfos = validDimensions.map((dimension) => {
1138
+ var _a;
1139
+ const axisLabel = ((_a = dimension.labels.find((l2) => l2.role === "http://www.xbrl.org/2003/role/label")) == null ? void 0 : _a.label) || dimension.conceptName;
1140
+ if (dimension.typedMember) {
1141
+ const typedMemberLabel = dimension.typedMember.id.split("_").pop() || "TypedMember";
1142
+ return {
1143
+ id: dimension.id,
1144
+ axisLabel,
1145
+ isTypedDimension: true,
1146
+ // Flag to track typed dimensions
1147
+ members: [{
1148
+ id: dimension.typedMember.id,
1149
+ label: typedMemberLabel,
1150
+ isTypedMember: true
1151
+ // Flag for the member itself
1152
+ }]
1153
+ };
1154
+ }
1155
+ const allMembers = this.getAllDimensionMembers(dimension.members);
1156
+ return {
1157
+ id: dimension.id,
1158
+ axisLabel,
1159
+ members: allMembers.map((member) => {
1160
+ var _a2;
1161
+ return {
1162
+ id: member.id,
1163
+ label: ((_a2 = member.labels.find((l2) => l2.role === "http://www.xbrl.org/2003/role/label")) == null ? void 0 : _a2.label) || member.conceptName
1164
+ };
1165
+ })
1166
+ };
1167
+ });
1168
+ const combinations = this.generateDimensionCombinations(dimensionInfos);
1169
+ console.log(`📊 Generated ${combinations.length} dimension combinations`);
1170
+ const columns = [];
1171
+ combinations.forEach((combination, index) => {
1172
+ const columnTitle = combination.map((c2) => c2.memberLabel).join(" | ");
1173
+ const hasTypedMembers = combination.some((c2) => c2.isTypedMember);
1174
+ const dimensionData = {
1175
+ dimensionId: `multi_${index}`,
1176
+ memberValue: columnTitle,
1177
+ // Required field
1178
+ memberLabel: columnTitle,
1179
+ // Required field
1180
+ isTypedMember: hasTypedMembers,
1181
+ // Flag if any dimension in combination is typed
1182
+ combinations: combination.map((c2) => ({
1183
+ axisId: c2.axisId,
1184
+ axisLabel: c2.axisLabel,
1185
+ memberId: c2.memberId,
1186
+ memberLabel: c2.memberLabel,
1187
+ isTypedMember: c2.isTypedMember || false
1188
+ })),
1189
+ memberKey: columnTitle,
1190
+ dimensionIdKey: combination.map((c2) => `${c2.axisId}|${c2.memberId}`).join("::")
1191
+ };
1192
+ if (periodTypes.size === 0 || periodTypes.size === 1 && periodTypes.has("duration")) {
1193
+ columns.push({
1194
+ id: `duration_${index}`,
1195
+ title: `${columnTitle} (${this.formatDateForDisplay(periodStartDate)} / ${this.formatDateForDisplay(periodEndDate)})`,
1196
+ description: `Period: ${periodStartDate} to ${periodEndDate}`,
1197
+ type: "dimension",
1198
+ dimensionData: {
1199
+ ...dimensionData,
1200
+ dimensionId: `duration_${index}`
1201
+ },
1202
+ order: index * 2,
1203
+ removable: false
1204
+ });
1205
+ } else if (periodTypes.size === 1 && periodTypes.has("instant")) {
1206
+ columns.push({
1207
+ id: `instant_${index}`,
1208
+ title: `${columnTitle} (${this.formatDateForDisplay(periodStartDate)})`,
1209
+ description: `Values as of ${periodStartDate}`,
1210
+ type: "dimension",
1211
+ dimensionData: {
1212
+ ...dimensionData,
1213
+ dimensionId: `instant_${index}`
1214
+ },
1215
+ order: index * 2,
1216
+ removable: false
1217
+ });
1218
+ } else {
1219
+ columns.push({
1220
+ id: `duration_${index}`,
1221
+ title: `${columnTitle} (${this.formatDateForDisplay(periodStartDate)} / ${this.formatDateForDisplay(periodEndDate)})`,
1222
+ description: `Period: ${periodStartDate} to ${periodEndDate}`,
1223
+ type: "dimension",
1224
+ dimensionData: {
1225
+ ...dimensionData,
1226
+ dimensionId: `duration_${index}`
1227
+ },
1228
+ order: index * 2,
1229
+ removable: false
1230
+ });
1231
+ columns.push({
1232
+ id: `instant_${index}`,
1233
+ title: `${columnTitle} (${this.formatDateForDisplay(periodStartDate)})`,
1234
+ description: `Values as of ${periodStartDate}`,
1235
+ type: "dimension",
1236
+ dimensionData: {
1237
+ ...dimensionData,
1238
+ dimensionId: `instant_${index}`
1239
+ },
1240
+ order: index * 2 + 1,
1241
+ removable: false
1242
+ });
1243
+ }
1244
+ });
1245
+ console.log(`📊 Generated ${columns.length} multi-dimensional columns`);
939
1246
  return columns;
940
1247
  }
1248
+ /**
1249
+ * Get all members including children recursively
1250
+ */
1251
+ static getAllDimensionMembers(members) {
1252
+ if (!members || !Array.isArray(members)) {
1253
+ return [];
1254
+ }
1255
+ const allMembers = [];
1256
+ members.forEach((member) => {
1257
+ allMembers.push(member);
1258
+ if (member.children && member.children.length > 0) {
1259
+ allMembers.push(...this.getAllDimensionMembers(member.children));
1260
+ }
1261
+ });
1262
+ return allMembers;
1263
+ }
1264
+ /**
1265
+ * Generate all combinations of dimension members
1266
+ */
1267
+ static generateDimensionCombinations(dimensionInfos) {
1268
+ if (dimensionInfos.length === 0)
1269
+ return [];
1270
+ if (dimensionInfos.length === 1) {
1271
+ return dimensionInfos[0].members.map((member) => [{
1272
+ axisId: dimensionInfos[0].id,
1273
+ axisLabel: dimensionInfos[0].axisLabel,
1274
+ memberId: member.id,
1275
+ memberLabel: member.label
1276
+ }]);
1277
+ }
1278
+ const [firstDimension, ...restDimensions] = dimensionInfos;
1279
+ const restCombinations = this.generateDimensionCombinations(restDimensions);
1280
+ const combinations = [];
1281
+ firstDimension.members.forEach((member) => {
1282
+ if (restCombinations.length === 0) {
1283
+ combinations.push([{
1284
+ axisId: firstDimension.id,
1285
+ axisLabel: firstDimension.axisLabel,
1286
+ memberId: member.id,
1287
+ memberLabel: member.label
1288
+ }]);
1289
+ } else {
1290
+ restCombinations.forEach((restCombination) => {
1291
+ combinations.push([
1292
+ {
1293
+ axisId: firstDimension.id,
1294
+ axisLabel: firstDimension.axisLabel,
1295
+ memberId: member.id,
1296
+ memberLabel: member.label
1297
+ },
1298
+ ...restCombination
1299
+ ]);
1300
+ });
1301
+ }
1302
+ });
1303
+ return combinations;
1304
+ }
941
1305
  /**
942
1306
  * Format date for display in column headers
943
1307
  */
@@ -1909,6 +2273,7 @@ let JupiterFormSection = class extends LitElement {
1909
2273
  this._expanded = true;
1910
2274
  this._showAddColumnDialog = false;
1911
2275
  this._sectionPeriodType = "duration";
2276
+ this._typedMemberValues = {};
1912
2277
  this._expandedConcepts = /* @__PURE__ */ new Set();
1913
2278
  }
1914
2279
  connectedCallback() {
@@ -2036,6 +2401,14 @@ let JupiterFormSection = class extends LitElement {
2036
2401
  bubbles: true
2037
2402
  }));
2038
2403
  }
2404
+ _handleTypedMemberValueChange(columnId, value) {
2405
+ this._typedMemberValues[columnId] = value;
2406
+ this.dispatchEvent(new CustomEvent("typed-member-change", {
2407
+ detail: { columnId, value, sectionId: this.section.id },
2408
+ bubbles: true
2409
+ }));
2410
+ this.requestUpdate();
2411
+ }
2039
2412
  _flattenConcepts(concepts, expanded = /* @__PURE__ */ new Set()) {
2040
2413
  const result = [];
2041
2414
  for (const concept of concepts) {
@@ -2104,22 +2477,36 @@ let JupiterFormSection = class extends LitElement {
2104
2477
  <thead class="table-header">
2105
2478
  <tr class="header-row">
2106
2479
  <th class="header-cell concept-column">Concept</th>
2107
- ${this.columns.map((column) => html`
2480
+ ${this.columns.map((column) => {
2481
+ var _a;
2482
+ return html`
2108
2483
  <th class="header-cell ${column.removable ? "removable" : ""}">
2109
2484
  ${column.title}
2110
2485
  ${column.description ? html`<div style="font-weight: normal; font-size: 12px; color: var(--jupiter-text-secondary, #666);">${column.description}</div>` : ""}
2486
+ ${((_a = column.dimensionData) == null ? void 0 : _a.isTypedMember) ? html`
2487
+ <div style="margin-top: 8px;">
2488
+ <input
2489
+ type="text"
2490
+ placeholder="Enter typed member value"
2491
+ .value="${this._typedMemberValues[column.id] || ""}"
2492
+ @input="${(e2) => this._handleTypedMemberValueChange(column.id, e2.target.value)}"
2493
+ style="width: 100%; padding: 4px; border: 1px solid #ccc; border-radius: 3px; font-size: 12px;"
2494
+ />
2495
+ </div>
2496
+ ` : ""}
2111
2497
  ${column.removable ? html`
2112
2498
  <button
2113
2499
  class="remove-column-btn"
2114
2500
  @click="${(e2) => {
2115
- e2.stopPropagation();
2116
- this._handleRemoveColumn(column.id);
2117
- }}"
2501
+ e2.stopPropagation();
2502
+ this._handleRemoveColumn(column.id);
2503
+ }}"
2118
2504
  title="Remove column"
2119
2505
  >×</button>
2120
2506
  ` : ""}
2121
2507
  </th>
2122
- `)}
2508
+ `;
2509
+ })}
2123
2510
  <th class="header-cell">
2124
2511
  <button class="add-column-btn" @click="${(e2) => {
2125
2512
  e2.stopPropagation();
@@ -2352,6 +2739,9 @@ __decorateClass$1([
2352
2739
  __decorateClass$1([
2353
2740
  r()
2354
2741
  ], JupiterFormSection.prototype, "_sectionPeriodType", 2);
2742
+ __decorateClass$1([
2743
+ r()
2744
+ ], JupiterFormSection.prototype, "_typedMemberValues", 2);
2355
2745
  __decorateClass$1([
2356
2746
  r()
2357
2747
  ], JupiterFormSection.prototype, "_expandedConcepts", 2);
@@ -2385,6 +2775,7 @@ let JupiterDynamicForm = class extends LitElement {
2385
2775
  this._dirty = false;
2386
2776
  this._valid = true;
2387
2777
  this._submitted = false;
2778
+ this._typedMemberValues = {};
2388
2779
  }
2389
2780
  connectedCallback() {
2390
2781
  super.connectedCallback();
@@ -2497,6 +2888,16 @@ let JupiterDynamicForm = class extends LitElement {
2497
2888
  bubbles: true
2498
2889
  }));
2499
2890
  }
2891
+ _handleTypedMemberChange(event) {
2892
+ const { columnId, value, sectionId } = event.detail;
2893
+ this._typedMemberValues[columnId] = value;
2894
+ this._dirty = true;
2895
+ this.requestUpdate();
2896
+ this.dispatchEvent(new CustomEvent("typed-member-change", {
2897
+ detail: { columnId, value, sectionId },
2898
+ bubbles: true
2899
+ }));
2900
+ }
2500
2901
  _handleSectionExpand(event) {
2501
2902
  this.dispatchEvent(new CustomEvent("section-expand", {
2502
2903
  detail: event.detail,
@@ -2540,7 +2941,7 @@ let JupiterDynamicForm = class extends LitElement {
2540
2941
  this._addColumnFromRequest(columnRequest, sectionId);
2541
2942
  }
2542
2943
  _addColumnFromRequest(request, sectionId) {
2543
- var _a, _b, _c, _d, _e;
2944
+ var _a, _b, _c, _d, _e, _f;
2544
2945
  const timestamp = Date.now();
2545
2946
  const newColumnId = `col-${timestamp}`;
2546
2947
  let title = "";
@@ -2563,10 +2964,28 @@ let JupiterDynamicForm = class extends LitElement {
2563
2964
  const item = hypercubeRole.items[0];
2564
2965
  if (item.dimensions.length === 1) {
2565
2966
  const dimension = item.dimensions[0];
2566
- if (dimension.members.length > 0) {
2967
+ if (dimension.typedMember) {
2567
2968
  const axisLabel = ((_d = dimension.labels.find((l2) => l2.role === "http://www.xbrl.org/2003/role/label")) == null ? void 0 : _d.label) || dimension.conceptName;
2969
+ const typedMemberLabel = dimension.typedMember.id.split("_").pop() || "TypedMember";
2970
+ const periodPart = request.periodType === "instant" ? `(${request.instantDate})` : `(${request.startDate} / ${request.endDate})`;
2971
+ title = `${typedMemberLabel} ${periodPart}`;
2972
+ dimensionData = {
2973
+ dimensionId: newColumnId,
2974
+ axisId: dimension.id,
2975
+ memberId: dimension.typedMember.id,
2976
+ memberValue: typedMemberLabel,
2977
+ memberLabel: typedMemberLabel,
2978
+ axis: axisLabel,
2979
+ axisLabel,
2980
+ memberKey: `${axisLabel} | ${typedMemberLabel}`,
2981
+ dimensionIdKey: `${dimension.id} | ${dimension.typedMember.id}`,
2982
+ isTypedMember: true
2983
+ };
2984
+ console.log(`📊 Applied typed member dimension to new column: ${dimensionData.memberKey}`);
2985
+ } else if (dimension.members && dimension.members.length > 0) {
2986
+ const axisLabel = ((_e = dimension.labels.find((l2) => l2.role === "http://www.xbrl.org/2003/role/label")) == null ? void 0 : _e.label) || dimension.conceptName;
2568
2987
  const firstMember = dimension.members[0];
2569
- const memberLabel = ((_e = firstMember.labels.find((l2) => l2.role === "http://www.xbrl.org/2003/role/label")) == null ? void 0 : _e.label) || firstMember.conceptName;
2988
+ const memberLabel = ((_f = firstMember.labels.find((l2) => l2.role === "http://www.xbrl.org/2003/role/label")) == null ? void 0 : _f.label) || firstMember.conceptName;
2570
2989
  const periodPart = request.periodType === "instant" ? `(${request.instantDate})` : `(${request.startDate} / ${request.endDate})`;
2571
2990
  title = `${memberLabel} ${periodPart}`;
2572
2991
  dimensionData = {
@@ -2788,11 +3207,18 @@ let JupiterDynamicForm = class extends LitElement {
2788
3207
  concepts.forEach((concept) => {
2789
3208
  if (concept.fields && concept.fields.length > 0) {
2790
3209
  concept.fields.forEach((field) => {
2791
- var _a, _b, _c;
3210
+ var _a, _b, _c, _d;
2792
3211
  const conceptData = this._formData[concept.id];
2793
3212
  const fieldValue = conceptData == null ? void 0 : conceptData[field.columnId];
2794
3213
  if (fieldValue !== void 0 && fieldValue !== null && fieldValue !== "") {
2795
3214
  const column = this._findColumnById(field.columnId);
3215
+ console.log(`🔍 Processing field for concept ${concept.id}:`, {
3216
+ fieldColumnId: field.columnId,
3217
+ foundColumn: column,
3218
+ columnType: column == null ? void 0 : column.type,
3219
+ dimensionData: column == null ? void 0 : column.dimensionData,
3220
+ isTypedMember: (_a = column == null ? void 0 : column.dimensionData) == null ? void 0 : _a.isTypedMember
3221
+ });
2796
3222
  const submissionEntry = {
2797
3223
  conceptId: concept.id,
2798
3224
  value: fieldValue,
@@ -2806,15 +3232,43 @@ let JupiterDynamicForm = class extends LitElement {
2806
3232
  submissionEntry.period.startDate = field.periodStartDate || this.periodStartDate;
2807
3233
  submissionEntry.period.endDate = field.periodEndDate || this.periodEndDate;
2808
3234
  }
2809
- if ((column == null ? void 0 : column.type) === "dimension" && ((_a = column.dimensionData) == null ? void 0 : _a.dimensionIdKey)) {
2810
- submissionEntry.dimension = column.dimensionData.dimensionIdKey;
2811
- } else if ((_b = section == null ? void 0 : section.columns) == null ? void 0 : _b.length) {
3235
+ if ((column == null ? void 0 : column.type) === "dimension" && ((_b = column.dimensionData) == null ? void 0 : _b.dimensionIdKey)) {
3236
+ console.log(`✅ Found column dimension data:`, column.dimensionData);
3237
+ if (column.dimensionData.isTypedMember) {
3238
+ submissionEntry.dimension = column.dimensionData.dimensionIdKey;
3239
+ submissionEntry.typedDimension = true;
3240
+ submissionEntry.typedMemberValue = this._typedMemberValues[column.id] || "";
3241
+ } else {
3242
+ submissionEntry.dimension = column.dimensionData.dimensionIdKey;
3243
+ }
3244
+ } else if ((_c = section == null ? void 0 : section.columns) == null ? void 0 : _c.length) {
3245
+ console.log(`🔍 Checking section columns for dimension data:`, {
3246
+ sectionId: section.id,
3247
+ columnsCount: section.columns.length,
3248
+ columns: section.columns.map((col) => {
3249
+ var _a2, _b2;
3250
+ return {
3251
+ id: col.id,
3252
+ type: col.type,
3253
+ hasDimensionData: !!col.dimensionData,
3254
+ dimensionIdKey: (_a2 = col.dimensionData) == null ? void 0 : _a2.dimensionIdKey,
3255
+ isTypedMember: (_b2 = col.dimensionData) == null ? void 0 : _b2.isTypedMember
3256
+ };
3257
+ })
3258
+ });
2812
3259
  const sectionDimensionColumn = section.columns.find((col) => {
2813
3260
  var _a2;
2814
3261
  return col.type === "dimension" && ((_a2 = col.dimensionData) == null ? void 0 : _a2.dimensionIdKey);
2815
3262
  });
2816
- if ((_c = sectionDimensionColumn == null ? void 0 : sectionDimensionColumn.dimensionData) == null ? void 0 : _c.dimensionIdKey) {
2817
- submissionEntry.dimension = sectionDimensionColumn.dimensionData.dimensionIdKey;
3263
+ if ((_d = sectionDimensionColumn == null ? void 0 : sectionDimensionColumn.dimensionData) == null ? void 0 : _d.dimensionIdKey) {
3264
+ console.log(`✅ Found section dimension data:`, sectionDimensionColumn.dimensionData);
3265
+ if (sectionDimensionColumn.dimensionData.isTypedMember) {
3266
+ submissionEntry.dimension = sectionDimensionColumn.dimensionData.dimensionIdKey;
3267
+ submissionEntry.typedDimension = true;
3268
+ submissionEntry.typedMemberValue = this._typedMemberValues[sectionDimensionColumn.id] || "";
3269
+ } else {
3270
+ submissionEntry.dimension = sectionDimensionColumn.dimensionData.dimensionIdKey;
3271
+ }
2818
3272
  }
2819
3273
  }
2820
3274
  submissionData.push(submissionEntry);
@@ -2910,6 +3364,7 @@ let JupiterDynamicForm = class extends LitElement {
2910
3364
  .collapsible="${config.collapsibleSections !== false}"
2911
3365
  .locale="${config.locale || "en-US"}"
2912
3366
  @field-change="${this._handleFieldChange}"
3367
+ @typed-member-change="${this._handleTypedMemberChange}"
2913
3368
  @section-expand="${this._handleSectionExpand}"
2914
3369
  @concept-expand="${this._handleConceptExpand}"
2915
3370
  @column-remove="${this._handleColumnRemove}"
@@ -3125,6 +3580,9 @@ __decorateClass([
3125
3580
  __decorateClass([
3126
3581
  r()
3127
3582
  ], JupiterDynamicForm.prototype, "_currentSchema", 2);
3583
+ __decorateClass([
3584
+ r()
3585
+ ], JupiterDynamicForm.prototype, "_typedMemberValues", 2);
3128
3586
  JupiterDynamicForm = __decorateClass([
3129
3587
  t$1("jupiter-dynamic-form")
3130
3588
  ], JupiterDynamicForm);