@gravity-ui/date-components 2.10.3 → 2.11.0

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 (103) hide show
  1. package/dist/cjs/components/RangeDateSelection/RangeDateSelection.css +28 -0
  2. package/dist/cjs/components/RangeDateSelection/RangeDateSelection.d.ts +24 -0
  3. package/dist/cjs/components/RangeDateSelection/RangeDateSelection.js +49 -0
  4. package/dist/cjs/components/RangeDateSelection/components/NowLine/NowLine.css +4 -0
  5. package/dist/cjs/components/RangeDateSelection/components/NowLine/NowLine.d.ts +2 -0
  6. package/dist/cjs/components/RangeDateSelection/components/NowLine/NowLine.js +42 -0
  7. package/dist/cjs/components/RangeDateSelection/components/Ruler/Ruler.d.ts +32 -0
  8. package/dist/cjs/components/RangeDateSelection/components/Ruler/Ruler.js +61 -0
  9. package/dist/cjs/components/RangeDateSelection/components/RulerViewport/RulerViewport.css +25 -0
  10. package/dist/cjs/components/RangeDateSelection/components/RulerViewport/RulerViewport.d.ts +13 -0
  11. package/dist/cjs/components/RangeDateSelection/components/RulerViewport/RulerViewport.js +35 -0
  12. package/dist/cjs/components/RangeDateSelection/components/SelectionControl/SelectionControl.css +78 -0
  13. package/dist/cjs/components/RangeDateSelection/components/SelectionControl/SelectionControl.d.ts +8 -0
  14. package/dist/cjs/components/RangeDateSelection/components/SelectionControl/SelectionControl.js +135 -0
  15. package/dist/cjs/components/RangeDateSelection/components/Ticks/MiddleTicks.d.ts +3 -0
  16. package/dist/cjs/components/RangeDateSelection/components/Ticks/MiddleTicks.js +10 -0
  17. package/dist/cjs/components/RangeDateSelection/components/Ticks/SlitTicks.d.ts +5 -0
  18. package/dist/cjs/components/RangeDateSelection/components/Ticks/SlitTicks.js +10 -0
  19. package/dist/cjs/components/RangeDateSelection/components/Ticks/Ticks.css +16 -0
  20. package/dist/cjs/components/RangeDateSelection/components/Ticks/Ticks.d.ts +18 -0
  21. package/dist/cjs/components/RangeDateSelection/components/Ticks/Ticks.js +52 -0
  22. package/dist/cjs/components/RangeDateSelection/components/Ticks/UnavialableTicks.d.ts +15 -0
  23. package/dist/cjs/components/RangeDateSelection/components/Ticks/UnavialableTicks.js +50 -0
  24. package/dist/cjs/components/RangeDateSelection/components/Ticks/utils.d.ts +24 -0
  25. package/dist/cjs/components/RangeDateSelection/components/Ticks/utils.js +166 -0
  26. package/dist/cjs/components/RangeDateSelection/hooks/useRangeDateSelectionState.d.ts +60 -0
  27. package/dist/cjs/components/RangeDateSelection/hooks/useRangeDateSelectionState.js +150 -0
  28. package/dist/cjs/components/RangeDateSelection/i18n/en.json +7 -0
  29. package/dist/cjs/components/RangeDateSelection/i18n/index.d.ts +1 -0
  30. package/dist/cjs/components/RangeDateSelection/i18n/index.js +11 -0
  31. package/dist/cjs/components/RangeDateSelection/i18n/ru.json +7 -0
  32. package/dist/cjs/components/RangeDateSelection/index.d.ts +3 -0
  33. package/dist/cjs/components/RangeDateSelection/index.js +18 -0
  34. package/dist/cjs/components/RangeDateSelection/utils/date.d.ts +2 -0
  35. package/dist/cjs/components/RangeDateSelection/utils/date.js +10 -0
  36. package/dist/cjs/components/RangeDateSelection/utils/span.d.ts +23 -0
  37. package/dist/cjs/components/RangeDateSelection/utils/span.js +27 -0
  38. package/dist/cjs/components/RelativeRangeDatePicker/components/Presets/i18n/index.d.ts +1 -1
  39. package/dist/cjs/components/index.d.ts +1 -0
  40. package/dist/cjs/components/index.js +1 -0
  41. package/dist/cjs/components/mixins.css +0 -0
  42. package/dist/cjs/components/utils/constants.d.ts +7 -0
  43. package/dist/cjs/components/utils/constants.js +10 -0
  44. package/dist/cjs/components/utils/filterDOMProps.d.ts +17 -0
  45. package/dist/cjs/components/utils/filterDOMProps.js +27 -0
  46. package/dist/cjs/hooks/useEventHandler.d.ts +1 -0
  47. package/dist/cjs/hooks/useEventHandler.js +24 -0
  48. package/dist/cjs/hooks/useMove.d.ts +31 -0
  49. package/dist/cjs/hooks/useMove.js +173 -0
  50. package/dist/cjs/hooks/useResizeObserver.d.ts +8 -0
  51. package/dist/cjs/hooks/useResizeObserver.js +32 -0
  52. package/dist/esm/components/RangeDateSelection/RangeDateSelection.css +28 -0
  53. package/dist/esm/components/RangeDateSelection/RangeDateSelection.d.ts +24 -0
  54. package/dist/esm/components/RangeDateSelection/RangeDateSelection.js +43 -0
  55. package/dist/esm/components/RangeDateSelection/components/NowLine/NowLine.css +4 -0
  56. package/dist/esm/components/RangeDateSelection/components/NowLine/NowLine.d.ts +2 -0
  57. package/dist/esm/components/RangeDateSelection/components/NowLine/NowLine.js +36 -0
  58. package/dist/esm/components/RangeDateSelection/components/Ruler/Ruler.d.ts +32 -0
  59. package/dist/esm/components/RangeDateSelection/components/Ruler/Ruler.js +53 -0
  60. package/dist/esm/components/RangeDateSelection/components/RulerViewport/RulerViewport.css +25 -0
  61. package/dist/esm/components/RangeDateSelection/components/RulerViewport/RulerViewport.d.ts +13 -0
  62. package/dist/esm/components/RangeDateSelection/components/RulerViewport/RulerViewport.js +29 -0
  63. package/dist/esm/components/RangeDateSelection/components/SelectionControl/SelectionControl.css +78 -0
  64. package/dist/esm/components/RangeDateSelection/components/SelectionControl/SelectionControl.d.ts +8 -0
  65. package/dist/esm/components/RangeDateSelection/components/SelectionControl/SelectionControl.js +132 -0
  66. package/dist/esm/components/RangeDateSelection/components/Ticks/MiddleTicks.d.ts +3 -0
  67. package/dist/esm/components/RangeDateSelection/components/Ticks/MiddleTicks.js +7 -0
  68. package/dist/esm/components/RangeDateSelection/components/Ticks/SlitTicks.d.ts +5 -0
  69. package/dist/esm/components/RangeDateSelection/components/Ticks/SlitTicks.js +7 -0
  70. package/dist/esm/components/RangeDateSelection/components/Ticks/Ticks.css +16 -0
  71. package/dist/esm/components/RangeDateSelection/components/Ticks/Ticks.d.ts +18 -0
  72. package/dist/esm/components/RangeDateSelection/components/Ticks/Ticks.js +44 -0
  73. package/dist/esm/components/RangeDateSelection/components/Ticks/UnavialableTicks.d.ts +15 -0
  74. package/dist/esm/components/RangeDateSelection/components/Ticks/UnavialableTicks.js +42 -0
  75. package/dist/esm/components/RangeDateSelection/components/Ticks/utils.d.ts +24 -0
  76. package/dist/esm/components/RangeDateSelection/components/Ticks/utils.js +158 -0
  77. package/dist/esm/components/RangeDateSelection/hooks/useRangeDateSelectionState.d.ts +60 -0
  78. package/dist/esm/components/RangeDateSelection/hooks/useRangeDateSelectionState.js +144 -0
  79. package/dist/esm/components/RangeDateSelection/i18n/en.json +7 -0
  80. package/dist/esm/components/RangeDateSelection/i18n/index.d.ts +1 -0
  81. package/dist/esm/components/RangeDateSelection/i18n/index.js +5 -0
  82. package/dist/esm/components/RangeDateSelection/i18n/ru.json +7 -0
  83. package/dist/esm/components/RangeDateSelection/index.d.ts +3 -0
  84. package/dist/esm/components/RangeDateSelection/index.js +2 -0
  85. package/dist/esm/components/RangeDateSelection/utils/date.d.ts +2 -0
  86. package/dist/esm/components/RangeDateSelection/utils/date.js +7 -0
  87. package/dist/esm/components/RangeDateSelection/utils/span.d.ts +23 -0
  88. package/dist/esm/components/RangeDateSelection/utils/span.js +23 -0
  89. package/dist/esm/components/RelativeRangeDatePicker/components/Presets/i18n/index.d.ts +1 -1
  90. package/dist/esm/components/index.d.ts +1 -0
  91. package/dist/esm/components/index.js +1 -0
  92. package/dist/esm/components/mixins.css +0 -0
  93. package/dist/esm/components/utils/constants.d.ts +7 -0
  94. package/dist/esm/components/utils/constants.js +7 -0
  95. package/dist/esm/components/utils/filterDOMProps.d.ts +17 -0
  96. package/dist/esm/components/utils/filterDOMProps.js +24 -0
  97. package/dist/esm/hooks/useEventHandler.d.ts +1 -0
  98. package/dist/esm/hooks/useEventHandler.js +18 -0
  99. package/dist/esm/hooks/useMove.d.ts +31 -0
  100. package/dist/esm/hooks/useMove.js +167 -0
  101. package/dist/esm/hooks/useResizeObserver.d.ts +8 -0
  102. package/dist/esm/hooks/useResizeObserver.js +26 -0
  103. package/package.json +1 -1
