@datalayer/core 0.0.26 → 0.0.27
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.
- package/lib/components/auth/Login.d.ts +4 -0
- package/lib/components/auth/Login.js +8 -2
- package/lib/components/auth/Login.stories.d.ts +1 -0
- package/lib/components/progress/ConsumptionBar.js +7 -7
- package/lib/components/progress/CreditsIndicator.d.ts +7 -1
- package/lib/components/progress/CreditsIndicator.js +4 -2
- package/lib/components/{screenshot/ScreenCapture.d.ts → screencapture/Screencapture.d.ts} +5 -5
- package/lib/components/{screenshot/ScreenCapture.js → screencapture/Screencapture.js} +2 -2
- package/lib/components/screencapture/ScreencaptureButton.d.ts +3 -0
- package/lib/components/{screenshot/ScreenCaptureButton.js → screencapture/ScreencaptureButton.js} +8 -8
- package/lib/components/screencapture/index.d.ts +2 -0
- package/lib/components/{screenshot → screencapture}/index.js +2 -2
- package/lib/hooks/index.d.ts +1 -1
- package/lib/hooks/index.js +1 -1
- package/lib/hooks/layouts/{LayoutScreenshot.css → LayoutScreencapture.css} +2 -2
- package/lib/hooks/layouts/LayoutScreencapture.d.ts +3 -0
- package/lib/hooks/layouts/{LayoutScreenshot.js → LayoutScreencapture.js} +14 -14
- package/lib/hooks/layouts/index.d.ts +1 -1
- package/lib/hooks/layouts/index.js +1 -1
- package/lib/hooks/useCache.d.ts +3 -1
- package/lib/hooks/useCache.js +113 -62
- package/lib/hooks/useCellOutputshot.js +2 -2
- package/lib/hooks/useScreencapture.d.ts +18 -0
- package/lib/hooks/useScreencapture.js +53 -0
- package/lib/models/IAMProviderUsers.d.ts +11 -0
- package/lib/models/IAMProvidersSpecs.d.ts +2 -1
- package/lib/models/IAMProvidersSpecs.js +14 -0
- package/lib/models/Page.js +1 -1
- package/lib/models/PageTag.d.ts +1 -1
- package/lib/models/PageTag.js +21 -0
- package/lib/state/substates/LayoutState.d.ts +5 -5
- package/lib/state/substates/LayoutState.js +3 -3
- package/lib/utils/Screencapture.d.ts +1 -0
- package/lib/utils/{Screenshot.js → Screencapture.js} +1 -1
- package/lib/utils/index.js +1 -1
- package/lib/views/datasources/DatasourceNew.d.ts +7 -1
- package/lib/views/datasources/DatasourceNew.js +3 -3
- package/lib/views/datasources/Datasources.d.ts +7 -1
- package/lib/views/datasources/Datasources.js +6 -4
- package/package.json +1 -1
- package/style/screencapture/index.css +58 -0
- package/lib/components/screenshot/ScreenCaptureButton.d.ts +0 -3
- package/lib/components/screenshot/index.d.ts +0 -2
- package/lib/hooks/layouts/LayoutScreenshot.d.ts +0 -3
- package/lib/hooks/useScreenshot.d.ts +0 -18
- package/lib/hooks/useScreenshot.js +0 -53
- package/lib/utils/Screenshot.d.ts +0 -1
|
@@ -14,8 +14,10 @@ import { CenteredSpinner } from '../display';
|
|
|
14
14
|
import { isInsideJupyterLab, validateLength } from '../../utils';
|
|
15
15
|
import { useNavigate, useCache, useToast, useIAM } from '../../hooks';
|
|
16
16
|
import { LoginToken } from './LoginToken';
|
|
17
|
+
/** Inline Google "G" icon for the login button. */
|
|
18
|
+
const GoogleIcon = () => (_jsxs("svg", { width: "16", height: "16", viewBox: "0 0 48 48", children: [_jsx("path", { fill: "#EA4335", d: "M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z" }), _jsx("path", { fill: "#4285F4", d: "M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z" }), _jsx("path", { fill: "#FBBC05", d: "M10.53 28.59a14.5 14.5 0 0 1 0-9.18l-7.98-6.19a24.1 24.1 0 0 0 0 21.56l7.98-6.19z" }), _jsx("path", { fill: "#34A853", d: "M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z" })] }));
|
|
17
19
|
export const Login = (props) => {
|
|
18
|
-
const { heading, homeRoute, loginRoute, showEmailLogin = true, showGitHubLogin = true, showTokenLogin = true, } = props;
|
|
20
|
+
const { heading, homeRoute, loginRoute, showEmailLogin = true, showGitHubLogin = true, showGoogleLogin = true, showTokenLogin = true, } = props;
|
|
19
21
|
const { useLogin, useOAuth2AuthorizationURL } = useCache({ loginRoute });
|
|
20
22
|
const loginMutation = useLogin();
|
|
21
23
|
const getOAuth2URLMutation = useOAuth2AuthorizationURL();
|
|
@@ -68,6 +70,9 @@ export const Login = (props) => {
|
|
|
68
70
|
if (!iamProvidersAuthorizationURL[IAMProvidersSpecs.GitHub.name]) {
|
|
69
71
|
initIAMProvider(IAMProvidersSpecs.GitHub);
|
|
70
72
|
}
|
|
73
|
+
if (!iamProvidersAuthorizationURL[IAMProvidersSpecs.Google.name]) {
|
|
74
|
+
initIAMProvider(IAMProvidersSpecs.Google);
|
|
75
|
+
}
|
|
71
76
|
if (!iamProvidersAuthorizationURL[IAMProvidersSpecs.LinkedIn.name]) {
|
|
72
77
|
initIAMProvider(IAMProvidersSpecs.LinkedIn);
|
|
73
78
|
}
|
|
@@ -163,6 +168,7 @@ export const Login = (props) => {
|
|
|
163
168
|
: heading
|
|
164
169
|
? 'Login with Datalayer'
|
|
165
170
|
: 'Login' }), _jsx(Box, { pt: 6 }), _jsx(Link, { href: "https://datalayer.app/password", target: "_blank", children: "Forgot password?" })] })] })), _jsx(Box, { children: _jsxs(Box, { display: "flex", flexDirection: "column", sx: { margin: 'auto' }, children: [showGitHubLogin &&
|
|
166
|
-
iamProvidersAuthorizationURL[IAMProvidersSpecs.GitHub.name] && (_jsx(Button, { leadingVisual: MarkGithubIcon, href: iamProvidersAuthorizationURL[IAMProvidersSpecs.GitHub.name], as: "a", style: { margin: '10px 0' }, children: "Login with GitHub" })),
|
|
171
|
+
iamProvidersAuthorizationURL[IAMProvidersSpecs.GitHub.name] && (_jsx(Button, { leadingVisual: MarkGithubIcon, href: iamProvidersAuthorizationURL[IAMProvidersSpecs.GitHub.name], as: "a", style: { margin: '10px 0' }, children: "Login with GitHub" })), showGoogleLogin &&
|
|
172
|
+
iamProvidersAuthorizationURL[IAMProvidersSpecs.Google.name] && (_jsx(Button, { leadingVisual: GoogleIcon, href: iamProvidersAuthorizationURL[IAMProvidersSpecs.Google.name], as: "a", style: { margin: '10px 0' }, children: "Login with Google" })), showTokenLogin && (_jsx(LoginToken, { homeRoute: homeRoute, style: { margin: '10px 0' } }))] }) })] }) })) : loadingWithToken ? (_jsx(CenteredSpinner, { message: "Checking authentication\u2026" })) : (_jsx(_Fragment, {})) })] }));
|
|
167
173
|
};
|
|
168
174
|
export default Login;
|
|
@@ -22,6 +22,7 @@ declare const meta: {
|
|
|
22
22
|
passwordRoute?: string | undefined;
|
|
23
23
|
showEmailLogin?: boolean | undefined;
|
|
24
24
|
showGitHubLogin?: boolean | undefined;
|
|
25
|
+
showGoogleLogin?: boolean | undefined;
|
|
25
26
|
showTokenLogin?: boolean | undefined;
|
|
26
27
|
}>) => import("react/jsx-runtime").JSX.Element)[];
|
|
27
28
|
tags: string[];
|
|
@@ -57,11 +57,11 @@ export function ConsumptionBar(props) {
|
|
|
57
57
|
const title = duration
|
|
58
58
|
? `${formatTimeRemaining(secondsRemaining)} left - ${((progress / 100) * burntCredits).toFixed(2)} / ${burntCredits.toFixed(2)} credits`
|
|
59
59
|
: `Started at ${new Date(startedAt * 1000).toISOString()} - ${burntCredits.toFixed(2)} credits consumed`;
|
|
60
|
-
return (_jsx(_Fragment, { children: _jsx(Tooltip, { text: title, direction: "w", children: _jsx(Button, { variant: "invisible",
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
return (_jsx(_Fragment, { children: _jsx(Tooltip, { text: title, direction: "w", children: _jsx(Button, { variant: "invisible", onClick: onClick, onKeyDown: onClick
|
|
61
|
+
? event => {
|
|
62
|
+
if (event.key === 'Enter' || event.key === 'Space') {
|
|
63
|
+
onClick();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
: undefined, tabIndex: onClick ? 0 : -1, sx: { cursor: onClick ? 'pointer' : 'default' }, children: _jsx(Box, { sx: { width: '70px' }, children: _jsx(ProgressBar, { style: style, animated: expiredAt ? false : true, bg: bg, progress: progress }) }) }) }) }));
|
|
67
67
|
}
|
|
@@ -9,7 +9,13 @@ type ICreditsIndicatorProps = {
|
|
|
9
9
|
*/
|
|
10
10
|
kernelId: string;
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* Route to navigate to when the indicator is clicked.
|
|
13
|
+
* Ignored if `onClick` is provided.
|
|
14
|
+
*/
|
|
15
|
+
navigateTo?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Callback on progress bar click event.
|
|
18
|
+
* Takes precedence over `navigateTo`.
|
|
13
19
|
*/
|
|
14
20
|
onClick?: () => void;
|
|
15
21
|
/**
|
|
@@ -6,16 +6,18 @@ import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
|
6
6
|
import { useState, useEffect } from 'react';
|
|
7
7
|
import { Box } from '@datalayer/primer-addons';
|
|
8
8
|
import { ConsumptionBar } from '../../components/progress';
|
|
9
|
+
import useNavigate from '../../hooks/useNavigate';
|
|
9
10
|
/**
|
|
10
11
|
* Credits indicator component.
|
|
11
12
|
*/
|
|
12
13
|
export function CreditsIndicator(props) {
|
|
13
|
-
const { serviceManager, kernelId, onClick, onUpdate } = props;
|
|
14
|
+
const { serviceManager, kernelId, navigateTo, onClick, onUpdate } = props;
|
|
15
|
+
const navigate = useNavigate();
|
|
14
16
|
const [model, setModel] = useState();
|
|
15
17
|
useEffect(() => {
|
|
16
18
|
serviceManager.runtimesManager.findById(kernelId).then(model => {
|
|
17
19
|
setModel(model);
|
|
18
20
|
});
|
|
19
21
|
}, [kernelId, serviceManager]);
|
|
20
|
-
return model ? (_jsx(Box, { display: "flex", style: { alignItems: 'center' }, children: _jsx(ConsumptionBar, { startedAt: parseFloat(model.started_at), expiredAt: model.expired_at ? parseFloat(model.expired_at) : undefined, burningRate: model.burning_rate, onClick: onClick, onUpdate: onUpdate, style: { cursor: 'pointer' } }) })) : (_jsx(_Fragment, {}));
|
|
22
|
+
return model ? (_jsx(Box, { display: "flex", style: { alignItems: 'center' }, children: _jsx(ConsumptionBar, { startedAt: parseFloat(model.started_at), expiredAt: model.expired_at ? parseFloat(model.expired_at) : undefined, burningRate: model.burning_rate, onClick: onClick ?? (navigateTo ? () => navigate(navigateTo) : undefined), onUpdate: onUpdate, style: { cursor: 'pointer' } }) })) : (_jsx(_Fragment, {}));
|
|
21
23
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Component, CSSProperties } from 'react';
|
|
2
|
-
type
|
|
2
|
+
type ScreencaptureProps = {
|
|
3
3
|
children: any;
|
|
4
4
|
onStartCapture?: () => void;
|
|
5
5
|
onEndCapture: (url: string) => void;
|
|
6
6
|
};
|
|
7
|
-
type
|
|
7
|
+
type ScreencaptureState = {
|
|
8
8
|
on: boolean;
|
|
9
9
|
startX: number;
|
|
10
10
|
startY: number;
|
|
@@ -22,8 +22,8 @@ type ScreenCaptureState = {
|
|
|
22
22
|
cropHeigth: number;
|
|
23
23
|
imageURL: string;
|
|
24
24
|
};
|
|
25
|
-
export declare class
|
|
26
|
-
state:
|
|
25
|
+
export declare class Screencapture extends Component<ScreencaptureProps, ScreencaptureState> {
|
|
26
|
+
state: ScreencaptureState;
|
|
27
27
|
handleWindowResize: () => void;
|
|
28
28
|
componentDidMount: () => void;
|
|
29
29
|
componentWillUnmount: () => void;
|
|
@@ -35,4 +35,4 @@ export declare class ScreenCapture extends Component<ScreenCaptureProps, ScreenC
|
|
|
35
35
|
renderChild: () => any;
|
|
36
36
|
render(): any;
|
|
37
37
|
}
|
|
38
|
-
export default
|
|
38
|
+
export default Screencapture;
|
|
@@ -5,7 +5,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
5
5
|
*/
|
|
6
6
|
import { Component } from 'react';
|
|
7
7
|
import html2canvas from 'html2canvas';
|
|
8
|
-
export class
|
|
8
|
+
export class Screencapture extends Component {
|
|
9
9
|
state = {
|
|
10
10
|
on: false,
|
|
11
11
|
startX: 0,
|
|
@@ -167,4 +167,4 @@ export class ScreenCapture extends Component {
|
|
|
167
167
|
return (_jsxs("div", { onMouseMove: this.handleMouseMove, onMouseDown: this.handleMouseDown, onMouseUp: this.handleMouseUp, children: [this.renderChild(), _jsx("div", { className: `overlay ${isMouseDown && 'highlighting'}`, style: { borderWidth: `${borderWidth}` } }), _jsx("div", { className: "crosshairs", style: { left: crossHairsLeft + 'px', top: crossHairsTop + 'px' } })] }));
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
|
-
export default
|
|
170
|
+
export default Screencapture;
|
package/lib/components/{screenshot/ScreenCaptureButton.js → screencapture/ScreencaptureButton.js}
RENAMED
|
@@ -4,16 +4,16 @@ import { ScreenFullIcon } from '@primer/octicons-react';
|
|
|
4
4
|
import { lazyWithPreload, WithSuspense } from '../../utils';
|
|
5
5
|
import { useToast } from '../../hooks';
|
|
6
6
|
import { useLayoutStore } from '../../state';
|
|
7
|
-
const
|
|
8
|
-
export const
|
|
7
|
+
const Screencapture = WithSuspense(lazyWithPreload(() => import('./Screencapture')));
|
|
8
|
+
export const ScreencaptureButton = (props) => {
|
|
9
9
|
const { enqueueToast } = useToast();
|
|
10
|
-
const {
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
const { setScreencapture, hideScreencapture } = useLayoutStore();
|
|
11
|
+
const handleScreencapture = (screenCapture) => {
|
|
12
|
+
setScreencapture(screenCapture);
|
|
13
|
+
hideScreencapture();
|
|
14
14
|
enqueueToast('Screen is captured.', { variant: 'success' });
|
|
15
15
|
};
|
|
16
|
-
return (_jsx(
|
|
16
|
+
return (_jsx(Screencapture, { onEndCapture: handleScreencapture, children: ({ onStartCapture }) => (_jsx(Tooltip, { text: "Take a screen capture", direction: "s", children: _jsx(Button, { variant: "invisible", children: _jsx(Link, { href: "javascript: return false;", sx: {
|
|
17
17
|
color: 'fg.muted',
|
|
18
18
|
':hover, :focus, &[aria-expanded=true]': {
|
|
19
19
|
background: 'none !important',
|
|
@@ -24,4 +24,4 @@ export const ScreenCaptureButton = (props) => {
|
|
|
24
24
|
onStartCapture();
|
|
25
25
|
}, children: _jsx(ScreenFullIcon, {}) }) }) })) }));
|
|
26
26
|
};
|
|
27
|
-
export default
|
|
27
|
+
export default ScreencaptureButton;
|
package/lib/hooks/index.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export * from './useParams';
|
|
|
19
19
|
export * from './useOnClickOutside';
|
|
20
20
|
export * from './useRef';
|
|
21
21
|
export * from './useRuntimes';
|
|
22
|
-
export * from './
|
|
22
|
+
export * from './useScreencapture';
|
|
23
23
|
export * from './useToast';
|
|
24
24
|
export * from './useUpload';
|
|
25
25
|
export * from './useUser';
|
package/lib/hooks/index.js
CHANGED
|
@@ -24,7 +24,7 @@ export * from './useParams';
|
|
|
24
24
|
export * from './useOnClickOutside';
|
|
25
25
|
export * from './useRef';
|
|
26
26
|
export * from './useRuntimes';
|
|
27
|
-
export * from './
|
|
27
|
+
export * from './useScreencapture';
|
|
28
28
|
export * from './useToast';
|
|
29
29
|
export * from './useUpload';
|
|
30
30
|
export * from './useUser';
|
|
@@ -22,14 +22,14 @@
|
|
|
22
22
|
.crosshairs::before {
|
|
23
23
|
height: 24px;
|
|
24
24
|
width: 2px;
|
|
25
|
-
background: #
|
|
25
|
+
background: #fff;
|
|
26
26
|
top: -11px;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
.crosshairs::after {
|
|
30
30
|
width: 24px;
|
|
31
31
|
height: 2px;
|
|
32
|
-
background: #
|
|
32
|
+
background: #fff;
|
|
33
33
|
left: -11px;
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -5,11 +5,11 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
|
5
5
|
*/
|
|
6
6
|
import { useEffect } from 'react';
|
|
7
7
|
import { Box } from '@primer/react';
|
|
8
|
-
import {
|
|
8
|
+
import { useScreencapture, useToast } from '..';
|
|
9
9
|
import { lazyWithPreload, WithSuspense } from '../../utils';
|
|
10
10
|
import { useLayoutStore } from '../../state';
|
|
11
|
-
import '
|
|
12
|
-
const
|
|
11
|
+
import '../../../style/screencapture/index.css';
|
|
12
|
+
const Screencapture = WithSuspense(lazyWithPreload(() => import('../../components/screencapture/Screencapture')));
|
|
13
13
|
const Capture = (props) => {
|
|
14
14
|
const { onStartCapture } = props;
|
|
15
15
|
useEffect(() => {
|
|
@@ -17,28 +17,28 @@ const Capture = (props) => {
|
|
|
17
17
|
}, []);
|
|
18
18
|
return _jsx(_Fragment, {});
|
|
19
19
|
};
|
|
20
|
-
const
|
|
20
|
+
const ScreencaptureContent = (props) => {
|
|
21
21
|
// const { screenshotDisplay } = props;
|
|
22
22
|
const { enqueueToast } = useToast();
|
|
23
|
-
const {
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
const { setScreencapture, hideScreencapture } = useLayoutStore();
|
|
24
|
+
const handleScreencapture = (screenCapture) => {
|
|
25
|
+
setScreencapture(screenCapture);
|
|
26
|
+
hideScreencapture();
|
|
27
27
|
enqueueToast('Screen is captured.', { variant: 'success' });
|
|
28
28
|
};
|
|
29
|
-
return (_jsx(Box, { children: _jsx(
|
|
29
|
+
return (_jsx(Box, { children: _jsx(Screencapture, { onEndCapture: handleScreencapture, children: ({ onStartCapture }) => _jsx(Capture, { onStartCapture: onStartCapture }) }) }));
|
|
30
30
|
};
|
|
31
|
-
export const
|
|
31
|
+
export const LayoutScreencapture = () => {
|
|
32
32
|
const { screenshot } = useLayoutStore();
|
|
33
|
-
const {
|
|
33
|
+
const { displayScreencapture, closeScreencapture } = useScreencapture();
|
|
34
34
|
useEffect(() => {
|
|
35
35
|
if (screenshot && screenshot.open) {
|
|
36
|
-
|
|
36
|
+
displayScreencapture(() => (_jsx(ScreencaptureContent, { screenshotDisplay: screenshot })));
|
|
37
37
|
}
|
|
38
38
|
else {
|
|
39
|
-
|
|
39
|
+
closeScreencapture();
|
|
40
40
|
}
|
|
41
41
|
}, [screenshot]);
|
|
42
42
|
return _jsx(_Fragment, {});
|
|
43
43
|
};
|
|
44
|
-
export default
|
|
44
|
+
export default LayoutScreencapture;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from './LayoutBackdrop';
|
|
2
|
-
export * from './
|
|
2
|
+
export * from './LayoutScreencapture';
|
package/lib/hooks/useCache.d.ts
CHANGED
|
@@ -316,6 +316,7 @@ export declare const useCache: ({ loginRoute }?: CacheProps) => {
|
|
|
316
316
|
autorization_url: string;
|
|
317
317
|
}, Error, Record<string, string>, unknown>;
|
|
318
318
|
useGetGitHubProfile: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
|
|
319
|
+
useGetGoogleProfile: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
|
|
319
320
|
useGetLinkedinProfile: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
|
|
320
321
|
usePostLinkedinShare: () => import("@tanstack/react-query").UseMutationResult<any, Error, {
|
|
321
322
|
linkedinUserUrn: string;
|
|
@@ -325,7 +326,7 @@ export declare const useCache: ({ loginRoute }?: CacheProps) => {
|
|
|
325
326
|
usePostLinkedinShareWithUpload: () => import("@tanstack/react-query").UseMutationResult<any, Error, {
|
|
326
327
|
linkedinUserUrn: string;
|
|
327
328
|
postText: string;
|
|
328
|
-
uploadObject
|
|
329
|
+
uploadObject?: string;
|
|
329
330
|
accessToken: string;
|
|
330
331
|
}, unknown>;
|
|
331
332
|
useRegisterToWaitingList: () => import("@tanstack/react-query").UseMutationResult<any, Error, {
|
|
@@ -544,6 +545,7 @@ export declare const useCache: ({ loginRoute }?: CacheProps) => {
|
|
|
544
545
|
creditsLimit?: number;
|
|
545
546
|
type?: string;
|
|
546
547
|
editorVariant?: string;
|
|
548
|
+
enableCodemode?: boolean;
|
|
547
549
|
}, unknown>;
|
|
548
550
|
useDeleteAgentRuntime: () => import("@tanstack/react-query").UseMutationResult<any, Error, string, unknown>;
|
|
549
551
|
useRefreshAgentRuntimes: () => () => void;
|
package/lib/hooks/useCache.js
CHANGED
|
@@ -1673,6 +1673,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
1673
1673
|
credits_limit: data.creditsLimit || 10,
|
|
1674
1674
|
type: data.type || 'notebook',
|
|
1675
1675
|
editor_variant: data.editorVariant || 'none',
|
|
1676
|
+
enable_codemode: data.enableCodemode ?? false,
|
|
1676
1677
|
},
|
|
1677
1678
|
});
|
|
1678
1679
|
},
|
|
@@ -1710,10 +1711,21 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
1710
1711
|
method: 'DELETE',
|
|
1711
1712
|
});
|
|
1712
1713
|
},
|
|
1713
|
-
onSuccess: () => {
|
|
1714
|
-
//
|
|
1714
|
+
onSuccess: (_data, podName) => {
|
|
1715
|
+
// Cancel any in-flight queries for the deleted runtime so they
|
|
1716
|
+
// don't re-fetch a resource that no longer exists.
|
|
1717
|
+
queryClient.cancelQueries({
|
|
1718
|
+
queryKey: queryKeys.agentRuntimes.detail(podName),
|
|
1719
|
+
});
|
|
1720
|
+
// Remove the detail cache entry immediately — prevents React
|
|
1721
|
+
// Query from triggering a stale re-fetch while the component
|
|
1722
|
+
// unmounts.
|
|
1723
|
+
queryClient.removeQueries({
|
|
1724
|
+
queryKey: queryKeys.agentRuntimes.detail(podName),
|
|
1725
|
+
});
|
|
1726
|
+
// Invalidate the list so the sidebar refreshes.
|
|
1715
1727
|
queryClient.invalidateQueries({
|
|
1716
|
-
queryKey: queryKeys.agentRuntimes.
|
|
1728
|
+
queryKey: queryKeys.agentRuntimes.lists(),
|
|
1717
1729
|
});
|
|
1718
1730
|
},
|
|
1719
1731
|
});
|
|
@@ -5194,7 +5206,9 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
5194
5206
|
if (!resp.success) {
|
|
5195
5207
|
throw new Error(resp.message || 'Failed to search public items');
|
|
5196
5208
|
}
|
|
5197
|
-
return resp.items || []
|
|
5209
|
+
return (resp.items || [])
|
|
5210
|
+
.map((item) => toItem(item))
|
|
5211
|
+
.filter(Boolean);
|
|
5198
5212
|
},
|
|
5199
5213
|
});
|
|
5200
5214
|
};
|
|
@@ -5219,6 +5233,23 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
5219
5233
|
},
|
|
5220
5234
|
});
|
|
5221
5235
|
};
|
|
5236
|
+
/**
|
|
5237
|
+
* Get Google profile from access token
|
|
5238
|
+
*/
|
|
5239
|
+
const useGetGoogleProfile = () => {
|
|
5240
|
+
return useMutation({
|
|
5241
|
+
mutationFn: async (accessToken) => {
|
|
5242
|
+
const response = await fetch('https://openidconnect.googleapis.com/v1/userinfo', {
|
|
5243
|
+
method: 'GET',
|
|
5244
|
+
headers: {
|
|
5245
|
+
Accept: 'application/json',
|
|
5246
|
+
Authorization: `Bearer ${accessToken}`,
|
|
5247
|
+
},
|
|
5248
|
+
});
|
|
5249
|
+
return response.json();
|
|
5250
|
+
},
|
|
5251
|
+
});
|
|
5252
|
+
};
|
|
5222
5253
|
/**
|
|
5223
5254
|
* Get LinkedIn profile via proxy
|
|
5224
5255
|
*/
|
|
@@ -5275,68 +5306,87 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
5275
5306
|
const usePostLinkedinShareWithUpload = () => {
|
|
5276
5307
|
return useMutation({
|
|
5277
5308
|
mutationFn: async ({ linkedinUserUrn, postText, uploadObject, accessToken, }) => {
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
identifier: 'urn:li:userGeneratedContent',
|
|
5287
|
-
},
|
|
5288
|
-
],
|
|
5289
|
-
},
|
|
5290
|
-
};
|
|
5291
|
-
const registerResp = await requestDatalayer({
|
|
5292
|
-
url: `${configuration.iamRunUrl}/api/iam/v1/proxy/request`,
|
|
5293
|
-
method: 'POST',
|
|
5294
|
-
body: {
|
|
5295
|
-
request_method: 'POST',
|
|
5296
|
-
request_url: 'https://api.linkedin.com/v2/assets?action=registerUpload',
|
|
5297
|
-
request_token: accessToken,
|
|
5298
|
-
request_body: registerUploadRequest,
|
|
5299
|
-
},
|
|
5300
|
-
});
|
|
5301
|
-
const asset = registerResp.response.value.asset;
|
|
5302
|
-
const uploadUrl = registerResp.response.value.uploadMechanism['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest'].uploadUrl;
|
|
5303
|
-
// Step 2: Upload image
|
|
5304
|
-
await requestDatalayer({
|
|
5305
|
-
url: `${configuration.iamRunUrl}/api/iam/v1/proxy/request`,
|
|
5306
|
-
method: 'POST',
|
|
5307
|
-
body: {
|
|
5308
|
-
request_method: 'PUT',
|
|
5309
|
-
request_url: uploadUrl,
|
|
5310
|
-
request_token: accessToken,
|
|
5311
|
-
request_body: {
|
|
5312
|
-
uploadURL: uploadUrl,
|
|
5313
|
-
content: uploadObject,
|
|
5314
|
-
userURN: linkedinUserUrn,
|
|
5315
|
-
},
|
|
5316
|
-
},
|
|
5317
|
-
});
|
|
5318
|
-
// Step 3: Create share with media
|
|
5319
|
-
const shareRequest = {
|
|
5320
|
-
author: linkedinUserUrn,
|
|
5321
|
-
lifecycleState: 'PUBLISHED',
|
|
5322
|
-
specificContent: {
|
|
5323
|
-
'com.linkedin.ugc.ShareContent': {
|
|
5324
|
-
shareCommentary: { text: postText },
|
|
5325
|
-
shareMediaCategory: 'IMAGE',
|
|
5326
|
-
media: [
|
|
5309
|
+
let shareRequest;
|
|
5310
|
+
if (uploadObject) {
|
|
5311
|
+
// Step 1: Register upload
|
|
5312
|
+
const registerUploadRequest = {
|
|
5313
|
+
registerUploadRequest: {
|
|
5314
|
+
recipes: ['urn:li:digitalmediaRecipe:feedshare-image'],
|
|
5315
|
+
owner: linkedinUserUrn,
|
|
5316
|
+
serviceRelationships: [
|
|
5327
5317
|
{
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
media: asset,
|
|
5331
|
-
title: { text: 'Datalayer Notebook' },
|
|
5318
|
+
relationshipType: 'OWNER',
|
|
5319
|
+
identifier: 'urn:li:userGeneratedContent',
|
|
5332
5320
|
},
|
|
5333
5321
|
],
|
|
5334
5322
|
},
|
|
5335
|
-
}
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5339
|
-
|
|
5323
|
+
};
|
|
5324
|
+
const registerResp = await requestDatalayer({
|
|
5325
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/proxy/request`,
|
|
5326
|
+
method: 'POST',
|
|
5327
|
+
body: {
|
|
5328
|
+
request_method: 'POST',
|
|
5329
|
+
request_url: 'https://api.linkedin.com/v2/assets?action=registerUpload',
|
|
5330
|
+
request_token: accessToken,
|
|
5331
|
+
request_body: registerUploadRequest,
|
|
5332
|
+
},
|
|
5333
|
+
});
|
|
5334
|
+
const asset = registerResp.response.value.asset;
|
|
5335
|
+
const uploadUrl = registerResp.response.value.uploadMechanism['com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest'].uploadUrl;
|
|
5336
|
+
// Step 2: Upload image
|
|
5337
|
+
await requestDatalayer({
|
|
5338
|
+
url: `${configuration.iamRunUrl}/api/iam/v1/proxy/request`,
|
|
5339
|
+
method: 'POST',
|
|
5340
|
+
body: {
|
|
5341
|
+
request_method: 'PUT',
|
|
5342
|
+
request_url: uploadUrl,
|
|
5343
|
+
request_token: accessToken,
|
|
5344
|
+
request_body: {
|
|
5345
|
+
uploadURL: uploadUrl,
|
|
5346
|
+
content: uploadObject,
|
|
5347
|
+
userURN: linkedinUserUrn,
|
|
5348
|
+
},
|
|
5349
|
+
},
|
|
5350
|
+
});
|
|
5351
|
+
// Step 3: Create share with media
|
|
5352
|
+
shareRequest = {
|
|
5353
|
+
author: linkedinUserUrn,
|
|
5354
|
+
lifecycleState: 'PUBLISHED',
|
|
5355
|
+
specificContent: {
|
|
5356
|
+
'com.linkedin.ugc.ShareContent': {
|
|
5357
|
+
shareCommentary: { text: postText },
|
|
5358
|
+
shareMediaCategory: 'IMAGE',
|
|
5359
|
+
media: [
|
|
5360
|
+
{
|
|
5361
|
+
status: 'READY',
|
|
5362
|
+
description: { text: 'Datalayer Notebook' },
|
|
5363
|
+
media: asset,
|
|
5364
|
+
title: { text: 'Datalayer Notebook' },
|
|
5365
|
+
},
|
|
5366
|
+
],
|
|
5367
|
+
},
|
|
5368
|
+
},
|
|
5369
|
+
visibility: {
|
|
5370
|
+
'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC',
|
|
5371
|
+
},
|
|
5372
|
+
};
|
|
5373
|
+
}
|
|
5374
|
+
else {
|
|
5375
|
+
// Text-only share (no image upload)
|
|
5376
|
+
shareRequest = {
|
|
5377
|
+
author: linkedinUserUrn,
|
|
5378
|
+
lifecycleState: 'PUBLISHED',
|
|
5379
|
+
specificContent: {
|
|
5380
|
+
'com.linkedin.ugc.ShareContent': {
|
|
5381
|
+
shareCommentary: { text: postText },
|
|
5382
|
+
shareMediaCategory: 'NONE',
|
|
5383
|
+
},
|
|
5384
|
+
},
|
|
5385
|
+
visibility: {
|
|
5386
|
+
'com.linkedin.ugc.MemberNetworkVisibility': 'PUBLIC',
|
|
5387
|
+
},
|
|
5388
|
+
};
|
|
5389
|
+
}
|
|
5340
5390
|
return requestDatalayer({
|
|
5341
5391
|
url: `${configuration.iamRunUrl}/api/iam/v1/proxy/request`,
|
|
5342
5392
|
method: 'POST',
|
|
@@ -6353,6 +6403,7 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
|
|
|
6353
6403
|
useOAuth2AuthorizationURL,
|
|
6354
6404
|
useOAuth2AuthorizationLinkURL,
|
|
6355
6405
|
useGetGitHubProfile,
|
|
6406
|
+
useGetGoogleProfile,
|
|
6356
6407
|
useGetLinkedinProfile,
|
|
6357
6408
|
usePostLinkedinShare,
|
|
6358
6409
|
usePostLinkedinShareWithUpload,
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { useState } from 'react';
|
|
6
6
|
import { useCellStore } from '../state';
|
|
7
|
-
import {
|
|
7
|
+
import { takeHTMLNodeScreencapture } from '../utils/Screencapture';
|
|
8
8
|
const useCellOutputshot = () => {
|
|
9
9
|
const [outputshot, setOutputshot] = useState('');
|
|
10
10
|
const [error, setError] = useState();
|
|
11
11
|
const { update } = useCellStore();
|
|
12
12
|
const takeOutputshot = (node) => {
|
|
13
|
-
|
|
13
|
+
takeHTMLNodeScreencapture(node)
|
|
14
14
|
.then(outputshotData => {
|
|
15
15
|
setOutputshot(outputshotData);
|
|
16
16
|
update({
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export type ScreencaptureContextType = {
|
|
3
|
+
closeScreencapture: () => void;
|
|
4
|
+
displayScreencapture: (nextScreencapture: any) => void;
|
|
5
|
+
};
|
|
6
|
+
export declare const ScreencaptureContext: import("react").Context<ScreencaptureContextType>;
|
|
7
|
+
export declare function useScreencapture(): ScreencaptureContextType;
|
|
8
|
+
/**
|
|
9
|
+
* The type for the Screencapture context provider.
|
|
10
|
+
*/
|
|
11
|
+
export declare const ScreencaptureContextProvider: import("react").Provider<ScreencaptureContextType>;
|
|
12
|
+
export type IScreencaptureProviderProps = {
|
|
13
|
+
children?: ReactNode;
|
|
14
|
+
zIndex?: number;
|
|
15
|
+
disableDarken?: boolean;
|
|
16
|
+
screenshotSurface?: (qfds: any) => JSX.Element;
|
|
17
|
+
};
|
|
18
|
+
export declare function ScreencaptureProvider({ children, zIndex, disableDarken, screenshotSurface, }: IScreencaptureProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
import { createContext, useState, useContext } from 'react';
|
|
7
|
+
import { LayoutScreencapture } from './layouts';
|
|
8
|
+
export const ScreencaptureContext = createContext({
|
|
9
|
+
closeScreencapture: () => { },
|
|
10
|
+
displayScreencapture: (nextScreencapture) => { },
|
|
11
|
+
});
|
|
12
|
+
export function useScreencapture() {
|
|
13
|
+
const context = useContext(ScreencaptureContext);
|
|
14
|
+
if (!context)
|
|
15
|
+
throw new Error('useContext must be inside a provider with a value.');
|
|
16
|
+
return context;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The type for the Screencapture context provider.
|
|
20
|
+
*/
|
|
21
|
+
export const ScreencaptureContextProvider = ScreencaptureContext.Provider;
|
|
22
|
+
export function ScreencaptureProvider({ children = null, zIndex = 9999, disableDarken = false, screenshotSurface = undefined, }) {
|
|
23
|
+
const defaultScreencaptureSurface = {
|
|
24
|
+
position: 'fixed',
|
|
25
|
+
top: 0,
|
|
26
|
+
left: 0,
|
|
27
|
+
width: '100%',
|
|
28
|
+
height: '100%',
|
|
29
|
+
display: 'flex',
|
|
30
|
+
alignItems: 'center',
|
|
31
|
+
justifyContent: 'center',
|
|
32
|
+
backgroundColor: disableDarken ? 'initial' : 'rgba(0, 0, 0, 0.5)',
|
|
33
|
+
zIndex,
|
|
34
|
+
};
|
|
35
|
+
const [screenshot, setScreencapture] = useState({
|
|
36
|
+
open: false,
|
|
37
|
+
render: (closeScreencapture) => _jsx(_Fragment, {}),
|
|
38
|
+
});
|
|
39
|
+
const displayScreencapture = (nextScreencapture) => {
|
|
40
|
+
setScreencapture({
|
|
41
|
+
open: true,
|
|
42
|
+
render: nextScreencapture,
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
const closeScreencapture = () => {
|
|
46
|
+
setScreencapture({
|
|
47
|
+
open: false,
|
|
48
|
+
render: (closeScreencapture) => _jsx(_Fragment, {}),
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
return (_jsxs(ScreencaptureContextProvider, { value: { closeScreencapture, displayScreencapture }, children: [_jsx(LayoutScreencapture, {}), children, screenshot.open &&
|
|
52
|
+
(screenshotSurface ? (screenshotSurface(screenshot.render(closeScreencapture))) : (_jsx("div", { style: defaultScreencaptureSurface, children: screenshot.render(closeScreencapture) })))] }));
|
|
53
|
+
}
|
|
@@ -24,6 +24,17 @@ export type ILinkedInUser = {
|
|
|
24
24
|
picture: string;
|
|
25
25
|
getUrn(): string;
|
|
26
26
|
};
|
|
27
|
+
export type IGoogleUser = {
|
|
28
|
+
iamProvider: IIAMProviderName;
|
|
29
|
+
sub: string;
|
|
30
|
+
email_verified: boolean;
|
|
31
|
+
name: string;
|
|
32
|
+
given_name: string;
|
|
33
|
+
family_name: string;
|
|
34
|
+
email: string;
|
|
35
|
+
picture: string;
|
|
36
|
+
locale: string;
|
|
37
|
+
};
|
|
27
38
|
export type IXUser = {
|
|
28
39
|
iamProvider: IIAMProviderName;
|
|
29
40
|
sub: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { IUser } from './User';
|
|
2
|
-
export type IIAMProviderName = 'bluesky' | 'discord' | 'github' | 'linkedin' | 'okta' | 'x';
|
|
2
|
+
export type IIAMProviderName = 'bluesky' | 'discord' | 'github' | 'google' | 'linkedin' | 'okta' | 'x';
|
|
3
3
|
export type IIAMProviderSpec = {
|
|
4
4
|
name: IIAMProviderName;
|
|
5
5
|
oauth2CallbackServerRoute: string;
|
|
@@ -16,6 +16,7 @@ export declare class IAMProvidersSpecs {
|
|
|
16
16
|
static getProvider(providerIAMProvidersType: any): IIAMProviderSpec;
|
|
17
17
|
static readonly Bluesky: IIAMProviderSpec;
|
|
18
18
|
static readonly GitHub: IIAMProviderSpec;
|
|
19
|
+
static readonly Google: IIAMProviderSpec;
|
|
19
20
|
static readonly LinkedIn: IIAMProviderSpec;
|
|
20
21
|
static readonly Okta: IIAMProviderSpec;
|
|
21
22
|
}
|
|
@@ -12,6 +12,9 @@ export class IAMProvidersSpecs {
|
|
|
12
12
|
case 'github': {
|
|
13
13
|
return this.GitHub;
|
|
14
14
|
}
|
|
15
|
+
case 'google': {
|
|
16
|
+
return this.Google;
|
|
17
|
+
}
|
|
15
18
|
case 'linkedin': {
|
|
16
19
|
return this.LinkedIn;
|
|
17
20
|
}
|
|
@@ -46,6 +49,17 @@ export class IAMProvidersSpecs {
|
|
|
46
49
|
postShareURL: '',
|
|
47
50
|
registerUploadURL: '',
|
|
48
51
|
};
|
|
52
|
+
static Google = {
|
|
53
|
+
name: 'google',
|
|
54
|
+
oauth2CallbackServerRoute: 'jupyter_iam/oauth2/callback',
|
|
55
|
+
oauth2CallbackUIRoute: '/iam/oauth2/google/callback',
|
|
56
|
+
accessTokenCookieName: (user) => `__datalayer__google_access_token_${user.id}`,
|
|
57
|
+
refreshTokenCookieName: '__datalayer__google_refresh_token',
|
|
58
|
+
userInfoURL: 'https://openidconnect.googleapis.com/v1/userinfo',
|
|
59
|
+
tokenRefreshURL: 'https://oauth2.googleapis.com/token',
|
|
60
|
+
postShareURL: '',
|
|
61
|
+
registerUploadURL: '',
|
|
62
|
+
};
|
|
49
63
|
static LinkedIn = {
|
|
50
64
|
name: 'linkedin',
|
|
51
65
|
oauth2CallbackServerRoute: 'jupyter_iam/oauth2/callback',
|
package/lib/models/Page.js
CHANGED
|
@@ -13,7 +13,7 @@ export const asPage = (s) => {
|
|
|
13
13
|
description: s.description_t,
|
|
14
14
|
theme: s.theme_s,
|
|
15
15
|
nbformat: s.nbformat_s ? JSON.parse(s.nbformat_s) : undefined,
|
|
16
|
-
screenCapture: s.screen_capture_s,
|
|
16
|
+
screenCapture: s.screen_capture_cdn_url_s || s.screen_capture_s,
|
|
17
17
|
tags: s.tags_ss ?? [],
|
|
18
18
|
creator: s.creator ? asUser(s.creator) : undefined,
|
|
19
19
|
creatorId: s.creator_uid,
|
package/lib/models/PageTag.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ type CardIconColorsType = (typeof CardIconColors)[number];
|
|
|
4
4
|
export type PageTagMetadata = {
|
|
5
5
|
fillColor: React.CSSProperties['backgroundColor'];
|
|
6
6
|
};
|
|
7
|
-
export type PageTagName = 'ai' | 'deep-learning' | 'example' | 'llm' | 'python' | 'pytorch' | 'spatial' | 'tutorial';
|
|
7
|
+
export type PageTagName = 'agent' | 'ai' | 'ai-agent' | 'deep-learning' | 'example' | 'llm' | 'notebook' | 'python' | 'pytorch' | 'spatial' | 'tutorial';
|
|
8
8
|
export type PageTag = {
|
|
9
9
|
id: string;
|
|
10
10
|
text?: PageTagName;
|
package/lib/models/PageTag.js
CHANGED
|
@@ -9,12 +9,24 @@ export const PAGE_TAGE_NONE = {
|
|
|
9
9
|
Icon: CopilotIcon,
|
|
10
10
|
color: 'pink',
|
|
11
11
|
};
|
|
12
|
+
const PAGE_TAGE_AGENT = {
|
|
13
|
+
id: '9',
|
|
14
|
+
text: 'agent',
|
|
15
|
+
Icon: CopilotIcon,
|
|
16
|
+
color: 'teal',
|
|
17
|
+
};
|
|
12
18
|
const PAGE_TAGE_AI = {
|
|
13
19
|
id: '1',
|
|
14
20
|
text: 'ai',
|
|
15
21
|
Icon: CopilotIcon,
|
|
16
22
|
color: 'pink',
|
|
17
23
|
};
|
|
24
|
+
const PAGE_TAGE_AI_AGENT = {
|
|
25
|
+
id: '10',
|
|
26
|
+
text: 'ai-agent',
|
|
27
|
+
Icon: CopilotIcon,
|
|
28
|
+
color: 'purple',
|
|
29
|
+
};
|
|
18
30
|
const PAGE_TAGE_DEEP_LEARNING = {
|
|
19
31
|
id: '2',
|
|
20
32
|
text: 'deep-learning',
|
|
@@ -33,6 +45,12 @@ const PAGE_TAGE_LLM = {
|
|
|
33
45
|
Icon: CopilotIcon,
|
|
34
46
|
color: 'coral',
|
|
35
47
|
};
|
|
48
|
+
const PAGE_TAGE_NOTEBOOK = {
|
|
49
|
+
id: '11',
|
|
50
|
+
text: 'notebook',
|
|
51
|
+
Icon: CopilotIcon,
|
|
52
|
+
color: 'blue',
|
|
53
|
+
};
|
|
36
54
|
const PAGE_TAGE_PYTHON = {
|
|
37
55
|
id: '5',
|
|
38
56
|
text: 'python',
|
|
@@ -60,10 +78,13 @@ const PAGE_TAGE_TUTORIAL = {
|
|
|
60
78
|
metadata: { fillColor: 'yellow' },
|
|
61
79
|
};
|
|
62
80
|
export const PAGE_TAGS = [
|
|
81
|
+
PAGE_TAGE_AGENT,
|
|
63
82
|
PAGE_TAGE_AI,
|
|
83
|
+
PAGE_TAGE_AI_AGENT,
|
|
64
84
|
PAGE_TAGE_DEEP_LEARNING,
|
|
65
85
|
PAGE_TAGE_EXAMPLE,
|
|
66
86
|
PAGE_TAGE_LLM,
|
|
87
|
+
PAGE_TAGE_NOTEBOOK,
|
|
67
88
|
PAGE_TAGE_PYTHON,
|
|
68
89
|
PAGE_TAGE_PYTORCH,
|
|
69
90
|
PAGE_TAGE_SPATIAL,
|
|
@@ -15,7 +15,7 @@ export type PortalDisplay = {
|
|
|
15
15
|
portal: ReactPortal;
|
|
16
16
|
pinned: boolean;
|
|
17
17
|
};
|
|
18
|
-
export type
|
|
18
|
+
export type ScreencaptureDisplay = {
|
|
19
19
|
open: boolean;
|
|
20
20
|
message?: string | void;
|
|
21
21
|
};
|
|
@@ -30,13 +30,13 @@ export type ILayoutState = {
|
|
|
30
30
|
organization?: IAnyOrganization;
|
|
31
31
|
rightPortal?: PortalDisplay;
|
|
32
32
|
screenCapture?: string;
|
|
33
|
-
screenshot?:
|
|
33
|
+
screenshot?: ScreencaptureDisplay;
|
|
34
34
|
space?: IAnySpace;
|
|
35
35
|
team?: IAnyTeam;
|
|
36
36
|
};
|
|
37
37
|
export type LayoutState = ILayoutState & {
|
|
38
38
|
hideBackdrop: () => void;
|
|
39
|
-
|
|
39
|
+
hideScreencapture: () => void;
|
|
40
40
|
reset: () => void;
|
|
41
41
|
resetForcedLeftPortal: () => void;
|
|
42
42
|
resetForcedRightPortal: () => void;
|
|
@@ -48,9 +48,9 @@ export type LayoutState = ILayoutState & {
|
|
|
48
48
|
setLeftPortal: (leftPortal: PortalDisplay) => void;
|
|
49
49
|
setLeftSidebarVariant: (leftSidebarVariant: LeftSidebarVariant) => void;
|
|
50
50
|
setRightPortal: (rightPortal: PortalDisplay) => void;
|
|
51
|
-
|
|
51
|
+
setScreencapture: (screenCapture?: string) => void;
|
|
52
52
|
showBackdrop: (message?: string) => void;
|
|
53
|
-
|
|
53
|
+
showScreencapture: (message?: string) => void;
|
|
54
54
|
triggerItemsRefresh: () => void;
|
|
55
55
|
updateLayoutOrganization: (organization?: Partial<IAnyOrganization>) => void;
|
|
56
56
|
updateLayoutSpace: (space?: Partial<IAnySpace>) => void;
|
|
@@ -20,12 +20,12 @@ export const layoutStore = createStore((set, get) => ({
|
|
|
20
20
|
hideBackdrop: () => set((state) => ({
|
|
21
21
|
backdrop: { open: false, message: undefined },
|
|
22
22
|
})),
|
|
23
|
-
|
|
23
|
+
hideScreencapture: () => set((state) => ({
|
|
24
24
|
screenshot: { open: false, message: undefined },
|
|
25
25
|
})),
|
|
26
26
|
setBootstrapped: (bootstrapped) => set((state) => ({ bootstrapped })),
|
|
27
27
|
showBackdrop: (message) => set((state) => ({ backdrop: { open: true, message } })),
|
|
28
|
-
|
|
28
|
+
showScreencapture: (message) => set((state) => ({ screenshot: { open: true, message } })),
|
|
29
29
|
setBanner: (bannerDisplay) => set((state) => ({
|
|
30
30
|
banner: {
|
|
31
31
|
timestamp: new Date(),
|
|
@@ -78,7 +78,7 @@ export const layoutStore = createStore((set, get) => ({
|
|
|
78
78
|
triggerItemsRefresh: () => set((state) => ({
|
|
79
79
|
itemsRefreshCount: state.itemsRefreshCount + 1,
|
|
80
80
|
})),
|
|
81
|
-
|
|
81
|
+
setScreencapture: (screenCapture) => set((state) => ({ screenCapture })),
|
|
82
82
|
reset: () => set((state) => ({ bootstrapped: false })),
|
|
83
83
|
}));
|
|
84
84
|
export function useLayoutStore(selector) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const takeHTMLNodeScreencapture: (node: HTMLDivElement) => Promise<string>;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
5
|
import html2canvas from 'html2canvas';
|
|
6
|
-
export const
|
|
6
|
+
export const takeHTMLNodeScreencapture = async (node) => {
|
|
7
7
|
const sc = html2canvas(node, {
|
|
8
8
|
width: node.getBoundingClientRect().width,
|
|
9
9
|
height: node.getBoundingClientRect().height,
|
package/lib/utils/index.js
CHANGED
|
@@ -23,7 +23,7 @@ export * from './Notebook';
|
|
|
23
23
|
export * from './Number';
|
|
24
24
|
export * from './Plots';
|
|
25
25
|
export * from './Random';
|
|
26
|
-
// export * from './
|
|
26
|
+
// export * from './Screencapture'; Do not export html2canvas for now.
|
|
27
27
|
export * from './Sleep';
|
|
28
28
|
export * from './Snapshot';
|
|
29
29
|
export * from './String';
|
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type DatasourceNewProps = {
|
|
2
|
+
/** Route to navigate after creating a datasource. Defaults to '/settings/integrations/datasources'. */
|
|
3
|
+
datasourcesListRoute?: string;
|
|
4
|
+
/** Route to navigate to the secrets page. Defaults to '/settings/iam/secrets'. */
|
|
5
|
+
secretsRoute?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const DatasourceNew: ({ datasourcesListRoute, secretsRoute, }?: DatasourceNewProps) => import("react/jsx-runtime").JSX.Element;
|
|
2
8
|
export default DatasourceNew;
|
|
@@ -8,7 +8,7 @@ import { PageHeader, FormControl, Button, TextInput, Text, Textarea, Select, Fla
|
|
|
8
8
|
import { Box } from '@datalayer/primer-addons';
|
|
9
9
|
import { useCache, useNavigate, useToast } from '../../hooks';
|
|
10
10
|
import { useRunStore } from '../../state';
|
|
11
|
-
export const DatasourceNew = () => {
|
|
11
|
+
export const DatasourceNew = ({ datasourcesListRoute = '/settings/integrations/datasources', secretsRoute = '/settings/iam/secrets', } = {}) => {
|
|
12
12
|
const runStore = useRunStore();
|
|
13
13
|
const { useCreateDatasource } = useCache();
|
|
14
14
|
const createDatasourceMutation = useCreateDatasource();
|
|
@@ -99,7 +99,7 @@ export const DatasourceNew = () => {
|
|
|
99
99
|
onSuccess: (resp) => {
|
|
100
100
|
if (resp.success) {
|
|
101
101
|
enqueueToast(resp.message, { variant: 'success' });
|
|
102
|
-
navigate(
|
|
102
|
+
navigate(datasourcesListRoute);
|
|
103
103
|
}
|
|
104
104
|
},
|
|
105
105
|
onSettled: () => {
|
|
@@ -107,7 +107,7 @@ export const DatasourceNew = () => {
|
|
|
107
107
|
},
|
|
108
108
|
});
|
|
109
109
|
};
|
|
110
|
-
return (_jsxs(Box, { children: [_jsx(PageHeader, { children: _jsx(PageHeader.TitleArea, { variant: "large", children: _jsx(PageHeader.Title, { children: "New Datasource" }) }) }), _jsxs(Flash, { variant: "warning", children: [formValues.variant === 'athena' && (_jsxs(Text, { children: ["For ", _jsx(Link, { href: "https://aws.amazon.com/athena", children: "Amazon Athena" }), ", ensure the following", ' ', _jsx(Link, { href: "javascript: return false;", onClick: e => navigate(
|
|
110
|
+
return (_jsxs(Box, { children: [_jsx(PageHeader, { children: _jsx(PageHeader.TitleArea, { variant: "large", children: _jsx(PageHeader.Title, { children: "New Datasource" }) }) }), _jsxs(Flash, { variant: "warning", children: [formValues.variant === 'athena' && (_jsxs(Text, { children: ["For ", _jsx(Link, { href: "https://aws.amazon.com/athena", children: "Amazon Athena" }), ", ensure the following", ' ', _jsx(Link, { href: "javascript: return false;", onClick: e => navigate(secretsRoute, e), children: "Secrets" }), ' ', "are available:", ' ', _jsx(Text, { as: "code", children: "AWS_SECRET_ACCESS_KEY" }), ' ', _jsx(Text, { as: "code", children: "AWS_ACCESS_KEY_ID" }), ' ', _jsx(Text, { as: "code", children: "AWS_DEFAULT_REGION" })] })), formValues.variant === 'bigquery' && (_jsxs(Text, { children: ["For", ' ', _jsx(Link, { href: "https://cloud.google.com/bigquery", children: "Google Big Query" }), ", ensure the following", ' ', _jsx(Link, { href: "javascript: return false;", onClick: e => navigate(secretsRoute, e), children: "Secret" }), ' ', "is available:", ' ', _jsx(Text, { as: "code", children: "GOOGLE_APPLICATION_CREDENTIALS" })] })), formValues.variant === 'mssentinel' && (_jsxs(Text, { children: ["For", ' ', _jsx(Link, { href: "https://learn.microsoft.com/en-us/azure/sentinel/overview?tabs=defender-portaly", children: "Microsoft Sentinel" }), ", ensure the following", ' ', _jsx(Link, { href: "javascript: return false;", onClick: e => navigate(secretsRoute, e), children: "Secret" }), ' ', "is available:", ' ', _jsx(Text, { as: "code", children: "AZURE_TENANT_ID" }), ` `, _jsx(Text, { as: "code", children: "AZURE_CLIENT_ID" }), ` `, _jsx(Text, { as: "code", children: "AZURE_CLIENT_SECRET" }), ` `, _jsx(Text, { as: "code", children: "AZURE_SUBSCRIPTION_ID" }), ` `, _jsx(Text, { as: "code", children: "AZURE_RESOURCE_GROUP" }), ` `, _jsx(Text, { as: "code", children: "MSSENTINEL_WORKSPACE_ID" }), ` `, _jsx(Text, { as: "code", children: "MSSENTINEL_WORKSPACE_NAME" })] })), formValues.variant === 'splunk' && (_jsxs(Text, { children: ["For ", _jsx(Link, { href: "https://www.splunk.com/", children: "Splunk" }), ", ensure the following", ' ', _jsx(Link, { href: "javascript: return false;", onClick: e => navigate(secretsRoute, e), children: "Secret" }), ' ', "is available:", ' ', _jsx(Text, { as: "code", children: "SPLUNK_HOST" }), ` `, _jsx(Text, { as: "code", children: "SPLUNK_PORT" }), ` `, _jsx(Text, { as: "code", children: "SPLUNK_USERNAME" }), ` `, _jsx(Text, { as: "code", children: "SPLUNK_PASSWORD" })] }))] }), _jsx(Box, { display: "grid", gridTemplateColumns: "1fr 1fr", sx: { gap: 3 }, children: _jsx(Box, { children: _jsxs(Box, { sx: { label: { marginTop: 2 } }, children: [_jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Datasource type" }), _jsxs(Select, { name: "type", value: formValues.variant, onChange: valueVariantChange, children: [_jsx(Select.Option, { value: "athena", children: "Amazon Athena" }), _jsx(Select.Option, { value: "bigquery", children: "Google BigQuery" }), _jsx(Select.Option, { value: "mssentinel", children: "Microsoft Sentinel" }), _jsx(Select.Option, { value: "splunk", children: "Splunk" })] }), _jsx(FormControl.Caption, { children: "Pick the most appropriate datasource type." })] }), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Name" }), _jsx(TextInput, { block: true, value: formValues.name, onChange: valueNameChange, autoFocus: true }), _jsx(FormControl.Caption, { children: "Hint: The datasource name is a short name that identifies in a unique way your datasource." }), validationResult.name === false && (_jsx(FormControl.Validation, { variant: "error", children: "Name length must be between 2 and 32 characters." }))] }), formValues.variant === 'athena' && (_jsxs(_Fragment, { children: [_jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Database" }), _jsx(TextInput, { block: true, value: formValues.database, onChange: valueDatabaseChange }), validationResult.database === false && (_jsx(FormControl.Validation, { variant: "error", children: "Database must have more than 1." }))] }), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Output Bucket" }), _jsx(TextInput, { block: true, value: formValues.outputBucket, onChange: valueOutputBucketChange }), validationResult.database === false && (_jsx(FormControl.Validation, { variant: "error", children: "Output bucket must have more than 1." }))] })] })), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Description" }), _jsx(Textarea, { block: true, value: formValues.description, onChange: valueDescriptionChange }), validationResult.description === false && (_jsx(FormControl.Validation, { variant: "error", children: "Description must have more than 2 characters." }))] }), _jsx(Button, { variant: "primary", disabled: !validationResult.database ||
|
|
111
111
|
!validationResult.outputBucket ||
|
|
112
112
|
!validationResult.name ||
|
|
113
113
|
!validationResult.description, sx: { marginTop: 2 }, onClick: e => {
|
|
@@ -1,2 +1,8 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type DatasourcesProps = {
|
|
2
|
+
/** Route to navigate when clicking "New datasource" button. Defaults to '/new/datasource'. */
|
|
3
|
+
newDatasourceRoute?: string;
|
|
4
|
+
/** Base route for the datasources list (used for edit navigation). Defaults to current relative path. */
|
|
5
|
+
datasourcesListRoute?: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const Datasources: ({ newDatasourceRoute, datasourcesListRoute, }?: DatasourcesProps) => import("react/jsx-runtime").JSX.Element;
|
|
2
8
|
export default Datasources;
|
|
@@ -9,7 +9,7 @@ import { Blankslate, PageHeader, Table, DataTable, } from '@primer/react/experim
|
|
|
9
9
|
import { Box } from '@datalayer/primer-addons';
|
|
10
10
|
import { EditIcon } from '@datalayer/icons-react';
|
|
11
11
|
import { useCache, useNavigate } from '../../hooks';
|
|
12
|
-
const DatasourcesTable = () => {
|
|
12
|
+
const DatasourcesTable = ({ datasourcesListRoute, }) => {
|
|
13
13
|
const { useDatasources } = useCache();
|
|
14
14
|
const datasourcesQuery = useDatasources();
|
|
15
15
|
const navigate = useNavigate();
|
|
@@ -38,12 +38,14 @@ const DatasourcesTable = () => {
|
|
|
38
38
|
{
|
|
39
39
|
header: '',
|
|
40
40
|
field: 'id',
|
|
41
|
-
renderCell: datasource => (_jsx(IconButton, { icon: EditIcon, "aria-label": "Edit", size: "small", variant: "invisible", onClick: e => navigate(
|
|
41
|
+
renderCell: datasource => (_jsx(IconButton, { icon: EditIcon, "aria-label": "Edit", size: "small", variant: "invisible", onClick: e => navigate(datasourcesListRoute
|
|
42
|
+
? `${datasourcesListRoute}/${datasource.id}`
|
|
43
|
+
: `${datasource.id}`, e) })),
|
|
42
44
|
},
|
|
43
45
|
] })] }));
|
|
44
46
|
};
|
|
45
|
-
export const Datasources = () => {
|
|
47
|
+
export const Datasources = ({ newDatasourceRoute = '/new/datasource', datasourcesListRoute, } = {}) => {
|
|
46
48
|
const navigate = useNavigate();
|
|
47
|
-
return (_jsxs(PageLayout, { containerWidth: "full", padding: "normal", style: { overflow: 'visible', minHeight: 'calc(100vh - 45px)' }, children: [_jsx(PageLayout.Header, { children: _jsxs(PageHeader, { children: [_jsx(PageHeader.TitleArea, { variant: "large", children: _jsx(PageHeader.Title, { children: "Datasources" }) }), _jsx(PageHeader.Actions, { children: _jsx(Button, { size: "small", variant: "primary", onClick: e => navigate(
|
|
49
|
+
return (_jsxs(PageLayout, { containerWidth: "full", padding: "normal", style: { overflow: 'visible', minHeight: 'calc(100vh - 45px)' }, children: [_jsx(PageLayout.Header, { children: _jsxs(PageHeader, { children: [_jsx(PageHeader.TitleArea, { variant: "large", children: _jsx(PageHeader.Title, { children: "Datasources" }) }), _jsx(PageHeader.Actions, { children: _jsx(Button, { size: "small", variant: "primary", onClick: e => navigate(newDatasourceRoute, e), children: "New datasource" }) })] }) }), _jsx(PageLayout.Content, { children: _jsx(Box, { children: _jsx(DatasourcesTable, { datasourcesListRoute: datasourcesListRoute }) }) })] }));
|
|
48
50
|
};
|
|
49
51
|
export default Datasources;
|
package/package.json
CHANGED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
.crosshairs {
|
|
7
|
+
position: fixed;
|
|
8
|
+
width: 100%;
|
|
9
|
+
z-index: 2147483645;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.crosshairs.hidden {
|
|
13
|
+
display: none;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.crosshairs::before,
|
|
17
|
+
.crosshairs::after {
|
|
18
|
+
content: '';
|
|
19
|
+
position: absolute;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.crosshairs::before {
|
|
23
|
+
height: 24px;
|
|
24
|
+
width: 2px;
|
|
25
|
+
background: #fff;
|
|
26
|
+
top: -11px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.crosshairs::after {
|
|
30
|
+
width: 24px;
|
|
31
|
+
height: 2px;
|
|
32
|
+
background: #fff;
|
|
33
|
+
left: -11px;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.overlay {
|
|
37
|
+
position: fixed;
|
|
38
|
+
top: 0;
|
|
39
|
+
left: 0;
|
|
40
|
+
width: 100%;
|
|
41
|
+
height: 100%;
|
|
42
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.overlay.highlighting {
|
|
46
|
+
background: none;
|
|
47
|
+
border-color: rgba(0, 0, 0, 0.5);
|
|
48
|
+
border-style: solid;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.crosshairs,
|
|
52
|
+
.crosshairs:before,
|
|
53
|
+
.crosshairs:after,
|
|
54
|
+
.overlay,
|
|
55
|
+
.overlay:before,
|
|
56
|
+
.overlay:after {
|
|
57
|
+
box-sizing: border-box;
|
|
58
|
+
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from 'react';
|
|
2
|
-
export type ScreenshotContextType = {
|
|
3
|
-
closeScreenshot: () => void;
|
|
4
|
-
displayScreenshot: (nextScreenshot: any) => void;
|
|
5
|
-
};
|
|
6
|
-
export declare const ScreenshotContext: import("react").Context<ScreenshotContextType>;
|
|
7
|
-
export declare function useScreenshot(): ScreenshotContextType;
|
|
8
|
-
/**
|
|
9
|
-
* The type for the Screenshot context provider.
|
|
10
|
-
*/
|
|
11
|
-
export declare const ScreenshotContextProvider: import("react").Provider<ScreenshotContextType>;
|
|
12
|
-
export type IScreenshotProviderProps = {
|
|
13
|
-
children?: ReactNode;
|
|
14
|
-
zIndex?: number;
|
|
15
|
-
disableDarken?: boolean;
|
|
16
|
-
screenshotSurface?: (qfds: any) => JSX.Element;
|
|
17
|
-
};
|
|
18
|
-
export declare function ScreenshotProvider({ children, zIndex, disableDarken, screenshotSurface, }: IScreenshotProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
/*
|
|
3
|
-
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
4
|
-
* Distributed under the terms of the Modified BSD License.
|
|
5
|
-
*/
|
|
6
|
-
import { createContext, useState, useContext } from 'react';
|
|
7
|
-
import { LayoutScreenshot } from './layouts';
|
|
8
|
-
export const ScreenshotContext = createContext({
|
|
9
|
-
closeScreenshot: () => { },
|
|
10
|
-
displayScreenshot: (nextScreenshot) => { },
|
|
11
|
-
});
|
|
12
|
-
export function useScreenshot() {
|
|
13
|
-
const context = useContext(ScreenshotContext);
|
|
14
|
-
if (!context)
|
|
15
|
-
throw new Error('useContext must be inside a provider with a value.');
|
|
16
|
-
return context;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* The type for the Screenshot context provider.
|
|
20
|
-
*/
|
|
21
|
-
export const ScreenshotContextProvider = ScreenshotContext.Provider;
|
|
22
|
-
export function ScreenshotProvider({ children = null, zIndex = 9999, disableDarken = false, screenshotSurface = undefined, }) {
|
|
23
|
-
const defaultScreenshotSurface = {
|
|
24
|
-
position: 'fixed',
|
|
25
|
-
top: 0,
|
|
26
|
-
left: 0,
|
|
27
|
-
width: '100%',
|
|
28
|
-
height: '100%',
|
|
29
|
-
display: 'flex',
|
|
30
|
-
alignItems: 'center',
|
|
31
|
-
justifyContent: 'center',
|
|
32
|
-
backgroundColor: disableDarken ? 'initial' : 'rgba(0, 0, 0, 0.5)',
|
|
33
|
-
zIndex,
|
|
34
|
-
};
|
|
35
|
-
const [screenshot, setScreenshot] = useState({
|
|
36
|
-
open: false,
|
|
37
|
-
render: (closeScreenshot) => _jsx(_Fragment, {}),
|
|
38
|
-
});
|
|
39
|
-
const displayScreenshot = (nextScreenshot) => {
|
|
40
|
-
setScreenshot({
|
|
41
|
-
open: true,
|
|
42
|
-
render: nextScreenshot,
|
|
43
|
-
});
|
|
44
|
-
};
|
|
45
|
-
const closeScreenshot = () => {
|
|
46
|
-
setScreenshot({
|
|
47
|
-
open: false,
|
|
48
|
-
render: (closeScreenshot) => _jsx(_Fragment, {}),
|
|
49
|
-
});
|
|
50
|
-
};
|
|
51
|
-
return (_jsxs(ScreenshotContextProvider, { value: { closeScreenshot, displayScreenshot }, children: [_jsx(LayoutScreenshot, {}), children, screenshot.open &&
|
|
52
|
-
(screenshotSurface ? (screenshotSurface(screenshot.render(closeScreenshot))) : (_jsx("div", { style: defaultScreenshotSurface, children: screenshot.render(closeScreenshot) })))] }));
|
|
53
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const takeHTMLNodeScreenshot: (node: HTMLDivElement) => Promise<string>;
|