@levi-gemcommerce/analytics 1.0.0-dev.15 → 1.0.0-dev.17

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.
Files changed (37) hide show
  1. package/dist/esm/components/GTimePicker/hooks/useDateTimeFilter.d.ts +2 -2
  2. package/dist/esm/core/gemxql/helpers/extractQueryData.d.ts +1 -1
  3. package/dist/esm/core/gemxql/hooks/useAnalyticData.d.ts +1 -2
  4. package/dist/esm/gemxql.js +184 -2
  5. package/dist/esm/gemxql.mjs +184 -2
  6. package/dist/esm/hooks/index.d.ts +2 -1
  7. package/dist/esm/hooks/useFetchCurrencyRates.d.ts +1 -0
  8. package/dist/esm/index.d.ts +3 -0
  9. package/dist/esm/index.js +176 -29
  10. package/dist/esm/index.mjs +176 -29
  11. package/dist/esm/providers/ConvertMoneyProvider.d.ts +13 -0
  12. package/dist/esm/providers/currencyRatesStore.d.ts +7 -0
  13. package/dist/esm/providers/index.d.ts +2 -0
  14. package/dist/esm/providers/useFetchCurrencyRates.d.ts +1 -0
  15. package/dist/esm/shared/charts/components/GPolarisViz/components/TooltipWrapper/utilities/getDonutChartTooltipPosition.d.ts +1 -1
  16. package/dist/esm/shared/charts/components/GPolarisViz/components/TooltipWrapper/utilities/getLineChartTooltipPosition.d.ts +1 -1
  17. package/dist/esm/stores/currencyRatesStore.d.ts +7 -0
  18. package/dist/esm/stores/index.d.ts +2 -0
  19. package/dist/esm/utils/currency.d.ts +5 -0
  20. package/dist/umd/esm/components/GTimePicker/hooks/useDateTimeFilter.d.ts +2 -2
  21. package/dist/umd/esm/core/gemxql/helpers/extractQueryData.d.ts +1 -1
  22. package/dist/umd/esm/core/gemxql/hooks/useAnalyticData.d.ts +1 -2
  23. package/dist/umd/esm/hooks/index.d.ts +2 -1
  24. package/dist/umd/esm/hooks/useFetchCurrencyRates.d.ts +1 -0
  25. package/dist/umd/esm/index.d.ts +3 -0
  26. package/dist/umd/esm/providers/ConvertMoneyProvider.d.ts +13 -0
  27. package/dist/umd/esm/providers/currencyRatesStore.d.ts +7 -0
  28. package/dist/umd/esm/providers/index.d.ts +2 -0
  29. package/dist/umd/esm/providers/useFetchCurrencyRates.d.ts +1 -0
  30. package/dist/umd/esm/shared/charts/components/GPolarisViz/components/TooltipWrapper/utilities/getDonutChartTooltipPosition.d.ts +1 -1
  31. package/dist/umd/esm/shared/charts/components/GPolarisViz/components/TooltipWrapper/utilities/getLineChartTooltipPosition.d.ts +1 -1
  32. package/dist/umd/esm/stores/currencyRatesStore.d.ts +7 -0
  33. package/dist/umd/esm/stores/index.d.ts +2 -0
  34. package/dist/umd/esm/utils/currency.d.ts +5 -0
  35. package/dist/umd/gemxql.js +1 -1
  36. package/dist/umd/index.js +1 -1
  37. package/package.json +1 -1
package/dist/esm/index.js CHANGED
@@ -1,15 +1,17 @@
1
1
  "use client"
2
2
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
3
  import { Text, Box, InlineStack, Icon, InlineGrid, Tooltip, Button, BlockStack, Checkbox, RadioButton, Popover, ActionList, Link, SkeletonDisplayText, List, Card, SkeletonBodyText, TextField, Collapsible, useBreakpoints, Select, Scrollable, OptionList, DatePicker, ButtonGroup } from '@shopify/polaris';
4
- import React, { useMemo, useCallback, useState, useEffect, forwardRef, Fragment as Fragment$1, useRef, useImperativeHandle, createContext, useContext } from 'react';
4
+ import * as React from 'react';
5
+ import React__default, { useMemo, useCallback, useState, useEffect, forwardRef, Fragment as Fragment$1, useRef, useImperativeHandle, createContext, useContext } from 'react';
5
6
  import dayjs from 'dayjs';
6
7
  export { default as dayjs } from 'dayjs';
7
8
  import quarterOfYear from 'dayjs/plugin/quarterOfYear.js';
8
9
  import timezone from 'dayjs/plugin/timezone.js';
9
10
  import utc from 'dayjs/plugin/utc.js';
10
11
  import { useTranslation } from 'react-i18next';
12
+ import { create } from 'zustand';
13
+ import { useQuery } from '@tanstack/react-query';
11
14
  import { PolarisVizProvider, LineChart, DonutChart } from '@shopify/polaris-viz';
12
- import '@tanstack/react-query';
13
15
 
14
16
  var EMetricKey;
