@grafana/ui
Version:
Grafana Components Library
1 lines • 5.98 kB
Source Map (JSON)
{"version":3,"file":"useTimeSync.mjs","sources":["../../../../../src/components/DateTimePickers/utils/useTimeSync.tsx"],"sourcesContent":["import { useCallback, useEffect } 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":[],"mappings":";;;;;;AAaO,SAAS,YAAY,OAMzB,EAAA;AACD,EAAA,MAAM,EAAE,KAAO,EAAA,YAAA,EAAc,YAAc,EAAA,eAAA,EAAiB,oBAAuB,GAAA,OAAA;AACnF,EAAA,MAAM,gBAAmB,GAAA,mBAAA,CAAoB,eAAmB,IAAA,KAAA,GAAQ,QAAQ,KAAS,CAAA,CAAA;AAGzF,EAAA,MAAM,yBAAyB,gBAAkB,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAA,MAAA;AACjD,EAAA,MAAM,8BAA8B,gBAAkB,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAA,WAAA;AACtD,EAAA,MAAM,2BAA2B,gBAAkB,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAA,IAAA;AAInD,EAAA,MAAM,qBAAwB,GAAA,OAAA,CAAQ,OAAQ,CAAA,YAAA,KAAiB,UAAa,gBAAgB,CAAA;AAG5F,EAAA,MAAM,gBAAmB,GAAA,WAAA;AAAA,IACvB,CAAC,SAAyB,KAAA;AACxB,MAAA,YAAA,CAAa,SAAS,CAAA;AACtB,MAAA,IAAI,yBAAyB,sBAAwB,EAAA;AACnD,QAA2B,wBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,wBAAA,CAAA,SAAA,CAAA;AAAA;AAC7B,KACF;AAAA,IACA,CAAC,YAAA,EAAc,qBAAuB,EAAA,wBAAA,EAA0B,sBAAsB;AAAA,GACxF;AAEA,EAAM,MAAA,SAAA,GAAY,YAAY,KAAK,CAAA;AACnC,EAAM,MAAA,eAAA,GAAkB,WAAY,CAAA,gBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAkB,WAAW,CAAA;AAKjE,EAAA,SAAA,CAAU,MAAM;AAEd,IAAA,IAAI,yBAAyB,sBAAwB,EAAA;AACnD,MAAI,IAAA,KAAA,KAAU,SAAa,IAAA,KAAA,KAAU,2BAA6B,EAAA;AAEhE,QAA2B,wBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,wBAAA,CAAA,KAAA,CAAA;AAAA,OAE3B,MAAA,IAAA,2BAAA,IACA,2BAAgC,KAAA,eAAA,IAChC,gCAAgC,KAChC,EAAA;AAEA,QAAA,YAAA,CAAa,2BAA2B,CAAA;AAAA;AAC1C;AACF,GACC,EAAA;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,EAAM,MAAA,QAAA,GAAW,qBAAwB,GAAA,gBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAkB,MAAS,GAAA,YAAA;AAGpE,EAAM,MAAA,MAAA,GAAS,qBACX,GAAA,CAAA,gBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAkB,YAChB,qBAAA,GAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,UAAU,gBAAkB,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAA,MAAA;AAAA,MAC5B,OAAA,EAAS,OAAO,gBAAkB,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAA,MAAA,IAAS,iBAAiB,MAAO,EAAA,GAAI,gBAAiB,CAAA,IAAA,CAAK,KAAK;AAAA;AAAA,GAGtG,GAAA,kBAAA;AAEJ,EAAO,OAAA;AAAA,IACL,gBAAA;AAAA,IACA,QAAA;AAAA,IACA,cAAgB,EAAA;AAAA,GAClB;AACF;;;;"}