@datarobot/design-system 28.9.2 → 28.10.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 (61) hide show
  1. package/cjs/floating-panel/constants.d.ts +21 -0
  2. package/cjs/floating-panel/constants.js +94 -0
  3. package/cjs/floating-panel/draggable-area.d.ts +12 -0
  4. package/cjs/floating-panel/draggable-area.js +72 -0
  5. package/cjs/floating-panel/floating-panel-dock-button.d.ts +5 -0
  6. package/cjs/floating-panel/floating-panel-dock-button.js +37 -0
  7. package/cjs/floating-panel/floating-panel-drag-handle.d.ts +5 -0
  8. package/cjs/floating-panel/floating-panel-drag-handle.js +51 -0
  9. package/cjs/floating-panel/floating-panel-header.d.ts +11 -0
  10. package/cjs/floating-panel/floating-panel-header.js +46 -0
  11. package/cjs/floating-panel/floating-panel.d.ts +66 -0
  12. package/cjs/floating-panel/floating-panel.js +140 -0
  13. package/cjs/floating-panel/index.d.ts +4 -0
  14. package/cjs/floating-panel/index.js +19 -0
  15. package/cjs/floating-panel/types.d.ts +21 -0
  16. package/cjs/floating-panel/types.js +5 -0
  17. package/cjs/floating-panel/use-floating-panel-root.d.ts +6 -0
  18. package/cjs/floating-panel/use-floating-panel-root.js +31 -0
  19. package/cjs/floating-panel/use-floating-panel-state.d.ts +27 -0
  20. package/cjs/floating-panel/use-floating-panel-state.js +316 -0
  21. package/cjs/floating-panel/use-floating-panel.d.ts +4 -0
  22. package/cjs/floating-panel/use-floating-panel.js +14 -0
  23. package/cjs/index.d.ts +1 -0
  24. package/cjs/index.js +11 -0
  25. package/cjs/table-react/hooks/useColumns.js +13 -5
  26. package/esm/floating-panel/constants.d.ts +21 -0
  27. package/esm/floating-panel/constants.js +86 -0
  28. package/esm/floating-panel/draggable-area.d.ts +12 -0
  29. package/esm/floating-panel/draggable-area.js +65 -0
  30. package/esm/floating-panel/floating-panel-dock-button.d.ts +5 -0
  31. package/esm/floating-panel/floating-panel-dock-button.js +30 -0
  32. package/esm/floating-panel/floating-panel-drag-handle.d.ts +5 -0
  33. package/esm/floating-panel/floating-panel-drag-handle.js +44 -0
  34. package/esm/floating-panel/floating-panel-header.d.ts +11 -0
  35. package/esm/floating-panel/floating-panel-header.js +39 -0
  36. package/esm/floating-panel/floating-panel.d.ts +66 -0
  37. package/esm/floating-panel/floating-panel.js +132 -0
  38. package/esm/floating-panel/index.d.ts +4 -0
  39. package/esm/floating-panel/index.js +2 -0
  40. package/esm/floating-panel/types.d.ts +21 -0
  41. package/esm/floating-panel/types.js +1 -0
  42. package/esm/floating-panel/use-floating-panel-root.d.ts +6 -0
  43. package/esm/floating-panel/use-floating-panel-root.js +24 -0
  44. package/esm/floating-panel/use-floating-panel-state.d.ts +27 -0
  45. package/esm/floating-panel/use-floating-panel-state.js +310 -0
  46. package/esm/floating-panel/use-floating-panel.d.ts +4 -0
  47. package/esm/floating-panel/use-floating-panel.js +9 -0
  48. package/esm/index.d.ts +1 -0
  49. package/esm/index.js +1 -0
  50. package/esm/table-react/hooks/useColumns.js +13 -5
  51. package/floating-panel/package.json +7 -0
  52. package/js/bundle/bundle.js +1351 -332
  53. package/js/bundle/bundle.min.js +1 -1
  54. package/js/bundle/index.d.ts +94 -1
  55. package/package.json +1 -1
  56. package/styles/index.css +150 -0
  57. package/styles/index.min.css +1 -1
  58. package/styles/themes/alpine-light.css +12 -0
  59. package/styles/themes/alpine-light.min.css +1 -1
  60. package/styles/themes/midnight-gray.css +12 -0
  61. package/styles/themes/midnight-gray.min.css +1 -1