15
17
  (function (EMetricKey) {
@@ -199,9 +201,9 @@ const DEFAULT_CURRENCY_ANALYTIC = 'USD';
199
201
  var THUMB_PRODUCT_DEFAULT = "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSI5MCIKICBoZWlnaHQ9IjcyIgogIHZpZXdCb3g9IjAgMCA5MCA3MiIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNNDguNzUgMzQuNUM0OS45OTI2IDM0LjUgNTEgMzMuNDkyNiA1MSAzMi4yNUM1MSAzMS4wMDc0IDQ5Ljk5MjYgMzAgNDguNzUgMzBDNDcuNTA3NCAzMCA0Ni41IDMxLjAwNzQgNDYuNSAzMi4yNUM0Ni41IDMzLjQ5MjYgNDcuNTA3NCAzNC41IDQ4Ljc1IDM0LjVaIgogICAgZmlsbD0iIzYxNjE2MSIKICAvPgogIDxwYXRoCiAgICBmaWxsUnVsZT0iZXZlbm9kZCIKICAgIGNsaXBSdWxlPSJldmVub2RkIgogICAgZD0iTTQzLjUyNjggMjYuMjVINDYuNDczMkM0Ny42OTI0IDI2LjI1IDQ4LjY3NTggMjYuMjUgNDkuNDcyMiAyNi4zMTVDNTAuMjkyMiAyNi4zODIgNTEuMDEyNCAyNi41MjM2IDUxLjY3ODcgMjYuODYzMUM1Mi43MzcxIDI3LjQwMjQgNTMuNTk3NiAyOC4yNjI5IDU0LjEzNjkgMjkuMzIxM0M1NC40NzY0IDI5Ljk4NzYgNTQuNjE4IDMwLjcwNzggNTQuNjg1IDMxLjUyNzhDNTQuNzUgMzIuMzI0MiA1NC43NSAzMy4zMDc2IDU0Ljc1IDM0LjUyNjhWMzcuNDczMkM1NC43NSAzOC42OTI0IDU0Ljc1IDM5LjY3NTggNTQuNjg1IDQwLjQ3MjJDNTQuNjE4IDQxLjI5MjIgNTQuNDc2NCA0Mi4wMTI0IDU0LjEzNjkgNDIuNjc4N0M1My41OTc2IDQzLjczNzEgNTIuNzM3MSA0NC41OTc2IDUxLjY3ODcgNDUuMTM2OUM1MS4wMTI0IDQ1LjQ3NjQgNTAuMjkyMiA0NS42MTggNDkuNDcyMiA0NS42ODVDNDguNjc1OCA0NS43NSA0Ny42OTI0IDQ1Ljc1IDQ2LjQ3MzIgNDUuNzVINDMuNTI2OEM0Mi4zMDc2IDQ1Ljc1IDQxLjMyNDIgNDUuNzUgNDAuNTI3OCA0NS42ODVDMzkuNzA3OCA0NS42MTggMzguOTg3NiA0NS40NzY0IDM4LjMyMTMgNDUuMTM2OUMzNy4yNjI5IDQ0LjU5NzYgMzYuNDAyNCA0My43MzcxIDM1Ljg2MzEgNDIuNjc4N0MzNS41MjM2IDQyLjAxMjQgMzUuMzgyIDQxLjI5MjIgMzUuMzE1IDQwLjQ3MjJDMzUuMjUgMzkuNjc1OCAzNS4yNSAzOC42OTI0IDM1LjI1IDM3LjQ3MzJWMzQuNTI2OEMzNS4yNSAzMy4zMDc2IDM1LjI1IDMyLjMyNDIgMzUuMzE1IDMxLjUyNzhDMzUuMzgyIDMwLjcwNzggMzUuNTIzNiAyOS45ODc2IDM1Ljg2MzEgMjkuMzIxM0MzNi40MDI0IDI4LjI2MjkgMzcuMjYyOSAyNy40MDI0IDM4LjMyMTMgMjYuODYzMUMzOC45ODc2IDI2LjUyMzYgMzkuNzA3OCAyNi4zODIgNDAuNTI3OCAyNi4zMTVDNDEuMzI0MiAyNi4yNSA0Mi4zMDc2IDI2LjI1IDQzLjUyNjggMjYuMjVaTTQwLjcxMSAyOC41NTc2QzQwLjAzMDIgMjguNjEzMiAzOS42MzkxIDI4LjcxNjkgMzkuMzQyOCAyOC44Njc5QzM4LjcwNzcgMjkuMTkxNCAzOC4xOTE0IDI5LjcwNzcgMzcuODY3OSAzMC4zNDI4QzM3LjcxNjkgMzAuNjM5MSAzNy42MTMyIDMxLjAzMDIgMzcuNTU3NiAzMS43MTFDMzcuNTAwOSAzMi40MDUgMzcuNSAzMy4yOTYzIDM3LjUgMzQuNTc1VjM2LjcxNzdMMzguNTg0MiAzNS40MTY3QzM5LjU3MjQgMzQuMjMwOSA0MS4zNjU1IDM0LjE0OTYgNDIuNDU2OSAzNS4yNDFMNDYuNSAzOS4yODQxTDQ4LjI2OTQgMzcuNTE0NkM0OS4zNzU3IDM2LjQwODMgNTEuMTk4IDM2LjUwOTMgNTIuMTc1NCAzNy43MzA5TDUyLjQ5OTUgMzguMTM2MUM1Mi41IDM3LjkxMzEgNTIuNSAzNy42NzY1IDUyLjUgMzcuNDI1VjM0LjU3NUM1Mi41IDMzLjI5NjMgNTIuNDk5MSAzMi40MDUgNTIuNDQyNCAzMS43MTFDNTIuMzg2OCAzMS4wMzAyIDUyLjI4MzEgMzAuNjM5MSA1Mi4xMzIxIDMwLjM0MjhDNTEuODA4NiAyOS43MDc3IDUxLjI5MjMgMjkuMTkxNCA1MC42NTcyIDI4Ljg2NzlDNTAuMzYwOSAyOC43MTY5IDQ5Ljk2OTggMjguNjEzMiA0OS4yODkgMjguNTU3NkM0OC41OTUgMjguNTAwOSA0Ny43MDM3IDI4LjUgNDYuNDI1IDI4LjVINDMuNTc1QzQyLjI5NjMgMjguNSA0MS40MDUgMjguNTAwOSA0MC43MTEgMjguNTU3NlpNMzcuNTU3NiA0MC4yODlDMzcuNTU0MyA0MC4yNDkyIDM3LjU1MTMgNDAuMjA4OCAzNy41NDg0IDQwLjE2NzhDMzcuNTcxMSA0MC4xNDQ4IDM3LjU5MzEgNDAuMTIwNiAzNy42MTQyIDQwLjA5NTNMNDAuMzEyNyAzNi44NTcxQzQwLjQ1MzkgMzYuNjg3NyA0MC43MSAzNi42NzYxIDQwLjg2NTkgMzYuODMyTDQ1LjcwNDUgNDEuNjcwNkM0Ni4xNDM4IDQyLjEwOTkgNDYuODU2MSA0Mi4xMDk5IDQ3LjI5NTUgNDEuNjcwNkw0OS44NjA0IDM5LjEwNTZDNTAuMDE4NSAzOC45NDc2IDUwLjI3ODggMzguOTYyIDUwLjQxODQgMzkuMTM2NUw1Mi4yMzc3IDQxLjQxMDdDNTIuMjA1NiA0MS41MDEgNTIuMTcwNCA0MS41ODIyIDUyLjEzMjEgNDEuNjU3MkM1MS44MDg2IDQyLjI5MjMgNTEuMjkyMyA0Mi44MDg2IDUwLjY1NzIgNDMuMTMyMUM1MC4zNjA5IDQzLjI4MzEgNDkuOTY5OCA0My4zODY4IDQ5LjI4OSA0My40NDI0QzQ4LjU5NSA0My40OTkxIDQ3LjcwMzcgNDMuNSA0Ni40MjUgNDMuNUg0My41NzVDNDIuMjk2MyA0My41IDQxLjQwNSA0My40OTkxIDQwLjcxMSA0My40NDI0QzQwLjAzMDIgNDMuMzg2OCAzOS42MzkxIDQzLjI4MzEgMzkuMzQyOCA0My4xMzIxQzM4LjcwNzcgNDIuODA4NiAzOC4xOTE0IDQyLjI5MjMgMzcuODY3OSA0MS42NTcyQzM3LjcxNjkgNDEuMzYwOSAzNy42MTMyIDQwLjk2OTggMzcuNTU3NiA0MC4yODlaIgogICAgZmlsbD0iIzYxNjE2MSIKICAvPgo8L3N2Zz4K";
200
202
 
201
203
  var SvgArrowRightIcon = function SvgArrowRightIcon(props) {
202
- return /*#__PURE__*/React.createElement("svg", Object.assign({
204
+ return /*#__PURE__*/React__default.createElement("svg", Object.assign({
203
205
  viewBox: "0 0 20 20"
204
- }, props), /*#__PURE__*/React.createElement("path", {
206
+ }, props), /*#__PURE__*/React__default.createElement("path", {
205
207
  fillRule: "evenodd",
206
208
  d: "M3.5 10a.75.75 0 0 1 .75-.75h9.69l-2.72-2.72a.75.75 0 1 1 1.06-1.06l4 4a.75.75 0 0 1 0 1.06l-4 4a.75.75 0 0 1-1.06-1.06l2.72-2.72h-9.69a.75.75 0 0 1-.75-.75Z"
207
209
  }));
@@ -209,9 +211,9 @@ var SvgArrowRightIcon = function SvgArrowRightIcon(props) {
209
211
  SvgArrowRightIcon.displayName = "ArrowRightIcon";
210
212
 
211
213
  var SvgCalendarIcon = function SvgCalendarIcon(props) {
212
- return /*#__PURE__*/React.createElement("svg", Object.assign({
214
+ return /*#__PURE__*/React__default.createElement("svg", Object.assign({
213
215
  viewBox: "0 0 20 20"
214
- }, props), /*#__PURE__*/React.createElement("path", {
216
+ }, props), /*#__PURE__*/React__default.createElement("path", {
215
217
  fillRule: "evenodd",
216
218
  d: "M7.75 3.5a.75.75 0 0 0-1.5 0v.407a3.075 3.075 0 0 0-.702.252 3.75 3.75 0 0 0-1.64 1.639c-.226.444-.32.924-.365 1.47-.043.531-.043 1.187-.043 2v1.464c0 .813 0 1.469.043 2 .045.546.14 1.026.366 1.47a3.75 3.75 0 0 0 1.639 1.64c.444.226.924.32 1.47.365.531.043 1.187.043 2 .043h3.383c.323 0 .542 0 .735-.02a3.75 3.75 0 0 0 3.344-3.344c.02-.193.02-.412.02-.735v-2.883c0-.813 0-1.469-.043-2-.045-.546-.14-1.026-.366-1.47a3.75 3.75 0 0 0-1.639-1.64 3.076 3.076 0 0 0-.702-.251v-.407a.75.75 0 0 0-1.5 0v.259c-.373-.009-.794-.009-1.268-.009h-1.964c-.474 0-.895 0-1.268.009v-.259Zm-1.521 1.995c.197-.1.458-.17.912-.207.462-.037 1.057-.038 1.909-.038h1.9c.853 0 1.447 0 1.91.038.453.037.714.107.912.207.423.216.767.56.983.984.1.197.17.458.207.912.014.18.024.38.029.609h-9.982c.006-.228.015-.429.03-.61.036-.453.106-.714.206-.911a2.25 2.25 0 0 1 .984-.984Zm-1.229 4.005v1.2c0 .853 0 1.447.038 1.91.037.453.107.714.207.912.216.423.56.767.984.983.197.1.458.17.912.207.462.037 1.057.038 1.909.038h3.306c.385 0 .52-.001.626-.012a2.25 2.25 0 0 0 2.006-2.006c.011-.106.012-.241.012-.626v-2.606h-10Z"
217
219
  }));
@@ -219,9 +221,9 @@ var SvgCalendarIcon = function SvgCalendarIcon(props) {
219
221
  SvgCalendarIcon.displayName = "CalendarIcon";
220
222
 
221
223
  var SvgCheckIcon = function SvgCheckIcon(props) {
222
- return /*#__PURE__*/React.createElement("svg", Object.assign({
224
+ return /*#__PURE__*/React__default.createElement("svg", Object.assign({
223
225
  viewBox: "0 0 20 20"
224
- }, props), /*#__PURE__*/React.createElement("path", {
226
+ }, props), /*#__PURE__*/React__default.createElement("path", {
225
227
  fillRule: "evenodd",
226
228
  d: "M15.78 5.97a.75.75 0 0 1 0 1.06l-6.5 6.5a.75.75 0 0 1-1.06 0l-3.25-3.25a.75.75 0 1 1 1.06-1.06l2.72 2.72 5.97-5.97a.75.75 0 0 1 1.06 0Z"
227
229
  }));
@@ -229,9 +231,9 @@ var SvgCheckIcon = function SvgCheckIcon(props) {
229
231
  SvgCheckIcon.displayName = "CheckIcon";
230
232
 
231
233
  var SvgChevronDownIcon = function SvgChevronDownIcon(props) {
232
- return /*#__PURE__*/React.createElement("svg", Object.assign({
234
+ return /*#__PURE__*/React__default.createElement("svg", Object.assign({
233
235
  viewBox: "0 0 20 20"
234
- }, props), /*#__PURE__*/React.createElement("path", {
236
+ }, props), /*#__PURE__*/React__default.createElement("path", {
235
237
  fillRule: "evenodd",
236
238
  d: "M5.72 8.47a.75.75 0 0 1 1.06 0l3.47 3.47 3.47-3.47a.75.75 0 1 1 1.06 1.06l-4 4a.75.75 0 0 1-1.06 0l-4-4a.75.75 0 0 1 0-1.06Z"
237
239
  }));
@@ -239,9 +241,9 @@ var SvgChevronDownIcon = function SvgChevronDownIcon(props) {
239
241
  SvgChevronDownIcon.displayName = "ChevronDownIcon";
240
242
 
241
243
  var SvgChevronRightIcon = function SvgChevronRightIcon(props) {
242
- return /*#__PURE__*/React.createElement("svg", Object.assign({
244
+ return /*#__PURE__*/React__default.createElement("svg", Object.assign({
243
245
  viewBox: "0 0 20 20"
244
- }, props), /*#__PURE__*/React.createElement("path", {
246
+ }, props), /*#__PURE__*/React__default.createElement("path", {
245
247
  fillRule: "evenodd",
246
248
  d: "M7.72 14.53a.75.75 0 0 1 0-1.06l3.47-3.47-3.47-3.47a.75.75 0 0 1 1.06-1.06l4 4a.75.75 0 0 1 0 1.06l-4 4a.75.75 0 0 1-1.06 0Z"
247
249
  }));
@@ -249,9 +251,9 @@ var SvgChevronRightIcon = function SvgChevronRightIcon(props) {
249
251
  SvgChevronRightIcon.displayName = "ChevronRightIcon";
250
252
 
251
253
  var SvgChevronUpIcon = function SvgChevronUpIcon(props) {
252
- return /*#__PURE__*/React.createElement("svg", Object.assign({
254
+ return /*#__PURE__*/React__default.createElement("svg", Object.assign({
253
255
  viewBox: "0 0 20 20"
254
- }, props), /*#__PURE__*/React.createElement("path", {
256
+ }, props), /*#__PURE__*/React__default.createElement("path", {
255
257
  fillRule: "evenodd",
256
258
  d: "M14.53 12.28a.75.75 0 0 1-1.06 0l-3.47-3.47-3.47 3.47a.75.75 0 0 1-1.06-1.06l4-4a.75.75 0 0 1 1.06 0l4 4a.75.75 0 0 1 0 1.06Z"
257
259
  }));
@@ -879,6 +881,118 @@ const GChartSkeleton = () => {
879
881
  return jsx(GSkeletonDisplayText, { height: "188px" });
880
882
  };
881
883
 
884
+ const useCurrencyRatesStore = create((set) => ({
885
+ currencyRates: null,
886
+ setCurrencyRates: (rates) => set({ currencyRates: rates }),
887
+ }));
888
+
889
+ const SHOPIFY_CURRENCIES_URL = 'https://cdn.shopify.com/s/javascripts/currencies.js';
890
+ const parseCurrencyRates = (scriptText) => {
891
+ const rates = {};
892
+ const match = /var Currency=\{rates:\{(.*?)\}\};/s.exec(scriptText);
893
+ const ratesStr = match?.[1];
894
+ if (!ratesStr)
895
+ return rates;
896
+ const ratePattern = /([A-Z]+):\s*([\d.e+-]+),/g;
897
+ let m;
898
+ while ((m = ratePattern.exec(ratesStr)) !== null) {
899
+ const [, code, value] = m;
900
+ if (code && value)
901
+ rates[code] = parseFloat(value);
902
+ }
903
+ return rates;
904
+ };
905
+ const fetchCurrencyRates = async () => {
906
+ const res = await fetch(SHOPIFY_CURRENCIES_URL);
907
+ if (!res.ok)
908
+ throw new Error('Failed to fetch currency rates');
909
+ const text = await res.text();
910
+ return parseCurrencyRates(text);
911
+ };
912
+ const useFetchCurrencyRates = () => {
913
+ const setCurrencyRates = useCurrencyRatesStore((state) => state.setCurrencyRates);
914
+ const { data } = useQuery({
915
+ queryKey: ['sdk-currency-rates'],
916
+ queryFn: fetchCurrencyRates,
917
+ staleTime: 1000 * 60 * 60, // 1 hour — rates don't change often
918
+ });
919
+ useEffect(() => {
920
+ if (data)
921
+ setCurrencyRates(data);
922
+ }, [data, setCurrencyRates]);
923
+ };
924
+
925
+ const getPriceByCurrency = (price, currency = DEFAULT_CURRENCY_ANALYTIC, options) => {
926
+ if (typeof price === 'string')
927
+ return price;
928
+ if (typeof price !== 'number')
929
+ return;
930
+ // Support legacy 3rd arg as locale string
931
+ const opts = typeof options === 'string' ? { locale: options } : options;
932
+ const locale = opts?.locale ?? 'en-US';
933
+ if (price >= 1_000_000_000) {
934
+ return `${new Intl.NumberFormat(locale, {
935
+ style: 'currency',
936
+ currency,
937
+ minimumFractionDigits: 2,
938
+ maximumFractionDigits: 2,
939
+ }).format(price / 1_000_000_000)}B`;
940
+ }
941
+ if (price >= 1_000_000) {
942
+ return `${new Intl.NumberFormat(locale, {
943
+ style: 'currency',
944
+ currency,
945
+ minimumFractionDigits: 2,
946
+ maximumFractionDigits: 2,
947
+ }).format(price / 1_000_000)}M`;
948
+ }
949
+ if (opts?.compact && Math.abs(price) >= 1_000) {
950
+ return `${new Intl.NumberFormat(locale, {
951
+ style: 'currency',
952
+ currency,
953
+ minimumFractionDigits: 1,
954
+ maximumFractionDigits: 1,
955
+ }).format(price / 1_000)}K`;
956
+ }
957
+ return new Intl.NumberFormat(locale, {
958
+ style: 'currency',
959
+ currency,
960
+ }).format(price);
961
+ };
962
+
963
+ const ConvertMoneyContext = createContext({
964
+ getTextPrice: (price) => {
965
+ if (typeof price === 'string')
966
+ return price;
967
+ return `${price ?? 0}`;
968
+ },
969
+ });
970
+ const convertAmount = (amount, from, to, rates) => {
971
+ if (from === to || !rates[from] || !rates[to])
972
+ return amount;
973
+ const converted = (amount * rates[from]) / rates[to];
974
+ return converted ? Number(converted.toFixed(2)) : amount;
975
+ };
976
+ const ConvertMoneyProvider = ({ children, currency, locale = 'en-US' }) => {
977
+ useFetchCurrencyRates();
978
+ const currencyRates = useCurrencyRatesStore((state) => state.currencyRates);
979
+ const getTextPrice = useCallback((price, _hasCurrency, options) => {
980
+ if (typeof price === 'string')
981
+ return price;
982
+ if (typeof price !== 'number')
983
+ return '0';
984
+ if (!currency)
985
+ return price.toString();
986
+ const converted = currencyRates
987
+ ? convertAmount(price, DEFAULT_CURRENCY_ANALYTIC, currency, currencyRates)
988
+ : price;
989
+ return trimDecimalZeros(getPriceByCurrency(converted, currency, { locale, compact: options?.compact }) ?? '0');
990
+ }, [currency, locale, currencyRates]);
991
+ const value = useMemo(() => ({ getTextPrice }), [getTextPrice]);
992
+ return jsx(ConvertMoneyContext.Provider, { value: value, children: children });
993
+ };
994
+ const useConvertMoneyContext = () => useContext(ConvertMoneyContext);
995
+
882
996
  const LINE_SERIES_COLORS = {
883
997
  comparison: SERIES_COLORS.comparison,
884
998
  single: SERIES_COLORS.current,
@@ -900,19 +1014,7 @@ const MetricChartProvider = ({ children, minHeight = CHART_MIN_HEIGHT, seriesCol
900
1014
  }, children: children }));
901
1015
  };
902
1016
 
903
- /**
904
- * Returns a stateful value, and a set of memoized functions to toggle it,
905
- * set it to true and set it to false
906
- */
907
- function useToggle(initialState) {
908
- const [value, setState] = useState(initialState);
909
- return {
910
- value,
911
- toggle: useCallback(() => setState((state) => !state), []),
912
- setTrue: useCallback(() => setState(true), []),
913
- setFalse: useCallback(() => setState(false), []),
914
- };
915
- }
1017
+ const useEnhancedEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
916
1018
 
917
1019
  const NONE_VALUE = 'None';
918
1020
  const PLACEHOLDER_VALUE = '-';
@@ -1169,8 +1271,10 @@ const readNumeric = (metric, key) => {
1169
1271
  return typeof raw === 'number' ? raw : 0;
1170
1272
  };
1171
1273
 
1172
- const useAnalyticData = (getTextPrice) => {
1274
+ const useAnalyticData = () => {
1275
+ const { getTextPrice } = useConvertMoneyContext();
1173
1276
  const formatData = ({ value, formatter, name }) => {
1277
+ console.log({ value, formatter, getTextPrice, name });
1174
1278
  return formatAnalyticData({ value, formatter, getTextPrice, name });
1175
1279
  };
1176
1280
  const computeMetric = ({ metric, previousMetric, metricKey, formatter, }) => {
@@ -1209,6 +1313,49 @@ const useFormatLineChartData = ({ metricKey, columnTypes }) => {
1209
1313
  return { formatValue, yAxisOptions };
1210
1314
  };
1211
1315
 
1316
+ const usePopoverResizeObserver = ({ active, onHeightChange, selector = '.Polaris-Popover__Content--fluidContent', }) => {
1317
+ useEffect(() => {
1318
+ if (!active)
1319
+ return;
1320
+ let resizeObserver = null;
1321
+ const setupResizeObserver = () => {
1322
+ const popoverContent = document.querySelector(selector);
1323
+ if (popoverContent && !resizeObserver) {
1324
+ resizeObserver = new ResizeObserver((entries) => {
1325
+ for (const entry of entries) {
1326
+ const { height } = entry.contentRect;
1327
+ onHeightChange?.(height);
1328
+ }
1329
+ });
1330
+ resizeObserver.observe(popoverContent);
1331
+ }
1332
+ };
1333
+ setTimeout(() => {
1334
+ setupResizeObserver();
1335
+ }, 200);
1336
+ return () => {
1337
+ if (resizeObserver) {
1338
+ resizeObserver.disconnect();
1339
+ resizeObserver = null;
1340
+ }
1341
+ };
1342
+ }, [active, selector]);
1343
+ };
1344
+
1345
+ /**
1346
+ * Returns a stateful value, and a set of memoized functions to toggle it,
1347
+ * set it to true and set it to false
1348
+ */
1349
+ function useToggle(initialState) {
1350
+ const [value, setState] = useState(initialState);
1351
+ return {
1352
+ value,
1353
+ toggle: useCallback(() => setState((state) => !state), []),
1354
+ setTrue: useCallback(() => setState(true), []),
1355
+ setFalse: useCallback(() => setState(false), []),
1356
+ };
1357
+ }
1358
+
1212
1359
  const useWindowSize = () => {
1213
1360
  const [windowSize, setWindowSize] = useState(() => ({
1214
1361
  width: typeof window !== 'undefined' ? window.innerWidth : 0,
@@ -2525,4 +2672,4 @@ const GTimePicker = (props) => {
2525
2672
  return (jsxs(InlineStack, { gap: "200", children: [jsx(MainTimePicker, { ...timePickerProps }), isCompare && (jsx(CompareTimePicker, { rangeAddition: timePickerProps.rangeAddition, popoverProps: timePickerProps.popoverProps }))] }));
2526
2673
  };
2527
2674
 
2528
- export { ANALYTICS_METRIC_TOOLTIP, AnalyticModeSelector, CAMPAIGN_BACKGROUND_MAIN, CHART_MIN_HEIGHT, COMPARE_DATE_TIME_FILTERS_MAP, CompareDateTimePickerAlias, CurrencySelector, DATE_TIME_COMPARISON_FILTERS, DEFAULT_CURRENCY_ANALYTIC, DEFAULT_CURRENT_PERIOD_LABEL, DEFAULT_PREVIOUS_PERIOD_LABEL, DateTimeFilterInputs, DateTimeFilters, DateTimePickerContext, DateTimePickerProvider, GSelectableMetricChartCard, GTimePicker, MainDateTimePickerAlias, MetricDonutChartCard, PLACEHOLDER_VALUE$1 as PLACEHOLDER_VALUE, PREVIOUS_PERIOD_FILTER, SERIES_COLORS, SingleMetricChartCard, TARGET_CHANNEL, TARGET_DEVICES, TARGET_VISITOR, THUMB_PRODUCT_DEFAULT, TREND_TONE, convertDateToTz, convertToDateTimeFilters, createLastDaysRange, dayjsTz, dayjsTzToDate, dayjsTzToLocalTZ, formatDate, formatDateTimeRange, formatDayjs, formatMs, formatTime, formatTimeRange, getDateRangeTitle, getDateTimeFilterBase, getDateTimeFilterByAlias, getDateTimeFilterMapping, getEndOfDayBy, getInitialTimezone, getLast12Months, getLast30Days, getLast365Days, getLast7Days, getLast90Days, getLastMonth, getLastYear, getMonthAndYearByDateFilter, getNoComparison, getPreviousMonth, getPreviousPeriod, getPreviousQuarter, getPreviousWeek, getPreviousYear, getToday, getVersionDateDescription, getVersionDateRangeTitle, getYesterday, isDate, isMidnight, isSameDayTimestamp, isValidDate, isValidYearMonthDayDateString, parseYearMonthDayDateString, setTz, useDateTimeFilter, useDateTimePicker, useDateTimePickerContext, useVersionDateTimeFilters };
2675
+ export { ANALYTICS_METRIC_TOOLTIP, AnalyticModeSelector, CAMPAIGN_BACKGROUND_MAIN, CHART_MIN_HEIGHT, COMPARE_DATE_TIME_FILTERS_MAP, CompareDateTimePickerAlias, ConvertMoneyProvider, CurrencySelector, DATE_TIME_COMPARISON_FILTERS, DEFAULT_CURRENCY_ANALYTIC, DEFAULT_CURRENT_PERIOD_LABEL, DEFAULT_PREVIOUS_PERIOD_LABEL, DateTimeFilterInputs, DateTimeFilters, DateTimePickerContext, DateTimePickerProvider, GSelectableMetricChartCard, GTimePicker, MainDateTimePickerAlias, MetricChartProvider, MetricDonutChartCard, PLACEHOLDER_VALUE$1 as PLACEHOLDER_VALUE, PREVIOUS_PERIOD_FILTER, SERIES_COLORS, SingleMetricChartCard, TARGET_CHANNEL, TARGET_DEVICES, TARGET_VISITOR, THUMB_PRODUCT_DEFAULT, TREND_TONE, convertDateToTz, convertToDateTimeFilters, createLastDaysRange, dayjsTz, dayjsTzToDate, dayjsTzToLocalTZ, formatDate, formatDateTimeRange, formatDayjs, formatMs, formatTime, formatTimeRange, getDateRangeTitle, getDateTimeFilterBase, getDateTimeFilterByAlias, getDateTimeFilterMapping, getEndOfDayBy, getInitialTimezone, getLast12Months, getLast30Days, getLast365Days, getLast7Days, getLast90Days, getLastMonth, getLastYear, getMonthAndYearByDateFilter, getNoComparison, getPreviousMonth, getPreviousPeriod, getPreviousQuarter, getPreviousWeek, getPreviousYear, getToday, getVersionDateDescription, getVersionDateRangeTitle, getYesterday, isDate, isMidnight, isSameDayTimestamp, isValidDate, isValidYearMonthDayDateString, parseYearMonthDayDateString, setTz, useConvertMoneyContext, useCurrencyRatesStore, useDateTimeFilter, useDateTimePicker, useDateTimePickerContext, useEnhancedEffect, useFetchCurrencyRates, useFormatLineChartData, usePopoverResizeObserver, useToggle, useVersionDateTimeFilters, useWindowSize };
@@ -1,15 +1,17 @@
1
1
  "use client"
2
2
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
3
  import { Text, Box, InlineStack, Icon, InlineGrid, Tooltip, Button, BlockStack, Checkbox, RadioButton, Popover, ActionList, Link, SkeletonDisplayText, List, Card, SkeletonBodyText, TextField, Collapsible, useBreakpoints, Select, Scrollable, OptionList, DatePicker, ButtonGroup } from '@shopify/polaris';
4
- import React, { useMemo, useCallback, useState, useEffect, forwardRef, Fragment as Fragment$1, useRef, useImperativeHandle, createContext, useContext } from 'react';
4
+ import * as React from 'react';
5
+ import React__default, { useMemo, useCallback, useState, useEffect, forwardRef, Fragment as Fragment$1, useRef, useImperativeHandle, createContext, useContext } from 'react';
5
6
  import dayjs from 'dayjs';
6
7
  export { default as dayjs } from 'dayjs';
7
8
  import quarterOfYear from 'dayjs/plugin/quarterOfYear.js';
8
9
  import timezone from 'dayjs/plugin/timezone.js';
9
10
  import utc from 'dayjs/plugin/utc.js';
10
11
  import { useTranslation } from 'react-i18next';
12
+ import { create } from 'zustand';
13
+ import { useQuery } from '@tanstack/react-query';
11
14
  import { PolarisVizProvider, LineChart, DonutChart } from '@shopify/polaris-viz';
12
- import '@tanstack/react-query';
13
15
 
14
16
  var EMetricKey;
15
17
  (function (EMetricKey) {
@@ -199,9 +201,9 @@ const DEFAULT_CURRENCY_ANALYTIC = 'USD';
199
201
  var THUMB_PRODUCT_DEFAULT = "data:image/svg+xml;base64,PHN2ZwogIHdpZHRoPSI5MCIKICBoZWlnaHQ9IjcyIgogIHZpZXdCb3g9IjAgMCA5MCA3MiIKICBmaWxsPSJub25lIgogIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKPgogIDxwYXRoCiAgICBkPSJNNDguNzUgMzQuNUM0OS45OTI2IDM0LjUgNTEgMzMuNDkyNiA1MSAzMi4yNUM1MSAzMS4wMDc0IDQ5Ljk5MjYgMzAgNDguNzUgMzBDNDcuNTA3NCAzMCA0Ni41IDMxLjAwNzQgNDYuNSAzMi4yNUM0Ni41IDMzLjQ5MjYgNDcuNTA3NCAzNC41IDQ4Ljc1IDM0LjVaIgogICAgZmlsbD0iIzYxNjE2MSIKICAvPgogIDxwYXRoCiAgICBmaWxsUnVsZT0iZXZlbm9kZCIKICAgIGNsaXBSdWxlPSJldmVub2RkIgogICAgZD0iTTQzLjUyNjggMjYuMjVINDYuNDczMkM0Ny42OTI0IDI2LjI1IDQ4LjY3NTggMjYuMjUgNDkuNDcyMiAyNi4zMTVDNTAuMjkyMiAyNi4zODIgNTEuMDEyNCAyNi41MjM2IDUxLjY3ODcgMjYuODYzMUM1Mi43MzcxIDI3LjQwMjQgNTMuNTk3NiAyOC4yNjI5IDU0LjEzNjkgMjkuMzIxM0M1NC40NzY0IDI5Ljk4NzYgNTQuNjE4IDMwLjcwNzggNTQuNjg1IDMxLjUyNzhDNTQuNzUgMzIuMzI0MiA1NC43NSAzMy4zMDc2IDU0Ljc1IDM0LjUyNjhWMzcuNDczMkM1NC43NSAzOC42OTI0IDU0Ljc1IDM5LjY3NTggNTQuNjg1IDQwLjQ3MjJDNTQuNjE4IDQxLjI5MjIgNTQuNDc2NCA0Mi4wMTI0IDU0LjEzNjkgNDIuNjc4N0M1My41OTc2IDQzLjczNzEgNTIuNzM3MSA0NC41OTc2IDUxLjY3ODcgNDUuMTM2OUM1MS4wMTI0IDQ1LjQ3NjQgNTAuMjkyMiA0NS42MTggNDkuNDcyMiA0NS42ODVDNDguNjc1OCA0NS43NSA0Ny42OTI0IDQ1Ljc1IDQ2LjQ3MzIgNDUuNzVINDMuNTI2OEM0Mi4zMDc2IDQ1Ljc1IDQxLjMyNDIgNDUuNzUgNDAuNTI3OCA0NS42ODVDMzkuNzA3OCA0NS42MTggMzguOTg3NiA0NS40NzY0IDM4LjMyMTMgNDUuMTM2OUMzNy4yNjI5IDQ0LjU5NzYgMzYuNDAyNCA0My43MzcxIDM1Ljg2MzEgNDIuNjc4N0MzNS41MjM2IDQyLjAxMjQgMzUuMzgyIDQxLjI5MjIgMzUuMzE1IDQwLjQ3MjJDMzUuMjUgMzkuNjc1OCAzNS4yNSAzOC42OTI0IDM1LjI1IDM3LjQ3MzJWMzQuNTI2OEMzNS4yNSAzMy4zMDc2IDM1LjI1IDMyLjMyNDIgMzUuMzE1IDMxLjUyNzhDMzUuMzgyIDMwLjcwNzggMzUuNTIzNiAyOS45ODc2IDM1Ljg2MzEgMjkuMzIxM0MzNi40MDI0IDI4LjI2MjkgMzcuMjYyOSAyNy40MDI0IDM4LjMyMTMgMjYuODYzMUMzOC45ODc2IDI2LjUyMzYgMzkuNzA3OCAyNi4zODIgNDAuNTI3OCAyNi4zMTVDNDEuMzI0MiAyNi4yNSA0Mi4zMDc2IDI2LjI1IDQzLjUyNjggMjYuMjVaTTQwLjcxMSAyOC41NTc2QzQwLjAzMDIgMjguNjEzMiAzOS42MzkxIDI4LjcxNjkgMzkuMzQyOCAyOC44Njc5QzM4LjcwNzcgMjkuMTkxNCAzOC4xOTE0IDI5LjcwNzcgMzcuODY3OSAzMC4zNDI4QzM3LjcxNjkgMzAuNjM5MSAzNy42MTMyIDMxLjAzMDIgMzcuNTU3NiAzMS43MTFDMzcuNTAwOSAzMi40MDUgMzcuNSAzMy4yOTYzIDM3LjUgMzQuNTc1VjM2LjcxNzdMMzguNTg0MiAzNS40MTY3QzM5LjU3MjQgMzQuMjMwOSA0MS4zNjU1IDM0LjE0OTYgNDIuNDU2OSAzNS4yNDFMNDYuNSAzOS4yODQxTDQ4LjI2OTQgMzcuNTE0NkM0OS4zNzU3IDM2LjQwODMgNTEuMTk4IDM2LjUwOTMgNTIuMTc1NCAzNy43MzA5TDUyLjQ5OTUgMzguMTM2MUM1Mi41IDM3LjkxMzEgNTIuNSAzNy42NzY1IDUyLjUgMzcuNDI1VjM0LjU3NUM1Mi41IDMzLjI5NjMgNTIuNDk5MSAzMi40MDUgNTIuNDQyNCAzMS43MTFDNTIuMzg2OCAzMS4wMzAyIDUyLjI4MzEgMzAuNjM5MSA1Mi4xMzIxIDMwLjM0MjhDNTEuODA4NiAyOS43MDc3IDUxLjI5MjMgMjkuMTkxNCA1MC42NTcyIDI4Ljg2NzlDNTAuMzYwOSAyOC43MTY5IDQ5Ljk2OTggMjguNjEzMiA0OS4yODkgMjguNTU3NkM0OC41OTUgMjguNTAwOSA0Ny43MDM3IDI4LjUgNDYuNDI1IDI4LjVINDMuNTc1QzQyLjI5NjMgMjguNSA0MS40MDUgMjguNTAwOSA0MC43MTEgMjguNTU3NlpNMzcuNTU3NiA0MC4yODlDMzcuNTU0MyA0MC4yNDkyIDM3LjU1MTMgNDAuMjA4OCAzNy41NDg0IDQwLjE2NzhDMzcuNTcxMSA0MC4xNDQ4IDM3LjU5MzEgNDAuMTIwNiAzNy42MTQyIDQwLjA5NTNMNDAuMzEyNyAzNi44NTcxQzQwLjQ1MzkgMzYuNjg3NyA0MC43MSAzNi42NzYxIDQwLjg2NTkgMzYuODMyTDQ1LjcwNDUgNDEuNjcwNkM0Ni4xNDM4IDQyLjEwOTkgNDYuODU2MSA0Mi4xMDk5IDQ3LjI5NTUgNDEuNjcwNkw0OS44NjA0IDM5LjEwNTZDNTAuMDE4NSAzOC45NDc2IDUwLjI3ODggMzguOTYyIDUwLjQxODQgMzkuMTM2NUw1Mi4yMzc3IDQxLjQxMDdDNTIuMjA1NiA0MS41MDEgNTIuMTcwNCA0MS41ODIyIDUyLjEzMjEgNDEuNjU3MkM1MS44MDg2IDQyLjI5MjMgNTEuMjkyMyA0Mi44MDg2IDUwLjY1NzIgNDMuMTMyMUM1MC4zNjA5IDQzLjI4MzEgNDkuOTY5OCA0My4zODY4IDQ5LjI4OSA0My40NDI0QzQ4LjU5NSA0My40OTkxIDQ3LjcwMzcgNDMuNSA0Ni40MjUgNDMuNUg0My41NzVDNDIuMjk2MyA0My41IDQxLjQwNSA0My40OTkxIDQwLjcxMSA0My40NDI0QzQwLjAzMDIgNDMuMzg2OCAzOS42MzkxIDQzLjI4MzEgMzkuMzQyOCA0My4xMzIxQzM4LjcwNzcgNDIuODA4NiAzOC4xOTE0IDQyLjI5MjMgMzcuODY3OSA0MS42NTcyQzM3LjcxNjkgNDEuMzYwOSAzNy42MTMyIDQwLjk2OTggMzcuNTU3NiA0MC4yODlaIgogICAgZmlsbD0iIzYxNjE2MSIKICAvPgo8L3N2Zz4K";
200
202
 
201
203
  var SvgArrowRightIcon = function SvgArrowRightIcon(props) {
202
- return /*#__PURE__*/React.createElement("svg", Object.assign({
204
+ return /*#__PURE__*/React__default.createElement("svg", Object.assign({
203
205
  viewBox: "0 0 20 20"
204
- }, props), /*#__PURE__*/React.createElement("path", {
206
+ }, props), /*#__PURE__*/React__default.createElement("path", {
205
207
  fillRule: "evenodd",
206
208
  d: "M3.5 10a.75.75 0 0 1 .75-.75h9.69l-2.72-2.72a.75.75 0 1 1 1.06-1.06l4 4a.75.75 0 0 1 0 1.06l-4 4a.75.75 0 0 1-1.06-1.06l2.72-2.72h-9.69a.75.75 0 0 1-.75-.75Z"
207
209
  }));
@@ -209,9 +211,9 @@ var SvgArrowRightIcon = function SvgArrowRightIcon(props) {
209
211
  SvgArrowRightIcon.displayName = "ArrowRightIcon";
210
212
 
211
213
  var SvgCalendarIcon = function SvgCalendarIcon(props) {
212
- return /*#__PURE__*/React.createElement("svg", Object.assign({
214
+ return /*#__PURE__*/React__default.createElement("svg", Object.assign({
213
215
  viewBox: "0 0 20 20"
214
- }, props), /*#__PURE__*/React.createElement("path", {
216
+ }, props), /*#__PURE__*/React__default.createElement("path", {
215
217
  fillRule: "evenodd",
216
218
  d: "M7.75 3.5a.75.75 0 0 0-1.5 0v.407a3.075 3.075 0 0 0-.702.252 3.75 3.75 0 0 0-1.64 1.639c-.226.444-.32.924-.365 1.47-.043.531-.043 1.187-.043 2v1.464c0 .813 0 1.469.043 2 .045.546.14 1.026.366 1.47a3.75 3.75 0 0 0 1.639 1.64c.444.226.924.32 1.47.365.531.043 1.187.043 2 .043h3.383c.323 0 .542 0 .735-.02a3.75 3.75 0 0 0 3.344-3.344c.02-.193.02-.412.02-.735v-2.883c0-.813 0-1.469-.043-2-.045-.546-.14-1.026-.366-1.47a3.75 3.75 0 0 0-1.639-1.64 3.076 3.076 0 0 0-.702-.251v-.407a.75.75 0 0 0-1.5 0v.259c-.373-.009-.794-.009-1.268-.009h-1.964c-.474 0-.895 0-1.268.009v-.259Zm-1.521 1.995c.197-.1.458-.17.912-.207.462-.037 1.057-.038 1.909-.038h1.9c.853 0 1.447 0 1.91.038.453.037.714.107.912.207.423.216.767.56.983.984.1.197.17.458.207.912.014.18.024.38.029.609h-9.982c.006-.228.015-.429.03-.61.036-.453.106-.714.206-.911a2.25 2.25 0 0 1 .984-.984Zm-1.229 4.005v1.2c0 .853 0 1.447.038 1.91.037.453.107.714.207.912.216.423.56.767.984.983.197.1.458.17.912.207.462.037 1.057.038 1.909.038h3.306c.385 0 .52-.001.626-.012a2.25 2.25 0 0 0 2.006-2.006c.011-.106.012-.241.012-.626v-2.606h-10Z"
217
219
  }));
@@ -219,9 +221,9 @@ var SvgCalendarIcon = function SvgCalendarIcon(props) {
219
221
  SvgCalendarIcon.displayName = "CalendarIcon";
220
222
 
221
223
  var SvgCheckIcon = function SvgCheckIcon(props) {
222
- return /*#__PURE__*/React.createElement("svg", Object.assign({
224
+ return /*#__PURE__*/React__default.createElement("svg", Object.assign({
223
225
  viewBox: "0 0 20 20"
224
- }, props), /*#__PURE__*/React.createElement("path", {
226
+ }, props), /*#__PURE__*/React__default.createElement("path", {
225
227
  fillRule: "evenodd",
226
228
  d: "M15.78 5.97a.75.75 0 0 1 0 1.06l-6.5 6.5a.75.75 0 0 1-1.06 0l-3.25-3.25a.75.75 0 1 1 1.06-1.06l2.72 2.72 5.97-5.97a.75.75 0 0 1 1.06 0Z"
227
229
  }));
@@ -229,9 +231,9 @@ var SvgCheckIcon = function SvgCheckIcon(props) {
229
231
  SvgCheckIcon.displayName = "CheckIcon";
230
232
 
231
233
  var SvgChevronDownIcon = function SvgChevronDownIcon(props) {
232
- return /*#__PURE__*/React.createElement("svg", Object.assign({
234
+ return /*#__PURE__*/React__default.createElement("svg", Object.assign({
233
235
  viewBox: "0 0 20 20"
234
- }, props), /*#__PURE__*/React.createElement("path", {
236
+ }, props), /*#__PURE__*/React__default.createElement("path", {
235
237
  fillRule: "evenodd",
236
238
  d: "M5.72 8.47a.75.75 0 0 1 1.06 0l3.47 3.47 3.47-3.47a.75.75 0 1 1 1.06 1.06l-4 4a.75.75 0 0 1-1.06 0l-4-4a.75.75 0 0 1 0-1.06Z"
237
239
  }));
@@ -239,9 +241,9 @@ var SvgChevronDownIcon = function SvgChevronDownIcon(props) {
239
241
  SvgChevronDownIcon.displayName = "ChevronDownIcon";
240
242
 
241
243
  var SvgChevronRightIcon = function SvgChevronRightIcon(props) {
242
- return /*#__PURE__*/React.createElement("svg", Object.assign({
244
+ return /*#__PURE__*/React__default.createElement("svg", Object.assign({
243
245
  viewBox: "0 0 20 20"
244
- }, props), /*#__PURE__*/React.createElement("path", {
246
+ }, props), /*#__PURE__*/React__default.createElement("path", {
245
247
  fillRule: "evenodd",
246
248
  d: "M7.72 14.53a.75.75 0 0 1 0-1.06l3.47-3.47-3.47-3.47a.75.75 0 0 1 1.06-1.06l4 4a.75.75 0 0 1 0 1.06l-4 4a.75.75 0 0 1-1.06 0Z"
247
249
  }));
@@ -249,9 +251,9 @@ var SvgChevronRightIcon = function SvgChevronRightIcon(props) {
249
251
  SvgChevronRightIcon.displayName = "ChevronRightIcon";
250
252
 
251
253
  var SvgChevronUpIcon = function SvgChevronUpIcon(props) {
252
- return /*#__PURE__*/React.createElement("svg", Object.assign({
254
+ return /*#__PURE__*/React__default.createElement("svg", Object.assign({
253
255
  viewBox: "0 0 20 20"
254
- }, props), /*#__PURE__*/React.createElement("path", {
256
+ }, props), /*#__PURE__*/React__default.createElement("path", {
255
257
  fillRule: "evenodd",
256
258
  d: "M14.53 12.28a.75.75 0 0 1-1.06 0l-3.47-3.47-3.47 3.47a.75.75 0 0 1-1.06-1.06l4-4a.75.75 0 0 1 1.06 0l4 4a.75.75 0 0 1 0 1.06Z"
257
259
  }));
@@ -879,6 +881,118 @@ const GChartSkeleton = () => {
879
881
  return jsx(GSkeletonDisplayText, { height: "188px" });
880
882
  };
881
883
 
884
+ const useCurrencyRatesStore = create((set) => ({
885
+ currencyRates: null,
886
+ setCurrencyRates: (rates) => set({ currencyRates: rates }),
887
+ }));
888
+
889
+ const SHOPIFY_CURRENCIES_URL = 'https://cdn.shopify.com/s/javascripts/currencies.js';
890
+ const parseCurrencyRates = (scriptText) => {
891
+ const rates = {};
892
+ const match = /var Currency=\{rates:\{(.*?)\}\};/s.exec(scriptText);
893
+ const ratesStr = match?.[1];
894
+ if (!ratesStr)
895
+ return rates;
896
+ const ratePattern = /([A-Z]+):\s*([\d.e+-]+),/g;
897
+ let m;
898
+ while ((m = ratePattern.exec(ratesStr)) !== null) {
899
+ const [, code, value] = m;
900
+ if (code && value)
901
+ rates[code] = parseFloat(value);
902
+ }
903
+ return rates;
904
+ };
905
+ const fetchCurrencyRates = async () => {
906
+ const res = await fetch(SHOPIFY_CURRENCIES_URL);
907
+ if (!res.ok)
908
+ throw new Error('Failed to fetch currency rates');
909
+ const text = await res.text();
910
+ return parseCurrencyRates(text);
911
+ };
912
+ const useFetchCurrencyRates = () => {
913
+ const setCurrencyRates = useCurrencyRatesStore((state) => state.setCurrencyRates);
914
+ const { data } = useQuery({
915
+ queryKey: ['sdk-currency-rates'],
916
+ queryFn: fetchCurrencyRates,
917
+ staleTime: 1000 * 60 * 60, // 1 hour — rates don't change often
918
+ });
919
+ useEffect(() => {
920
+ if (data)
921
+ setCurrencyRates(data);
922
+ }, [data, setCurrencyRates]);
923
+ };
924
+
925
+ const getPriceByCurrency = (price, currency = DEFAULT_CURRENCY_ANALYTIC, options) => {
926
+ if (typeof price === 'string')
927
+ return price;
928
+ if (typeof price !== 'number')
929
+ return;
930
+ // Support legacy 3rd arg as locale string
931
+ const opts = typeof options === 'string' ? { locale: options } : options;
932
+ const locale = opts?.locale ?? 'en-US';
933
+ if (price >= 1_000_000_000) {
934
+ return `${new Intl.NumberFormat(locale, {
935
+ style: 'currency',
936
+ currency,
937
+ minimumFractionDigits: 2,
938
+ maximumFractionDigits: 2,
939
+ }).format(price / 1_000_000_000)}B`;
940
+ }
941
+ if (price >= 1_000_000) {
942
+ return `${new Intl.NumberFormat(locale, {
943
+ style: 'currency',
944
+ currency,
945
+ minimumFractionDigits: 2,
946
+ maximumFractionDigits: 2,
947
+ }).format(price / 1_000_000)}M`;
948
+ }
949
+ if (opts?.compact && Math.abs(price) >= 1_000) {
950
+ return `${new Intl.NumberFormat(locale, {
951
+ style: 'currency',
952
+ currency,
953
+ minimumFractionDigits: 1,
954
+ maximumFractionDigits: 1,
955
+ }).format(price / 1_000)}K`;
956
+ }
957
+ return new Intl.NumberFormat(locale, {
958
+ style: 'currency',
959
+ currency,
960
+ }).format(price);
961
+ };
962
+
963
+ const ConvertMoneyContext = createContext({
964
+ getTextPrice: (price) => {
965
+ if (typeof price === 'string')
966
+ return price;
967
+ return `${price ?? 0}`;
968
+ },
969
+ });
970
+ const convertAmount = (amount, from, to, rates) => {
971
+ if (from === to || !rates[from] || !rates[to])
972
+ return amount;
973
+ const converted = (amount * rates[from]) / rates[to];
974
+ return converted ? Number(converted.toFixed(2)) : amount;
975
+ };
976
+ const ConvertMoneyProvider = ({ children, currency, locale = 'en-US' }) => {
977
+ useFetchCurrencyRates();
978
+ const currencyRates = useCurrencyRatesStore((state) => state.currencyRates);
979
+ const getTextPrice = useCallback((price, _hasCurrency, options) => {
980
+ if (typeof price === 'string')
981
+ return price;
982
+ if (typeof price !== 'number')
983
+ return '0';
984
+ if (!currency)
985
+ return price.toString();
986
+ const converted = currencyRates
987
+ ? convertAmount(price, DEFAULT_CURRENCY_ANALYTIC, currency, currencyRates)
988
+ : price;
989
+ return trimDecimalZeros(getPriceByCurrency(converted, currency, { locale, compact: options?.compact }) ?? '0');
990
+ }, [currency, locale, currencyRates]);
991
+ const value = useMemo(() => ({ getTextPrice }), [getTextPrice]);
992
+ return jsx(ConvertMoneyContext.Provider, { value: value, children: children });
993
+ };
994
+ const useConvertMoneyContext = () => useContext(ConvertMoneyContext);
995
+
882
996
  const LINE_SERIES_COLORS = {
883
997
  comparison: SERIES_COLORS.comparison,
884
998
  single: SERIES_COLORS.current,
@@ -900,19 +1014,7 @@ const MetricChartProvider = ({ children, minHeight = CHART_MIN_HEIGHT, seriesCol
900
1014
  }, children: children }));
901
1015
  };
902
1016
 
903
- /**
904
- * Returns a stateful value, and a set of memoized functions to toggle it,
905
- * set it to true and set it to false
906
- */
907
- function useToggle(initialState) {
908
- const [value, setState] = useState(initialState);
909
- return {
910
- value,
911
- toggle: useCallback(() => setState((state) => !state), []),
912
- setTrue: useCallback(() => setState(true), []),
913
- setFalse: useCallback(() => setState(false), []),
914
- };
915
- }
1017
+ const useEnhancedEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
916
1018
 
917
1019
  const NONE_VALUE = 'None';
918
1020
  const PLACEHOLDER_VALUE = '-';
@@ -1169,8 +1271,10 @@ const readNumeric = (metric, key) => {
1169
1271
  return typeof raw === 'number' ? raw : 0;
1170
1272
  };
1171
1273
 
1172
- const useAnalyticData = (getTextPrice) => {
1274
+ const useAnalyticData = () => {
1275
+ const { getTextPrice } = useConvertMoneyContext();
1173
1276
  const formatData = ({ value, formatter, name }) => {
1277
+ console.log({ value, formatter, getTextPrice, name });
1174
1278
  return formatAnalyticData({ value, formatter, getTextPrice, name });
1175
1279
  };
1176
1280
  const computeMetric = ({ metric, previousMetric, metricKey, formatter, }) => {
@@ -1209,6 +1313,49 @@ const useFormatLineChartData = ({ metricKey, columnTypes }) => {
1209
1313
  return { formatValue, yAxisOptions };
1210
1314
  };
1211
1315
 
1316
+ const usePopoverResizeObserver = ({ active, onHeightChange, selector = '.Polaris-Popover__Content--fluidContent', }) => {
1317
+ useEffect(() => {
1318
+ if (!active)
1319
+ return;
1320
+ let resizeObserver = null;
1321
+ const setupResizeObserver = () => {
1322
+ const popoverContent = document.querySelector(selector);
1323
+ if (popoverContent && !resizeObserver) {
1324
+ resizeObserver = new ResizeObserver((entries) => {
1325
+ for (const entry of entries) {
1326
+ const { height } = entry.contentRect;
1327
+ onHeightChange?.(height);
1328
+ }
1329
+ });
1330
+ resizeObserver.observe(popoverContent);
1331
+ }
1332
+ };
1333
+ setTimeout(() => {
1334
+ setupResizeObserver();
1335
+ }, 200);
1336
+ return () => {
1337
+ if (resizeObserver) {
1338
+ resizeObserver.disconnect();
1339
+ resizeObserver = null;
1340
+ }
1341
+ };
1342
+ }, [active, selector]);
1343
+ };
1344
+
1345
+ /**
1346
+ * Returns a stateful value, and a set of memoized functions to toggle it,
1347
+ * set it to true and set it to false
1348
+ */
1349
+ function useToggle(initialState) {
1350
+ const [value, setState] = useState(initialState);
1351
+ return {
1352
+ value,
1353
+ toggle: useCallback(() => setState((state) => !state), []),
1354
+ setTrue: useCallback(() => setState(true), []),
1355
+ setFalse: useCallback(() => setState(false), []),
1356
+ };
1357
+ }
1358
+
1212
1359
  const useWindowSize = () => {
1213
1360
  const [windowSize, setWindowSize] = useState(() => ({
1214
1361
  width: typeof window !== 'undefined' ? window.innerWidth : 0,
@@ -2525,4 +2672,4 @@ const GTimePicker = (props) => {
2525
2672
  return (jsxs(InlineStack, { gap: "200", children: [jsx(MainTimePicker, { ...timePickerProps }), isCompare && (jsx(CompareTimePicker, { rangeAddition: timePickerProps.rangeAddition, popoverProps: timePickerProps.popoverProps }))] }));
2526
2673
  };
2527
2674
 
2528
- export { ANALYTICS_METRIC_TOOLTIP, AnalyticModeSelector, CAMPAIGN_BACKGROUND_MAIN, CHART_MIN_HEIGHT, COMPARE_DATE_TIME_FILTERS_MAP, CompareDateTimePickerAlias, CurrencySelector, DATE_TIME_COMPARISON_FILTERS, DEFAULT_CURRENCY_ANALYTIC, DEFAULT_CURRENT_PERIOD_LABEL, DEFAULT_PREVIOUS_PERIOD_LABEL, DateTimeFilterInputs, DateTimeFilters, DateTimePickerContext, DateTimePickerProvider, GSelectableMetricChartCard, GTimePicker, MainDateTimePickerAlias, MetricDonutChartCard, PLACEHOLDER_VALUE$1 as PLACEHOLDER_VALUE, PREVIOUS_PERIOD_FILTER, SERIES_COLORS, SingleMetricChartCard, TARGET_CHANNEL, TARGET_DEVICES, TARGET_VISITOR, THUMB_PRODUCT_DEFAULT, TREND_TONE, convertDateToTz, convertToDateTimeFilters, createLastDaysRange, dayjsTz, dayjsTzToDate, dayjsTzToLocalTZ, formatDate, formatDateTimeRange, formatDayjs, formatMs, formatTime, formatTimeRange, getDateRangeTitle, getDateTimeFilterBase, getDateTimeFilterByAlias, getDateTimeFilterMapping, getEndOfDayBy, getInitialTimezone, getLast12Months, getLast30Days, getLast365Days, getLast7Days, getLast90Days, getLastMonth, getLastYear, getMonthAndYearByDateFilter, getNoComparison, getPreviousMonth, getPreviousPeriod, getPreviousQuarter, getPreviousWeek, getPreviousYear, getToday, getVersionDateDescription, getVersionDateRangeTitle, getYesterday, isDate, isMidnight, isSameDayTimestamp, isValidDate, isValidYearMonthDayDateString, parseYearMonthDayDateString, setTz, useDateTimeFilter, useDateTimePicker, useDateTimePickerContext, useVersionDateTimeFilters };
2675
+ export { ANALYTICS_METRIC_TOOLTIP, AnalyticModeSelector, CAMPAIGN_BACKGROUND_MAIN, CHART_MIN_HEIGHT, COMPARE_DATE_TIME_FILTERS_MAP, CompareDateTimePickerAlias, ConvertMoneyProvider, CurrencySelector, DATE_TIME_COMPARISON_FILTERS, DEFAULT_CURRENCY_ANALYTIC, DEFAULT_CURRENT_PERIOD_LABEL, DEFAULT_PREVIOUS_PERIOD_LABEL, DateTimeFilterInputs, DateTimeFilters, DateTimePickerContext, DateTimePickerProvider, GSelectableMetricChartCard, GTimePicker, MainDateTimePickerAlias, MetricChartProvider, MetricDonutChartCard, PLACEHOLDER_VALUE$1 as PLACEHOLDER_VALUE, PREVIOUS_PERIOD_FILTER, SERIES_COLORS, SingleMetricChartCard, TARGET_CHANNEL, TARGET_DEVICES, TARGET_VISITOR, THUMB_PRODUCT_DEFAULT, TREND_TONE, convertDateToTz, convertToDateTimeFilters, createLastDaysRange, dayjsTz, dayjsTzToDate, dayjsTzToLocalTZ, formatDate, formatDateTimeRange, formatDayjs, formatMs, formatTime, formatTimeRange, getDateRangeTitle, getDateTimeFilterBase, getDateTimeFilterByAlias, getDateTimeFilterMapping, getEndOfDayBy, getInitialTimezone, getLast12Months, getLast30Days, getLast365Days, getLast7Days, getLast90Days, getLastMonth, getLastYear, getMonthAndYearByDateFilter, getNoComparison, getPreviousMonth, getPreviousPeriod, getPreviousQuarter, getPreviousWeek, getPreviousYear, getToday, getVersionDateDescription, getVersionDateRangeTitle, getYesterday, isDate, isMidnight, isSameDayTimestamp, isValidDate, isValidYearMonthDayDateString, parseYearMonthDayDateString, setTz, useConvertMoneyContext, useCurrencyRatesStore, useDateTimeFilter, useDateTimePicker, useDateTimePickerContext, useEnhancedEffect, useFetchCurrencyRates, useFormatLineChartData, usePopoverResizeObserver, useToggle, useVersionDateTimeFilters, useWindowSize };
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { IGetTextPrice } from '@/core/gemxql/helpers/formatAnalyticData';
3
+ interface IConvertMoneyContext {
4
+ getTextPrice: IGetTextPrice;
5
+ }
6
+ export interface IProps {
7
+ children: ReactNode;
8
+ currency?: string;
9
+ locale?: string;
10
+ }
11
+ export declare const ConvertMoneyProvider: ({ children, currency, locale }: IProps) => import("react/jsx-runtime").JSX.Element;
12
+ export declare const useConvertMoneyContext: () => IConvertMoneyContext;
13
+ export {};
@@ -0,0 +1,7 @@
1
+ export type ICurrencyRates = Record<string, number>;
2
+ interface ICurrencyRatesStore {
3
+ currencyRates: ICurrencyRates | null;
4
+ setCurrencyRates: (rates: ICurrencyRates) => void;
5
+ }
6
+ export declare const useCurrencyRatesStore: import("zustand").UseBoundStore<import("zustand").StoreApi<ICurrencyRatesStore>>;
7
+ export {};
@@ -1 +1,3 @@
1
+ export { ConvertMoneyProvider, useConvertMoneyContext } from './ConvertMoneyProvider';
2
+ export type { IProps as IConvertMoneyProviderProps } from './ConvertMoneyProvider';
1
3
  export { MetricChartProvider } from './MetricChartProvider';
@@ -0,0 +1 @@
1
+ export declare const useFetchCurrencyRates: () => void;
@@ -4,5 +4,5 @@ interface Props extends Pick<TooltipPositionParams, 'event' | 'eventType' | 'ind
4
4
  containerBounds: BoundingRect;
5
5
  parentElement: SVGSVGElement | null;
6
6
  }
7
- export declare function getDonutChartTooltipPosition({ containerBounds, event, eventType, index, parentElement }: Props): import("../types").TooltipPosition;
7
+ export declare function getDonutChartTooltipPosition({ containerBounds, event, eventType, index, parentElement }: Props): import("..").TooltipPosition;
8
8
  export {};