sag_components 2.0.0-beta52 → 2.0.0-beta53

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.js CHANGED
@@ -1912,7 +1912,7 @@ const ControlsContainer$a = styled__default["default"].div`
1912
1912
  box-sizing: border-box;
1913
1913
  }
1914
1914
  `;
1915
- const Controls$8 = styled__default["default"].div`
1915
+ const Controls$9 = styled__default["default"].div`
1916
1916
  display: flex;
1917
1917
  flex-direction: column;
1918
1918
  width: 100%;
@@ -2036,7 +2036,7 @@ const ControlsContainer$9 = styled__default["default"].div`
2036
2036
  //border: 1px solid red;
2037
2037
  align-items: center;
2038
2038
  `;
2039
- const Controls$7 = styled__default["default"].div`
2039
+ const Controls$8 = styled__default["default"].div`
2040
2040
  position: relative;
2041
2041
  border-radius: 100px;
2042
2042
  width: ${props => props.width.toString().concat('', 'px')};
@@ -2292,7 +2292,7 @@ const Benchmark = props => {
2292
2292
  id: "Tooltip",
2293
2293
  content: getTooltipText(),
2294
2294
  direction: tooltipDirection
2295
- }, /*#__PURE__*/React__default["default"].createElement(Controls$7, {
2295
+ }, /*#__PURE__*/React__default["default"].createElement(Controls$8, {
2296
2296
  id: "ControlsBenchmark",
2297
2297
  height: height,
2298
2298
  width: width
@@ -2417,7 +2417,7 @@ const PieChart = props => {
2417
2417
  }, legendData.length === 0 || legendData.every(item => item.value === undefined || item.value === null) ? /*#__PURE__*/React__default["default"].createElement(NoDataFoundMessage, {
2418
2418
  className: "NoDataFoundMessage",
2419
2419
  noDataText: noDataText
2420
- }) : /*#__PURE__*/React__default["default"].createElement(Controls$8, {
2420
+ }) : /*#__PURE__*/React__default["default"].createElement(Controls$9, {
2421
2421
  className: "Controls",
2422
2422
  height: height,
2423
2423
  width: width
@@ -25157,8 +25157,8 @@ function styleInject(css, ref) {
25157
25157
  }
25158
25158
  }
25159
25159
 
25160
- var css_248z = "@keyframes react-loading-skeleton {\n 100% {\n transform: translateX(100%);\n }\n}\n\n.react-loading-skeleton {\n --base-color: #ebebeb;\n --highlight-color: #f5f5f5;\n --animation-duration: 1.5s;\n --animation-direction: normal;\n --pseudo-element-display: block; /* Enable animation */\n\n background-color: var(--base-color);\n\n width: 100%;\n border-radius: 0.25rem;\n display: inline-flex;\n line-height: 1;\n\n position: relative;\n user-select: none;\n overflow: hidden;\n}\n\n.react-loading-skeleton::after {\n content: ' ';\n display: var(--pseudo-element-display);\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 100%;\n background-repeat: no-repeat;\n background-image: var(\n --custom-highlight-background,\n linear-gradient(\n 90deg,\n var(--base-color) 0%,\n var(--highlight-color) 50%,\n var(--base-color) 100%\n )\n );\n transform: translateX(-100%);\n\n animation-name: react-loading-skeleton;\n animation-direction: var(--animation-direction);\n animation-duration: var(--animation-duration);\n animation-timing-function: ease-in-out;\n animation-iteration-count: infinite;\n}\n\n@media (prefers-reduced-motion) {\n .react-loading-skeleton {\n --pseudo-element-display: none; /* Disable animation */\n }\n}\n";
25161
- styleInject(css_248z);
25160
+ var css_248z$1 = "@keyframes react-loading-skeleton {\n 100% {\n transform: translateX(100%);\n }\n}\n\n.react-loading-skeleton {\n --base-color: #ebebeb;\n --highlight-color: #f5f5f5;\n --animation-duration: 1.5s;\n --animation-direction: normal;\n --pseudo-element-display: block; /* Enable animation */\n\n background-color: var(--base-color);\n\n width: 100%;\n border-radius: 0.25rem;\n display: inline-flex;\n line-height: 1;\n\n position: relative;\n user-select: none;\n overflow: hidden;\n}\n\n.react-loading-skeleton::after {\n content: ' ';\n display: var(--pseudo-element-display);\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 100%;\n background-repeat: no-repeat;\n background-image: var(\n --custom-highlight-background,\n linear-gradient(\n 90deg,\n var(--base-color) 0%,\n var(--highlight-color) 50%,\n var(--base-color) 100%\n )\n );\n transform: translateX(-100%);\n\n animation-name: react-loading-skeleton;\n animation-direction: var(--animation-direction);\n animation-duration: var(--animation-duration);\n animation-timing-function: ease-in-out;\n animation-iteration-count: infinite;\n}\n\n@media (prefers-reduced-motion) {\n .react-loading-skeleton {\n --pseudo-element-display: none; /* Disable animation */\n }\n}\n";
25161
+ styleInject(css_248z$1);
25162
25162
 
25163
25163
  const OneColumnContainer = props => {
25164
25164
  const {
@@ -25355,7 +25355,7 @@ const ControlsContainer$7 = styled__default["default"].div`
25355
25355
  box-sizing: border-box;
25356
25356
  }
25357
25357
  `;
25358
- const Controls$6 = styled__default["default"].div`
25358
+ const Controls$7 = styled__default["default"].div`
25359
25359
  display: flex;
25360
25360
  flex-direction: column;
25361
25361
  width: 100%;
@@ -25423,7 +25423,7 @@ const FormattedValue$3 = props => {
25423
25423
  height: height,
25424
25424
  width: width,
25425
25425
  textcolor: textcolor
25426
- }, /*#__PURE__*/React__default["default"].createElement(Controls$6, {
25426
+ }, /*#__PURE__*/React__default["default"].createElement(Controls$7, {
25427
25427
  className: "Controls",
25428
25428
  height: height,
25429
25429
  width: width
@@ -25483,7 +25483,7 @@ const ControlsContainer$6 = styled__default["default"].div`
25483
25483
  height: ${props => props.height};
25484
25484
  min-width: 250px;
25485
25485
  `;
25486
- const Controls$5 = styled__default["default"].div`
25486
+ const Controls$6 = styled__default["default"].div`
25487
25487
  height: 100%;
25488
25488
  width: 100%;
25489
25489
  background: white;
@@ -25616,7 +25616,7 @@ const ControlsContainer$5 = styled__default["default"].div`
25616
25616
  box-sizing: border-box;
25617
25617
  }
25618
25618
  `;
25619
- const Controls$4 = styled__default["default"].div`
25619
+ const Controls$5 = styled__default["default"].div`
25620
25620
  display: flex;
25621
25621
  gap: 20px;
25622
25622
  flex-direction: column;
@@ -25679,7 +25679,7 @@ const PerformanceAnalyticsLegend = props => {
25679
25679
  className: className,
25680
25680
  height: height,
25681
25681
  width: width
25682
- }, legendData?.length > 0 ? /*#__PURE__*/React__default["default"].createElement(Controls$4, {
25682
+ }, legendData?.length > 0 ? /*#__PURE__*/React__default["default"].createElement(Controls$5, {
25683
25683
  height: height,
25684
25684
  width: width
25685
25685
  }, /*#__PURE__*/React__default["default"].createElement(LegendDataContainer, {
@@ -25847,7 +25847,7 @@ const BarChartsByWeeks = props => {
25847
25847
  height: height,
25848
25848
  width: width,
25849
25849
  ref: controlsContainerRef
25850
- }, /*#__PURE__*/React__default["default"].createElement(Controls$5, {
25850
+ }, /*#__PURE__*/React__default["default"].createElement(Controls$6, {
25851
25851
  height: getControlsHeight()
25852
25852
  }, showTitle && /*#__PURE__*/React__default["default"].createElement(TitleAndValueContainer$2, null, /*#__PURE__*/React__default["default"].createElement(Title$b, null, title), /*#__PURE__*/React__default["default"].createElement(FormattedValue$3, {
25853
25853
  title: headerValueTopTitle,
@@ -26053,7 +26053,7 @@ const ControlsContainer$4 = styled__default["default"].div`
26053
26053
  box-sizing: border-box;
26054
26054
  }
26055
26055
  `;
26056
- const Controls$3 = styled__default["default"].div`
26056
+ const Controls$4 = styled__default["default"].div`
26057
26057
  display: flex;
26058
26058
  flex-direction: column;
26059
26059
  width: 100%;
@@ -26279,7 +26279,7 @@ const TotalDoughnutChart = props => {
26279
26279
  }, legendData.length === 0 || legendData.every(item => item.value === undefined || item.value === null) ? /*#__PURE__*/React__default["default"].createElement(NoDataFoundMessage, {
26280
26280
  className: "NoDataFoundMessage",
26281
26281
  noDataText: noDataText
26282
- }) : /*#__PURE__*/React__default["default"].createElement(Controls$3, {
26282
+ }) : /*#__PURE__*/React__default["default"].createElement(Controls$4, {
26283
26283
  className: "Controls",
26284
26284
  height: height,
26285
26285
  width: width
@@ -28531,7 +28531,7 @@ const ControlsContainer$1 = styled__default["default"].div`
28531
28531
  height: ${props => props.height};
28532
28532
  min-width: 250px;
28533
28533
  `;
28534
- const Controls$2 = styled__default["default"].div`
28534
+ const Controls$3 = styled__default["default"].div`
28535
28535
  height: 100%;
28536
28536
  width: 100%;
28537
28537
  background: white;
@@ -28716,7 +28716,7 @@ const BarChart = props => {
28716
28716
  height: height,
28717
28717
  width: width,
28718
28718
  ref: controlsContainerRef
28719
- }, /*#__PURE__*/React__default["default"].createElement(Controls$2, null, /*#__PURE__*/React__default["default"].createElement(Title$3, null, title), /*#__PURE__*/React__default["default"].createElement(recharts.ResponsiveContainer, {
28719
+ }, /*#__PURE__*/React__default["default"].createElement(Controls$3, null, /*#__PURE__*/React__default["default"].createElement(Title$3, null, title), /*#__PURE__*/React__default["default"].createElement(recharts.ResponsiveContainer, {
28720
28720
  width: "100%",
28721
28721
  height: 400
28722
28722
  }, /*#__PURE__*/React__default["default"].createElement(recharts.BarChart, {
@@ -28880,7 +28880,7 @@ const LegendContainer = styled__default["default"].div`
28880
28880
  width: ${props => `${props.width}px`};
28881
28881
  bottom: 20px;
28882
28882
  `;
28883
- const Controls$1 = styled__default["default"].div`
28883
+ const Controls$2 = styled__default["default"].div`
28884
28884
  /* height: calc(100% - 30px); */
28885
28885
  height: 100%;
28886
28886
  display: flex;
@@ -29144,7 +29144,7 @@ const DoubleBarSingleLine = props => {
29144
29144
  hasScroll: hasScroll
29145
29145
  }, data.length === 0 ? /*#__PURE__*/React__default["default"].createElement(NoDataFoundMessage, {
29146
29146
  noDataText: noDataText
29147
- }) : /*#__PURE__*/React__default["default"].createElement(Controls$1, {
29147
+ }) : /*#__PURE__*/React__default["default"].createElement(Controls$2, {
29148
29148
  className: "Controls"
29149
29149
  }, title && title.trim() !== '' && /*#__PURE__*/React__default["default"].createElement(Title$2, null, title), /*#__PURE__*/React__default["default"].createElement(ChartsWrapper, {
29150
29150
  width: hasScroll ? `${data.length * 178}px` : 'auto'
@@ -29234,7 +29234,7 @@ const AreaChartContaner = styled__default["default"].div`
29234
29234
  height: ${props => props.height};
29235
29235
  min-width: 1100px;
29236
29236
  `;
29237
- const HeaderContainer$1 = styled__default["default"].div`
29237
+ const HeaderContainer$2 = styled__default["default"].div`
29238
29238
  display: flex;
29239
29239
  justify-content: space-between;
29240
29240
  padding: 10px 40px;
@@ -29293,7 +29293,7 @@ const ControlsContainer = styled__default["default"].div`
29293
29293
  font-family: Poppins;
29294
29294
  margin: 0;
29295
29295
  `;
29296
- const Controls = styled__default["default"].div`
29296
+ const Controls$1 = styled__default["default"].div`
29297
29297
  display: flex;
29298
29298
  align-items: center;
29299
29299
  `;
@@ -29339,7 +29339,7 @@ const CheckBox = props => {
29339
29339
  fontSize: fontSize,
29340
29340
  width: width,
29341
29341
  height: height
29342
- }, /*#__PURE__*/React__default["default"].createElement(Controls, {
29342
+ }, /*#__PURE__*/React__default["default"].createElement(Controls$1, {
29343
29343
  className: "Controls",
29344
29344
  "data-testid": "controls"
29345
29345
  }, checkedState ? /*#__PURE__*/React__default["default"].createElement(CheckBoxIconContainer, {
@@ -29571,7 +29571,7 @@ const AreaChart = props => {
29571
29571
  noDataText: "",
29572
29572
  width: width,
29573
29573
  height: height
29574
- }) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(HeaderContainer$1, {
29574
+ }) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(HeaderContainer$2, {
29575
29575
  "data-testid": "header-container"
29576
29576
  }, /*#__PURE__*/React__default["default"].createElement(Title$1, {
29577
29577
  "data-testid": "title"
@@ -30065,7 +30065,7 @@ const BreakdownPanelContainer = styled__default["default"].div`
30065
30065
  height: ${props => props.height};
30066
30066
  min-width: 1100px;
30067
30067
  `;
30068
- const HeaderContainer = styled__default["default"].div`
30068
+ const HeaderContainer$1 = styled__default["default"].div`
30069
30069
  display: flex;
30070
30070
  justify-content: space-between;
30071
30071
  align-items: center;
@@ -30138,7 +30138,7 @@ const BreakdownPanel = props => {
30138
30138
  noDataText: "",
30139
30139
  width: width,
30140
30140
  height: height
30141
- }) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(HeaderContainer, {
30141
+ }) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, /*#__PURE__*/React__default["default"].createElement(HeaderContainer$1, {
30142
30142
  "data-testid": "header-container"
30143
30143
  }, /*#__PURE__*/React__default["default"].createElement(Title, {
30144
30144
  "data-testid": "title"
@@ -30164,263 +30164,2069 @@ const BreakdownPanel = props => {
30164
30164
  }))))));
30165
30165
  };
30166
30166
 
30167
- const BatteryChartContainer = styled__default["default"].div`
30168
- position: relative;
30169
- font-family: "Poppins", sans-serif;
30170
- display: grid;
30171
- grid-template-columns: auto auto;
30172
- grid-template-rows: auto 1fr auto;
30173
- color: #212121;
30174
- background-color: ${props => props.backgroundColor || 'transparent'};
30175
- padding: ${props => props.containerPadding || '25px 30px 0'};
30176
- width: ${props => props.width};
30177
- height: ${props => props.height};
30178
- `;
30179
- const PanelSide = styled__default["default"].div`
30180
- display: flex;
30181
- flex-direction: column;
30182
- justify-content: space-between;
30167
+ const BubbleChartContainer = styled__default["default"].div`
30168
+ position: relative;
30169
+ width: ${props => props.width};
30170
+ height: ${props => props.height};
30171
+ display: flex;
30172
+ flex-direction: column;
30173
+ background-color: ${props => props.backgroundColor};
30174
+ border-radius: 8px;
30175
+ padding: 10px;
30176
+ box-sizing: border-box;
30177
+ font-family: "Poppins", sans-serif;
30178
+ min-width: 800px;
30179
+
30180
+ /* Enable proper overflow handling */
30181
+ overflow: hidden;
30183
30182
  `;
30184
- const ProgressDetails = styled__default["default"].div`
30185
- display: flex;
30186
- flex-direction: column;
30187
- flex-grow: 1;
30183
+ styled__default["default"].div`
30184
+ position: absolute;
30185
+ font-family: "Poppins", sans-serif;
30186
+ font-size: 12px;
30187
+ font-weight: 500;
30188
+ color: #555;
30189
+ text-align: center;
30190
+
30191
+ &.top-left {
30192
+ top: 20px;
30193
+ left: 20px;
30194
+ }
30195
+
30196
+ &.top-right {
30197
+ top: 20px;
30198
+ right: 20px;
30199
+ }
30200
+
30201
+ &.bottom-left {
30202
+ bottom: 20px;
30203
+ left: 20px;
30204
+ }
30205
+
30206
+ &.bottom-right {
30207
+ bottom: 20px;
30208
+ right: 20px;
30209
+ }
30188
30210
  `;
30189
- const HeadingText = styled__default["default"].p`
30190
- grid-column: 1 / span 2;
30191
- color: #212121;
30192
- font-size: 18px;
30193
- font-weight: 400;
30194
- padding-left: 10px;
30211
+ const CustomTooltipContainer = styled__default["default"].div`
30212
+ background-color: white;
30213
+ border-radius: 6px;
30214
+ z-index: 1000;
30215
+ padding: 10px 14px;
30216
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.15);
30217
+ max-width: 220px;
30218
+ font-family: "Poppins", sans-serif;
30219
+
30220
+ h4 {
30195
30221
  margin: 0 0 8px;
30196
- `;
30197
- const HeadingPercentage = styled__default["default"].p`
30198
- color: #212121;
30199
- font-size: 32px;
30200
- font-weight: 500;
30201
- padding-left: 10px;
30202
- margin: 0;
30203
- `;
30204
- const ChartSide = styled__default["default"].div`
30205
- text-align: center;
30206
- `;
30207
- const ChartWrapper = styled__default["default"].div`
30208
- position: relative;
30209
- width: 110px;
30210
- `;
30211
- const GoalValue = styled__default["default"].div`
30212
- text-align: center;
30213
- font-size: 18px;
30214
- color: #8B8989;
30215
- line-height: 1;
30216
- &.overload {
30217
- position: absolute;
30218
- top: ${props => props.goalValuePosition}px;
30219
- left: 0;
30220
- right: 0;
30221
- z-index: 2;
30222
- margin: 0 auto;
30223
- width: 40%;
30224
- display: inline;
30225
- padding: 0px 8px;
30226
- border: 2px solid #F2F2F2;
30227
- border-bottom: none;
30228
- border-radius: 6px 6px 0px 0px;
30229
- background-color: white;
30222
+ font-size: 14px;
30223
+ font-weight: 600;
30224
+ }
30225
+
30226
+ p {
30227
+ margin: 3px 0;
30228
+ font-size: 12px;
30229
+ color: #555;
30230
+ }
30231
+
30232
+ @media (max-width: 768px) {
30233
+ padding: 8px 12px;
30234
+ max-width: 180px;
30235
+
30236
+ h4 {
30237
+ font-size: 12px;
30238
+ margin: 0 0 6px;
30230
30239
  }
30240
+
30241
+ p {
30242
+ font-size: 10px;
30243
+ }
30244
+ }
30231
30245
  `;
30232
- const Indicator = styled__default["default"].div`
30233
- position: absolute;
30234
- top: ${props => props.top}px;
30235
- left: 0;
30236
- transform: translateY(50%);
30237
- width: calc(100% + 60px);
30238
- display: flex;
30239
- gap: 6px;
30240
- justify-content: center;
30241
- padding-left: 4px;
30242
- align-items: center;
30243
- z-index: 1;
30244
- `;
30245
- const IndicatorLine = styled__default["default"].div`
30246
- width: 100%;
30247
- height: 0;
30248
- border-top: 4px dashed ${props => props.color};
30246
+ const TooltipMetric = styled__default["default"].div`
30247
+ display: flex;
30248
+ justify-content: space-between;
30249
+ margin: 5px 0;
30250
+ font-size: 12px;
30251
+
30252
+ span:last-child {
30253
+ font-weight: 500;
30254
+ }
30255
+
30256
+ @media (max-width: 768px) {
30257
+ font-size: 10px;
30258
+ margin: 4px 0;
30259
+ }
30249
30260
  `;
30250
- const IndicatorText = styled__default["default"].span`
30251
- font-size: 18px;
30252
- font-weight: 400;
30253
- color: ${props => props.color};
30261
+ styled__default["default"].div`
30262
+ position: relative;
30263
+ width: 100%;
30264
+ height: 100%;
30254
30265
  `;
30255
- const ProgressLegend = styled__default["default"].div`
30256
- margin-top: 12px;
30266
+ const HeaderContainer = styled__default["default"].div`
30267
+ display: flex;
30268
+ justify-content: space-between;
30269
+ align-items: baseline;
30270
+ padding: 0;
30271
+ margin-bottom: 10px;
30257
30272
  `;
30258
- const LegendItem = styled__default["default"].div`
30259
- display: flex;
30260
- gap: 4px;
30261
- align-items: center;
30262
- margin-bottom: 12px;
30273
+ const ChartTitle = styled__default["default"].h2`
30274
+ font-family: "Poppins", sans-serif;
30275
+ font-size: 18px;
30276
+ font-weight: 400;
30277
+ margin: 0;
30278
+ color: #212121;
30263
30279
  `;
30264
- const LegendText = styled__default["default"].span`
30265
- color: #8B8989;
30266
- font-size: 14px;
30280
+ const ChartSubtitle = styled__default["default"].p`
30281
+ font-family: "Poppins", sans-serif;
30282
+ font-size: 14px;
30283
+ font-weight: 500;
30284
+ color: #484A4C;
30285
+ margin: 0;
30267
30286
  `;
30268
- const LegendCube = styled__default["default"].div`
30269
- border-radius: 3px;
30270
- width: 17px;
30271
- height: 17px;
30272
- background-color: ${props => props.color};
30287
+ const ChartContainer = styled__default["default"].div`
30288
+ position: relative;
30289
+ width: 100%;
30290
+ height: 90%; /* Reduced from 93% to make room for the zoom controls */
30291
+ flex: 1;
30273
30292
  `;
30274
- const ProgressDescription = styled__default["default"].div`
30275
- color: #8B8989;
30276
- font-size: 12px;
30277
- font-weight: 400;
30278
- margin-top: auto;
30293
+
30294
+ /* Updated Zoom Controls Styles to match the new design */
30295
+ const ZoomControlsContainer = styled__default["default"].div`
30296
+ display: flex;
30297
+ align-items: center;
30298
+ align-self: flex-start;
30299
+ margin-top: 10px;
30300
+ background: linear-gradient(to right, rgba(255, 255, 255, 0.98), rgba(245, 245, 245, 0.92));
30301
+ border-radius: 8px;
30302
+ padding: 6px 6px 6px 12px;
30303
+ box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.1);
30304
+ z-index: 10;
30305
+ font-family: "Poppins", sans-serif;
30306
+ backdrop-filter: blur(8px);
30307
+ transition: background-color 0.3s ease, box-shadow 0.3s ease;
30279
30308
  `;
30280
- const ProgressItem = styled__default["default"].p`
30281
- margin: 0 0 6px;
30309
+ const ZoomPercentage = styled__default["default"].span`
30310
+ font-size: 18px;
30311
+ font-weight: 500;
30312
+ color: #726F6F;
30313
+ margin: 0;
30314
+ min-width: 50px;
30282
30315
  `;
30283
- const StarText = styled__default["default"].span`
30284
- width: 100%;
30285
- color: #B1B1B1;
30286
- font-size: 9px;
30287
- grid-column: 1 / span 2;
30288
- padding-top: 10px;
30316
+ const ZoomButton = styled__default["default"].button`
30317
+ width: 26px;
30318
+ height: 20px;
30319
+ border: none;
30320
+ background: none;
30321
+ font-size: 24px;
30322
+ font-weight: 500;
30323
+ color: #726F6F;
30324
+ cursor: pointer;
30325
+ display: flex;
30326
+ align-items: center;
30327
+ justify-content: center;
30328
+ padding: 0;
30329
+ margin: 0 ;
30330
+
30331
+ &:hover {
30332
+ color: #333;
30333
+ }
30334
+
30335
+ &:focus {
30336
+ outline: none;
30337
+ }
30289
30338
  `;
30339
+ const ZoomResetButton = styled__default["default"].button`
30340
+ font-family: "Poppins", sans-serif;
30341
+ font-size: 14px;
30342
+ font-weight: 400;
30343
+ height: 32px;
30344
+ padding: 0 12px;
30345
+ margin-left: 5px;
30346
+ border-radius: 8px;
30347
+ background-color: white;
30348
+ border: 1px solid #ddd;
30349
+ cursor: pointer;
30350
+ color: #212121;
30351
+ background: linear-gradient(to right, rgba(255, 255, 255, 0.98), rgba(245, 245, 245, 0.92));
30352
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
30353
+ transition: all 0.2s ease-in-out;
30290
30354
 
30291
- const BatteryChart = props => {
30355
+ &:hover {
30356
+ background: linear-gradient(to right, #f0f0f0, #eaeaea);
30357
+ border-color: #ccc;
30358
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08);
30359
+ }
30360
+
30361
+ &:active {
30362
+ background: #e0e0e0;
30363
+ transform: scale(0.98);
30364
+ box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15);
30365
+ }
30366
+
30367
+ &:focus {
30368
+ outline: none;
30369
+ box-shadow: 0 0 0 3px rgba(100, 150, 250, 0.4);
30370
+ }
30371
+ `;
30372
+
30373
+ // Enhanced color palette with bubble-like transparency and gradients
30374
+ const defaultColorPalette = [
30375
+ // Top Left - Yellow Bubbles
30376
+ 'rgba(255, 249, 220, 0.7)',
30377
+ // Inner highlight
30378
+ 'rgba(255, 235, 165, 0.4)',
30379
+ // Outer edge
30380
+
30381
+ // Top Right - Green Bubbles
30382
+ 'rgba(235, 255, 240, 0.7)',
30383
+ // Inner highlight
30384
+ 'rgba(190, 235, 200, 0.4)',
30385
+ // Outer edge
30386
+
30387
+ // Bottom Left - Pink Bubbles
30388
+ 'rgba(255, 235, 240, 0.7)',
30389
+ // Inner highlight
30390
+ 'rgba(255, 190, 200, 0.4)',
30391
+ // Outer edge
30392
+
30393
+ // Bottom Right - Cream/Yellow Bubbles
30394
+ 'rgba(255, 250, 230, 0.7)',
30395
+ // Inner highlight
30396
+ 'rgba(255, 235, 180, 0.4)' // Outer edge
30397
+ ];
30398
+
30399
+ // Main component
30400
+ const BubbleChart = _ref => {
30401
+ let {
30402
+ data = [],
30403
+ title = 'Event Performance Based on Incrementality',
30404
+ subtitle = '* Total cost is reflected by the circle size',
30405
+ leftHeader = 'Low INC Sales ROI',
30406
+ rightHeader = 'High INC Sales ROI',
30407
+ topHeader = 'High INC Sales',
30408
+ bottomHeader = 'Low INC Sales',
30409
+ colorPalette = defaultColorPalette,
30410
+ height = '600px',
30411
+ width = '100%',
30412
+ backgroundColor = 'white',
30413
+ showAxis = false
30414
+ } = _ref;
30415
+ // Calculate the medians and domain for raw X, Y, and Z values
30292
30416
  const {
30293
- className,
30294
- containerPadding,
30295
- width,
30296
- height,
30297
- title,
30298
- color,
30299
- backgroundColor,
30300
- indicatorColor,
30301
- noCommitment,
30302
- goalAmount,
30303
- currentAmount,
30304
- ask,
30305
- target,
30306
- totalSegmentsLines,
30307
- starText
30308
- } = props;
30309
- const [top, setTop] = React$1.useState(0);
30310
- const [goalValuePosition, setGoalValuePosition] = React$1.useState(0);
30311
- const [containerHeight, setContainerHeight] = React$1.useState(0); // State to store container height
30312
- const containerRef = React$1.useRef(null); // Ref for BatteryChartContainer
30417
+ xMedian,
30418
+ yMedian,
30419
+ xDomain,
30420
+ yDomain,
30421
+ zRange
30422
+ } = React$1.useMemo(() => {
30423
+ if (!data || !Array.isArray(data) || data.length === 0) {
30424
+ return {
30425
+ xMedian: 0,
30426
+ yMedian: 0,
30427
+ xDomain: [0, 100],
30428
+ yDomain: [0, 100],
30429
+ zRange: [0, 3600]
30430
+ };
30431
+ }
30313
30432
 
30314
- // Calculate the percentage and completed segments
30315
- const percentage = Math.round(currentAmount / goalAmount * 100);
30316
- const completedSegments = Math.min(Math.floor(currentAmount / goalAmount * totalSegmentsLines), totalSegmentsLines);
30433
+ // Extract x, y, and size values
30434
+ const xValues = data.map(item => item.x).filter(x => x !== undefined && x !== null);
30435
+ const yValues = data.map(item => item.y).filter(y => y !== undefined && y !== null);
30436
+ const sizeValues = data.map(item => item.size).filter(size => size !== undefined && size !== null);
30437
+
30438
+ // Calculate min and max values
30439
+ const minX = Math.min(...xValues);
30440
+ const maxX = Math.max(...xValues);
30441
+ const minY = Math.min(...yValues);
30442
+ const maxY = Math.max(...yValues);
30443
+ Math.min(...sizeValues);
30444
+ const maxSize = Math.max(...sizeValues);
30445
+
30446
+ // Calculate medians
30447
+ const calculateMedian = arr => {
30448
+ if (!arr || arr.length === 0) return 0;
30449
+ const sorted = [...arr].sort((a, b) => a - b);
30450
+ const middle = Math.floor(sorted.length / 2);
30451
+ if (sorted.length % 2 === 1) {
30452
+ return sorted[middle];
30453
+ }
30454
+ return (sorted[middle - 1] + sorted[middle]) / 2;
30455
+ };
30456
+ const medianX = calculateMedian(xValues);
30457
+ const medianY = calculateMedian(yValues);
30317
30458
 
30318
- // Dynamically create the data for the bar chart
30319
- let barsChips = Array.from({
30320
- length: totalSegmentsLines
30321
- }).map((_, index) => ({
30322
- name: `segment-${index}`,
30323
- value: 100,
30324
- isCompleted: index >= totalSegmentsLines - completedSegments,
30325
- // Fill from bottom up
30326
- color: index >= totalSegmentsLines - completedSegments ? color : "#e5e7eb" // Completed or remaining color
30327
- }));
30459
+ // Calculate domains based on median-centered logic
30460
+ const calculateDomainBasedOnMedian = (min, max, median) => {
30461
+ const distance = Math.max(Math.abs(max - median), Math.abs(min - median));
30462
+ return [median - distance, median + distance];
30463
+ };
30464
+ const xDom = calculateDomainBasedOnMedian(minX, maxX, medianX);
30465
+ const yDom = calculateDomainBasedOnMedian(minY, maxY, medianY);
30328
30466
 
30329
- // Add 4 extra chips if currentAmount > goalAmount
30330
- if (currentAmount > goalAmount && !noCommitment) {
30331
- const extraSegments = 4;
30332
- const extraData = Array.from({
30333
- length: extraSegments
30334
- }).map((_, index) => ({
30335
- name: `extra-segment-${index}`,
30336
- value: 100,
30337
- isCompleted: true,
30338
- color: "#E8F5EB"
30339
- }));
30467
+ // Determine z-axis range scaled appropriately
30468
+ const zRng = [0, maxSize * 7];
30469
+ return {
30470
+ xMedian: medianX,
30471
+ yMedian: medianY,
30472
+ xDomain: xDom,
30473
+ yDomain: yDom,
30474
+ zRange: zRng
30475
+ };
30476
+ }, [data]);
30340
30477
 
30341
- // Prepend the extra segments to the barsChips array
30342
- barsChips = [...extraData, ...barsChips];
30343
- }
30478
+ // Init viewDomain with calculated domain values
30479
+ const fullDomain = React$1.useMemo(() => ({
30480
+ x: xDomain,
30481
+ y: yDomain
30482
+ }), [xDomain, yDomain]);
30344
30483
 
30345
- // Calculate the top position for the indicator and goal value
30484
+ // State for current view domain
30485
+ const [viewDomain, setViewDomain] = React$1.useState(fullDomain);
30486
+ const [zoomLevel, setZoomLevel] = React$1.useState(100);
30487
+
30488
+ // Drag state
30489
+ const [isDragging, setIsDragging] = React$1.useState(false);
30490
+ const [dragStart, setDragStart] = React$1.useState({
30491
+ x: 0,
30492
+ y: 0
30493
+ });
30494
+ const [domainStart, setDomainStart] = React$1.useState(fullDomain);
30495
+
30496
+ // Refs for the chart container
30497
+ const containerRef = React$1.useRef(null);
30498
+ const scatterChartRef = React$1.useRef(null);
30499
+
30500
+ // Set up initial domain
30346
30501
  React$1.useEffect(() => {
30347
- const barHeight = containerHeight / (totalSegmentsLines + (currentAmount > goalAmount ? 4 : 0)); // Adjust for extra chips
30348
- let newTop;
30349
- let newGoalValuePosition;
30350
- if (currentAmount > goalAmount) {
30351
- // Position the indicator slightly below the top chip
30352
- newTop = barHeight * 1.5; // Slightly below the 4th chip
30353
- // Position the goal value just above the active chips
30502
+ // Set initial viewDomain from fullDomain
30503
+ setViewDomain(fullDomain);
30504
+ }, [fullDomain]);
30505
+
30506
+ // Function to get gradient fill based on quadrant
30507
+ const getFill = React$1.useCallback((x, y) => {
30508
+ if (x < xMedian && y > yMedian) return 'url(#topLeftGradient)'; // Top Left
30509
+ if (x >= xMedian && y > yMedian) return 'url(#topRightGradient)'; // Top Right
30510
+ if (x < xMedian && y <= yMedian) return 'url(#bottomLeftGradient)'; // Bottom Left
30511
+ if (x >= xMedian && y <= yMedian) return 'url(#bottomRightGradient)'; // Bottom Right
30512
+ return 'gray'; // fallback
30513
+ }, [xMedian, yMedian]);
30514
+
30515
+ // CustomTooltip component inside BubbleChart
30516
+ const CustomTooltip = React$1.useCallback(_ref2 => {
30517
+ let {
30518
+ active,
30519
+ payload
30520
+ } = _ref2;
30521
+ if (active && payload && payload.length && payload[0].payload.tooltip) {
30522
+ const data = payload[0].payload;
30523
+ return /*#__PURE__*/React__default["default"].createElement(CustomTooltipContainer, {
30524
+ "data-testid": "tooltip-container"
30525
+ }, /*#__PURE__*/React__default["default"].createElement("h4", {
30526
+ "data-testid": "tooltip-title"
30527
+ }, data.tooltip.title), data.tooltip.description && /*#__PURE__*/React__default["default"].createElement(TooltipMetric, {
30528
+ "data-testid": "tooltip-description"
30529
+ }, /*#__PURE__*/React__default["default"].createElement("span", null, data.tooltip.description)), /*#__PURE__*/React__default["default"].createElement(TooltipMetric, {
30530
+ "data-testid": "tooltip-cost"
30531
+ }, /*#__PURE__*/React__default["default"].createElement("span", null, "Total cost:"), /*#__PURE__*/React__default["default"].createElement("span", null, formatCurrency(data.tooltip.cost))), /*#__PURE__*/React__default["default"].createElement(TooltipMetric, {
30532
+ "data-testid": "tooltip-sales"
30533
+ }, /*#__PURE__*/React__default["default"].createElement("span", null, "INC Sales:"), /*#__PURE__*/React__default["default"].createElement("span", null, formatCurrency(data.tooltip.incSales))), /*#__PURE__*/React__default["default"].createElement(TooltipMetric, {
30534
+ "data-testid": "tooltip-roi"
30535
+ }, /*#__PURE__*/React__default["default"].createElement("span", null, "INC Sales ROI:"), /*#__PURE__*/React__default["default"].createElement("span", null, formatROI(data.tooltip.roi))), /*#__PURE__*/React__default["default"].createElement(TooltipMetric, {
30536
+ "data-testid": "tooltip-units"
30537
+ }, /*#__PURE__*/React__default["default"].createElement("span", null, "INC Units:"), /*#__PURE__*/React__default["default"].createElement("span", null, formatUnits(data.tooltip.units))));
30538
+ }
30539
+ return null;
30540
+ }, []);
30354
30541
 
30355
- newGoalValuePosition = barHeight * 2.3;
30356
- // newGoalValuePosition = (totalSegmentsLines - completedSegments + 4) * barHeight - barHeight / 2;
30542
+ // Process all chart data - use original data values
30543
+ const allChartData = React$1.useMemo(() => {
30544
+ return data.map((item, index) => {
30545
+ if (item.x === undefined || item.y === undefined || item.size === undefined) {
30546
+ console.warn('Skipping data item with missing values:', item);
30547
+ return null;
30548
+ }
30549
+ const tooltipInfo = {
30550
+ title: item.name || 'Marketing event',
30551
+ description: item.description || '',
30552
+ cost: item.size || 0,
30553
+ units: item.units || 0,
30554
+ roi: item.x || 0,
30555
+ incSales: item.y || 0,
30556
+ ...(item.tooltip || {})
30557
+ };
30558
+ return {
30559
+ x: item.x,
30560
+ // Use original x value
30561
+ y: item.y,
30562
+ // Use original y value
30563
+ z: item.size,
30564
+ // Use original size value
30565
+ tooltip: tooltipInfo,
30566
+ fill: getFill(item.x, item.y),
30567
+ key: `bubble-${index}` // Use index for stable keys
30568
+ };
30569
+ }).filter(Boolean); // Filter out null items
30570
+ }, [data, getFill]);
30571
+
30572
+ // Function to determine which data points should be visible
30573
+ const getVisibleData = React$1.useCallback(() => {
30574
+ return allChartData.filter(item => item.x >= viewDomain.x[0] && item.x <= viewDomain.x[1] && item.y >= viewDomain.y[0] && item.y <= viewDomain.y[1]);
30575
+ }, [allChartData, viewDomain]);
30576
+
30577
+ // Get visible data - memoized
30578
+ const visibleData = React$1.useMemo(() => getVisibleData(), [getVisibleData]);
30579
+
30580
+ // Calculate a new domain based on zoom level and center point - memoized
30581
+ const calculateDomain = React$1.useCallback((center, zoomFactor) => {
30582
+ // Calculate new domain size
30583
+ const xSize = (fullDomain.x[1] - fullDomain.x[0]) * zoomFactor;
30584
+ const ySize = (fullDomain.y[1] - fullDomain.y[0]) * zoomFactor;
30585
+
30586
+ // Calculate new domain
30587
+ return {
30588
+ x: [center.x - xSize / 2, center.x + xSize / 2],
30589
+ y: [center.y - ySize / 2, center.y + ySize / 2]
30590
+ };
30591
+ }, [fullDomain]);
30592
+
30593
+ // Rendering gradients with enhanced bubble-like appearance
30594
+ const renderGradients = React$1.useCallback(() => /*#__PURE__*/React__default["default"].createElement("defs", null, /*#__PURE__*/React__default["default"].createElement("radialGradient", {
30595
+ id: "topLeftGradient",
30596
+ cx: "25%",
30597
+ cy: "25%",
30598
+ r: "70%",
30599
+ fx: "20%",
30600
+ fy: "20%"
30601
+ }, /*#__PURE__*/React__default["default"].createElement("stop", {
30602
+ offset: "0%",
30603
+ stopColor: colorPalette[0]
30604
+ }), /*#__PURE__*/React__default["default"].createElement("stop", {
30605
+ offset: "85%",
30606
+ stopColor: colorPalette[1]
30607
+ })), /*#__PURE__*/React__default["default"].createElement("radialGradient", {
30608
+ id: "topRightGradient",
30609
+ cx: "25%",
30610
+ cy: "25%",
30611
+ r: "70%",
30612
+ fx: "20%",
30613
+ fy: "20%"
30614
+ }, /*#__PURE__*/React__default["default"].createElement("stop", {
30615
+ offset: "0%",
30616
+ stopColor: colorPalette[2]
30617
+ }), /*#__PURE__*/React__default["default"].createElement("stop", {
30618
+ offset: "85%",
30619
+ stopColor: colorPalette[3]
30620
+ })), /*#__PURE__*/React__default["default"].createElement("radialGradient", {
30621
+ id: "bottomLeftGradient",
30622
+ cx: "25%",
30623
+ cy: "25%",
30624
+ r: "70%",
30625
+ fx: "20%",
30626
+ fy: "20%"
30627
+ }, /*#__PURE__*/React__default["default"].createElement("stop", {
30628
+ offset: "0%",
30629
+ stopColor: colorPalette[4]
30630
+ }), /*#__PURE__*/React__default["default"].createElement("stop", {
30631
+ offset: "85%",
30632
+ stopColor: colorPalette[5]
30633
+ })), /*#__PURE__*/React__default["default"].createElement("radialGradient", {
30634
+ id: "bottomRightGradient",
30635
+ cx: "25%",
30636
+ cy: "25%",
30637
+ r: "70%",
30638
+ fx: "20%",
30639
+ fy: "20%"
30640
+ }, /*#__PURE__*/React__default["default"].createElement("stop", {
30641
+ offset: "0%",
30642
+ stopColor: colorPalette[6]
30643
+ }), /*#__PURE__*/React__default["default"].createElement("stop", {
30644
+ offset: "85%",
30645
+ stopColor: colorPalette[7]
30646
+ })), /*#__PURE__*/React__default["default"].createElement("filter", {
30647
+ id: "bubble-blur",
30648
+ x: "-50%",
30649
+ y: "-50%",
30650
+ width: "200%",
30651
+ height: "200%"
30652
+ }, /*#__PURE__*/React__default["default"].createElement("feGaussianBlur", {
30653
+ in: "SourceGraphic",
30654
+ stdDeviation: "0.3"
30655
+ }))), [colorPalette]);
30656
+
30657
+ // Handle mouse down for dragging
30658
+ const handleMouseDown = React$1.useCallback(e => {
30659
+ if (containerRef.current?.contains(e.target)) {
30660
+ setIsDragging(true);
30661
+ setDragStart({
30662
+ x: e.clientX,
30663
+ y: e.clientY
30664
+ });
30665
+ setDomainStart({
30666
+ ...viewDomain
30667
+ }); // Store current domain, not fullDomain
30668
+ e.preventDefault();
30669
+ }
30670
+ }, [viewDomain]); // Add viewDomain as dependency to capture current value
30671
+
30672
+ // Handle mouse move for dragging
30673
+ const handleMouseMove = React$1.useCallback(e => {
30674
+ if (!isDragging) return;
30675
+ const dx = e.clientX - dragStart.x;
30676
+ const dy = e.clientY - dragStart.y;
30677
+ const containerWidth = containerRef.current?.clientWidth || 800;
30678
+ const containerHeight = containerRef.current?.clientHeight || 600;
30679
+
30680
+ // Calculate the domain range from the domainStart (which preserves zoom level)
30681
+ const xRange = domainStart.x[1] - domainStart.x[0];
30682
+ const yRange = domainStart.y[1] - domainStart.y[0];
30683
+
30684
+ // Calculate the shift amount (negative for dx to make drag direction feel natural)
30685
+ const xShift = -(dx / containerWidth) * xRange * 1.5; // Multiply by 1.5 to make dragging more responsive
30686
+ const yShift = dy / containerHeight * yRange * 1.5; // Y is inverted in charts
30687
+
30688
+ // Create new domain values based on the domainStart (preserves zoom level)
30689
+ const newXDomain = [domainStart.x[0] + xShift, domainStart.x[1] + xShift];
30690
+ const newYDomain = [domainStart.y[0] + yShift, domainStart.y[1] + yShift];
30691
+
30692
+ // Update the domain
30693
+ setViewDomain({
30694
+ x: newXDomain,
30695
+ y: newYDomain
30696
+ });
30697
+ }, [isDragging, dragStart, domainStart]);
30698
+
30699
+ // Handle mouse up for dragging
30700
+ const handleMouseUp = React$1.useCallback(() => {
30701
+ setIsDragging(false);
30702
+ }, []);
30703
+
30704
+ // Handle zoom in
30705
+ const handleZoomIn = React$1.useCallback(() => {
30706
+ if (zoomLevel >= 400) return;
30707
+ const newZoomLevel = zoomLevel + 20;
30708
+ setZoomLevel(newZoomLevel);
30709
+
30710
+ // Calculate zoom factor (smaller factor = more zoomed in)
30711
+ const zoomFactor = 100 / newZoomLevel;
30712
+
30713
+ // Get current domain center
30714
+ const centerX = (viewDomain.x[0] + viewDomain.x[1]) / 2;
30715
+ const centerY = (viewDomain.y[0] + viewDomain.y[1]) / 2;
30716
+
30717
+ // Calculate new domain
30718
+ const newDomain = calculateDomain({
30719
+ x: centerX,
30720
+ y: centerY
30721
+ }, zoomFactor);
30722
+
30723
+ // Update domain
30724
+ setViewDomain(newDomain);
30725
+ }, [zoomLevel, viewDomain, calculateDomain]);
30726
+
30727
+ // Handle zoom out
30728
+ const handleZoomOut = React$1.useCallback(() => {
30729
+ if (zoomLevel <= 50) return;
30730
+ const newZoomLevel = zoomLevel - 20;
30731
+
30732
+ // If returning to 100%, reset to full domain
30733
+ if (newZoomLevel === 100) {
30734
+ setViewDomain({
30735
+ ...fullDomain
30736
+ });
30737
+ setZoomLevel(100);
30738
+ return;
30739
+ }
30740
+ setZoomLevel(newZoomLevel);
30741
+
30742
+ // Calculate zoom factor (larger factor = more zoomed out)
30743
+ const zoomFactor = 100 / newZoomLevel;
30744
+
30745
+ // Get current domain center
30746
+ const centerX = (viewDomain.x[0] + viewDomain.x[1]) / 2;
30747
+ const centerY = (viewDomain.y[0] + viewDomain.y[1]) / 2;
30748
+
30749
+ // Calculate new domain size
30750
+ const xSize = (fullDomain.x[1] - fullDomain.x[0]) * zoomFactor;
30751
+ const ySize = (fullDomain.y[1] - fullDomain.y[0]) * zoomFactor;
30752
+
30753
+ // If new domain would be larger than full domain, reset to full
30754
+ if (xSize >= fullDomain.x[1] - fullDomain.x[0] || ySize >= fullDomain.y[1] - fullDomain.y[0]) {
30755
+ setViewDomain({
30756
+ ...fullDomain
30757
+ });
30758
+ setZoomLevel(100);
30759
+ return;
30760
+ }
30761
+
30762
+ // Calculate new domain
30763
+ const newDomain = calculateDomain({
30764
+ x: centerX,
30765
+ y: centerY
30766
+ }, zoomFactor);
30767
+
30768
+ // Update domain
30769
+ setViewDomain(newDomain);
30770
+ }, [zoomLevel, viewDomain, fullDomain, calculateDomain]);
30771
+
30772
+ // Handle reset
30773
+ const handleReset = React$1.useCallback(() => {
30774
+ setZoomLevel(100);
30775
+ setViewDomain({
30776
+ ...fullDomain
30777
+ });
30778
+ }, [fullDomain]);
30779
+
30780
+ // Handle mouse wheel
30781
+ const handleWheel = React$1.useCallback(e => {
30782
+ e.preventDefault();
30783
+ if (e.deltaY < 0) {
30784
+ handleZoomIn();
30357
30785
  } else {
30358
- // Normal case: position the indicator above the active chips
30359
- newTop = (totalSegmentsLines - completedSegments) * barHeight / 1.65;
30360
- // Position the goal value just above the active chips
30361
- newGoalValuePosition = newTop;
30786
+ handleZoomOut();
30362
30787
  }
30363
- setTop(newTop);
30364
- setGoalValuePosition(newGoalValuePosition);
30365
- }, [completedSegments, totalSegmentsLines, currentAmount, goalAmount, containerHeight]);
30788
+ }, [handleZoomIn, handleZoomOut]);
30789
+
30790
+ // Memoize the visibility condition for the middle value label
30791
+ const isMiddleValueVisible = React$1.useMemo(() => xMedian >= viewDomain.x[0] && xMedian <= viewDomain.x[1] && yMedian >= viewDomain.y[0] && yMedian <= viewDomain.y[1], [viewDomain, xMedian, yMedian]);
30792
+
30793
+ // Set up event listeners
30366
30794
  React$1.useEffect(() => {
30367
- if (containerRef.current) {
30368
- const height = containerRef.current.offsetHeight;
30369
- if (height > 0) {
30370
- setContainerHeight(height);
30371
- }
30795
+ const container = containerRef.current;
30796
+ if (!container) return;
30797
+ container.addEventListener('wheel', handleWheel, {
30798
+ passive: false
30799
+ });
30800
+ container.addEventListener('mousedown', handleMouseDown);
30801
+ window.addEventListener('mousemove', handleMouseMove);
30802
+ window.addEventListener('mouseup', handleMouseUp);
30803
+ return () => {
30804
+ container.removeEventListener('wheel', handleWheel);
30805
+ container.removeEventListener('mousedown', handleMouseDown);
30806
+ window.removeEventListener('mousemove', handleMouseMove);
30807
+ window.removeEventListener('mouseup', handleMouseUp);
30808
+ };
30809
+ }, [handleWheel, handleMouseDown, handleMouseMove, handleMouseUp]);
30810
+
30811
+ // Unified arrow component with direction parameter
30812
+ const Arrow = _ref3 => {
30813
+ let {
30814
+ viewBox,
30815
+ direction
30816
+ } = _ref3;
30817
+ // Define points based on direction
30818
+ let points = '';
30819
+ switch (direction) {
30820
+ case 'top':
30821
+ points = `${viewBox.x},${viewBox.y - 10} ${viewBox.x - 5},${viewBox.y} ${viewBox.x + 5},${viewBox.y}`;
30822
+ break;
30823
+ case 'bottom':
30824
+ points = `${viewBox.x},${viewBox.y + viewBox.height + 10} ${viewBox.x - 5},${viewBox.y + viewBox.height} ${viewBox.x + 5},${viewBox.y + viewBox.height}`;
30825
+ break;
30826
+ case 'left':
30827
+ points = `${viewBox.x - 10},${viewBox.y} ${viewBox.x},${viewBox.y - 5} ${viewBox.x},${viewBox.y + 5}`;
30828
+ break;
30829
+ case 'right':
30830
+ points = `${viewBox.x + viewBox.width + 10},${viewBox.y} ${viewBox.x + viewBox.width},${viewBox.y - 5} ${viewBox.x + viewBox.width},${viewBox.y + 5}`;
30831
+ break;
30372
30832
  }
30373
- }, [containerRef, width, height]);
30374
- return /*#__PURE__*/React__default["default"].createElement(BatteryChartContainer, {
30375
- ref: containerRef,
30833
+ return /*#__PURE__*/React__default["default"].createElement("polygon", {
30834
+ points: points,
30835
+ fill: "#D0D0D0"
30836
+ });
30837
+ };
30838
+
30839
+ // Function to format currency values
30840
+ const formatCurrency = value => {
30841
+ if (Math.abs(value) >= 1000000) {
30842
+ return `$${(value / 1000000).toFixed(1)}M`;
30843
+ } else if (Math.abs(value) >= 1000) {
30844
+ return `$${(value / 1000).toFixed(1)}K`;
30845
+ }
30846
+ return `$${value.toFixed(1)}`;
30847
+ };
30848
+
30849
+ // Function to format units values
30850
+ const formatUnits = value => {
30851
+ if (Math.abs(value) >= 1000000) {
30852
+ return `${(value / 1000000).toFixed(1)}M`;
30853
+ } else if (Math.abs(value) >= 1000) {
30854
+ return `${(value / 1000).toFixed(1)}K`;
30855
+ }
30856
+ return `${value.toFixed(1)}`;
30857
+ };
30858
+
30859
+ // Function to format ROI values
30860
+ const formatROI = value => {
30861
+ return value.toFixed(1);
30862
+ };
30863
+
30864
+ // Format the median values for display
30865
+ const formattedMedianValue = React$1.useMemo(() => {
30866
+ const formattedX = formatROI(xMedian);
30867
+ const formattedY = formatUnits(yMedian);
30868
+ return `${formattedX}, ${formattedY}`;
30869
+ }, [xMedian, yMedian]);
30870
+
30871
+ // Render the component
30872
+ return /*#__PURE__*/React__default["default"].createElement(BubbleChartContainer, {
30376
30873
  width: width,
30377
30874
  height: height,
30378
- className: className,
30379
- containerPadding: containerPadding,
30380
- backgroundColor: backgroundColor
30381
- }, /*#__PURE__*/React__default["default"].createElement(HeadingText, null, title), /*#__PURE__*/React__default["default"].createElement(PanelSide, null, /*#__PURE__*/React__default["default"].createElement(ProgressDetails, null, !noCommitment && /*#__PURE__*/React__default["default"].createElement(HeadingPercentage, null, percentage, "%"), /*#__PURE__*/React__default["default"].createElement(ProgressDescription, null, ask && /*#__PURE__*/React__default["default"].createElement(ProgressItem, null, "ASK: ", `$${getFormattedValue(ask, false) + getFormattedUnits(ask)}`), target && /*#__PURE__*/React__default["default"].createElement(ProgressItem, null, "Target: ", `$${getFormattedValue(target, false) + getFormattedUnits(target)}`)), /*#__PURE__*/React__default["default"].createElement(ProgressLegend, null, /*#__PURE__*/React__default["default"].createElement(LegendItem, null, /*#__PURE__*/React__default["default"].createElement(LegendCube, {
30382
- color: color
30383
- }), /*#__PURE__*/React__default["default"].createElement(LegendText, null, "Spend")), !noCommitment && /*#__PURE__*/React__default["default"].createElement(LegendItem, null, /*#__PURE__*/React__default["default"].createElement(LegendCube, {
30384
- color: "#E3E4E5"
30385
- }), /*#__PURE__*/React__default["default"].createElement(LegendText, null, "Commitment"))))), /*#__PURE__*/React__default["default"].createElement(ChartSide, null, /*#__PURE__*/React__default["default"].createElement(ChartWrapper, null, /*#__PURE__*/React__default["default"].createElement(GoalValue, {
30386
- className: currentAmount > goalAmount && !noCommitment ? "overload" : "",
30387
- goalValuePosition: goalValuePosition
30388
- }, !noCommitment ? `$${getFormattedValue(goalAmount, false) + getFormattedUnits(goalAmount)}` : `$${getFormattedValue(currentAmount, false) + getFormattedUnits(currentAmount)}`), !noCommitment && /*#__PURE__*/React__default["default"].createElement(Indicator, {
30389
- top: top
30390
- }, /*#__PURE__*/React__default["default"].createElement(IndicatorLine, {
30391
- color: indicatorColor
30392
- }), /*#__PURE__*/React__default["default"].createElement(IndicatorText, {
30393
- color: indicatorColor
30394
- }, `$${getFormattedValue(currentAmount, false) + getFormattedUnits(currentAmount)}`)), /*#__PURE__*/React__default["default"].createElement(recharts.ResponsiveContainer, {
30395
- height: Math.max(containerHeight - 105, 210)
30396
- }, /*#__PURE__*/React__default["default"].createElement(recharts.BarChart, {
30397
- data: barsChips,
30398
- layout: "vertical",
30875
+ ref: containerRef,
30876
+ style: {
30877
+ cursor: isDragging ? 'grabbing' : 'grab'
30878
+ },
30879
+ backgroundColor: backgroundColor,
30880
+ "data-testid": "bubble-chart-container"
30881
+ }, /*#__PURE__*/React__default["default"].createElement(HeaderContainer, {
30882
+ "data-testid": "header-container"
30883
+ }, /*#__PURE__*/React__default["default"].createElement(ChartTitle, {
30884
+ "data-testid": "chart-title"
30885
+ }, title), /*#__PURE__*/React__default["default"].createElement(ChartSubtitle, {
30886
+ "data-testid": "chart-subtitle"
30887
+ }, subtitle)), /*#__PURE__*/React__default["default"].createElement(ChartContainer, {
30888
+ ref: scatterChartRef,
30889
+ "data-testid": "chart-container"
30890
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.ResponsiveContainer, {
30891
+ width: "100%",
30892
+ height: "100%",
30893
+ "data-testid": "responsive-container"
30894
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.ScatterChart, {
30399
30895
  margin: {
30400
- top: 5,
30401
- right: 5,
30402
- left: 5,
30403
- bottom: 5
30896
+ top: 60,
30897
+ right: 190,
30898
+ bottom: 50,
30899
+ left: 180
30404
30900
  },
30405
- barSize: 4
30406
- }, /*#__PURE__*/React__default["default"].createElement(recharts.XAxis, {
30901
+ "data-testid": "scatter-chart"
30902
+ }, renderGradients(), /*#__PURE__*/React__default["default"].createElement(recharts.XAxis, {
30407
30903
  type: "number",
30408
- hide: true,
30409
- domain: [0, 100]
30904
+ dataKey: "x",
30905
+ domain: viewDomain.x,
30906
+ axisLine: showAxis,
30907
+ tickLine: showAxis,
30908
+ tick: showAxis ? {
30909
+ fontSize: 10,
30910
+ fontWeight: 400,
30911
+ fontFamily: 'Poppins'
30912
+ } : false,
30913
+ tickFormatter: value => formatUnits(value),
30914
+ hide: !showAxis,
30915
+ "data-testid": "x-axis",
30916
+ style: {
30917
+ fontSize: '10px',
30918
+ fontWeight: 400,
30919
+ fontFamily: 'Poppins'
30920
+ }
30410
30921
  }), /*#__PURE__*/React__default["default"].createElement(recharts.YAxis, {
30411
- type: "category",
30412
- hide: true,
30413
- dataKey: "name"
30414
- }), /*#__PURE__*/React__default["default"].createElement(recharts.Bar, {
30415
- dataKey: "value",
30416
- background: {
30417
- fill: "#f3f4f6"
30922
+ type: "number",
30923
+ dataKey: "y",
30924
+ domain: viewDomain.y,
30925
+ axisLine: showAxis,
30926
+ tickLine: showAxis,
30927
+ tick: showAxis ? {
30928
+ fontSize: 10,
30929
+ fontWeight: 400,
30930
+ fontFamily: 'Poppins'
30931
+ } : false,
30932
+ tickFormatter: value => formatUnits(value),
30933
+ hide: !showAxis,
30934
+ "data-testid": "y-axis",
30935
+ style: {
30936
+ fontSize: '10px',
30937
+ fontWeight: 400,
30938
+ fontFamily: 'Poppins'
30939
+ }
30940
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.ZAxis, {
30941
+ type: "number",
30942
+ dataKey: "z",
30943
+ range: [0, 7000],
30944
+ domain: [0, Math.max(...data.map(item => item.size || 0))],
30945
+ "data-testid": "z-axis"
30946
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.ReferenceLine, {
30947
+ x: xMedian,
30948
+ stroke: "#D0D0D0",
30949
+ strokeDasharray: "4 4",
30950
+ isFront: false,
30951
+ "data-testid": "reference-line-x",
30952
+ label: xMedian >= viewDomain.x[0] && xMedian <= viewDomain.x[1] ? {
30953
+ value: topHeader,
30954
+ position: "top",
30955
+ offset: 40,
30956
+ fill: '#484A4C',
30957
+ fontSize: 16,
30958
+ fontWeight: 500
30959
+ } : null
30960
+ }), xMedian >= viewDomain.x[0] && xMedian <= viewDomain.x[1] && /*#__PURE__*/React__default["default"].createElement(recharts.ReferenceLine, {
30961
+ x: xMedian,
30962
+ stroke: "transparent",
30963
+ isFront: true,
30964
+ label: _ref4 => {
30965
+ let {
30966
+ viewBox
30967
+ } = _ref4;
30968
+ return /*#__PURE__*/React__default["default"].createElement(Arrow, {
30969
+ viewBox: viewBox,
30970
+ direction: "top"
30971
+ });
30972
+ }
30973
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.ReferenceLine, {
30974
+ x: xMedian,
30975
+ stroke: "transparent",
30976
+ isFront: false,
30977
+ "data-testid": "reference-line-x-bottom",
30978
+ label: xMedian >= viewDomain.x[0] && xMedian <= viewDomain.x[1] ? {
30979
+ value: bottomHeader,
30980
+ position: "bottom",
30981
+ offset: 30,
30982
+ fill: '#484A4C',
30983
+ fontSize: 16,
30984
+ fontWeight: 500
30985
+ } : null
30986
+ }), xMedian >= viewDomain.x[0] && xMedian <= viewDomain.x[1] && /*#__PURE__*/React__default["default"].createElement(recharts.ReferenceLine, {
30987
+ x: xMedian,
30988
+ stroke: "transparent",
30989
+ isFront: true,
30990
+ label: _ref5 => {
30991
+ let {
30992
+ viewBox
30993
+ } = _ref5;
30994
+ return /*#__PURE__*/React__default["default"].createElement(Arrow, {
30995
+ viewBox: viewBox,
30996
+ direction: "bottom"
30997
+ });
30998
+ }
30999
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.ReferenceLine, {
31000
+ y: yMedian,
31001
+ stroke: "#D0D0D0",
31002
+ strokeDasharray: "4 4",
31003
+ isFront: false,
31004
+ "data-testid": "reference-line-y",
31005
+ label: yMedian >= viewDomain.y[0] && yMedian <= viewDomain.y[1] ? {
31006
+ value: leftHeader,
31007
+ position: "left",
31008
+ offset: 30,
31009
+ fill: '#484A4C',
31010
+ fontSize: 16,
31011
+ fontWeight: 500
31012
+ } : null
31013
+ }), yMedian >= viewDomain.y[0] && yMedian <= viewDomain.y[1] && /*#__PURE__*/React__default["default"].createElement(recharts.ReferenceLine, {
31014
+ y: yMedian,
31015
+ isFront: true,
31016
+ stroke: "transparent",
31017
+ label: _ref6 => {
31018
+ let {
31019
+ viewBox
31020
+ } = _ref6;
31021
+ return /*#__PURE__*/React__default["default"].createElement(Arrow, {
31022
+ viewBox: viewBox,
31023
+ direction: "left"
31024
+ });
31025
+ }
31026
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.ReferenceLine, {
31027
+ y: yMedian,
31028
+ stroke: "transparent",
31029
+ isFront: false,
31030
+ "data-testid": "reference-line-y-transparent",
31031
+ label: yMedian >= viewDomain.y[0] && yMedian <= viewDomain.y[1] ? {
31032
+ value: rightHeader,
31033
+ position: "right",
31034
+ offset: 30,
31035
+ fill: '#484A4C',
31036
+ fontSize: 16,
31037
+ fontWeight: 500
31038
+ } : null
31039
+ }), yMedian >= viewDomain.y[0] && yMedian <= viewDomain.y[1] && /*#__PURE__*/React__default["default"].createElement(recharts.ReferenceLine, {
31040
+ y: yMedian,
31041
+ isFront: true,
31042
+ stroke: "transparent",
31043
+ label: _ref7 => {
31044
+ let {
31045
+ viewBox
31046
+ } = _ref7;
31047
+ return /*#__PURE__*/React__default["default"].createElement(Arrow, {
31048
+ viewBox: viewBox,
31049
+ direction: "right"
31050
+ });
31051
+ }
31052
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.Tooltip, {
31053
+ content: /*#__PURE__*/React__default["default"].createElement(CustomTooltip, null),
31054
+ cursor: false,
31055
+ wrapperStyle: {
31056
+ zIndex: 9999,
31057
+ position: 'absolute',
31058
+ pointerEvents: 'auto'
30418
31059
  },
30419
- radius: [8, 8, 8, 8]
30420
- }, barsChips.map((entry, index) => /*#__PURE__*/React__default["default"].createElement(recharts.Cell, {
30421
- key: `cell-${index}`,
30422
- fill: entry.color
30423
- }))))))), starText !== "" && /*#__PURE__*/React__default["default"].createElement(StarText, null, starText));
31060
+ allowEscapeViewBox: {
31061
+ x: false,
31062
+ y: false
31063
+ },
31064
+ "data-testid": "tooltip"
31065
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.Scatter, {
31066
+ name: "Bubble Chart",
31067
+ data: visibleData,
31068
+ shape: "circle",
31069
+ fill: "transparent",
31070
+ isAnimationActive: false,
31071
+ animationBegin: 0,
31072
+ animationDuration: 0,
31073
+ "data-testid": "scatter"
31074
+ }, visibleData.map((entry, index) => /*#__PURE__*/React__default["default"].createElement(recharts.Cell, {
31075
+ key: entry.key,
31076
+ fill: entry.fill,
31077
+ stroke: "rgba(255,255,255,0.6)",
31078
+ strokeWidth: 1.5,
31079
+ filter: "url(#bubble-blur)",
31080
+ "data-testid": `cell-${index}`
31081
+ }))), isMiddleValueVisible && /*#__PURE__*/React__default["default"].createElement(recharts.ReferenceLine, {
31082
+ x: xMedian,
31083
+ y: yMedian,
31084
+ stroke: "transparent",
31085
+ isFront: true,
31086
+ "data-testid": "middle-value-reference",
31087
+ label: _ref8 => {
31088
+ let {
31089
+ viewBox
31090
+ } = _ref8;
31091
+ // Calculate the exact position of the median point in the SVG
31092
+ const xPos = viewBox.x + (xMedian - viewDomain.x[0]) / (viewDomain.x[1] - viewDomain.x[0]) * viewBox.width;
31093
+ const yPos = viewBox.y + (1 - (yMedian - viewDomain.y[0]) / (viewDomain.y[1] - viewDomain.y[0])) * viewBox.height;
31094
+ return /*#__PURE__*/React__default["default"].createElement("text", {
31095
+ x: xPos,
31096
+ y: yPos,
31097
+ textAnchor: "middle",
31098
+ dominantBaseline: "middle",
31099
+ fill: "#484A4C",
31100
+ fontSize: 16,
31101
+ fontWeight: 600,
31102
+ style: {
31103
+ backgroundColor: 'rgba(255, 255, 255, 0.7)',
31104
+ padding: '2px'
31105
+ }
31106
+ }, formattedMedianValue);
31107
+ }
31108
+ })))), /*#__PURE__*/React__default["default"].createElement(ZoomControlsContainer, {
31109
+ "data-testid": "zoom-controls-container"
31110
+ }, /*#__PURE__*/React__default["default"].createElement(ZoomPercentage, {
31111
+ "data-testid": "zoom-percentage"
31112
+ }, zoomLevel, "%"), /*#__PURE__*/React__default["default"].createElement(ZoomButton, {
31113
+ onClick: handleZoomOut,
31114
+ title: "Zoom Out",
31115
+ "data-testid": "zoom-out-button"
31116
+ }, "\u2212"), /*#__PURE__*/React__default["default"].createElement(ZoomButton, {
31117
+ onClick: handleZoomIn,
31118
+ title: "Zoom In",
31119
+ "data-testid": "zoom-in-button"
31120
+ }, "+"), /*#__PURE__*/React__default["default"].createElement(ZoomResetButton, {
31121
+ onClick: handleReset,
31122
+ "data-testid": "zoom-reset-button"
31123
+ }, "Reset")));
31124
+ };
31125
+
31126
+ const BatteryChartContainer = styled__default["default"].div`
31127
+ position: relative;
31128
+ font-family: "Poppins", sans-serif;
31129
+ display: grid;
31130
+ grid-template-columns: auto auto;
31131
+ grid-template-rows: auto 1fr auto;
31132
+ color: #212121;
31133
+ background-color: ${props => props.backgroundColor || 'transparent'};
31134
+ padding: ${props => props.containerPadding || '25px 30px 0'};
31135
+ width: ${props => props.width};
31136
+ height: ${props => props.height};
31137
+ `;
31138
+ const PanelSide = styled__default["default"].div`
31139
+ display: flex;
31140
+ flex-direction: column;
31141
+ justify-content: space-between;
31142
+ `;
31143
+ const ProgressDetails = styled__default["default"].div`
31144
+ display: flex;
31145
+ flex-direction: column;
31146
+ flex-grow: 1;
31147
+ `;
31148
+ const HeadingText = styled__default["default"].p`
31149
+ grid-column: 1 / span 2;
31150
+ color: #212121;
31151
+ font-size: 18px;
31152
+ font-weight: 400;
31153
+ padding-left: 10px;
31154
+ margin: 0 0 8px;
31155
+ `;
31156
+ const HeadingPercentage = styled__default["default"].p`
31157
+ color: #212121;
31158
+ font-size: 32px;
31159
+ font-weight: 500;
31160
+ padding-left: 10px;
31161
+ margin: 0;
31162
+ `;
31163
+ const ChartSide = styled__default["default"].div`
31164
+ text-align: center;
31165
+ `;
31166
+ const ChartWrapper = styled__default["default"].div`
31167
+ position: relative;
31168
+ width: 110px;
31169
+ `;
31170
+ const GoalValue = styled__default["default"].div`
31171
+ text-align: center;
31172
+ font-size: 18px;
31173
+ color: #8B8989;
31174
+ line-height: 1;
31175
+ &.overload {
31176
+ position: absolute;
31177
+ top: ${props => props.goalValuePosition}px;
31178
+ left: 0;
31179
+ right: 0;
31180
+ z-index: 2;
31181
+ margin: 0 auto;
31182
+ width: 40%;
31183
+ display: inline;
31184
+ padding: 0px 8px;
31185
+ border: 2px solid #F2F2F2;
31186
+ border-bottom: none;
31187
+ border-radius: 6px 6px 0px 0px;
31188
+ background-color: white;
31189
+ }
31190
+ `;
31191
+ const Indicator = styled__default["default"].div`
31192
+ position: absolute;
31193
+ top: ${props => props.top}px;
31194
+ left: 0;
31195
+ transform: translateY(50%);
31196
+ width: calc(100% + 60px);
31197
+ display: flex;
31198
+ gap: 6px;
31199
+ justify-content: center;
31200
+ padding-left: 4px;
31201
+ align-items: center;
31202
+ z-index: 1;
31203
+ `;
31204
+ const IndicatorLine = styled__default["default"].div`
31205
+ width: 100%;
31206
+ height: 0;
31207
+ border-top: 4px dashed ${props => props.color};
31208
+ `;
31209
+ const IndicatorText = styled__default["default"].span`
31210
+ font-size: 18px;
31211
+ font-weight: 400;
31212
+ color: ${props => props.color};
31213
+ `;
31214
+ const ProgressLegend = styled__default["default"].div`
31215
+ margin-top: 12px;
31216
+ `;
31217
+ const LegendItem = styled__default["default"].div`
31218
+ display: flex;
31219
+ gap: 4px;
31220
+ align-items: center;
31221
+ margin-bottom: 12px;
31222
+ `;
31223
+ const LegendText = styled__default["default"].span`
31224
+ color: #8B8989;
31225
+ font-size: 14px;
31226
+ `;
31227
+ const LegendCube = styled__default["default"].div`
31228
+ border-radius: 3px;
31229
+ width: 17px;
31230
+ height: 17px;
31231
+ background-color: ${props => props.color};
31232
+ `;
31233
+ const ProgressDescription = styled__default["default"].div`
31234
+ color: #8B8989;
31235
+ font-size: 12px;
31236
+ font-weight: 400;
31237
+ margin-top: auto;
31238
+ `;
31239
+ const ProgressItem = styled__default["default"].p`
31240
+ margin: 0 0 6px;
31241
+ `;
31242
+ const StarText = styled__default["default"].span`
31243
+ width: 100%;
31244
+ color: #B1B1B1;
31245
+ font-size: 9px;
31246
+ grid-column: 1 / span 2;
31247
+ padding-top: 10px;
31248
+ `;
31249
+
31250
+ const BatteryChart = props => {
31251
+ const {
31252
+ className,
31253
+ containerPadding,
31254
+ width,
31255
+ height,
31256
+ title,
31257
+ color,
31258
+ backgroundColor,
31259
+ indicatorColor,
31260
+ noCommitment,
31261
+ goalAmount,
31262
+ currentAmount,
31263
+ ask,
31264
+ target,
31265
+ totalSegmentsLines,
31266
+ starText
31267
+ } = props;
31268
+ const [top, setTop] = React$1.useState(0);
31269
+ const [goalValuePosition, setGoalValuePosition] = React$1.useState(0);
31270
+ const [containerHeight, setContainerHeight] = React$1.useState(0); // State to store container height
31271
+ const containerRef = React$1.useRef(null); // Ref for BatteryChartContainer
31272
+
31273
+ // Calculate the percentage and completed segments
31274
+ const percentage = Math.round(currentAmount / goalAmount * 100);
31275
+ const completedSegments = Math.min(Math.floor(currentAmount / goalAmount * totalSegmentsLines), totalSegmentsLines);
31276
+
31277
+ // Dynamically create the data for the bar chart
31278
+ let barsChips = Array.from({
31279
+ length: totalSegmentsLines
31280
+ }).map((_, index) => ({
31281
+ name: `segment-${index}`,
31282
+ value: 100,
31283
+ isCompleted: index >= totalSegmentsLines - completedSegments,
31284
+ // Fill from bottom up
31285
+ color: index >= totalSegmentsLines - completedSegments ? color : "#e5e7eb" // Completed or remaining color
31286
+ }));
31287
+
31288
+ // Add 4 extra chips if currentAmount > goalAmount
31289
+ if (currentAmount > goalAmount && !noCommitment) {
31290
+ const extraSegments = 4;
31291
+ const extraData = Array.from({
31292
+ length: extraSegments
31293
+ }).map((_, index) => ({
31294
+ name: `extra-segment-${index}`,
31295
+ value: 100,
31296
+ isCompleted: true,
31297
+ color: "#E8F5EB"
31298
+ }));
31299
+
31300
+ // Prepend the extra segments to the barsChips array
31301
+ barsChips = [...extraData, ...barsChips];
31302
+ }
31303
+
31304
+ // Calculate the top position for the indicator and goal value
31305
+ React$1.useEffect(() => {
31306
+ const barHeight = containerHeight / (totalSegmentsLines + (currentAmount > goalAmount ? 4 : 0)); // Adjust for extra chips
31307
+ let newTop;
31308
+ let newGoalValuePosition;
31309
+ if (currentAmount > goalAmount) {
31310
+ // Position the indicator slightly below the top chip
31311
+ newTop = barHeight * 1.5; // Slightly below the 4th chip
31312
+ // Position the goal value just above the active chips
31313
+
31314
+ newGoalValuePosition = barHeight * 2.3;
31315
+ // newGoalValuePosition = (totalSegmentsLines - completedSegments + 4) * barHeight - barHeight / 2;
31316
+ } else {
31317
+ // Normal case: position the indicator above the active chips
31318
+ newTop = (totalSegmentsLines - completedSegments) * barHeight / 1.65;
31319
+ // Position the goal value just above the active chips
31320
+ newGoalValuePosition = newTop;
31321
+ }
31322
+ setTop(newTop);
31323
+ setGoalValuePosition(newGoalValuePosition);
31324
+ }, [completedSegments, totalSegmentsLines, currentAmount, goalAmount, containerHeight]);
31325
+ React$1.useEffect(() => {
31326
+ if (containerRef.current) {
31327
+ const height = containerRef.current.offsetHeight;
31328
+ if (height > 0) {
31329
+ setContainerHeight(height);
31330
+ }
31331
+ }
31332
+ }, [containerRef, width, height]);
31333
+ return /*#__PURE__*/React__default["default"].createElement(BatteryChartContainer, {
31334
+ ref: containerRef,
31335
+ width: width,
31336
+ height: height,
31337
+ className: className,
31338
+ containerPadding: containerPadding,
31339
+ backgroundColor: backgroundColor
31340
+ }, /*#__PURE__*/React__default["default"].createElement(HeadingText, null, title), /*#__PURE__*/React__default["default"].createElement(PanelSide, null, /*#__PURE__*/React__default["default"].createElement(ProgressDetails, null, !noCommitment && /*#__PURE__*/React__default["default"].createElement(HeadingPercentage, null, percentage, "%"), /*#__PURE__*/React__default["default"].createElement(ProgressDescription, null, ask && /*#__PURE__*/React__default["default"].createElement(ProgressItem, null, "ASK: ", `$${getFormattedValue(ask, false) + getFormattedUnits(ask)}`), target && /*#__PURE__*/React__default["default"].createElement(ProgressItem, null, "Target: ", `$${getFormattedValue(target, false) + getFormattedUnits(target)}`)), /*#__PURE__*/React__default["default"].createElement(ProgressLegend, null, /*#__PURE__*/React__default["default"].createElement(LegendItem, null, /*#__PURE__*/React__default["default"].createElement(LegendCube, {
31341
+ color: color
31342
+ }), /*#__PURE__*/React__default["default"].createElement(LegendText, null, "Spend")), !noCommitment && /*#__PURE__*/React__default["default"].createElement(LegendItem, null, /*#__PURE__*/React__default["default"].createElement(LegendCube, {
31343
+ color: "#E3E4E5"
31344
+ }), /*#__PURE__*/React__default["default"].createElement(LegendText, null, "Commitment"))))), /*#__PURE__*/React__default["default"].createElement(ChartSide, null, /*#__PURE__*/React__default["default"].createElement(ChartWrapper, null, /*#__PURE__*/React__default["default"].createElement(GoalValue, {
31345
+ className: currentAmount > goalAmount && !noCommitment ? "overload" : "",
31346
+ goalValuePosition: goalValuePosition
31347
+ }, !noCommitment ? `$${getFormattedValue(goalAmount, false) + getFormattedUnits(goalAmount)}` : `$${getFormattedValue(currentAmount, false) + getFormattedUnits(currentAmount)}`), !noCommitment && /*#__PURE__*/React__default["default"].createElement(Indicator, {
31348
+ top: top
31349
+ }, /*#__PURE__*/React__default["default"].createElement(IndicatorLine, {
31350
+ color: indicatorColor
31351
+ }), /*#__PURE__*/React__default["default"].createElement(IndicatorText, {
31352
+ color: indicatorColor
31353
+ }, `$${getFormattedValue(currentAmount, false) + getFormattedUnits(currentAmount)}`)), /*#__PURE__*/React__default["default"].createElement(recharts.ResponsiveContainer, {
31354
+ height: Math.max(containerHeight - 105, 210)
31355
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.BarChart, {
31356
+ data: barsChips,
31357
+ layout: "vertical",
31358
+ margin: {
31359
+ top: 5,
31360
+ right: 5,
31361
+ left: 5,
31362
+ bottom: 5
31363
+ },
31364
+ barSize: 4
31365
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.XAxis, {
31366
+ type: "number",
31367
+ hide: true,
31368
+ domain: [0, 100]
31369
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.YAxis, {
31370
+ type: "category",
31371
+ hide: true,
31372
+ dataKey: "name"
31373
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.Bar, {
31374
+ dataKey: "value",
31375
+ background: {
31376
+ fill: "#f3f4f6"
31377
+ },
31378
+ radius: [8, 8, 8, 8]
31379
+ }, barsChips.map((entry, index) => /*#__PURE__*/React__default["default"].createElement(recharts.Cell, {
31380
+ key: `cell-${index}`,
31381
+ fill: entry.color
31382
+ }))))))), starText !== "" && /*#__PURE__*/React__default["default"].createElement(StarText, null, starText));
31383
+ };
31384
+
31385
+ const originalData$1 = [{
31386
+ label: "Vendor Selling Event: Week 28",
31387
+ inc_unit: 20000,
31388
+ inc_roi: 1.2
31389
+ }, {
31390
+ label: "Vendor Selling Event: Week 29",
31391
+ inc_unit: 10000,
31392
+ inc_roi: 1.2
31393
+ }, {
31394
+ label: "Vendor Selling Event: Week 30",
31395
+ inc_unit: 8000,
31396
+ inc_roi: 0.8
31397
+ }, {
31398
+ label: "Vendor Selling Event: Week 33",
31399
+ inc_unit: 12000,
31400
+ inc_roi: 1.1
31401
+ }, {
31402
+ label: "Vendor Selling Event: Week 36",
31403
+ inc_unit: 8000,
31404
+ inc_roi: 1.2
31405
+ }, {
31406
+ label: "Vendor Selling Event: Week 34",
31407
+ inc_unit: 8000,
31408
+ inc_roi: 0.7
31409
+ }, {
31410
+ label: "Vendor Selling Event: Week 35",
31411
+ inc_unit: 8000,
31412
+ inc_roi: 0.8
31413
+ }, {
31414
+ label: "Vendor Selling Event: Week 38",
31415
+ inc_unit: 9000,
31416
+ inc_roi: 1.1
31417
+ }];
31418
+ const dataWithIndex$1 = originalData$1.map((item, index) => ({
31419
+ ...item,
31420
+ index,
31421
+ shortLabel: item.label.replace("Vendor Selling Event: ", "Wk ")
31422
+ }));
31423
+ const CustomizedTick$1 = ({
31424
+ x,
31425
+ y,
31426
+ payload
31427
+ }) => {
31428
+ const label = dataWithIndex$1[payload.value]?.label ?? "";
31429
+ const parts = label.replace("Vendor Selling Event: ", "").split(" ");
31430
+ return /*#__PURE__*/React__default["default"].createElement("g", {
31431
+ transform: `translate(${x},${y})`
31432
+ }, /*#__PURE__*/React__default["default"].createElement("text", {
31433
+ x: 0,
31434
+ y: 0,
31435
+ dy: 16,
31436
+ textAnchor: "middle",
31437
+ fill: "#212121",
31438
+ fontSize: 11,
31439
+ fontWeight: "400",
31440
+ fontFamily: "Poppins"
31441
+ }, /*#__PURE__*/React__default["default"].createElement("tspan", {
31442
+ x: 0,
31443
+ dy: 8
31444
+ }, "Vendor Selling"), /*#__PURE__*/React__default["default"].createElement("tspan", {
31445
+ x: 0,
31446
+ dy: 18
31447
+ }, "Event: ", parts.join(" "))));
31448
+ };
31449
+
31450
+ // Common chart configuration
31451
+ const chartMargins = {
31452
+ top: 15,
31453
+ right: 40,
31454
+ left: 20,
31455
+ bottom: 40
31456
+ };
31457
+ const SeparatedLineBarChart = () => {
31458
+ const [viewWindow, setViewWindow] = React$1.useState({
31459
+ startIndex: 0,
31460
+ endIndex: dataWithIndex$1.length - 1
31461
+ });
31462
+ return /*#__PURE__*/React__default["default"].createElement("div", {
31463
+ style: {
31464
+ width: "100%",
31465
+ height: 700
31466
+ }
31467
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
31468
+ style: {
31469
+ height: "40%"
31470
+ }
31471
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.ResponsiveContainer, {
31472
+ width: "100%",
31473
+ height: "100%"
31474
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.LineChart, {
31475
+ data: dataWithIndex$1 // Use full dataset for alignment
31476
+ ,
31477
+ margin: chartMargins
31478
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.CartesianGrid, {
31479
+ strokeDasharray: "3 3",
31480
+ vertical: false
31481
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.XAxis, {
31482
+ dataKey: "index",
31483
+ type: "number",
31484
+ domain: ['dataMin', 'dataMax'],
31485
+ padding: {
31486
+ left: 20,
31487
+ right: 20
31488
+ },
31489
+ hide: true
31490
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.YAxis, {
31491
+ domain: [0, 2],
31492
+ hide: true
31493
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.Tooltip, null), /*#__PURE__*/React__default["default"].createElement(recharts.Line, {
31494
+ type: "monotone",
31495
+ dataKey: "inc_roi",
31496
+ stroke: "#F8CD00",
31497
+ strokeWidth: 2,
31498
+ dot: {
31499
+ r: 4,
31500
+ fill: "#F8CD00"
31501
+ },
31502
+ activeDot: false,
31503
+ name: "INC Sales ROI"
31504
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.LabelList, {
31505
+ dataKey: "inc_roi",
31506
+ position: "top",
31507
+ formatter: value => value.toFixed(1)
31508
+ }))))), /*#__PURE__*/React__default["default"].createElement("div", {
31509
+ style: {
31510
+ height: "60%"
31511
+ }
31512
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.ResponsiveContainer, {
31513
+ width: "100%",
31514
+ height: "100%"
31515
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.ComposedChart, {
31516
+ data: dataWithIndex$1,
31517
+ margin: chartMargins
31518
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.CartesianGrid, {
31519
+ strokeDasharray: "3 3",
31520
+ vertical: false
31521
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.XAxis, {
31522
+ dataKey: "index",
31523
+ type: "number",
31524
+ domain: ['dataMin', 'dataMax'],
31525
+ padding: {
31526
+ left: 20,
31527
+ right: 20
31528
+ },
31529
+ tick: /*#__PURE__*/React__default["default"].createElement(CustomizedTick$1, null),
31530
+ interval: 0 // Force display all ticks
31531
+ ,
31532
+ height: 60,
31533
+ tickLine: false,
31534
+ ticks: dataWithIndex$1.map(item => item.index)
31535
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.YAxis, {
31536
+ tickFormatter: v => `$${v / 1000}k`,
31537
+ hide: true
31538
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.Tooltip, null), /*#__PURE__*/React__default["default"].createElement(recharts.Bar, {
31539
+ dataKey: "inc_unit",
31540
+ fill: "#CCDCDD",
31541
+ gap: "4px",
31542
+ borderRadius: [4, 4, 0, 8],
31543
+ barSize: 40,
31544
+ name: "INC Sales"
31545
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.LabelList, {
31546
+ dataKey: "inc_unit",
31547
+ position: "top",
31548
+ formatter: value => `$${value / 1000}k`,
31549
+ fill: "#212121",
31550
+ fontSize: 12,
31551
+ fontWeight: "400",
31552
+ fontFamily: "Poppins"
31553
+ })), /*#__PURE__*/React__default["default"].createElement(recharts.Brush, {
31554
+ dataKey: "index",
31555
+ height: 30,
31556
+ stroke: "#212121",
31557
+ startIndex: viewWindow.startIndex,
31558
+ endIndex: viewWindow.endIndex,
31559
+ onChange: e => {
31560
+ setViewWindow({
31561
+ startIndex: e.startIndex ?? 0,
31562
+ endIndex: e.endIndex ?? dataWithIndex$1.length - 1
31563
+ });
31564
+ },
31565
+ travellerWidth: 12
31566
+ })), /*#__PURE__*/React__default["default"].createElement("div", {
31567
+ style: {
31568
+ marginTop: "-28px"
31569
+ }
31570
+ }, /*#__PURE__*/React__default["default"].createElement(PerformanceAnalyticsLegend, {
31571
+ legendData: [{
31572
+ iconColor: "#CCDCDD",
31573
+ iconType: "Square",
31574
+ title: "INC Sales"
31575
+ }, {
31576
+ iconColor: "#F8CD00",
31577
+ iconType: "LegendUnionIcon",
31578
+ title: "INC Sales ROI"
31579
+ }]
31580
+ })))));
31581
+ };
31582
+
31583
+ const originalData = [{
31584
+ label: "Vendor Selling Event: Week 28",
31585
+ inc_unit: 20000
31586
+ }, {
31587
+ label: "Vendor Selling Event: Week 29",
31588
+ inc_unit: 10000
31589
+ }, {
31590
+ label: "Vendor Selling Event: Week 30",
31591
+ inc_unit: 8000
31592
+ }, {
31593
+ label: "Vendor Selling Event: Week 33",
31594
+ inc_unit: 12000
31595
+ }, {
31596
+ label: "Vendor Selling Event: Week 36",
31597
+ inc_unit: 8000
31598
+ }, {
31599
+ label: "Vendor Selling Event: Week 34",
31600
+ inc_unit: 8000
31601
+ }, {
31602
+ label: "Vendor Selling Event: Week 35",
31603
+ inc_unit: 8000
31604
+ }, {
31605
+ label: "Vendor Selling Event: Week 38",
31606
+ inc_unit: 9000
31607
+ }];
31608
+
31609
+ // Adding index and shortLabel to original data
31610
+ const dataWithIndex = originalData.map((item, index) => ({
31611
+ ...item,
31612
+ index,
31613
+ shortLabel: item.label.replace("Vendor Selling Event: ", "Wk ")
31614
+ }));
31615
+ const CustomizedTick = ({
31616
+ x,
31617
+ y,
31618
+ payload
31619
+ }) => {
31620
+ const label = dataWithIndex[payload.value]?.label ?? "";
31621
+ const parts = label.replace("Vendor Selling Event: ", "").split(" ");
31622
+ return /*#__PURE__*/React__default["default"].createElement("g", {
31623
+ transform: `translate(${x},${y})`
31624
+ }, /*#__PURE__*/React__default["default"].createElement("text", {
31625
+ x: 0,
31626
+ y: 0,
31627
+ dy: 16,
31628
+ textAnchor: "middle",
31629
+ fill: "#212121",
31630
+ fontSize: 11,
31631
+ fontWeight: "400",
31632
+ fontFamily: "Poppins"
31633
+ }, /*#__PURE__*/React__default["default"].createElement("tspan", {
31634
+ x: 0,
31635
+ dy: 8
31636
+ }, "Vendor Selling"), /*#__PURE__*/React__default["default"].createElement("tspan", {
31637
+ x: 0,
31638
+ dy: 18
31639
+ }, "Event: ", parts.join(" "))));
31640
+ };
31641
+ const SingleChart = () => {
31642
+ const [startIndex, setStartIndex] = React$1.useState(0);
31643
+ const [endIndex, setEndIndex] = React$1.useState(dataWithIndex.length - 1);
31644
+ dataWithIndex.slice(startIndex, endIndex + 1);
31645
+ return /*#__PURE__*/React__default["default"].createElement("div", {
31646
+ style: {
31647
+ width: "100%",
31648
+ height: 600
31649
+ }
31650
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
31651
+ style: {
31652
+ height: "100%"
31653
+ }
31654
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.ResponsiveContainer, {
31655
+ width: "100%",
31656
+ height: "100%"
31657
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.ComposedChart, {
31658
+ data: dataWithIndex,
31659
+ margin: {
31660
+ top: 40,
31661
+ right: 40,
31662
+ left: 20,
31663
+ bottom: 40
31664
+ }
31665
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.CartesianGrid, {
31666
+ strokeDasharray: "3 3",
31667
+ vertical: false
31668
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.XAxis, {
31669
+ dataKey: "index",
31670
+ tick: /*#__PURE__*/React__default["default"].createElement(CustomizedTick, null),
31671
+ interval: 0,
31672
+ height: 60,
31673
+ padding: {
31674
+ left: 20,
31675
+ right: 20
31676
+ },
31677
+ tickLine: false
31678
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.YAxis, {
31679
+ tickFormatter: v => `$${v / 1000}k`,
31680
+ hide: true
31681
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.Tooltip, null), /*#__PURE__*/React__default["default"].createElement(recharts.Bar, {
31682
+ dataKey: "inc_unit",
31683
+ fill: "#CCDCDD",
31684
+ gap: "4px",
31685
+ borderRadius: [4, 4, 0, 8],
31686
+ barSize: 40,
31687
+ name: "INC Sales"
31688
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.LabelList, {
31689
+ dataKey: "inc_unit",
31690
+ position: "top",
31691
+ formatter: value => `$${value / 1000}k`,
31692
+ fill: "#212121",
31693
+ fontSize: 12,
31694
+ fontWeight: "400",
31695
+ fontFamily: "Poppins"
31696
+ })), /*#__PURE__*/React__default["default"].createElement(recharts.Brush, {
31697
+ dataKey: "index",
31698
+ height: 30,
31699
+ stroke: "#212121",
31700
+ startIndex: startIndex,
31701
+ endIndex: endIndex,
31702
+ onChange: e => {
31703
+ setStartIndex(e.startIndex ?? 0);
31704
+ setEndIndex(e.endIndex ?? dataWithIndex.length - 1);
31705
+ },
31706
+ travellerWidth: 12
31707
+ })), /*#__PURE__*/React__default["default"].createElement(PerformanceAnalyticsLegend, {
31708
+ legendData: [{
31709
+ iconColor: "#CCDCDD",
31710
+ iconType: "Square",
31711
+ title: "INC Units"
31712
+ }]
31713
+ }))));
31714
+ };
31715
+
31716
+ styled__default["default"].div`
31717
+ display: flex;
31718
+ gap: 28px;
31719
+ @media (max-width: 1536px) {
31720
+ gap: 20px;
31721
+ }
31722
+ @media (max-width: 1366px) {
31723
+ gap: 17px;
31724
+ }
31725
+ `;
31726
+ const ButtonsControlsContainer = styled__default["default"].div`
31727
+ display: flex;
31728
+ font: ${props => props.fontSize?.toString().concat('', 'px Poppins, sans-serif')};
31729
+ margin: 0;
31730
+ --highlight-width: auto;
31731
+ --highlight-x-pos: 0;
31732
+ -webkit-font-smoothing: antialiased;
31733
+ -moz-osx-font-smoothing: grayscale;
31734
+ float: left;
31735
+
31736
+ &:not(:first-of-type) {
31737
+ padding-left: 40px;
31738
+ @media (max-width: 1536px) {
31739
+ padding-left: 35px;
31740
+ }
31741
+ @media (max-width: 1366px) {
31742
+ padding-left: 24px;
31743
+ }
31744
+ }
31745
+ `;
31746
+ const Controls = styled__default["default"].div`
31747
+ display: inline-flex;
31748
+ justify-content: space-between;
31749
+ background: #f2f2f2;
31750
+ border-radius: ${props => props.controlradius.toString().concat('', 'px')}; //12px
31751
+ // max-width: 500px; //use this to limit max lenght of the control
31752
+ padding: 6px;
31753
+ gap: ${props => props.gap};
31754
+ overflow: hidden;
31755
+ position: relative;
31756
+ &.controls::before {
31757
+ content: "";
31758
+ color: #212121;
31759
+ background: #FFFFFF;
31760
+ box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
31761
+ border-radius: ${props => props.segmentradius.toString().concat('', 'px')};
31762
+ width: var(--highlight-width);
31763
+ transform: translateX(var(--highlight-x-pos));
31764
+ position: absolute;
31765
+ top: 3px;
31766
+ bottom: 3px;
31767
+ left: 0;
31768
+ z-index: 0;
31769
+ }
31770
+ &.controls.ready::before {
31771
+ transition: transform 0.3s ease, width 0.3s ease;
31772
+ }
31773
+ `;
31774
+ const ControlsInput = styled__default["default"].input`
31775
+ opacity: 0;
31776
+ margin: 0;
31777
+ top: 0;
31778
+ right: 0;
31779
+ bottom: 0;
31780
+ left: 0;
31781
+ position: absolute;
31782
+ width: 100%;
31783
+ cursor: pointer;
31784
+ height: 100%;
31785
+ `;
31786
+ const Segment = styled__default["default"].div`
31787
+ /* width: 100%; uncomment for each segment to have matching width */
31788
+ width: 50%;
31789
+ min-width: ${props => props.segmentwidth.toString().concat('', 'px')}; //120px;
31790
+ position: relative;
31791
+ text-align: center;
31792
+ z-index: 1;
31793
+ `;
31794
+ const SegmentLabel = styled__default["default"].label`
31795
+ cursor: pointer;
31796
+ display: block;
31797
+ padding: 0 6px;
31798
+ transition: color 0.5s ease;
31799
+ &.active {
31800
+ color: ${props => props.selectedtextcolor};
31801
+ }
31802
+ &.inactive {
31803
+ color: ${props => props.unselectedtextcolor};
31804
+ }
31805
+ `;
31806
+
31807
+ /* eslint-disable react/require-default-props */
31808
+
31809
+ /* SegmentedButton */
31810
+ const SegmentedButton = props => {
31811
+ const {
31812
+ name,
31813
+ options,
31814
+ width,
31815
+ height,
31816
+ controlradius,
31817
+ segmentradius,
31818
+ fontSize,
31819
+ selectedsegmentcolor,
31820
+ selectedtextcolor,
31821
+ unselectedtextcolor,
31822
+ defaultIndex,
31823
+ onClick,
31824
+ gap
31825
+ } = props;
31826
+ const [activeIndex, setActiveIndex] = React$1.useState(defaultIndex);
31827
+ const controlRef = React$1.useRef();
31828
+ const componentReady = React$1.useRef();
31829
+ const optionsRef = options?.map((item, i) => ({
31830
+ ...item,
31831
+ id: i,
31832
+ ref: React$1.useRef()
31833
+ }));
31834
+
31835
+ // Determine when the component is "ready"
31836
+ React$1.useEffect(() => {
31837
+ componentReady.current = true;
31838
+ }, []);
31839
+ React$1.useEffect(() => {
31840
+ if (defaultIndex >= 0 && defaultIndex < options?.length) {
31841
+ setActiveIndex(defaultIndex);
31842
+ }
31843
+ }, [defaultIndex]);
31844
+ React$1.useEffect(() => {
31845
+ const activeSegmentRef = optionsRef[activeIndex].ref;
31846
+ const {
31847
+ offsetWidth,
31848
+ offsetLeft
31849
+ } = activeSegmentRef.current;
31850
+ const {
31851
+ style
31852
+ } = controlRef.current;
31853
+ style.setProperty('--highlight-width', `${offsetWidth}px`);
31854
+ style.setProperty('--highlight-x-pos', `${offsetLeft}px`);
31855
+ }, [activeIndex, controlRef, optionsRef]);
31856
+ const onInputChangeHandler = (value, index) => {
31857
+ setActiveIndex(index);
31858
+ onClick({
31859
+ index,
31860
+ value
31861
+ });
31862
+ };
31863
+ let segmentwidth = 120;
31864
+ if (options && options.length > 0 && width && width > 0) {
31865
+ segmentwidth = width / options.length;
31866
+ }
31867
+ return /*#__PURE__*/React__default["default"].createElement(ButtonsControlsContainer, {
31868
+ fontSize: fontSize,
31869
+ ref: controlRef
31870
+ }, /*#__PURE__*/React__default["default"].createElement(Controls, {
31871
+ id: "Controls",
31872
+ selectedsegmentcolor: selectedsegmentcolor,
31873
+ segmentradius: segmentradius,
31874
+ gap: gap,
31875
+ controlradius: controlradius,
31876
+ segmentwidth: segmentwidth,
31877
+ className: `controls ${componentReady.current ? 'ready' : 'idle'}`
31878
+ }, optionsRef?.map((item, i) => /*#__PURE__*/React__default["default"].createElement(Segment, {
31879
+ id: "Segment",
31880
+ key: item.id,
31881
+ selectedsegmentcolor: selectedsegmentcolor,
31882
+ controlradius: controlradius,
31883
+ segmentwidth: segmentwidth,
31884
+ className: `${activeIndex === i ? 'active' : 'inactive'}`,
31885
+ ref: item.ref
31886
+ }, /*#__PURE__*/React__default["default"].createElement(ControlsInput, {
31887
+ type: "radio",
31888
+ value: item.value,
31889
+ id: item.id,
31890
+ name: name,
31891
+ onChange: () => onInputChangeHandler(item.value, item.id),
31892
+ checked: i === activeIndex
31893
+ }), /*#__PURE__*/React__default["default"].createElement(SegmentLabel, {
31894
+ id: "SegmentLabel",
31895
+ selectedtextcolor: selectedtextcolor,
31896
+ unselectedtextcolor: unselectedtextcolor,
31897
+ segmentheight: height / 5,
31898
+ className: `${activeIndex === i ? 'active' : 'inactive'} `,
31899
+ htmlFor: item.value
31900
+ }, item.value)))));
31901
+ };
31902
+ SegmentedButton.propTypes = {
31903
+ name: PropTypes.string,
31904
+ options: PropTypes.arrayOf(PropTypes.shape({
31905
+ value: PropTypes.string
31906
+ })),
31907
+ width: PropTypes.number,
31908
+ height: PropTypes.number,
31909
+ controlradius: PropTypes.number,
31910
+ segmentradius: PropTypes.number,
31911
+ gap: PropTypes.string,
31912
+ fontSize: PropTypes.number,
31913
+ selectedsegmentcolor: PropTypes.string,
31914
+ selectedtextcolor: PropTypes.string,
31915
+ unselectedtextcolor: PropTypes.string,
31916
+ defaultIndex: PropTypes.number,
31917
+ onClick: PropTypes.func
31918
+ };
31919
+ SegmentedButton.defaultProps = {
31920
+ name: '',
31921
+ options: [{
31922
+ value: '4 w'
31923
+ }, {
31924
+ value: '8 w'
31925
+ }, {
31926
+ value: '13 w'
31927
+ }],
31928
+ width: 120,
31929
+ height: 40,
31930
+ controlradius: 8,
31931
+ segmentradius: 8,
31932
+ gap: '0px',
31933
+ fontSize: 14,
31934
+ selectedsegmentcolor: '#3a9df9',
31935
+ selectedtextcolor: '#212121',
31936
+ unselectedtextcolor: 'black',
31937
+ defaultIndex: 0,
31938
+ onClick: () => {}
31939
+ };
31940
+
31941
+ var css_248z = ".BarLine {\r\n font-family: sans-serif;\r\n text-align: center;\r\n }\r\n \r\n /* Make brush background darker */\r\n /* .recharts-brush .recharts-brush-slide {\r\n fill: #a52a2a !important;\r\n stroke: none;\r\n }\r\n \r\n /* Style draggable handles (travellers) */\r\n /* .recharts-brush-traveller {\r\n fill: limegreen !important; /* bright green like in the image */\r\n /* cursor: ew-resize;\r\n } */\r\n */\r\n \r\n /* Optional: center grip arrows (you can fake it with CSS) */\r\n /* .recharts-brush .recharts-brush-traveller > rect {\r\n rx: 2;\r\n ry: 2;\r\n width: 6;\r\n fill: #a52a2a !important; /* dark gray */\r\n /* } */ */\r\n */\r\n \r\n /* Remove tick labels if needed */\r\n .recharts-brush .recharts-layer text {\r\n display: none;\r\n }\r\n ";
31942
+ styleInject(css_248z);
31943
+
31944
+ function InnerBarChart() {
31945
+ const data = [{
31946
+ week: "Week 28",
31947
+ total: 20000,
31948
+ actual: 4000
31949
+ }, {
31950
+ week: "Week 29",
31951
+ total: 10000,
31952
+ actual: 8000
31953
+ }, {
31954
+ week: "Week 30",
31955
+ total: 8000,
31956
+ actual: 950
31957
+ }, {
31958
+ week: "Week 33",
31959
+ total: 12000,
31960
+ actual: 1000
31961
+ }, {
31962
+ week: "Week 36",
31963
+ total: 16000,
31964
+ actual: 13000
31965
+ }, {
31966
+ week: "Week 34",
31967
+ total: 30000,
31968
+ actual: 3000
31969
+ }, {
31970
+ week: "Week 35",
31971
+ total: 8000,
31972
+ actual: 950
31973
+ }, {
31974
+ week: "Week 37",
31975
+ total: 9000,
31976
+ actual: 3000
31977
+ }];
31978
+ const originalData = [{
31979
+ label: "Vendor Selling Event: Week 28",
31980
+ inc_unit: 20000,
31981
+ inc_roi: 1.2
31982
+ }, {
31983
+ label: "Vendor Selling Event: Week 29",
31984
+ inc_unit: 10000,
31985
+ inc_roi: 1.2
31986
+ }, {
31987
+ label: "Vendor Selling Event: Week 30",
31988
+ inc_unit: 8000,
31989
+ inc_roi: 0.8
31990
+ }, {
31991
+ label: "Vendor Selling Event: Week 33",
31992
+ inc_unit: 12000,
31993
+ inc_roi: 1.1
31994
+ }, {
31995
+ label: "Vendor Selling Event: Week 36",
31996
+ inc_unit: 8000,
31997
+ inc_roi: 1.2
31998
+ }, {
31999
+ label: "Vendor Selling Event: Week 34",
32000
+ inc_unit: 8000,
32001
+ inc_roi: 0.7
32002
+ }, {
32003
+ label: "Vendor Selling Event: Week 35",
32004
+ inc_unit: 8000,
32005
+ inc_roi: 0.8
32006
+ }, {
32007
+ label: "Vendor Selling Event: Week 38",
32008
+ inc_unit: 9000,
32009
+ inc_roi: 1.1
32010
+ }];
32011
+ const format = v => v >= 1000 ? `${v / 1000}K` : v;
32012
+ const CustomBarLabel = ({
32013
+ x,
32014
+ y,
32015
+ width,
32016
+ payload
32017
+ }) => {
32018
+ if (!payload || typeof payload.total === "undefined") {
32019
+ console.error("Invalid payload:", payload);
32020
+ return null;
32021
+ }
32022
+ const centerX = x + width / 2;
32023
+ return /*#__PURE__*/React__default["default"].createElement("text", {
32024
+ x: centerX,
32025
+ y: Math.max(y - 8, 10),
32026
+ textAnchor: "middle",
32027
+ fill: "black"
32028
+ }, format(payload.total));
32029
+ };
32030
+ const BarWithInner = props => {
32031
+ const {
32032
+ x,
32033
+ y,
32034
+ width,
32035
+ height,
32036
+ payload
32037
+ } = props;
32038
+ const totalHeight = height;
32039
+ const actualRatio = payload.actual / payload.total;
32040
+ const innerHeight = totalHeight * actualRatio;
32041
+ const innerY = y + (totalHeight - innerHeight);
32042
+ return /*#__PURE__*/React__default["default"].createElement("g", null, /*#__PURE__*/React__default["default"].createElement("rect", {
32043
+ x: x,
32044
+ y: y,
32045
+ width: width,
32046
+ height: height,
32047
+ fill: "#d0e6ea",
32048
+ rx: 4,
32049
+ ry: 4
32050
+ }), /*#__PURE__*/React__default["default"].createElement("text", {
32051
+ x: x + width / 2,
32052
+ y: y - 8,
32053
+ textAnchor: "middle",
32054
+ fontSize: 11,
32055
+ fontWeight: 400,
32056
+ fontFamily: "Poppins",
32057
+ fill: "#212121"
32058
+ }, format(payload.total)), /*#__PURE__*/React__default["default"].createElement("rect", {
32059
+ x: x + width * 0.2,
32060
+ y: innerY,
32061
+ width: width * 0.6,
32062
+ height: innerHeight,
32063
+ fill: "#07575b",
32064
+ rx: 2,
32065
+ ry: 2
32066
+ }), innerHeight > 16 && /*#__PURE__*/React__default["default"].createElement("text", {
32067
+ x: x + width / 2,
32068
+ y: innerY - 6,
32069
+ textAnchor: "middle",
32070
+ fontSize: 11,
32071
+ fontWeight: 400,
32072
+ fontFamily: "Poppins",
32073
+ fill: "#212121"
32074
+ }, format(payload.actual)));
32075
+ };
32076
+ const CustomTooltip = ({
32077
+ active,
32078
+ payload,
32079
+ label
32080
+ }) => {
32081
+ if (!active || !payload || !payload.length) return null;
32082
+ const data = payload[0].payload;
32083
+ return /*#__PURE__*/React__default["default"].createElement("div", {
32084
+ style: {
32085
+ background: "white",
32086
+ border: "1px solid #ccc",
32087
+ padding: "10px",
32088
+ borderRadius: "8px",
32089
+ fontSize: "14px"
32090
+ }
32091
+ }, /*#__PURE__*/React__default["default"].createElement("strong", null, label), /*#__PURE__*/React__default["default"].createElement("div", null, "Actual: ", format(data.actual)), /*#__PURE__*/React__default["default"].createElement("div", null, "Total: ", format(data.total)));
32092
+ };
32093
+ const dataWithIndex = originalData.map((item, index) => ({
32094
+ ...item,
32095
+ index,
32096
+ shortLabel: item.label.replace("Vendor Selling Event: ", "Wk ")
32097
+ }));
32098
+ const CustomizedTick = ({
32099
+ x,
32100
+ y,
32101
+ payload
32102
+ }) => {
32103
+ const label = dataWithIndex[payload.value]?.label ?? "";
32104
+ const parts = label.replace("Vendor Selling Event: ", "").split(" ");
32105
+ return /*#__PURE__*/React__default["default"].createElement("g", {
32106
+ transform: `translate(${x},${y})`
32107
+ }, /*#__PURE__*/React__default["default"].createElement("text", {
32108
+ x: 0,
32109
+ y: 0,
32110
+ dy: 16,
32111
+ textAnchor: "middle",
32112
+ fill: "#212121",
32113
+ fontSize: 11,
32114
+ fontWeight: "400",
32115
+ fontFamily: "Poppins"
32116
+ }, /*#__PURE__*/React__default["default"].createElement("tspan", {
32117
+ x: 0,
32118
+ dy: 8
32119
+ }, "Vendor Selling"), /*#__PURE__*/React__default["default"].createElement("tspan", {
32120
+ x: 0,
32121
+ dy: 18
32122
+ }, "Event: ", parts.join(" "))));
32123
+ };
32124
+ return /*#__PURE__*/React__default["default"].createElement(recharts.ResponsiveContainer, {
32125
+ width: "100%",
32126
+ height: 400
32127
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.BarChart, {
32128
+ data: data,
32129
+ margin: {
32130
+ top: 20,
32131
+ right: 30,
32132
+ left: 20,
32133
+ bottom: 10
32134
+ }
32135
+ }, /*#__PURE__*/React__default["default"].createElement(recharts.CartesianGrid, {
32136
+ strokeDasharray: "3 3",
32137
+ vertical: false
32138
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.XAxis, {
32139
+ dataKey: "week",
32140
+ tick: /*#__PURE__*/React__default["default"].createElement(CustomizedTick, null)
32141
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.YAxis, {
32142
+ type: "number",
32143
+ domain: [0, "dataMax + 2000"],
32144
+ hide: true
32145
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.Tooltip, {
32146
+ content: /*#__PURE__*/React__default["default"].createElement(CustomTooltip, null)
32147
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.Brush, {
32148
+ height: 30,
32149
+ travellerWidth: 10,
32150
+ startIndex: 1,
32151
+ endIndex: 5,
32152
+ y: 369
32153
+ }), /*#__PURE__*/React__default["default"].createElement(recharts.Bar, {
32154
+ dataKey: "total",
32155
+ shape: /*#__PURE__*/React__default["default"].createElement(BarWithInner, null),
32156
+ label: /*#__PURE__*/React__default["default"].createElement(CustomBarLabel, null),
32157
+ barSize: 30
32158
+ })));
32159
+ }
32160
+
32161
+ styled__default["default"].div`
32162
+ font-family: sans-serif;
32163
+ text-align: center;
32164
+ `;
32165
+ styled__default["default"].div`
32166
+ height: 25%;
32167
+ `;
32168
+ styled__default["default"].div`
32169
+ height: 75%;
32170
+ `;
32171
+ styled__default["default"].div`
32172
+ height: 100%;
32173
+ display: flex;
32174
+ flex-direction: column;
32175
+ background-color: white;
32176
+ `;
32177
+ const Container = styled__default["default"].div`
32178
+ width: 100%;
32179
+ height: 100%;
32180
+ display: flex;
32181
+ flex-direction: column;
32182
+ #Segment {
32183
+ width: auto;
32184
+ white-space: nowrap;
32185
+ font-size: 14px;
32186
+ font-weight: 500;
32187
+ font-family: "Poppins"
32188
+ }
32189
+ `;
32190
+ /* Make brush background darker */
32191
+ /* .recharts-brush .recharts-brush-slide {
32192
+ fill: #a52a2a !important;
32193
+ stroke: none;
32194
+ }
32195
+
32196
+ /* Style draggable handles (travellers) */
32197
+ /* .recharts-brush-traveller {
32198
+ fill: limegreen !important; /* bright green like in the image */
32199
+ /* cursor: ew-resize;
32200
+ } */
32201
+
32202
+ /* Optional: center grip arrows (you can fake it with CSS) */
32203
+ /* .recharts-brush .recharts-brush-traveller > rect {
32204
+ rx: 2;
32205
+ ry: 2;
32206
+ width: 6;
32207
+ fill: #a52a2a !important; /* dark gray */
32208
+ /* } */
32209
+
32210
+ /* Remove tick labels if needed */
32211
+ // .recharts-brush .recharts-layer text {
32212
+ // display: none;
32213
+ // }
32214
+
32215
+ const BrushChart = () => {
32216
+ const segmentedbuttonOptions = ["New Shoppers & Repeaters", "INC Sales & ROI", "INC Units", "Basket Lift"];
32217
+ const [selectedOption, setSelectedOption] = React$1.useState(segmentedbuttonOptions[0]);
32218
+ return /*#__PURE__*/React__default["default"].createElement(Container, null, /*#__PURE__*/React__default["default"].createElement(SegmentedButton, {
32219
+ gap: '8px',
32220
+ options: segmentedbuttonOptions.map(value => ({
32221
+ value
32222
+ })),
32223
+ onClick: _ref => {
32224
+ let {
32225
+ value
32226
+ } = _ref;
32227
+ return setSelectedOption(value);
32228
+ }
32229
+ }), selectedOption === "New Shoppers & Repeaters" && /*#__PURE__*/React__default["default"].createElement(InnerBarChart, null), selectedOption === "INC Sales & ROI" && /*#__PURE__*/React__default["default"].createElement(SeparatedLineBarChart, null), selectedOption === "INC Units" && /*#__PURE__*/React__default["default"].createElement(SingleChart, null), selectedOption === "Basket Lift" && /*#__PURE__*/React__default["default"].createElement(SingleChart, null));
30424
32230
  };
30425
32231
 
30426
32232
  exports.AreaChart = AreaChart;
@@ -30429,6 +32235,8 @@ exports.BarChart = BarChart;
30429
32235
  exports.BarChartsByWeeks = BarChartsByWeeks;
30430
32236
  exports.BatteryChart = BatteryChart;
30431
32237
  exports.BreakdownPanel = BreakdownPanel;
32238
+ exports.BrushChart = BrushChart;
32239
+ exports.BubbleChart = BubbleChart;
30432
32240
  exports.Button = Button;
30433
32241
  exports.CollapseHeader = CollapseHeader;
30434
32242
  exports.DialogOverlay = DialogOverlay;