{"version":3,"file":"useTimeSync.cjs","sources":["../../../../../src/components/DateTimePickers/utils/useTimeSync.tsx"],"sourcesContent":["import { useCallback, useEffect, type JSX } from 'react';\nimport { usePrevious } from 'react-use';\n\nimport { TimeRange } from '@grafana/data';\n\nimport { useTimeRangeContext } from '../TimeRangeContext';\nimport { TimeSyncButton } from '../TimeSyncButton';\n\n/**\n * Handle the behaviour of the time sync button and syncing the time range between pickers. It also takes care of\n * backward compatibility with the manually controlled isSynced prop.\n * @param options\n */\nexport function useTimeSync(options: {\n  initialIsSynced?: boolean;\n  value: TimeRange;\n  isSyncedProp?: boolean;\n  timeSyncButtonProp?: JSX.Element;\n  onChangeProp: (value: TimeRange) => void;\n}) {\n  const { value, onChangeProp, isSyncedProp, initialIsSynced, timeSyncButtonProp } = options;\n  const timeRangeContext = useTimeRangeContext(initialIsSynced && value ? value : undefined);\n\n  // Destructure to make it easier to use in hook deps.\n  const timeRangeContextSynced = timeRangeContext?.synced;\n  const timeRangeContextSyncedValue = timeRangeContext?.syncedValue;\n  const timeRangeContextSyncFunc = timeRangeContext?.sync;\n\n  // This is to determine if we should use the context to sync or not. This is for backward compatibility so that\n  // Explore with multiple panes still works as it is controlling the sync state itself for now.\n  const usingTimeRangeContext = Boolean(options.isSyncedProp === undefined && timeRangeContext);\n\n  // Create new onChange that handles propagating the value to the context if possible and synced is true.\n  const onChangeWithSync = useCallback(\n    (timeRange: TimeRange) => {\n      onChangeProp(timeRange);\n      if (usingTimeRangeContext && timeRangeContextSynced) {\n        timeRangeContextSyncFunc?.(timeRange);\n      }\n    },\n    [onChangeProp, usingTimeRangeContext, timeRangeContextSyncFunc, timeRangeContextSynced]\n  );\n\n  const prevValue = usePrevious(value);\n  const prevSyncedValue = usePrevious(timeRangeContext?.syncedValue);\n\n  // As timepicker is controlled component we need to sync the global sync value back to the parent with onChange\n  // handler whenever the outside global value changes. We do it here while checking if we are actually supposed\n  // to and making sure we don't go into a loop.\n  useEffect(() => {\n    // only react if we are actually synced\n    if (usingTimeRangeContext && timeRangeContextSynced) {\n      if (value !== prevValue && value !== timeRangeContextSyncedValue) {\n        // The value changed outside the picker. To keep the sync working we need to update the synced value.\n        timeRangeContextSyncFunc?.(value);\n      } else if (\n        timeRangeContextSyncedValue &&\n        timeRangeContextSyncedValue !== prevSyncedValue &&\n        timeRangeContextSyncedValue !== value\n      ) {\n        // The global synced value changed, so we need to update the picker value.\n        onChangeProp(timeRangeContextSyncedValue);\n      }\n    }\n  }, [\n    usingTimeRangeContext,\n    timeRangeContextSynced,\n    timeRangeContextSyncedValue,\n    timeRangeContextSyncFunc,\n    prevSyncedValue,\n    value,\n    prevValue,\n    onChangeProp,\n  ]);\n\n  // Decide if we are in synced state or not. This is complicated by the manual controlled isSynced prop that is used\n  // in Explore for now.\n  const isSynced = usingTimeRangeContext ? timeRangeContext?.synced : isSyncedProp;\n\n  // Again in Explore the sync button is controlled prop so here we also decide what kind of button to use.\n  const button = usingTimeRangeContext\n    ? timeRangeContext?.syncPossible && (\n        <TimeSyncButton\n          isSynced={timeRangeContext?.synced}\n          onClick={() => (timeRangeContext?.synced ? timeRangeContext.unSync() : timeRangeContext.sync(value))}\n        />\n      )\n    : timeSyncButtonProp;\n\n  return {\n    onChangeWithSync,\n    isSynced,\n    timeSyncButton: button,\n  };\n}\n"],"names":["useTimeRangeContext","useCallback","usePrevious","useEffect","jsx","TimeSyncButton"],"mappings":";;;;;;;;;;;AAaO,SAAS,YAAY,OAAA,EAMzB;AACD,EAAA,MAAM,EAAE,KAAA,EAAO,YAAA,EAAc,YAAA,EAAc,eAAA,EAAiB,oBAAmB,GAAI,OAAA;AACnF,EAAA,MAAM,gBAAA,GAAmBA,oCAAA,CAAoB,eAAA,IAAmB,KAAA,GAAQ,QAAQ,KAAA,CAAS,CAAA;AAGzF,EAAA,MAAM,yBAAyB,gBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAkB,MAAA;AACjD,EAAA,MAAM,8BAA8B,gBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAkB,WAAA;AACtD,EAAA,MAAM,2BAA2B,gBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAkB,IAAA;AAInD,EAAA,MAAM,qBAAA,GAAwB,OAAA,CAAQ,OAAA,CAAQ,YAAA,KAAiB,UAAa,gBAAgB,CAAA;AAG5F,EAAA,MAAM,gBAAA,GAAmBC,iBAAA;AAAA,IACvB,CAAC,SAAA,KAAyB;AACxB,MAAA,YAAA,CAAa,SAAS,CAAA;AACtB,MAAA,IAAI,yBAAyB,sBAAA,EAAwB;AACnD,QAAA,wBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,wBAAA,CAA2B,SAAA,CAAA;AAAA,MAC7B;AAAA,IACF,CAAA;AAAA,IACA,CAAC,YAAA,EAAc,qBAAA,EAAuB,wBAAA,EAA0B,sBAAsB;AAAA,GACxF;AAEA,EAAA,MAAM,SAAA,GAAYC,qBAAY,KAAK,CAAA;AACnC,EAAA,MAAM,eAAA,GAAkBA,oBAAA,CAAY,gBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAkB,WAAW,CAAA;AAKjE,EAAAC,eAAA,CAAU,MAAM;AAEd,IAAA,IAAI,yBAAyB,sBAAA,EAAwB;AACnD,MAAA,IAAI,KAAA,KAAU,SAAA,IAAa,KAAA,KAAU,2BAAA,EAA6B;AAEhE,QAAA,wBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,wBAAA,CAA2B,KAAA,CAAA;AAAA,MAC7B,CAAA,MAAA,IACE,2BAAA,IACA,2BAAA,KAAgC,eAAA,IAChC,gCAAgC,KAAA,EAChC;AAEA,QAAA,YAAA,CAAa,2BAA2B,CAAA;AAAA,MAC1C;AAAA,IACF;AAAA,EACF,CAAA,EAAG;AAAA,IACD,qBAAA;AAAA,IACA,sBAAA;AAAA,IACA,2BAAA;AAAA,IACA,wBAAA;AAAA,IACA,eAAA;AAAA,IACA,KAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACD,CAAA;AAID,EAAA,MAAM,QAAA,GAAW,qBAAA,GAAwB,gBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAkB,MAAA,GAAS,YAAA;AAGpE,EAAA,MAAM,MAAA,GAAS,qBAAA,GAAA,CACX,gBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAkB,YAAA,qBAChBC,cAAA;AAAA,IAACC,6BAAA;AAAA,IAAA;AAAA,MACC,UAAU,gBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAkB,MAAA;AAAA,MAC5B,OAAA,EAAS,OAAO,gBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAkB,MAAA,IAAS,iBAAiB,MAAA,EAAO,GAAI,gBAAA,CAAiB,IAAA,CAAK,KAAK;AAAA;AAAA,GACpG,GAEF,kBAAA;AAEJ,EAAA,OAAO;AAAA,IACL,gBAAA;AAAA,IACA,QAAA;AAAA,IACA,cAAA,EAAgB;AAAA,GAClB;AACF;;;;"}