@@ -0,0 +1,28 @@
1
+ .g-date-range-date-selection {
2
+ display: grid;
3
+ align-items: center;
4
+ grid-template-areas: "buttons-start ruler buttons-end";
5
+ grid-template-columns: auto 1fr auto;
6
+ border-block: 1px solid var(--g-color-line-generic);
7
+ }
8
+ .g-date-range-date-selection__ruler {
9
+ grid-area: ruler;
10
+ }
11
+ .g-date-range-date-selection__ruler_dragging .g-date-range-date-selection__selection {
12
+ pointer-events: none;
13
+ }
14
+ .g-date-range-date-selection__buttons {
15
+ display: flex;
16
+ align-items: center;
17
+ height: 22px;
18
+ }
19
+ .g-date-range-date-selection__buttons_position_start {
20
+ grid-area: buttons-start;
21
+ padding-inline-end: var(--g-spacing-half);
22
+ border-inline-end: 1px solid var(--g-color-line-generic);
23
+ }
24
+ .g-date-range-date-selection__buttons_position_end {
25
+ grid-area: buttons-end;
26
+ padding-inline-start: var(--g-spacing-half);
27
+ border-inline-start: 1px solid var(--g-color-line-generic);
28
+ }
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import type { DateTime } from '@gravity-ui/date-utils';
3
+ import type { AccessibilityProps, DomProps, StyleProps } from '../types';
4
+ import type { ViewportDimensions, ViewportInterval } from './components/Ruler/Ruler';
5
+ import type { RangeDateSelectionOptions } from './hooks/useRangeDateSelectionState';
6
+ import './RangeDateSelection.css';
7
+ export interface RangeDateSelectionProps extends RangeDateSelectionOptions, DomProps, StyleProps, AccessibilityProps {
8
+ /** Formats time ticks */
9
+ formatTime?: (time: DateTime) => string;
10
+ /** Displays now line */
11
+ displayNow?: boolean;
12
+ /** Enables dragging ruler */
13
+ draggableRuler?: boolean;
14
+ /** Displays buttons to scale selection */
15
+ hasScaleButtons?: boolean;
16
+ /** Position of scale buttons */
17
+ scaleButtonsPosition?: 'start' | 'end';
18
+ /** Renders additional svg content in the ruler */
19
+ renderAdditionalRulerContent?: (props: {
20
+ interval: ViewportInterval;
21
+ dimensions: ViewportDimensions;
22
+ }) => React.ReactNode;
23
+ }
24
+ export declare function RangeDateSelection(props: RangeDateSelectionProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,49 @@
1
+ 'use client';
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.RangeDateSelection = RangeDateSelection;
8
+ const jsx_runtime_1 = require("react/jsx-runtime");
9
+ const react_1 = __importDefault(require("react"));
10
+ const icons_1 = require("@gravity-ui/icons");
11
+ const uikit_1 = require("@gravity-ui/uikit");
12
+ const cn_1 = require("../../utils/cn");
13
+ const filterDOMProps_1 = require("../utils/filterDOMProps");
14
+ const Ruler_1 = require("./components/Ruler/Ruler");
15
+ const SelectionControl_1 = require("./components/SelectionControl/SelectionControl");
16
+ const useRangeDateSelectionState_1 = require("./hooks/useRangeDateSelectionState");
17
+ const i18n_1 = require("./i18n");
18
+ require("./RangeDateSelection.css");
19
+ const b = (0, cn_1.block)('range-date-selection');
20
+ function RangeDateSelection(props) {
21
+ var _a, _b;
22
+ const state = (0, useRangeDateSelectionState_1.useRangeDateSelectionState)(props);
23
+ const [isDraggingRuler, setDraggingRuler] = react_1.default.useState(false);
24
+ const handleRulerMoveStart = () => {
25
+ state.setDraggingValue(state.value);
26
+ setDraggingRuler(true);
27
+ };
28
+ const handleRulerMove = (d) => {
29
+ const intervalWidth = state.viewportInterval.end.diff(state.viewportInterval.start);
30
+ const delta = -Math.floor((d * intervalWidth) / 100);
31
+ state.move(delta);
32
+ };
33
+ const handleRulerMoveEnd = () => {
34
+ setDraggingRuler(false);
35
+ state.endDragging();
36
+ };
37
+ let id = react_1.default.useId();
38
+ id = (_a = props.id) !== null && _a !== void 0 ? _a : id;
39
+ return ((0, jsx_runtime_1.jsxs)("div", Object.assign({}, (0, filterDOMProps_1.filterDOMProps)(props, { labelable: true }), { id: id, className: b(null, props.className), style: props.style, dir: "ltr" // TODO: RTL support
40
+ , children: [(0, jsx_runtime_1.jsx)(Ruler_1.DateTimeRuler, Object.assign({ className: b('ruler', { dragging: isDraggingRuler }) }, state.viewportInterval, { onMoveStart: handleRulerMoveStart, onMove: props.draggableRuler ? handleRulerMove : undefined, onMoveEnd: handleRulerMoveEnd, dragDisabled: state.isDragging, displayNow: props.displayNow, minValue: props.minValue, maxValue: props.maxValue, formatTime: props.formatTime, timeZone: state.timeZone, renderAdditionalRulerContent: props.renderAdditionalRulerContent, children: (0, jsx_runtime_1.jsx)(SelectionControl_1.SelectionControl, { className: b('selection'), state: state, "aria-labelledby": id }) })), props.hasScaleButtons ? ((0, jsx_runtime_1.jsxs)("div", { className: b('buttons', { position: (_b = props.scaleButtonsPosition) !== null && _b !== void 0 ? _b : 'start' }), children: [(0, jsx_runtime_1.jsx)(uikit_1.Button, { view: "flat-secondary", size: "xs", onClick: () => {
41
+ state.startDragging();
42
+ state.scale(0.5);
43
+ state.endDragging();
44
+ }, extraProps: { 'aria-label': (0, i18n_1.i18n)('Decrease range') }, children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Minus }) }), (0, jsx_runtime_1.jsx)(uikit_1.Button, { view: "flat-secondary", size: "xs", onClick: () => {
45
+ state.startDragging();
46
+ state.scale(1.5);
47
+ state.endDragging();
48
+ }, extraProps: { 'aria-label': (0, i18n_1.i18n)('Increase range') }, children: (0, jsx_runtime_1.jsx)(uikit_1.Icon, { data: icons_1.Plus }) })] })) : null] })));
49
+ }
@@ -0,0 +1,4 @@
1
+ .g-date-timeline-now-line {
2
+ stroke: var(--g-date-thin-timeline-now-color);
3
+ stroke-width: 2px;
4
+ }
@@ -0,0 +1,2 @@
1
+ import './NowLine.css';
2
+ export declare function NowLine(): import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.NowLine = NowLine;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const react_1 = __importDefault(require("react"));
9
+ const cn_1 = require("../../../../utils/cn");
10
+ const constants_1 = require("../../../utils/constants");
11
+ const Ruler_1 = require("../Ruler/Ruler");
12
+ const MIN_UPDATE_DISTANCE = 4; // in px
13
+ require("./NowLine.css");
14
+ const b = (0, cn_1.block)('timeline-now-line');
15
+ function NowLine() {
16
+ const viewport = (0, Ruler_1.useViewportDimensions)();
17
+ const { start: startDate, end: endDate } = (0, Ruler_1.useViewportInterval)();
18
+ const [, rerender] = react_1.default.useState({});
19
+ const nowTime = Date.now();
20
+ const needUpdateNow = endDate.valueOf() > nowTime;
21
+ const interval = Math.max(constants_1.SECOND, (MIN_UPDATE_DISTANCE * endDate.diff(startDate)) / viewport.width, startDate.valueOf() - nowTime);
22
+ react_1.default.useEffect(() => {
23
+ let timer = null;
24
+ if (needUpdateNow) {
25
+ timer = window.setInterval(() => {
26
+ rerender({});
27
+ }, interval);
28
+ }
29
+ return () => {
30
+ if (timer) {
31
+ window.clearInterval(timer);
32
+ timer = null;
33
+ }
34
+ };
35
+ }, [needUpdateNow, interval]);
36
+ if (nowTime < startDate.valueOf() || endDate.valueOf() < nowTime) {
37
+ return null;
38
+ }
39
+ const nowX = ((nowTime - startDate.valueOf()) / (endDate.valueOf() - startDate.valueOf())) *
40
+ viewport.width;
41
+ return (0, jsx_runtime_1.jsx)("path", { d: `M${nowX},0l0,${viewport.height}`, className: b() });
42
+ }
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import type { DateTime } from '@gravity-ui/date-utils';
3
+ import type { MoveEndEvent, MoveMoveEvent, MoveStartEvent } from '../../../../hooks/useMove';
4
+ import type { RangeValue } from '../../../types';
5
+ interface RulerProps {
6
+ className?: string;
7
+ children?: React.ReactNode;
8
+ start: DateTime;
9
+ end: DateTime;
10
+ minValue?: DateTime;
11
+ maxValue?: DateTime;
12
+ onMoveStart?: (event: MoveStartEvent) => void;
13
+ onMove?: (delta: number, event: MoveMoveEvent) => void;
14
+ onMoveEnd?: (event: MoveEndEvent) => void;
15
+ displayNow?: boolean;
16
+ formatTime?: (time: DateTime) => string;
17
+ timeZone?: string;
18
+ dragDisabled?: boolean;
19
+ renderAdditionalRulerContent?: (props: {
20
+ interval: ViewportInterval;
21
+ dimensions: ViewportDimensions;
22
+ }) => React.ReactNode;
23
+ }
24
+ export interface ViewportDimensions {
25
+ width: number;
26
+ height: number;
27
+ }
28
+ export type ViewportInterval = RangeValue<DateTime>;
29
+ export declare function DateTimeRuler({ className, children, start, end, minValue, maxValue, onMove, onMoveStart, onMoveEnd, displayNow, formatTime, timeZone, dragDisabled, renderAdditionalRulerContent, }: RulerProps): import("react/jsx-runtime").JSX.Element;
30
+ export declare function useViewportDimensions(): ViewportDimensions;
31
+ export declare function useViewportInterval(): ViewportInterval;
32
+ export {};
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DateTimeRuler = DateTimeRuler;
7
+ exports.useViewportDimensions = useViewportDimensions;
8
+ exports.useViewportInterval = useViewportInterval;
9
+ const jsx_runtime_1 = require("react/jsx-runtime");
10
+ const react_1 = __importDefault(require("react"));
11
+ const react_dom_1 = __importDefault(require("react-dom"));
12
+ const useResizeObserver_1 = require("../../../../hooks/useResizeObserver");
13
+ const cn_1 = require("../../../../utils/cn");
14
+ const NowLine_1 = require("../NowLine/NowLine");
15
+ const RulerViewport_1 = require("../RulerViewport/RulerViewport");
16
+ const MiddleTicks_1 = require("../Ticks/MiddleTicks");
17
+ const SlitTicks_1 = require("../Ticks/SlitTicks");
18
+ const UnavialableTicks_1 = require("../Ticks/UnavialableTicks");
19
+ const utils_1 = require("../Ticks/utils");
20
+ const b = (0, cn_1.block)('ruler');
21
+ const viewportDimensionsContext = react_1.default.createContext(null);
22
+ const viewportIntervalContext = react_1.default.createContext(null);
23
+ function DateTimeRuler({ className, children, start, end, minValue, maxValue, onMove, onMoveStart, onMoveEnd, displayNow, formatTime, timeZone, dragDisabled, renderAdditionalRulerContent, }) {
24
+ const [container, setContainer] = react_1.default.useState(null);
25
+ const viewportInterval = react_1.default.useMemo(() => ({ start, end }), [start, end]);
26
+ const [viewportDimensions, setViewportDimensions] = react_1.default.useState({
27
+ width: 0,
28
+ height: 0,
29
+ });
30
+ const onResize = react_1.default.useCallback(() => {
31
+ if (!container) {
32
+ return;
33
+ }
34
+ const { width, height } = container.getBoundingClientRect();
35
+ setViewportDimensions({ width, height });
36
+ }, [container]);
37
+ const containerRef = react_1.default.useMemo(() => ({ current: container }), [container]);
38
+ (0, useResizeObserver_1.useResizeObserver)({ ref: containerRef, onResize });
39
+ const hasConstrains = Boolean(minValue || maxValue);
40
+ return ((0, jsx_runtime_1.jsx)("div", { className: b(null, className), children: (0, jsx_runtime_1.jsx)(viewportIntervalContext.Provider, { value: viewportInterval, children: (0, jsx_runtime_1.jsxs)(viewportDimensionsContext.Provider, { value: viewportDimensions, children: [(0, jsx_runtime_1.jsxs)(RulerViewport_1.RulerViewport, { ref: setContainer, onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd, dragDisabled: dragDisabled, children: [(0, jsx_runtime_1.jsx)(MiddleTicks_1.MiddleTicks, { timeZone: timeZone }), (0, jsx_runtime_1.jsx)(SlitTicks_1.SlitTicks, { formatTime: formatTime, timeZone: timeZone }), hasConstrains ? ((0, jsx_runtime_1.jsx)(UnavialableTicks_1.UnavailableTicks, { theme: "dim", minValue: minValue, maxValue: maxValue, geometry: (0, utils_1.makeUnavailableTicksGeometry)({
41
+ tickHeight: 10,
42
+ viewportHeight: viewportDimensions.height,
43
+ }), tickWidth: viewportDimensions.height + 10 })) : null, displayNow ? (0, jsx_runtime_1.jsx)(NowLine_1.NowLine, {}) : null, renderAdditionalRulerContent === null || renderAdditionalRulerContent === void 0 ? void 0 : renderAdditionalRulerContent({
44
+ interval: viewportInterval,
45
+ dimensions: viewportDimensions,
46
+ })] }), container ? react_dom_1.default.createPortal(children, container) : null] }) }) }));
47
+ }
48
+ function useViewportDimensions() {
49
+ const viewport = react_1.default.useContext(viewportDimensionsContext);
50
+ if (!viewport) {
51
+ throw new Error('useViewportDimensions must be used within a RulerViewport');
52
+ }
53
+ return viewport;
54
+ }
55
+ function useViewportInterval() {
56
+ const viewport = react_1.default.useContext(viewportIntervalContext);
57
+ if (!viewport) {
58
+ throw new Error('useViewportInterval must be used within a RulerViewport');
59
+ }
60
+ return viewport;
61
+ }
@@ -0,0 +1,25 @@
1
+ .g-date-ruler-viewport {
2
+ --_--g-date-ruler-viewport-background: var(
3
+ --g-date-ruler-viewport-background,
4
+ var(--g-color-base-background)
5
+ );
6
+ --g-date-thin-timeline-height: 22px;
7
+ --g-date-thin-timeline-now-color: var(--g-color-line-danger);
8
+ position: relative;
9
+ box-sizing: border-box;
10
+ height: var(--g-date-thin-timeline-height);
11
+ }
12
+ .g-date-ruler-viewport__dragger {
13
+ position: absolute;
14
+ inset: 0;
15
+ cursor: grab;
16
+ }
17
+ .g-date-ruler-viewport__dragger:focus-visible {
18
+ outline: 2px solid var(--g-color-line-focus);
19
+ }
20
+ .g-date-ruler-viewport__dragger_disabled {
21
+ pointer-events: none;
22
+ }
23
+ .g-date-ruler-viewport__svg {
24
+ pointer-events: none;
25
+ }
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ import type { MoveEndEvent, MoveMoveEvent, MoveStartEvent } from '../../../../hooks/useMove';
3
+ import './RulerViewport.css';
4
+ interface RulerViewportProps {
5
+ className?: string;
6
+ children?: React.ReactNode;
7
+ onMoveStart?: (event: MoveStartEvent) => void;
8
+ onMove?: (delta: number, event: MoveMoveEvent) => void;
9
+ onMoveEnd?: (event: MoveEndEvent) => void;
10
+ dragDisabled?: boolean;
11
+ }
12
+ declare const _RulerViewport: React.ForwardRefExoticComponent<RulerViewportProps & React.RefAttributes<HTMLDivElement>>;
13
+ export { _RulerViewport as RulerViewport };
@@ -0,0 +1,35 @@
1
+ 'use client';
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.RulerViewport = void 0;
8
+ const jsx_runtime_1 = require("react/jsx-runtime");
9
+ const react_1 = __importDefault(require("react"));
10
+ const useMove_1 = require("../../../../hooks/useMove");
11
+ const cn_1 = require("../../../../utils/cn");
12
+ require("./RulerViewport.css");
13
+ const b = (0, cn_1.block)('ruler-viewport');
14
+ function RulerViewport({ className, children, onMove, onMoveStart, onMoveEnd, dragDisabled }, ref) {
15
+ const containerRef = react_1.default.useRef(null);
16
+ const draggable = typeof onMove === 'function';
17
+ const { moveProps } = (0, useMove_1.useMove)({
18
+ onMoveStart: onMoveStart,
19
+ onMove: (e) => {
20
+ const container = containerRef.current;
21
+ if (e.deltaX !== 0 && container) {
22
+ const { width } = container.getBoundingClientRect();
23
+ let delta = (e.deltaX * 100) / width;
24
+ delta = Math.round(delta * 100) / 100;
25
+ if (delta !== 0) {
26
+ onMove === null || onMove === void 0 ? void 0 : onMove(delta, e);
27
+ }
28
+ }
29
+ },
30
+ onMoveEnd: onMoveEnd,
31
+ });
32
+ return ((0, jsx_runtime_1.jsxs)("div", { ref: ref, className: b(null, className), children: [(0, jsx_runtime_1.jsxs)("svg", { ref: containerRef, className: b('svg'), width: "100%", height: "100%", xmlns: "http://www.w3.org/2000/svg", xmlnsXlink: "http://www.w3.org/1999/xlink", children: [(0, jsx_runtime_1.jsx)("defs", { children: (0, jsx_runtime_1.jsxs)("filter", { x: "0", y: "0", width: "1", height: "1", id: "g-date-tt-ticklabelbg", children: [(0, jsx_runtime_1.jsx)("feFlood", { floodColor: "var(--_--g-date-ruler-viewport-background)" }), (0, jsx_runtime_1.jsx)("feComposite", { in: "SourceGraphic" })] }) }), children] }), draggable ? ((0, jsx_runtime_1.jsx)("div", Object.assign({ className: b('dragger', { disabled: dragDisabled }) }, moveProps))) : null] }));
33
+ }
34
+ const _RulerViewport = react_1.default.forwardRef(RulerViewport);
35
+ exports.RulerViewport = _RulerViewport;
@@ -0,0 +1,78 @@
1
+ .g-date-range-date-selection-control {
2
+ --_--g-date-timeline-color-selection: var(
3
+ --g-date-timeline-color-selection,
4
+ var(--g-color-base-info-light)
5
+ );
6
+ --_--g-date-timeline-color-selection-hover: var(
7
+ --g-date-timeline-color-selection-hover,
8
+ var(--g-color-base-info-light-hover)
9
+ );
10
+ --_--g-date-timeline-color-selection-handle: var(
11
+ --g-date-timeline-color-selection-handle,
12
+ var(--g-color-base-brand)
13
+ );
14
+ --_--g-date-timeline-color-selection-handle-hover: var(
15
+ --g-date-timeline-color-selection-handle-hover,
16
+ var(--g-color-base-brand-hover)
17
+ );
18
+ position: absolute;
19
+ z-index: 1;
20
+ inset-block: 0;
21
+ }
22
+ @supports (selector(:has(*))) and (selector(:focus-visible)) {
23
+ .g-date-range-date-selection-control__start:has(.g-date-range-date-selection-control__slider-input:focus-visible), .g-date-range-date-selection-control__end:has(.g-date-range-date-selection-control__slider-input:focus-visible), .g-date-range-date-selection-control__dragger:has(.g-date-range-date-selection-control__slider-input:focus-visible) {
24
+ border-radius: var(--g-border-radius-xs);
25
+ outline: var(--g-color-line-focus) solid 2px;
26
+ }
27
+ }
28
+ @supports not (selector(:has(*))) {
29
+ .g-date-range-date-selection-control__start:focus-within, .g-date-range-date-selection-control__end:focus-within, .g-date-range-date-selection-control__dragger:focus-within {
30
+ border-radius: var(--g-border-radius-xs);
31
+ outline: var(--g-color-line-focus) solid 2px;
32
+ }
33
+ }
34
+ .g-date-range-date-selection-control__dragger {
35
+ position: absolute;
36
+ inset-block: 0;
37
+ inset-inline: 2px;
38
+ cursor: move;
39
+ background: var(--_--g-date-timeline-color-selection);
40
+ }
41
+ .g-date-range-date-selection-control__dragger:hover, .g-date-range-date-selection-control__dragger_dragging {
42
+ background: var(--_--g-date-timeline-color-selection-hover);
43
+ }
44
+ .g-date-range-date-selection-control__dragger_disabled {
45
+ pointer-events: none;
46
+ }
47
+ .g-date-range-date-selection-control__start {
48
+ position: absolute;
49
+ inset-block: 0;
50
+ inset-inline-start: 0;
51
+ width: 4px;
52
+ background: var(--_--g-date-timeline-color-selection-handle);
53
+ }
54
+ .g-date-range-date-selection-control__end {
55
+ position: absolute;
56
+ inset-inline-end: 0;
57
+ width: 4px;
58
+ height: 100%;
59
+ background: var(--_--g-date-timeline-color-selection-handle);
60
+ }
61
+ .g-date-range-date-selection-control__start, .g-date-range-date-selection-control__end {
62
+ cursor: ew-resize;
63
+ }
64
+ .g-date-range-date-selection-control__start:hover, .g-date-range-date-selection-control__start_dragging, .g-date-range-date-selection-control__end:hover, .g-date-range-date-selection-control__end_dragging {
65
+ background: var(--_--g-date-timeline-color-selection-handle-hover);
66
+ }
67
+ .g-date-range-date-selection-control__slider-input-wrapper {
68
+ position: absolute;
69
+ overflow: hidden;
70
+ clip: rect(0, 0, 0, 0);
71
+ width: 1px;
72
+ height: 1px;
73
+ margin: -1px;
74
+ padding: 0;
75
+ white-space: nowrap;
76
+ border: 0;
77
+ clip-path: inset(50%);
78
+ }
@@ -0,0 +1,8 @@
1
+ import type { AccessibilityProps, DomProps, StyleProps } from '../../../types';
2
+ import type { RangeDateSelectionState } from '../../hooks/useRangeDateSelectionState';
3
+ import './SelectionControl.css';
4
+ interface SelectionControlProps extends DomProps, StyleProps, AccessibilityProps {
5
+ state: RangeDateSelectionState;
6
+ }
7
+ export declare function SelectionControl({ state, style, className, ...props }: SelectionControlProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SelectionControl = SelectionControl;
4
+ const tslib_1 = require("tslib");
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = tslib_1.__importDefault(require("react"));
7
+ const useMove_1 = require("../../../../hooks/useMove");
8
+ const cn_1 = require("../../../../utils/cn");
9
+ const i18n_1 = require("../../i18n");
10
+ const span_1 = require("../../utils/span");
11
+ const Ruler_1 = require("../Ruler/Ruler");
12
+ require("./SelectionControl.css");
13
+ const b = (0, cn_1.block)('range-date-selection-control');
14
+ const MIN_SELECTION_WIDTH = 12; // px;
15
+ const MIN_DRAG_SCALE = 0.01;
16
+ const MAX_DRAG_SCALE = 100;
17
+ const DRAG_SCALE_STRENGTH = 20;
18
+ function SelectionControl(_a) {
19
+ var _b;
20
+ var { state, style, className } = _a, props = tslib_1.__rest(_a, ["state", "style", "className"]);
21
+ const { start: startDate, end: endDate } = (0, Ruler_1.useViewportInterval)();
22
+ const viewport = (0, Ruler_1.useViewportDimensions)();
23
+ const [isDragging, setIsDragging] = react_1.default.useState(null);
24
+ const moveDataRef = react_1.default.useRef({
25
+ isZooming: false,
26
+ });
27
+ const visualMinDuration = (MIN_SELECTION_WIDTH * (endDate.valueOf() - startDate.valueOf())) / viewport.width;
28
+ const handleMoveEnd = () => {
29
+ state.endDragging();
30
+ setIsDragging(null);
31
+ };
32
+ const { moveProps } = (0, useMove_1.useMove)({
33
+ onMoveStart: (e) => {
34
+ setIsDragging('dragger');
35
+ state.startDragging();
36
+ moveDataRef.current = {
37
+ isZooming: state.canResize && (e.ctrlKey || e.metaKey),
38
+ };
39
+ },
40
+ onMoveEnd: handleMoveEnd,
41
+ onMove: (e) => {
42
+ if (e.deltaX === 0) {
43
+ return;
44
+ }
45
+ if (moveDataRef.current.isZooming) {
46
+ let scale = Math.exp((e.deltaX * DRAG_SCALE_STRENGTH) / viewport.width);
47
+ scale = Math.min(Math.max(scale, MIN_DRAG_SCALE), MAX_DRAG_SCALE);
48
+ state.scale(scale, { visualMinDuration });
49
+ }
50
+ else {
51
+ let delta = (e.deltaX * (endDate.valueOf() - startDate.valueOf())) / viewport.width;
52
+ if (e.pointerType === 'keyboard') {
53
+ delta =
54
+ delta > 0
55
+ ? Math.max(delta, state.align)
56
+ : Math.min(delta, -1 * state.align);
57
+ }
58
+ state.move(delta, { visualMinDuration });
59
+ }
60
+ },
61
+ });
62
+ const { moveProps: moveStartProps } = (0, useMove_1.useMove)({
63
+ onMoveStart: () => {
64
+ setIsDragging('start');
65
+ state.startDragging();
66
+ },
67
+ onMoveEnd: handleMoveEnd,
68
+ onMove: (e) => {
69
+ if (e.deltaX === 0) {
70
+ return;
71
+ }
72
+ let delta = (e.deltaX * (endDate.valueOf() - startDate.valueOf())) / viewport.width;
73
+ if (e.pointerType === 'keyboard') {
74
+ delta =
75
+ delta > 0 ? Math.max(delta, state.align) : Math.min(delta, -1 * state.align);
76
+ }
77
+ state.moveStart(delta, { visualMinDuration });
78
+ },
79
+ });
80
+ const { moveProps: moveEndProps } = (0, useMove_1.useMove)({
81
+ onMoveStart: () => {
82
+ setIsDragging('end');
83
+ state.startDragging();
84
+ },
85
+ onMoveEnd: handleMoveEnd,
86
+ onMove: (e) => {
87
+ if (e.deltaX === 0) {
88
+ return;
89
+ }
90
+ let delta = (e.deltaX * (endDate.valueOf() - startDate.valueOf())) / viewport.width;
91
+ if (e.pointerType === 'keyboard') {
92
+ delta =
93
+ delta > 0 ? Math.max(delta, state.align) : Math.min(delta, -1 * state.align);
94
+ }
95
+ state.moveEnd(delta, { visualMinDuration });
96
+ },
97
+ });
98
+ const { start: startValue, end: endValue } = state.value;
99
+ const startX = (0, span_1.lerp)({ start: startDate.valueOf(), end: endDate.valueOf() }, { start: 0, end: viewport.width }, startValue.valueOf());
100
+ const endX = (0, span_1.lerp)({ start: startDate.valueOf(), end: endDate.valueOf() }, { start: 0, end: viewport.width }, endValue.valueOf());
101
+ const draggerInputRef = react_1.default.useRef(null);
102
+ const startInputRef = react_1.default.useRef(null);
103
+ const endInputRef = react_1.default.useRef(null);
104
+ let id = react_1.default.useId();
105
+ id = (_b = props.id) !== null && _b !== void 0 ? _b : id;
106
+ return ((0, jsx_runtime_1.jsxs)("div", { className: b(null, className), style: Object.assign(Object.assign({}, style), { left: startX, width: endX - startX }), children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ className: b('dragger', {
107
+ dragging: isDragging === 'dragger',
108
+ disabled: Boolean(isDragging && isDragging !== 'dragger'),
109
+ }) }, moveProps, { onClick: () => {
110
+ var _a;
111
+ (_a = draggerInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
112
+ }, children: (0, jsx_runtime_1.jsx)("div", { className: b('slider-input-wrapper'), children: (0, jsx_runtime_1.jsx)("input", { id: `${id}-range`, ref: draggerInputRef, className: b('slider-input'), type: "range", step: 1, "aria-label": (0, i18n_1.i18n)('Range'), "aria-labelledby": [`${id}-range`, props['aria-labelledby']]
113
+ .filter(Boolean)
114
+ .join(' '), "aria-orientation": "horizontal", "aria-valuetext": `${startValue.format()} - ${endValue.format()}`, value: 0, onChange: () => { } }) }) })), state.canResize ? (
115
+ /* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */
116
+ (0, jsx_runtime_1.jsx)("div", Object.assign({ className: b('start', {
117
+ dragging: isDragging === 'start',
118
+ disabled: Boolean(isDragging && isDragging !== 'start'),
119
+ }) }, moveStartProps, { onClick: () => {
120
+ var _a;
121
+ (_a = startInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
122
+ }, children: (0, jsx_runtime_1.jsx)("div", { className: b('slider-input-wrapper'), children: (0, jsx_runtime_1.jsx)("input", { id: `${id}-start`, ref: startInputRef, className: b('slider-input'), type: "range", step: 1, "aria-label": (0, i18n_1.i18n)('Start of range'), "aria-labelledby": [`${id}-start`, props['aria-labelledby']]
123
+ .filter(Boolean)
124
+ .join(' '), "aria-orientation": "horizontal", "aria-valuetext": `${startValue.format()}`, value: 0, onChange: () => { } }) }) }))) : null, state.canResize ? (
125
+ /* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */
126
+ (0, jsx_runtime_1.jsx)("div", Object.assign({ className: b('end', {
127
+ dragging: isDragging === 'end',
128
+ disabled: Boolean(isDragging && isDragging !== 'end'),
129
+ }) }, moveEndProps, { onClick: () => {
130
+ var _a;
131
+ (_a = endInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
132
+ }, children: (0, jsx_runtime_1.jsx)("div", { className: b('slider-input-wrapper'), children: (0, jsx_runtime_1.jsx)("input", { id: `${id}-end`, ref: endInputRef, className: b('slider-input'), type: "range", step: 1, "aria-label": (0, i18n_1.i18n)('End of range'), "aria-labelledby": [`${id}-end`, props['aria-labelledby']]
133
+ .filter(Boolean)
134
+ .join(' '), "aria-orientation": "horizontal", "aria-valuetext": `${endValue.format()}`, value: 0, onChange: () => { } }) }) }))) : null] }));
135
+ }
@@ -0,0 +1,3 @@
1
+ export declare function MiddleTicks({ timeZone }: {
2
+ timeZone?: string;
3
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MiddleTicks = MiddleTicks;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const Ruler_1 = require("../Ruler/Ruler");
6
+ const Ticks_1 = require("./Ticks");
7
+ function MiddleTicks({ timeZone }) {
8
+ const { height } = (0, Ruler_1.useViewportDimensions)();
9
+ return ((0, jsx_runtime_1.jsx)(Ticks_1.Ticks, { minTickWidth: 8, maxTickWidth: 20, theme: "dim", geometry: (0, Ticks_1.makeMiddleTicksGeometry)({ tickHeight: 4, viewportHeight: height }), timeZone: timeZone }));
10
+ }
@@ -0,0 +1,5 @@
1
+ import type { DateTime } from '@gravity-ui/date-utils';
2
+ export declare function SlitTicks({ formatTime, timeZone, }: {
3
+ formatTime?: (time: DateTime) => string;
4
+ timeZone?: string;
5
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SlitTicks = SlitTicks;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const Ruler_1 = require("../Ruler/Ruler");
6
+ const Ticks_1 = require("./Ticks");
7
+ function SlitTicks({ formatTime, timeZone, }) {
8
+ const { height } = (0, Ruler_1.useViewportDimensions)();
9
+ return ((0, jsx_runtime_1.jsx)(Ticks_1.Ticks, { minTickWidth: 80, maxTickWidth: 200, theme: "normal", geometry: (0, Ticks_1.makeSlitTicksGeometry)({ tickHeight: 4, viewportHeight: height }), hasLabels: true, formatTime: formatTime, timeZone: timeZone }));
10
+ }
@@ -0,0 +1,16 @@
1
+ .g-date-timeline-ticks {
2
+ stroke: var(--g-color-text-secondary);
3
+ fill: var(--g-color-text-secondary);
4
+ stroke-width: 1px;
5
+ }
6
+ .g-date-timeline-ticks_theme_dim {
7
+ stroke: var(--g-color-line-generic-accent);
8
+ fill: var(--g-color-line-generic-accent);
9
+ }
10
+ .g-date-timeline-ticks__label {
11
+ font-size: 11px;
12
+ line-height: 14px;
13
+ user-select: none;
14
+ fill: var(--g-color-text-secondary);
15
+ text-anchor: middle;
16
+ }
@@ -0,0 +1,18 @@
1
+ import type { DateTime } from '@gravity-ui/date-utils';
2
+ import type { Geometry } from './utils';
3
+ import { makeMiddleTicksGeometry, makeSlitTicksGeometry } from './utils';
4
+ import './Ticks.css';
5
+ interface TicksProps {
6
+ theme: 'normal' | 'dim';
7
+ minTickWidth: number;
8
+ maxTickWidth: number;
9
+ hasLabels?: boolean;
10
+ geometry: Geometry;
11
+ className?: string;
12
+ labelsClassName?: string;
13
+ formatTime?: (time: DateTime) => string;
14
+ timeZone?: string;
15
+ }
16
+ export { makeMiddleTicksGeometry, makeSlitTicksGeometry };
17
+ export type { Geometry };
18
+ export declare function Ticks({ theme, minTickWidth, maxTickWidth, hasLabels, geometry, className, labelsClassName, formatTime, timeZone, }: TicksProps): import("react/jsx-runtime").JSX.Element;