@grafana/ui
Version:
Grafana Components Library
1 lines • 6.01 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,OAAA,EAMzB;AACD,EAAA,MAAM,EAAE,KAAA,EAAO,YAAA,EAAc,YAAA,EAAc,eAAA,EAAiB,oBAAmB,GAAI,OAAA;AACnF,EAAA,MAAM,gBAAA,GAAmB,mBAAA,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,GAAmB,WAAA;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,GAAY,YAAY,KAAK,CAAA;AACnC,EAAA,MAAM,eAAA,GAAkB,WAAA,CAAY,gBAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,gBAAA,CAAkB,WAAW,CAAA;AAKjE,EAAA,SAAA,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,qBAChB,GAAA;AAAA,IAAC,cAAA;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;;;;"}