@datalayer/core 0.0.3 → 0.0.4
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/README.md +114 -3
- package/lib/App.css +2 -2
- package/lib/App.d.ts +1 -1
- package/lib/App.js +9 -9
- package/lib/__tests__/index.test.js +5 -5
- package/lib/api/DatalayerApi.d.ts +1 -1
- package/lib/api/DatalayerApi.js +3 -3
- package/lib/api/index.d.ts +3 -3
- package/lib/api/index.js +3 -3
- package/lib/api/runtimes/actions.js +22 -23
- package/lib/api/runtimes/settings.js +3 -3
- package/lib/api/runtimes/snapshots.d.ts +1 -1
- package/lib/api/runtimes/snapshots.js +8 -8
- package/lib/api/runtimes/utils.js +1 -4
- package/lib/collaboration/DatalayerCollaboration.d.ts +9 -0
- package/lib/collaboration/DatalayerCollaboration.js +28 -0
- package/lib/collaboration/DatalayerCollaborationProvider.d.ts +54 -0
- package/lib/collaboration/DatalayerCollaborationProvider.js +162 -0
- package/lib/collaboration/index.d.ts +2 -0
- package/lib/collaboration/index.js +6 -0
- package/lib/components/avatars/BoringAvatar.d.ts +1 -1
- package/lib/components/avatars/BoringAvatar.js +2 -2
- package/lib/components/avatars/UserProfileAvatar.js +2 -9
- package/lib/components/banners/NoAutomationBanner.js +4 -4
- package/lib/components/buttons/DownloadCSVButton.js +1 -1
- package/lib/components/buttons/UploadButton.js +1 -1
- package/lib/components/checkout/StripeCheckout.d.ts +1 -1
- package/lib/components/checkout/StripeCheckout.js +6 -6
- package/lib/components/confetti/ConfettiSuccess.js +1 -1
- package/lib/components/context/OrganizationSelect.js +5 -5
- package/lib/components/context/SpaceSelect.js +7 -7
- package/lib/components/display/AvatarSkeleton.js +1 -1
- package/lib/components/display/CenteredSpinner.js +4 -4
- package/lib/components/display/CodePreview.js +4 -4
- package/lib/components/display/DatalayerBox.js +13 -14
- package/lib/components/display/HorizontalCenter.d.ts +1 -1
- package/lib/components/display/HorizontalCenter.js +1 -1
- package/lib/components/display/JupyterDialog.js +17 -15
- package/lib/components/display/NavLink.d.ts +4 -2
- package/lib/components/display/NavLink.js +6 -4
- package/lib/components/display/NotebookSkeleton.js +2 -2
- package/lib/components/display/Placeholder.js +1 -1
- package/lib/components/display/ToTopBranded.js +1 -1
- package/lib/components/echarts/EChartsReact.d.ts +1 -1
- package/lib/components/echarts/EChartsReact.js +1 -1
- package/lib/components/flashes/FlashClosable.js +11 -11
- package/lib/components/flashes/FlashDisclaimer.js +2 -3
- package/lib/components/flashes/FlashGuest.js +3 -4
- package/lib/components/flashes/FlashSurveys.js +3 -4
- package/lib/components/flashes/FlashUnauthorized.js +2 -2
- package/lib/components/flashes/surveys/Survey2025_1.d.ts +1 -1
- package/lib/components/flashes/surveys/Survey2025_1.js +62 -85
- package/lib/components/iam/ExternalTokenSilentLogin.js +6 -4
- package/lib/components/icons/ArtifactIcon.d.ts +2 -2
- package/lib/components/icons/ArtifactIcon.js +39 -39
- package/lib/components/labels/VisibilityLabel.js +2 -5
- package/lib/components/landings/StepBlock.d.ts +1 -1
- package/lib/components/landings/StepBlock.js +1 -1
- package/lib/components/navbar/NavigationVisbilityObserver.js +2 -2
- package/lib/components/navbar/SubdomainNavBar.js +45 -23
- package/lib/components/navbar/SubdomainNavBar.module.css +33 -14
- package/lib/components/nbgrader/NbGradesDetails.d.ts +1 -1
- package/lib/components/nbgrader/NbGradesDetails.js +5 -8
- package/lib/components/notebooks/JupyterNotebook.js +5 -5
- package/lib/components/notebooks/JupyterNotebookToolbar.js +3 -3
- package/lib/components/primer/Helper.d.ts +1 -1
- package/lib/components/primer/Helper.js +5 -3
- package/lib/components/primer/Portals.d.ts +1 -1
- package/lib/components/primer/Portals.js +2 -2
- package/lib/components/primer/Styles.js +1 -1
- package/lib/components/progress/ConsumptionBar.js +2 -2
- package/lib/components/progress/CreditsIndicator.d.ts +1 -1
- package/lib/components/progress/CreditsIndicator.js +4 -7
- package/lib/components/progress/ProgressRing.js +2 -2
- package/lib/components/runtimes/RuntimeCellVariables.js +9 -9
- package/lib/components/runtimes/RuntimeCellVariablesDialog.js +3 -3
- package/lib/components/runtimes/RuntimeLauncherDialog.js +30 -34
- package/lib/components/runtimes/RuntimePickerBase.js +42 -31
- package/lib/components/runtimes/RuntimePickerCell.js +9 -12
- package/lib/components/runtimes/RuntimePickerNotebook.js +44 -44
- package/lib/components/runtimes/RuntimeReservationControl.js +10 -15
- package/lib/components/runtimes/RuntimeSimplePicker.js +9 -12
- package/lib/components/runtimes/RuntimeUtils.js +22 -12
- package/lib/components/runtimes/RuntimeVariables.js +7 -7
- package/lib/components/screenshot/ScreenCapture.js +9 -13
- package/lib/components/screenshot/ScreenCaptureButton.d.ts +1 -1
- package/lib/components/screenshot/ScreenCaptureButton.js +14 -8
- package/lib/components/snapshots/RuntimeSnapshotMenu.js +19 -17
- package/lib/components/snippets/SnippetDialog.js +5 -5
- package/lib/components/storage/ContentsBrowser.js +63 -56
- package/lib/components/storage/ContentsItems.js +10 -8
- package/lib/components/students/StudentItemStatus.d.ts +1 -1
- package/lib/components/students/StudentItemStatus.js +35 -16
- package/lib/components/subnav/SubNav.d.ts +1 -1
- package/lib/components/subnav/SubNav.js +30 -15
- package/lib/components/subnav/SubNav.module.css +55 -21
- package/lib/components/tables/DataTable.js +1 -4
- package/lib/components/text-reveal/TextRevealAnimation.js +7 -2
- package/lib/components/text-reveal/TextRevealAnimation.module.css +4 -2
- package/lib/components/tokens/SpaceVariantToken.d.ts +1 -1
- package/lib/components/tokens/SpaceVariantToken.js +5 -5
- package/lib/components/toolbars/AssignmentEditorToolbar.js +1 -3
- package/lib/components/users/PeerIndicator.d.ts +1 -1
- package/lib/components/users/PeerIndicator.js +5 -5
- package/lib/config/Configuration.d.ts +48 -0
- package/lib/config/Configuration.js +42 -0
- package/lib/config/integrations/Loom.js +3 -3
- package/lib/examples/CellExample.d.ts +2 -2
- package/lib/examples/CellExample.js +34 -3
- package/lib/examples/DatalayerNotebookExample.d.ts +16 -0
- package/lib/examples/DatalayerNotebookExample.js +75 -0
- package/lib/examples/NativeNavigationExample.d.ts +8 -0
- package/lib/examples/NativeNavigationExample.js +97 -0
- package/lib/examples/NotebookExample.d.ts +1 -3
- package/lib/examples/NotebookExample.js +9 -7
- package/lib/examples/NotebookMutationsKernel.d.ts +2 -0
- package/lib/examples/NotebookMutationsKernel.js +115 -0
- package/lib/examples/NotebookMutationsServiceManager.d.ts +2 -0
- package/lib/examples/NotebookMutationsServiceManager.js +107 -0
- package/lib/examples/ReactRouterExample.d.ts +6 -0
- package/lib/examples/ReactRouterExample.js +175 -0
- package/lib/examples/example-selector.d.ts +22 -0
- package/lib/examples/example-selector.js +45 -0
- package/lib/examples/index.d.ts +2 -0
- package/lib/examples/index.js +6 -0
- package/lib/examples/main.js +153 -0
- package/lib/examples/notebooks/IPyWidgetsExample.ipynb.json +101 -0
- package/lib/examples/notebooks/IPyWidgetsExampleWithState.ipynb.json +112 -0
- package/lib/examples/{NotebookExample1.ipynb.json → notebooks/Lite.ipynb.json} +45 -53
- package/lib/examples/notebooks/Matplotlib.ipynb.json +137 -0
- package/lib/examples/notebooks/NotebookExample1.ipynb.json +126 -0
- package/lib/examples/notebooks/NotebookExample2.ipynb.json +48 -0
- package/lib/examples/notebooks/NotebookOutputs.ipynb.json +49 -0
- package/lib/examples/notebooks/NotebookToCExample.ipynb.json +102 -0
- package/lib/examples/notebooks/OutputIPyWidgetsExample.d.ts +145 -0
- package/lib/examples/notebooks/OutputIPyWidgetsExample.js +153 -0
- package/lib/examples/notebooks/PyGWalker.ipynb.json +55 -0
- package/lib/hooks/assets/OutputshotPlaceholders.d.ts +10 -10
- package/lib/hooks/assets/OutputshotPlaceholders.js +10 -10
- package/lib/hooks/index.d.ts +29 -28
- package/lib/hooks/index.js +29 -28
- package/lib/hooks/layouts/LayoutBackdrop.js +3 -6
- package/lib/hooks/layouts/LayoutScreenshot.css +1 -1
- package/lib/hooks/layouts/LayoutScreenshot.js +6 -6
- package/lib/hooks/useAIAgents.d.ts +1 -1
- package/lib/hooks/useAIAgents.js +6 -6
- package/lib/hooks/useAuthorization.js +4 -4
- package/lib/hooks/useBackdrop.js +7 -7
- package/lib/hooks/useBackdropJupyterLab.d.ts +1 -1
- package/lib/hooks/useBackdropJupyterLab.js +4 -4
- package/lib/hooks/useCache.d.ts +6 -2
- package/lib/hooks/useCache.js +233 -179
- package/lib/hooks/useCellOutputshot.js +3 -6
- package/lib/hooks/useContainsFocus.js +2 -1
- package/lib/hooks/useDatalayer.js +5 -3
- package/lib/hooks/useError.d.ts +1 -1
- package/lib/hooks/useError.js +2 -2
- package/lib/hooks/useExternalScript.js +4 -4
- package/lib/hooks/useFocusTrap.js +2 -1
- package/lib/hooks/useIAM.js +4 -5
- package/lib/hooks/useId.js +3 -3
- package/lib/hooks/useJupyterLabTheme.js +3 -1
- package/lib/hooks/useLocation.d.ts +22 -0
- package/lib/hooks/useLocation.js +149 -0
- package/lib/hooks/useLocationHandles.d.ts +2 -2
- package/lib/hooks/useLocationHandles.js +6 -4
- package/lib/hooks/useNavigate.d.ts +5 -1
- package/lib/hooks/useNavigate.js +62 -7
- package/lib/hooks/useNotebookAIAgent.js +3 -1
- package/lib/hooks/useParams.d.ts +5 -0
- package/lib/hooks/useParams.js +152 -0
- package/lib/hooks/useRuntimes.js +2 -2
- package/lib/hooks/useScreenshot.js +5 -5
- package/lib/hooks/useToast.js +15 -13
- package/lib/hooks/useUpload.js +9 -9
- package/lib/hooks/useUser.js +1 -1
- package/lib/index.css +1 -1
- package/lib/index.d.ts +6 -3
- package/lib/index.js +7 -3
- package/lib/mocks/components/FlashMock.js +4 -4
- package/lib/mocks/hooks/rests/rests.js +15 -18
- package/lib/mocks/hooks/useDatalayerMock.d.ts +2 -2
- package/lib/mocks/hooks/useDatalayerMock.js +7 -7
- package/lib/mocks/models/CodeBlockMock.js +1 -1
- package/lib/mocks/models/CodelineMock.js +1 -1
- package/lib/mocks/models/CourseMock.d.ts +1 -1
- package/lib/mocks/models/CourseMock.js +10 -10
- package/lib/mocks/models/InviteMock.d.ts +1 -1
- package/lib/mocks/models/InviteMock.js +21 -6
- package/lib/mocks/models/JupyterLabUserMock.js +2 -2
- package/lib/mocks/models/OrganisationMock.d.ts +1 -1
- package/lib/mocks/models/OrganisationMock.js +11 -7
- package/lib/mocks/models/SchoolMock.d.ts +1 -1
- package/lib/mocks/models/SchoolMock.js +6 -6
- package/lib/mocks/models/SpaceMock.d.ts +1 -1
- package/lib/mocks/models/SpaceMock.js +9 -9
- package/lib/mocks/models/TeamMock.d.ts +1 -1
- package/lib/mocks/models/TeamMock.js +6 -6
- package/lib/mocks/models/UserMock.d.ts +1 -1
- package/lib/mocks/models/UserMock.js +4 -6
- package/lib/mocks/views/ActionMenuMock.js +1 -1
- package/lib/mocks/views/ChartMock.js +3 -3
- package/lib/mocks/views/ChartMockOptions.js +24 -24
- package/lib/mocks/views/DashboardMock.js +74 -74
- package/lib/mocks/views/FormMock.js +1 -1
- package/lib/mocks/views/TableMock.js +1 -1
- package/lib/models/Account.d.ts +2 -2
- package/lib/models/Assignment.d.ts +2 -2
- package/lib/models/Cell.d.ts +1 -1
- package/lib/models/CodeBlock.d.ts +1 -1
- package/lib/models/CodefeedBlocks.d.ts +2 -2
- package/lib/models/Contact.d.ts +1 -1
- package/lib/models/Contact.js +14 -14
- package/lib/models/ContactIAMProvider.js +2 -2
- package/lib/models/Course.d.ts +7 -7
- package/lib/models/Dataset.d.ts +1 -1
- package/lib/models/Dean.d.ts +1 -1
- package/lib/models/Document.d.ts +1 -1
- package/lib/models/Environment.d.ts +2 -2
- package/lib/models/Exercise.d.ts +1 -1
- package/lib/models/IAMProviderLinked.js +1 -1
- package/lib/models/Instructor.d.ts +1 -1
- package/lib/models/Invite.d.ts +2 -2
- package/lib/models/Invite.js +1 -1
- package/lib/models/Item.d.ts +5 -5
- package/lib/models/LandingRoles.js +18 -18
- package/lib/models/Lesson.d.ts +1 -1
- package/lib/models/Member.d.ts +1 -1
- package/lib/models/Notebook.d.ts +1 -1
- package/lib/models/Organization.d.ts +4 -4
- package/lib/models/Organization.js +2 -2
- package/lib/models/OrganizationMember.d.ts +2 -2
- package/lib/models/Page.js +4 -2
- package/lib/models/PageTag.d.ts +1 -1
- package/lib/models/PageTag.js +56 -9
- package/lib/models/Profile.d.ts +1 -1
- package/lib/models/RolesOrganization.d.ts +1 -1
- package/lib/models/RolesOrganization.js +4 -12
- package/lib/models/RolesPlatform.d.ts +1 -1
- package/lib/models/RolesPlatform.js +12 -34
- package/lib/models/RolesTeam.d.ts +1 -1
- package/lib/models/RolesTeam.js +3 -10
- package/lib/models/Runtime.js +4 -4
- package/lib/models/RuntimeSnapshot.js +1 -1
- package/lib/models/School.d.ts +4 -4
- package/lib/models/Space.d.ts +5 -5
- package/lib/models/Space.js +3 -3
- package/lib/models/SpaceItem.d.ts +8 -8
- package/lib/models/SpaceMember.d.ts +2 -2
- package/lib/models/Student.d.ts +2 -2
- package/lib/models/StudentItem.d.ts +3 -3
- package/lib/models/Team.d.ts +3 -3
- package/lib/models/Team.js +2 -2
- package/lib/models/TeamMember.d.ts +2 -2
- package/lib/models/URN.js +1 -1
- package/lib/models/User.d.ts +2 -2
- package/lib/models/User.js +5 -3
- package/lib/models/UserOnboarding.d.ts +1 -1
- package/lib/models/UserOnboarding.js +7 -7
- package/lib/models/UserSettings.js +2 -2
- package/lib/models/index.d.ts +2 -2
- package/lib/models/index.js +2 -2
- package/lib/navigation/adapters/native.d.ts +11 -0
- package/lib/navigation/adapters/native.js +48 -0
- package/lib/navigation/adapters/nextjs.d.ts +9 -0
- package/lib/navigation/adapters/nextjs.js +35 -0
- package/lib/navigation/adapters/react-router.d.ts +4 -0
- package/lib/navigation/adapters/react-router.js +12 -0
- package/lib/navigation/components.d.ts +20 -0
- package/lib/navigation/components.js +36 -0
- package/lib/navigation/index.d.ts +4 -0
- package/lib/navigation/index.js +12 -0
- package/lib/routes/index.d.ts +1 -1
- package/lib/routes/index.js +1 -1
- package/lib/services/DatalayerServiceManager.d.ts +22 -0
- package/lib/services/DatalayerServiceManager.js +79 -0
- package/lib/services/index.d.ts +4 -0
- package/lib/services/index.js +7 -0
- package/lib/services/reconnectToRuntime.d.ts +32 -0
- package/lib/services/reconnectToRuntime.js +59 -0
- package/lib/state/State.d.ts +1 -1
- package/lib/state/State.js +1 -1
- package/lib/state/index.d.ts +1 -1
- package/lib/state/index.js +1 -1
- package/lib/state/storage/IAMStorage.js +14 -2
- package/lib/state/storage/index.d.ts +1 -1
- package/lib/state/storage/index.js +1 -1
- package/lib/state/substates/AIAgentState.js +4 -2
- package/lib/state/substates/CellState.js +6 -5
- package/lib/state/substates/CoreState.d.ts +1 -1
- package/lib/state/substates/CoreState.js +23 -15
- package/lib/state/substates/DatasourceState.js +1 -1
- package/lib/state/substates/IAMState.d.ts +4 -0
- package/lib/state/substates/IAMState.js +75 -56
- package/lib/state/substates/JupyterLabState.js +1 -1
- package/lib/state/substates/LayoutState.d.ts +2 -2
- package/lib/state/substates/LayoutState.js +41 -28
- package/lib/state/substates/OrganizationState.js +1 -1
- package/lib/state/substates/RuntimesState.js +6 -5
- package/lib/state/substates/SpaceState.js +1 -1
- package/lib/state/substates/SurveysState.js +4 -4
- package/lib/state/substates/TeamState.js +1 -1
- package/lib/test-setup.js +25 -3
- package/lib/theme/DatalayerTheme.js +1 -1
- package/lib/theme/DatalayerThemeProvider.js +17 -14
- package/lib/theme/Palette.js +1 -1
- package/lib/utils/Avatar.js +2 -2
- package/lib/utils/Browser.js +6 -6
- package/lib/utils/Cells.d.ts +1 -1
- package/lib/utils/Cookie.js +1 -1
- package/lib/utils/Date.js +2 -2
- package/lib/utils/Download.js +5 -3
- package/lib/utils/DownloadFile.js +4 -2
- package/lib/utils/Env.js +2 -1
- package/lib/utils/Lazy.d.ts +1 -1
- package/lib/utils/Lazy.js +2 -2
- package/lib/utils/Name.js +10 -8
- package/lib/utils/Notebook.d.ts +1 -1
- package/lib/utils/Notebook.js +3 -3
- package/lib/utils/Number.js +13 -9
- package/lib/utils/Plots.js +4 -4
- package/lib/utils/Screenshot.js +1 -1
- package/lib/utils/Sleep.js +1 -1
- package/lib/utils/Snapshot.js +2 -2
- package/lib/utils/String.js +2 -2
- package/lib/utils/Uri.js +1 -1
- package/lib/utils/WithSuspense.js +3 -6
- package/package.json +41 -5
- package/lib/__tests__/App.test.js +0 -17
- /package/lib/{__tests__/App.test.d.ts → examples/main.d.ts} +0 -0
|
@@ -10,7 +10,8 @@ const useCellOutputshot = () => {
|
|
|
10
10
|
const [error, setError] = useState();
|
|
11
11
|
const { update } = useCellStore();
|
|
12
12
|
const takeOutputshot = (node) => {
|
|
13
|
-
takeHTMLNodeScreenshot(node)
|
|
13
|
+
takeHTMLNodeScreenshot(node)
|
|
14
|
+
.then(outputshotData => {
|
|
14
15
|
setOutputshot(outputshotData);
|
|
15
16
|
update({
|
|
16
17
|
outputshotData,
|
|
@@ -19,10 +20,6 @@ const useCellOutputshot = () => {
|
|
|
19
20
|
})
|
|
20
21
|
.catch(reason => setError(reason));
|
|
21
22
|
};
|
|
22
|
-
return [
|
|
23
|
-
outputshot,
|
|
24
|
-
takeOutputshot,
|
|
25
|
-
{ error }
|
|
26
|
-
];
|
|
23
|
+
return [outputshot, takeOutputshot, { error }];
|
|
27
24
|
};
|
|
28
25
|
export default useCellOutputshot;
|
|
@@ -26,7 +26,8 @@ export const useContainsFocus = (containerRef, onFocusChange) => {
|
|
|
26
26
|
updateState(true);
|
|
27
27
|
};
|
|
28
28
|
const handleFocusOut = (event) => {
|
|
29
|
-
if (containerRef.current &&
|
|
29
|
+
if (containerRef.current &&
|
|
30
|
+
!containerRef.current.contains(event.relatedTarget)) {
|
|
30
31
|
updateState(false);
|
|
31
32
|
}
|
|
32
33
|
};
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
|
-
import { useLocation } from '
|
|
5
|
+
import { useLocation } from './useLocation';
|
|
6
6
|
import { useNavigate } from './useNavigate';
|
|
7
7
|
import { useToast } from './useToast';
|
|
8
8
|
// import { useRuMnock } from './../mocks';
|
|
9
|
-
import { useIAMStore
|
|
9
|
+
import { useIAMStore } from '../state';
|
|
10
10
|
import { requestDatalayerAPI } from '../api';
|
|
11
11
|
export function useDatalayer(props = {}) {
|
|
12
12
|
const { loginRoute = '/login', notifyOnError = true } = props;
|
|
@@ -57,7 +57,9 @@ export function useDatalayer(props = {}) {
|
|
|
57
57
|
enqueueToast(`API Error`, { variant: 'error' });
|
|
58
58
|
}
|
|
59
59
|
if (responseError.exceptionMessage) {
|
|
60
|
-
enqueueToast(`${responseError.exceptionMessage}`, {
|
|
60
|
+
enqueueToast(`${responseError.exceptionMessage}`, {
|
|
61
|
+
variant: 'error',
|
|
62
|
+
});
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
65
|
}
|
package/lib/hooks/useError.d.ts
CHANGED
package/lib/hooks/useError.js
CHANGED
|
@@ -3,11 +3,11 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
3
3
|
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
4
4
|
* Distributed under the terms of the Modified BSD License.
|
|
5
5
|
*/
|
|
6
|
-
import { useState } from
|
|
6
|
+
import { useState } from 'react';
|
|
7
7
|
import { Flash } from '@primer/react';
|
|
8
8
|
export const ErrorMessage = ({ message }) => {
|
|
9
9
|
if (message instanceof Array) {
|
|
10
|
-
return _jsx("div", { children: message.map((m, i) => _jsx(Flash, { variant: "danger", children: m }, i)) });
|
|
10
|
+
return (_jsx("div", { children: message.map((m, i) => (_jsx(Flash, { variant: "danger", children: m }, i))) }));
|
|
11
11
|
}
|
|
12
12
|
else {
|
|
13
13
|
return _jsx(Flash, { variant: "danger", children: message });
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
|
-
import { useEffect } from
|
|
5
|
+
import { useEffect } from 'react';
|
|
6
6
|
const useExternalScript = (url) => {
|
|
7
7
|
useEffect(() => {
|
|
8
|
-
const head = document.querySelector(
|
|
9
|
-
const script = document.createElement(
|
|
10
|
-
script.setAttribute(
|
|
8
|
+
const head = document.querySelector('head');
|
|
9
|
+
const script = document.createElement('script');
|
|
10
|
+
script.setAttribute('src', url);
|
|
11
11
|
head.appendChild(script);
|
|
12
12
|
return () => {
|
|
13
13
|
head.removeChild(script);
|
|
@@ -24,7 +24,8 @@ export function useFocusTrap(settings, dependencies = []) {
|
|
|
24
24
|
// to the previously-focused element (if necessary).
|
|
25
25
|
function disableTrap() {
|
|
26
26
|
abortController.current?.abort();
|
|
27
|
-
if (settings?.restoreFocusOnCleanUp &&
|
|
27
|
+
if (settings?.restoreFocusOnCleanUp &&
|
|
28
|
+
previousFocusedElement.current instanceof HTMLElement) {
|
|
28
29
|
previousFocusedElement.current.focus();
|
|
29
30
|
previousFocusedElement.current = null;
|
|
30
31
|
}
|
package/lib/hooks/useIAM.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { useEffect, useState } from 'react';
|
|
6
6
|
import { useCache } from './useCache';
|
|
7
|
-
import { coreStore, useIAMStore, useLayoutStore, useOrganizationStore, useSpaceStore } from '../state';
|
|
8
|
-
import { asUser, ANONYMOUS_USER, ANONYMOUS_USER_TOKEN } from '../models';
|
|
7
|
+
import { coreStore, useIAMStore, useLayoutStore, useOrganizationStore, useSpaceStore, } from '../state';
|
|
8
|
+
import { asUser, ANONYMOUS_USER, ANONYMOUS_USER_TOKEN, } from '../models';
|
|
9
9
|
import { requestDatalayerAPI } from '../api';
|
|
10
10
|
export const useIAM = (props = { user: undefined, token: undefined }) => {
|
|
11
11
|
const { token } = props;
|
|
@@ -65,8 +65,7 @@ export const useIAM = (props = { user: undefined, token: undefined }) => {
|
|
|
65
65
|
};
|
|
66
66
|
useEffect(() => {
|
|
67
67
|
if (token) {
|
|
68
|
-
whoami()
|
|
69
|
-
.then(resp => {
|
|
68
|
+
whoami().then(resp => {
|
|
70
69
|
if (resp.success) {
|
|
71
70
|
const user = asUser(resp.profile);
|
|
72
71
|
setIAMState({ user, token });
|
|
@@ -87,7 +86,7 @@ export const useIAM = (props = { user: undefined, token: undefined }) => {
|
|
|
87
86
|
token: iamState.token,
|
|
88
87
|
loginAndNavigate,
|
|
89
88
|
setLogin,
|
|
90
|
-
logout
|
|
89
|
+
logout,
|
|
91
90
|
};
|
|
92
91
|
};
|
|
93
92
|
export default useIAM;
|
package/lib/hooks/useId.js
CHANGED
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
* server hydration and never again, SO BACK OFF ALRIGHT?
|
|
59
59
|
*/
|
|
60
60
|
/* eslint-disable react-hooks/rules-of-hooks */
|
|
61
|
-
import * as React from
|
|
62
|
-
import { useLayoutEffect } from
|
|
61
|
+
import * as React from 'react';
|
|
62
|
+
import { useLayoutEffect } from 'react';
|
|
63
63
|
let serverHandoffComplete = false;
|
|
64
64
|
let id = 0;
|
|
65
65
|
function genId() {
|
|
@@ -67,7 +67,7 @@ function genId() {
|
|
|
67
67
|
}
|
|
68
68
|
// Workaround for https://github.com/webpack/webpack/issues/14814
|
|
69
69
|
// https://github.com/eps1lon/material-ui/blob/8d5f135b4d7a58253a99ab56dce4ac8de61f5dc1/packages/mui-utils/src/useId.ts#L21
|
|
70
|
-
const maybeReactUseId = React[
|
|
70
|
+
const maybeReactUseId = React['useId'.toString()];
|
|
71
71
|
function useId(providedId) {
|
|
72
72
|
if (maybeReactUseId !== undefined) {
|
|
73
73
|
const generatedId = maybeReactUseId();
|
|
@@ -9,7 +9,9 @@ export var JupyterLabTheme;
|
|
|
9
9
|
JupyterLabTheme["DARK"] = "JupyterLab Dark";
|
|
10
10
|
})(JupyterLabTheme || (JupyterLabTheme = {}));
|
|
11
11
|
export const useJupyterLabTheme = (themeManager) => {
|
|
12
|
-
const isLight = themeManager && themeManager.theme
|
|
12
|
+
const isLight = themeManager && themeManager.theme
|
|
13
|
+
? themeManager.isLight(themeManager.theme)
|
|
14
|
+
: true;
|
|
13
15
|
const [theme, setTheme] = useState(isLight ? JupyterLabTheme.LIGHT : JupyterLabTheme.DARK);
|
|
14
16
|
useEffect(() => {
|
|
15
17
|
const handleThemeChange = (newTheme, event) => {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface Location {
|
|
2
|
+
pathname: string;
|
|
3
|
+
search: string;
|
|
4
|
+
hash: string;
|
|
5
|
+
state: any;
|
|
6
|
+
key: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Hook to get current location
|
|
10
|
+
* Detects and uses React Router when available, falls back to native browser location
|
|
11
|
+
*/
|
|
12
|
+
export declare const useLocation: () => Location;
|
|
13
|
+
/**
|
|
14
|
+
* Hook to get history functions
|
|
15
|
+
* Detects and uses React Router history when available, falls back to browser history
|
|
16
|
+
*/
|
|
17
|
+
export declare const useHistory: () => {
|
|
18
|
+
back: () => void;
|
|
19
|
+
forward: () => void;
|
|
20
|
+
replace: (to: string, state?: any) => void;
|
|
21
|
+
push: (to: string, state?: any) => void;
|
|
22
|
+
};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
import { useEffect, useState } from 'react';
|
|
6
|
+
// Import React Router hooks from our wrapper
|
|
7
|
+
import { useLocationRR, useNavigateRR, } from '../navigation/adapters/react-router';
|
|
8
|
+
// Import Next.js hooks from our wrapper
|
|
9
|
+
// Currently not used but kept for future Next.js support
|
|
10
|
+
// import {
|
|
11
|
+
// usePathnameNext,
|
|
12
|
+
// useSearchParamsNext,
|
|
13
|
+
// } from '../navigation/adapters/nextjs';
|
|
14
|
+
/**
|
|
15
|
+
* Hook to get current location
|
|
16
|
+
* Detects and uses React Router when available, falls back to native browser location
|
|
17
|
+
*/
|
|
18
|
+
export const useLocation = () => {
|
|
19
|
+
// Native location state for fallback
|
|
20
|
+
const [nativeLocation, setNativeLocation] = useState(() => {
|
|
21
|
+
if (typeof window === 'undefined') {
|
|
22
|
+
return {
|
|
23
|
+
pathname: '/',
|
|
24
|
+
search: '',
|
|
25
|
+
hash: '',
|
|
26
|
+
state: null,
|
|
27
|
+
key: 'default',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
pathname: window.location.pathname,
|
|
32
|
+
search: window.location.search,
|
|
33
|
+
hash: window.location.hash,
|
|
34
|
+
state: window.history.state,
|
|
35
|
+
key: 'default',
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
// Detect environment
|
|
39
|
+
const isNextJs = typeof window !== 'undefined' && !!window.__NEXT_DATA__;
|
|
40
|
+
const isClient = typeof window !== 'undefined';
|
|
41
|
+
// Try to use React Router if available
|
|
42
|
+
let routerLocation = null;
|
|
43
|
+
let isReactRouter = false;
|
|
44
|
+
try {
|
|
45
|
+
// Only actually use the hook if we have it and not in Next.js
|
|
46
|
+
if (!isNextJs && useLocationRR && isClient) {
|
|
47
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
48
|
+
routerLocation = useLocationRR();
|
|
49
|
+
isReactRouter = !!routerLocation;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Not in a Router context, fallback to native
|
|
54
|
+
}
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
// Only set up native listeners if not using React Router
|
|
57
|
+
if (isReactRouter)
|
|
58
|
+
return;
|
|
59
|
+
// Listen to popstate for browser navigation changes
|
|
60
|
+
const handleLocationChange = () => {
|
|
61
|
+
setNativeLocation({
|
|
62
|
+
pathname: window.location.pathname,
|
|
63
|
+
search: window.location.search,
|
|
64
|
+
hash: window.location.hash,
|
|
65
|
+
state: window.history.state,
|
|
66
|
+
key: 'native-' + Date.now(),
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
window.addEventListener('popstate', handleLocationChange);
|
|
70
|
+
// Also listen for custom navigation events if needed
|
|
71
|
+
window.addEventListener('pushstate', handleLocationChange);
|
|
72
|
+
window.addEventListener('replacestate', handleLocationChange);
|
|
73
|
+
return () => {
|
|
74
|
+
window.removeEventListener('popstate', handleLocationChange);
|
|
75
|
+
window.removeEventListener('pushstate', handleLocationChange);
|
|
76
|
+
window.removeEventListener('replacestate', handleLocationChange);
|
|
77
|
+
};
|
|
78
|
+
}, [isReactRouter]);
|
|
79
|
+
// Return React Router location if available, otherwise native location
|
|
80
|
+
return isReactRouter && routerLocation ? routerLocation : nativeLocation;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Hook to get history functions
|
|
84
|
+
* Detects and uses React Router history when available, falls back to browser history
|
|
85
|
+
*/
|
|
86
|
+
export const useHistory = () => {
|
|
87
|
+
// Detect environment
|
|
88
|
+
const isNextJs = typeof window !== 'undefined' && !!window.__NEXT_DATA__;
|
|
89
|
+
const isClient = typeof window !== 'undefined';
|
|
90
|
+
// Try to use React Router if available
|
|
91
|
+
let routerNavigate = null;
|
|
92
|
+
let isReactRouter = false;
|
|
93
|
+
try {
|
|
94
|
+
if (!isNextJs && useNavigateRR && isClient) {
|
|
95
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
96
|
+
routerNavigate = useNavigateRR();
|
|
97
|
+
isReactRouter = true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
// Not in a Router context
|
|
102
|
+
}
|
|
103
|
+
if (isReactRouter && routerNavigate) {
|
|
104
|
+
// Use React Router navigation
|
|
105
|
+
return {
|
|
106
|
+
back: () => {
|
|
107
|
+
routerNavigate(-1);
|
|
108
|
+
},
|
|
109
|
+
forward: () => {
|
|
110
|
+
routerNavigate(1);
|
|
111
|
+
},
|
|
112
|
+
replace: (to, state) => {
|
|
113
|
+
routerNavigate(to, { replace: true, state });
|
|
114
|
+
},
|
|
115
|
+
push: (to, state) => {
|
|
116
|
+
routerNavigate(to, { state });
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
// Fall back to native browser history
|
|
121
|
+
return {
|
|
122
|
+
back: () => {
|
|
123
|
+
if (typeof window !== 'undefined') {
|
|
124
|
+
window.history.back();
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
forward: () => {
|
|
128
|
+
if (typeof window !== 'undefined') {
|
|
129
|
+
window.history.forward();
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
replace: (to, state) => {
|
|
133
|
+
if (typeof window !== 'undefined') {
|
|
134
|
+
const url = new URL(to, window.location.href);
|
|
135
|
+
window.history.replaceState(state || null, '', url.href);
|
|
136
|
+
// Dispatch custom event for location hooks
|
|
137
|
+
window.dispatchEvent(new Event('replacestate'));
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
push: (to, state) => {
|
|
141
|
+
if (typeof window !== 'undefined') {
|
|
142
|
+
const url = new URL(to, window.location.href);
|
|
143
|
+
window.history.pushState(state || null, '', url.href);
|
|
144
|
+
// Dispatch custom event for location hooks
|
|
145
|
+
window.dispatchEvent(new Event('pushstate'));
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
};
|
|
@@ -3,8 +3,8 @@ export declare const useLocationHandles: () => {
|
|
|
3
3
|
spaceHandler: string | undefined;
|
|
4
4
|
spaceHandle?: undefined;
|
|
5
5
|
} | {
|
|
6
|
-
accountHandle: string
|
|
7
|
-
spaceHandle: string
|
|
6
|
+
accountHandle: string;
|
|
7
|
+
spaceHandle: string;
|
|
8
8
|
spaceHandler?: undefined;
|
|
9
9
|
};
|
|
10
10
|
export default useLocationHandles;
|
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
|
-
import { useLocation
|
|
6
|
-
import {
|
|
5
|
+
import { useLocation } from './useLocation';
|
|
6
|
+
import { useParams } from './useParams';
|
|
7
|
+
import { useRunStore } from '../state';
|
|
7
8
|
export const useLocationHandles = () => {
|
|
8
|
-
const
|
|
9
|
+
const params = useParams();
|
|
10
|
+
const { accountHandle, spaceHandle } = params;
|
|
9
11
|
const { pathname } = useLocation();
|
|
10
12
|
const runStore = useRunStore();
|
|
11
|
-
if (pathname.startsWith(
|
|
13
|
+
if (pathname.startsWith('/public')) {
|
|
12
14
|
return {
|
|
13
15
|
accountHandle: runStore.iam().user?.handle,
|
|
14
16
|
spaceHandler: runStore.layout().space?.handle,
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Main navigation hook that provides a universal navigate function
|
|
3
|
+
* Works with React Router, Next.js, or native browser navigation
|
|
4
|
+
*/
|
|
5
|
+
export declare const useNavigate: () => (location: string, optionsOrEvent?: any, resetPortals?: boolean, extraOptions?: any) => void;
|
|
2
6
|
export default useNavigate;
|
package/lib/hooks/useNavigate.js
CHANGED
|
@@ -2,14 +2,68 @@
|
|
|
2
2
|
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import { useCallback } from 'react';
|
|
6
6
|
import { useLayoutStore } from '../state';
|
|
7
|
+
import { createNativeNavigate } from '../navigation/adapters/native';
|
|
8
|
+
// Import React Router hooks from our wrapper
|
|
9
|
+
import { useNavigateRR } from '../navigation/adapters/react-router';
|
|
10
|
+
// Import Next.js hooks from our wrapper
|
|
11
|
+
// Currently not used but kept for future Next.js support
|
|
12
|
+
// import { useRouterNext } from '../navigation/adapters/nextjs';
|
|
13
|
+
/**
|
|
14
|
+
* Main navigation hook that provides a universal navigate function
|
|
15
|
+
* Works with React Router, Next.js, or native browser navigation
|
|
16
|
+
*/
|
|
7
17
|
export const useNavigate = () => {
|
|
8
|
-
const routerNavigate = useRouterNavigate();
|
|
9
18
|
const layoutStore = useLayoutStore();
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
19
|
+
// Detect environment
|
|
20
|
+
const isNextJs = typeof window !== 'undefined' && !!window.__NEXT_DATA__;
|
|
21
|
+
const isClient = typeof window !== 'undefined';
|
|
22
|
+
// Try to use React Router's useNavigate if available
|
|
23
|
+
let rrNavigate = null;
|
|
24
|
+
let isReactRouter = false;
|
|
25
|
+
if (!isNextJs && useNavigateRR && isClient) {
|
|
26
|
+
try {
|
|
27
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
28
|
+
rrNavigate = useNavigateRR();
|
|
29
|
+
isReactRouter = !!rrNavigate;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Not in a Router context
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// If React Router is available, return it directly (wrapped for consistency)
|
|
36
|
+
if (isReactRouter && rrNavigate) {
|
|
37
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
38
|
+
return useCallback((to, options) => {
|
|
39
|
+
// For React Router, just pass through directly without side effects
|
|
40
|
+
return rrNavigate(to, options);
|
|
41
|
+
}, [rrNavigate]);
|
|
42
|
+
}
|
|
43
|
+
// Otherwise use native navigation with our custom behavior
|
|
44
|
+
const baseNavigate = createNativeNavigate();
|
|
45
|
+
// Wrap with our custom behavior for native navigation
|
|
46
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
47
|
+
const navigate = useCallback((location, optionsOrEvent, resetPortals = true, extraOptions) => {
|
|
48
|
+
// Handle different call signatures for native navigation
|
|
49
|
+
let options = undefined;
|
|
50
|
+
let event = undefined;
|
|
51
|
+
if (optionsOrEvent && optionsOrEvent.preventDefault) {
|
|
52
|
+
// Legacy signature with event as second parameter
|
|
53
|
+
event = optionsOrEvent;
|
|
54
|
+
options = extraOptions;
|
|
55
|
+
}
|
|
56
|
+
else if (typeof optionsOrEvent === 'boolean') {
|
|
57
|
+
// Legacy signature with resetPortals as second parameter
|
|
58
|
+
resetPortals = optionsOrEvent;
|
|
59
|
+
options = extraOptions;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// Standard signature with options as second parameter
|
|
63
|
+
options = optionsOrEvent;
|
|
64
|
+
}
|
|
65
|
+
if (event) {
|
|
66
|
+
event.preventDefault();
|
|
13
67
|
}
|
|
14
68
|
if (resetPortals) {
|
|
15
69
|
layoutStore.resetLeftPortal();
|
|
@@ -17,8 +71,9 @@ export const useNavigate = () => {
|
|
|
17
71
|
}
|
|
18
72
|
window.scrollTo(0, 0);
|
|
19
73
|
document.body.scrollTop = 0;
|
|
20
|
-
|
|
21
|
-
|
|
74
|
+
// Use native navigation
|
|
75
|
+
baseNavigate(location, options);
|
|
76
|
+
}, [baseNavigate, layoutStore]);
|
|
22
77
|
return navigate;
|
|
23
78
|
};
|
|
24
79
|
export default useNavigate;
|
|
@@ -19,7 +19,9 @@ export function useNotebookAIAgent(notebookId) {
|
|
|
19
19
|
const refreshAIAgent = async () => {
|
|
20
20
|
abortController = new AbortController();
|
|
21
21
|
try {
|
|
22
|
-
const response = await getAIAgent(notebookId, {
|
|
22
|
+
const response = await getAIAgent(notebookId, {
|
|
23
|
+
signal: abortController.signal,
|
|
24
|
+
});
|
|
23
25
|
if (!response.success) {
|
|
24
26
|
deleteAIAgent(notebookId);
|
|
25
27
|
return;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
import { useEffect, useState, useMemo } from 'react';
|
|
6
|
+
import { useParamsRR } from '../navigation/adapters/react-router';
|
|
7
|
+
import { useParamsNext, useSearchParamsNext, } from '../navigation/adapters/nextjs';
|
|
8
|
+
/**
|
|
9
|
+
* Hook to get URL parameters
|
|
10
|
+
* Works with Next.js App Router, React Router, or falls back to URL parsing
|
|
11
|
+
*/
|
|
12
|
+
export const useParams = () => {
|
|
13
|
+
// State for fallback URL search params
|
|
14
|
+
const [searchParams, setSearchParams] = useState({});
|
|
15
|
+
// Detect environment
|
|
16
|
+
const isNextJs = typeof window !== 'undefined' && !!window.__NEXT_DATA__;
|
|
17
|
+
const isClient = typeof window !== 'undefined';
|
|
18
|
+
// Try to get params from different sources
|
|
19
|
+
let routeParams = {};
|
|
20
|
+
const queryParams = {};
|
|
21
|
+
let paramsSource = 'fallback';
|
|
22
|
+
// 1. Try Next.js first (if detected)
|
|
23
|
+
if (isNextJs && useParamsNext) {
|
|
24
|
+
try {
|
|
25
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
26
|
+
routeParams = useParamsNext() || {};
|
|
27
|
+
paramsSource = 'nextjs';
|
|
28
|
+
// Also get search params in Next.js
|
|
29
|
+
if (useSearchParamsNext) {
|
|
30
|
+
try {
|
|
31
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
32
|
+
const searchParamsObj = useSearchParamsNext();
|
|
33
|
+
if (searchParamsObj) {
|
|
34
|
+
searchParamsObj.forEach((value, key) => {
|
|
35
|
+
queryParams[key] = value;
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// Not in Next.js context or search params not available
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// Not in Next.js router context
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// 2. Try React Router (if not Next.js)
|
|
49
|
+
if (paramsSource === 'fallback' && !isNextJs && useParamsRR) {
|
|
50
|
+
try {
|
|
51
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
52
|
+
routeParams = useParamsRR() || {};
|
|
53
|
+
paramsSource = 'react-router';
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// Not in React Router context
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// 3. Get URL search params (for React Router and fallback)
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (!isClient || paramsSource === 'nextjs')
|
|
62
|
+
return;
|
|
63
|
+
const updateSearchParams = () => {
|
|
64
|
+
const params = {};
|
|
65
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
66
|
+
urlParams.forEach((value, key) => {
|
|
67
|
+
params[key] = value;
|
|
68
|
+
});
|
|
69
|
+
setSearchParams(params);
|
|
70
|
+
};
|
|
71
|
+
updateSearchParams();
|
|
72
|
+
// Listen for URL changes
|
|
73
|
+
window.addEventListener('popstate', updateSearchParams);
|
|
74
|
+
window.addEventListener('pushstate', updateSearchParams);
|
|
75
|
+
window.addEventListener('replacestate', updateSearchParams);
|
|
76
|
+
return () => {
|
|
77
|
+
window.removeEventListener('popstate', updateSearchParams);
|
|
78
|
+
window.removeEventListener('pushstate', updateSearchParams);
|
|
79
|
+
window.removeEventListener('replacestate', updateSearchParams);
|
|
80
|
+
};
|
|
81
|
+
}, [isClient, paramsSource]);
|
|
82
|
+
// 4. For fallback, also try to parse route params from URL path
|
|
83
|
+
const fallbackRouteParams = useMemo(() => {
|
|
84
|
+
if (!isClient || paramsSource !== 'fallback')
|
|
85
|
+
return {};
|
|
86
|
+
const pathname = window.location.pathname;
|
|
87
|
+
const params = {};
|
|
88
|
+
// Common patterns to match
|
|
89
|
+
// /products/123 -> { id: '123' }
|
|
90
|
+
// /users/john-doe -> { username: 'john-doe' }
|
|
91
|
+
// /blog/2024/01/my-post -> { year: '2024', month: '01', slug: 'my-post' }
|
|
92
|
+
const patterns = [
|
|
93
|
+
{ regex: /^\/products\/([^/]+)$/, params: ['id'] },
|
|
94
|
+
{ regex: /^\/products\/([^/]+)\/reviews$/, params: ['id'] },
|
|
95
|
+
{ regex: /^\/users\/([^/]+)$/, params: ['username'] },
|
|
96
|
+
{
|
|
97
|
+
regex: /^\/blog\/(\d{4})\/(\d{2})\/([^/]+)$/,
|
|
98
|
+
params: ['year', 'month', 'slug'],
|
|
99
|
+
},
|
|
100
|
+
{ regex: /^\/posts\/([^/]+)$/, params: ['slug'] },
|
|
101
|
+
{ regex: /^\/([^/]+)\/([^/]+)$/, params: ['category', 'id'] },
|
|
102
|
+
];
|
|
103
|
+
for (const pattern of patterns) {
|
|
104
|
+
const match = pathname.match(pattern.regex);
|
|
105
|
+
if (match) {
|
|
106
|
+
pattern.params.forEach((paramName, index) => {
|
|
107
|
+
if (match[index + 1]) {
|
|
108
|
+
params[paramName] = match[index + 1];
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return params;
|
|
115
|
+
}, [isClient, paramsSource, isClient ? window.location.pathname : '']);
|
|
116
|
+
// Combine all params with proper memoization to prevent re-renders
|
|
117
|
+
const combinedParams = useMemo(() => {
|
|
118
|
+
const result = {};
|
|
119
|
+
// Add route params
|
|
120
|
+
for (const [key, value] of Object.entries(routeParams)) {
|
|
121
|
+
if (value !== undefined) {
|
|
122
|
+
// Handle array values (Next.js catch-all routes)
|
|
123
|
+
result[key] = Array.isArray(value) ? value.join('/') : String(value);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Add query params (Next.js)
|
|
127
|
+
for (const [key, value] of Object.entries(queryParams)) {
|
|
128
|
+
result[key] = value;
|
|
129
|
+
}
|
|
130
|
+
// Add search params (React Router and fallback)
|
|
131
|
+
if (paramsSource !== 'nextjs') {
|
|
132
|
+
for (const [key, value] of Object.entries(searchParams)) {
|
|
133
|
+
result[key] = value;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// Add fallback route params
|
|
137
|
+
if (paramsSource === 'fallback') {
|
|
138
|
+
for (const [key, value] of Object.entries(fallbackRouteParams)) {
|
|
139
|
+
result[key] = value;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return result;
|
|
143
|
+
}, [
|
|
144
|
+
// Use JSON.stringify for deep comparison
|
|
145
|
+
JSON.stringify(routeParams),
|
|
146
|
+
JSON.stringify(queryParams),
|
|
147
|
+
JSON.stringify(searchParams),
|
|
148
|
+
JSON.stringify(fallbackRouteParams),
|
|
149
|
+
paramsSource,
|
|
150
|
+
]);
|
|
151
|
+
return combinedParams;
|
|
152
|
+
};
|
package/lib/hooks/useRuntimes.js
CHANGED
|
@@ -16,7 +16,7 @@ export const useRuntimes = () => {
|
|
|
16
16
|
};
|
|
17
17
|
const unmountLocalFolder = (kernelId) => {
|
|
18
18
|
requestJupyterKernelsExtension(`jump/${kernelId}`, {
|
|
19
|
-
method: 'DELETE'
|
|
19
|
+
method: 'DELETE',
|
|
20
20
|
})
|
|
21
21
|
.then(data => {
|
|
22
22
|
// console.log('--- Unmount Local Folder', data);
|
|
@@ -28,7 +28,7 @@ export const useRuntimes = () => {
|
|
|
28
28
|
// --------------------------------------------------------------------------
|
|
29
29
|
return {
|
|
30
30
|
mountLocalFolder,
|
|
31
|
-
unmountLocalFolder
|
|
31
|
+
unmountLocalFolder,
|
|
32
32
|
};
|
|
33
33
|
};
|
|
34
34
|
export default useRuntimes;
|