sag_components 2.0.0-beta52 → 2.0.0-beta54

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