@@ -0,0 +1,44 @@
1
+ import React, { useContext } from 'react';
2
+ import { faGripDotsVertical } from '@fortawesome/pro-solid-svg-icons/faGripDotsVertical';
3
+ import { FontAwesomeIcon } from '../font-awesome-icon';
4
+ import { useTranslation } from '../hooks';
5
+ import { FloatingPanelContext } from './constants';
6
+ import { DraggableArea } from './draggable-area';
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ export function FloatingPanelDragHandle({
9
+ children
10
+ }) {
11
+ const content = children || /*#__PURE__*/_jsx(FontAwesomeIcon, {
12
+ icon: faGripDotsVertical
13
+ });
14
+ const {
15
+ t
16
+ } = useTranslation();
17
+ const {
18
+ onDrag,
19
+ onDragStart,
20
+ onDragEnd,
21
+ onMoveWithArrows,
22
+ isDocked
23
+ } = useContext(FloatingPanelContext);
24
+ if (isDocked) {
25
+ return /*#__PURE__*/_jsx("div", {
26
+ className: "drag-handle disabled",
27
+ "test-id": "floating-area-drag-handle",
28
+ children: content
29
+ });
30
+ }
31
+ return /*#__PURE__*/_jsx(DraggableArea, {
32
+ tabIndex: 0,
33
+ testId: "floating-area-drag-handle",
34
+ areaId: "drag-handle",
35
+ className: "drag-handle",
36
+ onDrag: onDrag,
37
+ onDragStart: onDragStart,
38
+ onDragEnd: onDragEnd,
39
+ onKeyDown: onMoveWithArrows,
40
+ "aria-label": t('Draggable handle: use arrows to change position of the panel'),
41
+ role: "button",
42
+ children: content
43
+ });
44
+ }
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import type { PanelState } from './types';
3
+ type FloatingPanelHeaderProps = {
4
+ onClose: (State: PanelState) => void;
5
+ isDocked: boolean;
6
+ setIsDocked: (docked: boolean) => void;
7
+ actions?: React.ReactNode;
8
+ getPosition: () => PanelState;
9
+ };
10
+ export declare const FloatingPanelHeader: React.ForwardRefExoticComponent<FloatingPanelHeaderProps & React.RefAttributes<HTMLElement>>;
11
+ export {};
@@ -0,0 +1,39 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { faXmark } from '@fortawesome/free-solid-svg-icons/faXmark';
3
+ import { Button, ACCENT_TYPES } from '../button';
4
+ import { FontAwesomeIcon } from '../font-awesome-icon';
5
+ import { useTranslation } from '../hooks/use-translation';
6
+ import { FloatingPanelDockButton } from './floating-panel-dock-button';
7
+ import { FloatingPanelDragHandle } from './floating-panel-drag-handle';
8
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
+ export const FloatingPanelHeader = /*#__PURE__*/forwardRef(({
10
+ actions = null,
11
+ onClose,
12
+ isDocked,
13
+ setIsDocked,
14
+ getPosition
15
+ }, ref) => {
16
+ const {
17
+ t
18
+ } = useTranslation();
19
+ return /*#__PURE__*/_jsxs("header", {
20
+ ref: ref,
21
+ className: "floating-panel-header",
22
+ children: [/*#__PURE__*/_jsx(FloatingPanelDragHandle, {}), /*#__PURE__*/_jsxs("div", {
23
+ className: "actions",
24
+ children: [actions, /*#__PURE__*/_jsx(FloatingPanelDockButton, {
25
+ isDocked: isDocked,
26
+ setIsDocked: setIsDocked
27
+ }), /*#__PURE__*/_jsx(Button, {
28
+ testId: "floating-panel-close-action",
29
+ accentType: ACCENT_TYPES.ROUND_ICON,
30
+ onClick: () => onClose(getPosition()),
31
+ "aria-label": t('Close'),
32
+ children: /*#__PURE__*/_jsx(FontAwesomeIcon, {
33
+ icon: faXmark
34
+ })
35
+ })]
36
+ })]
37
+ });
38
+ });
39
+ FloatingPanelHeader.displayName = 'FloatingPanelHeader';
@@ -0,0 +1,66 @@
1
+ import React, { Dispatch, SetStateAction } from 'react';
2
+ import { Modifier, Placement } from '@popperjs/core';
3
+ import './floating-panel.less';
4
+ import type { ElementReference, PanelState } from './types';
5
+ export type FloatingPanelProps = {
6
+ /**
7
+ * Panel's content
8
+ */
9
+ children: React.ReactNode;
10
+ /**
11
+ * Pass custom header action buttons here
12
+ */
13
+ actions?: React.ReactNode;
14
+ minHeight?: number;
15
+ minWidth?: number;
16
+ maxWidth?: number;
17
+ maxHeight?: number;
18
+ /**
19
+ * Position panel relative to this element. Alternative use `initialState`
20
+ */
21
+ anchorEl?: ElementReference;
22
+ /**
23
+ * Dock element. It should be placed after id="full-screen-modal-root"
24
+ */
25
+ dockEl?: ElementReference;
26
+ /**
27
+ * Pass an element where the main page content is rendered, this will help calculate the header size
28
+ */
29
+ pageContentEl?: ElementReference;
30
+ /**
31
+ * Popper's placement, used for initial position if `initialState` is not defined
32
+ */
33
+ placement?: Placement;
34
+ /**
35
+ * Popper modifies which will override default set of modifiers
36
+ */
37
+ popperModifiers?: Partial<Modifier<any, any>>[];
38
+ testId?: string;
39
+ /**
40
+ * Use this to set initial state. Update it in `onClose` handler to preserve last position.
41
+ */
42
+ initialState?: PanelState;
43
+ /**
44
+ * Use this to control docked state outside the component
45
+ */
46
+ isDocked?: boolean;
47
+ /**
48
+ * Use this to sync up the docked state with consumer when controlled outside
49
+ */
50
+ setIsDocked?: Dispatch<SetStateAction<boolean>>;
51
+ /**
52
+ * Use this in consumer to update `initialState` in order to preserve last position
53
+ */
54
+ onClose?: (State: PanelState) => void;
55
+ /**
56
+ * Aria label for the floating panel
57
+ */
58
+ ariaLabel?: string;
59
+ };
60
+ /**
61
+ * Floating panel
62
+ * @midnight-gray-supported
63
+ * @uxr-only-supported
64
+ * @alpine-light-supported
65
+ */
66
+ export declare function FloatingPanel({ children, minHeight, minWidth, maxWidth, maxHeight, anchorEl, dockEl, pageContentEl, initialState, testId, placement, popperModifiers, onClose, actions, ...props }: FloatingPanelProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,132 @@
1
+ import ReactDOM from 'react-dom';
2
+ import React, { useLayoutEffect, useRef } from 'react';
3
+ import classnames from 'classnames';
4
+ import { createPopper } from '@popperjs/core';
5
+ import { OFFSET_MODIFIER } from '../react-popper';
6
+ import { useTranslation } from '../hooks';
7
+ import { FloatingPanelContext, resizeHandles, getHtmlElement } from './constants';
8
+ import { useFloatingPanelState } from './use-floating-panel-state';
9
+ import { DraggableArea } from './draggable-area';
10
+ import { FloatingPanelHeader } from './floating-panel-header';
11
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
+ const noop = () => false;
13
+
14
+ /**
15
+ * Floating panel
16
+ * @midnight-gray-supported
17
+ * @uxr-only-supported
18
+ * @alpine-light-supported
19
+ */
20
+ export function FloatingPanel({
21
+ children,
22
+ minHeight = 648,
23
+ minWidth = 380,
24
+ maxWidth = 900,
25
+ maxHeight = 800,
26
+ anchorEl,
27
+ dockEl,
28
+ pageContentEl,
29
+ initialState,
30
+ testId = 'floating-panel',
31
+ placement = 'bottom',
32
+ popperModifiers = [OFFSET_MODIFIER],
33
+ onClose = noop,
34
+ actions,
35
+ ...props
36
+ }) {
37
+ const containerElement = getHtmlElement(dockEl) || document.getElementById('floating-panel-root') || document.body;
38
+ const initialStateAppliedOnce = useRef(false);
39
+ const {
40
+ t
41
+ } = useTranslation();
42
+ const {
43
+ panelRef,
44
+ headerRef,
45
+ style,
46
+ onResize,
47
+ onMovementStart,
48
+ onResizeEnd,
49
+ setState,
50
+ isDocked,
51
+ setIsDocked,
52
+ getPosition,
53
+ context
54
+ } = useFloatingPanelState({
55
+ minHeight,
56
+ minWidth,
57
+ maxWidth,
58
+ maxHeight,
59
+ initialState,
60
+ isDocked: props.isDocked ?? false,
61
+ setIsDocked: props.setIsDocked ?? noop,
62
+ containerElement,
63
+ pageContentElement: getHtmlElement(pageContentEl)
64
+ });
65
+
66
+ // use @popperjs/core to set initial position for the panel
67
+ useLayoutEffect(() => {
68
+ if (!panelRef.current) {
69
+ return;
70
+ }
71
+ panelRef.current.focus();
72
+ if (initialState && !initialStateAppliedOnce.current) {
73
+ initialStateAppliedOnce.current = true;
74
+ return setState(initialState);
75
+ }
76
+ if (!anchorEl) {
77
+ return;
78
+ }
79
+ const popperInstance = createPopper(getHtmlElement(anchorEl), panelRef.current, {
80
+ placement,
81
+ strategy: 'fixed',
82
+ modifiers: popperModifiers,
83
+ onFirstUpdate: () => {
84
+ const {
85
+ left,
86
+ top
87
+ } = panelRef.current.getBoundingClientRect();
88
+ setState(state => ({
89
+ ...state,
90
+ left,
91
+ top
92
+ }));
93
+ popperInstance.destroy();
94
+ }
95
+ });
96
+ }, [placement]);
97
+ return /*#__PURE__*/_jsx(FloatingPanelContext.Provider, {
98
+ value: context,
99
+ children: /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/_jsxs("section", {
100
+ ref: panelRef,
101
+ "test-id": testId,
102
+ className: classnames('floating-panel', {
103
+ docked: isDocked
104
+ })
105
+ /* eslint-disable-next-line react/forbid-dom-props */,
106
+ style: style,
107
+ "aria-modal": "true",
108
+ role: "dialog",
109
+ "aria-label": props.ariaLabel || t('Floating panel'),
110
+ "aria-describedby": "floating-panel-content",
111
+ tabIndex: -1,
112
+ children: [/*#__PURE__*/_jsx(FloatingPanelHeader, {
113
+ ref: headerRef,
114
+ onClose: onClose,
115
+ getPosition: getPosition,
116
+ isDocked: isDocked,
117
+ setIsDocked: setIsDocked,
118
+ actions: actions
119
+ }), /*#__PURE__*/_jsx("div", {
120
+ id: "floating-panel-content",
121
+ className: "floating-panel-content",
122
+ children: children
123
+ }), !isDocked && resizeHandles.map(handle => /*#__PURE__*/_jsx(DraggableArea, {
124
+ areaId: handle.id,
125
+ className: classnames('resize-handle', handle.id),
126
+ onDrag: onResize,
127
+ onDragStart: onMovementStart,
128
+ onDragEnd: onResizeEnd
129
+ }, handle.id))]
130
+ }), containerElement)
131
+ });
132
+ }
@@ -0,0 +1,4 @@
1
+ export type { FloatingPanelProps } from './floating-panel';
2
+ export type { PanelState, FloatingPanelContextType } from './types';
3
+ export { FloatingPanel } from './floating-panel';
4
+ export { useFloatingPanel } from './use-floating-panel';
@@ -0,0 +1,2 @@
1
+ export { FloatingPanel } from './floating-panel';
2
+ export { useFloatingPanel } from './use-floating-panel';
@@ -0,0 +1,21 @@
1
+ import React, { MutableRefObject } from 'react';
2
+ export type PanelState = {
3
+ top: number;
4
+ left: number;
5
+ width: number;
6
+ height: number;
7
+ };
8
+ export type DraggableEvent = MouseEvent & {
9
+ areaId: string;
10
+ };
11
+ export type FloatingPanelContextType = {
12
+ onDrag: (event: DraggableEvent) => void;
13
+ onDragStart: (event: DraggableEvent) => void;
14
+ onDragEnd: (event: DraggableEvent | string) => void;
15
+ onMoveWithArrows: (event: React.KeyboardEvent) => void;
16
+ isDocked: boolean;
17
+ setIsDocked: (docked: boolean) => void;
18
+ isMoving: boolean;
19
+ getPosition: () => PanelState;
20
+ };
21
+ export type ElementReference = HTMLElement | Element | MutableRefObject<HTMLElement> | (() => HTMLElement) | null;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ type UseFloatingPanelRootParams = {
2
+ containerElement: HTMLElement;
3
+ pageContentElement?: HTMLElement;
4
+ };
5
+ export declare function useFloatingPanelRoot({ containerElement, pageContentElement, }: UseFloatingPanelRootParams): void;
6
+ export {};
@@ -0,0 +1,24 @@
1
+ import { useEffect } from 'react';
2
+ import debounce from 'lodash-es/debounce';
3
+ export function useFloatingPanelRoot({
4
+ containerElement,
5
+ pageContentElement
6
+ }) {
7
+ useEffect(() => {
8
+ // this is not an exceptional case: when there is no header this could be omitted
9
+ if (!containerElement || !pageContentElement) {
10
+ return;
11
+ }
12
+ const onResize = debounce(() => {
13
+ const contentRect = pageContentElement.getBoundingClientRect();
14
+ containerElement.style.top = `${contentRect.top}px`;
15
+ }, 100);
16
+ onResize();
17
+ const resizeObserver = new ResizeObserver(onResize);
18
+ resizeObserver.observe(pageContentElement);
19
+ return () => {
20
+ onResize.cancel();
21
+ resizeObserver.disconnect();
22
+ };
23
+ }, [containerElement, pageContentElement]);
24
+ }
@@ -0,0 +1,27 @@
1
+ import React, { CSSProperties, Dispatch, SetStateAction } from 'react';
2
+ import { DraggableEvent, FloatingPanelContextType, PanelState } from './types';
3
+ export type UseFloatingPanelHook = {
4
+ style: CSSProperties;
5
+ context: FloatingPanelContextType;
6
+ panelRef: React.MutableRefObject<HTMLDivElement | null>;
7
+ headerRef: React.MutableRefObject<HTMLHeadElement | null>;
8
+ onResize: (event: DraggableEvent) => void;
9
+ onMovementStart: (event: DraggableEvent) => void;
10
+ onResizeEnd: (event: DraggableEvent | string) => void;
11
+ setState: Dispatch<SetStateAction<PanelState>>;
12
+ isDocked: boolean;
13
+ setIsDocked: (docked: boolean) => void;
14
+ getPosition: () => PanelState;
15
+ };
16
+ export type UseFloatingPanelParams = {
17
+ minHeight: number;
18
+ minWidth: number;
19
+ maxWidth: number;
20
+ maxHeight: number;
21
+ isDocked: boolean;
22
+ setIsDocked: Dispatch<SetStateAction<boolean>>;
23
+ initialState?: PanelState;
24
+ containerElement: HTMLElement;
25
+ pageContentElement?: HTMLElement;
26
+ };
27
+ export declare function useFloatingPanelState({ minWidth, minHeight, maxWidth, maxHeight, isDocked: isDockedExternal, setIsDocked: setIsDockedExternal, initialState, containerElement, pageContentElement, }: UseFloatingPanelParams): UseFloatingPanelHook;