mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-31 14:43:05 +02:00
remove codemirror dep and restructure a bit
This commit is contained in:
2277
package-lock.json
generated
2277
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
|||||||
import { SettingsTab } from '../components/Settings/SettingsTab';
|
import type { SettingsTab } from '../components/Settings/Settings';
|
||||||
import { activeWorkspaceIdAtom } from '../hooks/useActiveWorkspace';
|
import { activeWorkspaceIdAtom } from '../hooks/useActiveWorkspace';
|
||||||
import { createFastMutation } from '../hooks/useFastMutation';
|
import { createFastMutation } from '../hooks/useFastMutation';
|
||||||
import { jotaiStore } from '../lib/jotai';
|
import { jotaiStore } from '../lib/jotai';
|
||||||
@@ -14,8 +14,9 @@ export const openSettings = createFastMutation<void, string, SettingsTab | null>
|
|||||||
const location = router.buildLocation({
|
const location = router.buildLocation({
|
||||||
to: '/workspaces/$workspaceId/settings',
|
to: '/workspaces/$workspaceId/settings',
|
||||||
params: { workspaceId },
|
params: { workspaceId },
|
||||||
search: { tab: tab ?? SettingsTab.General },
|
search: { tab },
|
||||||
});
|
});
|
||||||
|
|
||||||
await invokeCmd('cmd_new_child_window', {
|
await invokeCmd('cmd_new_child_window', {
|
||||||
url: location.href,
|
url: location.href,
|
||||||
label: 'settings',
|
label: 'settings',
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import type { EditorView } from '@codemirror/view';
|
||||||
import type { HttpRequest } from '@yaakapp-internal/models';
|
import type { HttpRequest } from '@yaakapp-internal/models';
|
||||||
import { updateSchema } from 'cm6-graphql';
|
import { updateSchema } from 'cm6-graphql';
|
||||||
import type { EditorView } from 'codemirror';
|
|
||||||
|
|
||||||
import { formatSdl } from 'format-graphql';
|
import { formatSdl } from 'format-graphql';
|
||||||
import { useEffect, useMemo, useRef } from 'react';
|
import { useEffect, useMemo, useRef } from 'react';
|
||||||
@@ -60,7 +60,7 @@ export function GraphQLEditor({ request, onChange, baseRequest, ...extraEditorPr
|
|||||||
|
|
||||||
// Refetch the schema when the URL changes
|
// Refetch the schema when the URL changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (editorViewRef.current === null) return;
|
if (editorViewRef.current == null) return;
|
||||||
updateSchema(editorViewRef.current, schema ?? undefined);
|
updateSchema(editorViewRef.current, schema ?? undefined);
|
||||||
}, [schema]);
|
}, [schema]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { jsonLanguage } from '@codemirror/lang-json';
|
import { jsonLanguage } from '@codemirror/lang-json';
|
||||||
import { linter } from '@codemirror/lint';
|
import { linter } from '@codemirror/lint';
|
||||||
|
import type { EditorView } from '@codemirror/view';
|
||||||
import type { GrpcRequest } from '@yaakapp-internal/models';
|
import type { GrpcRequest } from '@yaakapp-internal/models';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import type { EditorView } from 'codemirror';
|
|
||||||
import {
|
import {
|
||||||
handleRefresh,
|
handleRefresh,
|
||||||
jsonCompletion,
|
jsonCompletion,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import type { GenericCompletionOption } from '@yaakapp-internal/plugins';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { atom, useAtomValue } from 'jotai';
|
import { atom, useAtomValue } from 'jotai';
|
||||||
import type { CSSProperties } from 'react';
|
import type { CSSProperties } from 'react';
|
||||||
import React, { useCallback, useMemo, useState } from 'react';
|
import React, { lazy, useCallback, useMemo, useState } from 'react';
|
||||||
import { activeRequestIdAtom } from '../hooks/useActiveRequestId';
|
import { activeRequestIdAtom } from '../hooks/useActiveRequestId';
|
||||||
import { useCancelHttpResponse } from '../hooks/useCancelHttpResponse';
|
import { useCancelHttpResponse } from '../hooks/useCancelHttpResponse';
|
||||||
import { useHttpAuthenticationSummaries } from '../hooks/useHttpAuthentication';
|
import { useHttpAuthenticationSummaries } from '../hooks/useHttpAuthentication';
|
||||||
@@ -44,13 +44,18 @@ import { TabContent, Tabs } from './core/Tabs/Tabs';
|
|||||||
import { EmptyStateText } from './EmptyStateText';
|
import { EmptyStateText } from './EmptyStateText';
|
||||||
import { FormMultipartEditor } from './FormMultipartEditor';
|
import { FormMultipartEditor } from './FormMultipartEditor';
|
||||||
import { FormUrlencodedEditor } from './FormUrlencodedEditor';
|
import { FormUrlencodedEditor } from './FormUrlencodedEditor';
|
||||||
import { GraphQLEditor } from './GraphQLEditor';
|
|
||||||
import { HeadersEditor } from './HeadersEditor';
|
import { HeadersEditor } from './HeadersEditor';
|
||||||
import { HttpAuthenticationEditor } from './HttpAuthenticationEditor';
|
import { HttpAuthenticationEditor } from './HttpAuthenticationEditor';
|
||||||
import { MarkdownEditor } from './MarkdownEditor';
|
|
||||||
import { UrlBar } from './UrlBar';
|
import { UrlBar } from './UrlBar';
|
||||||
import { UrlParametersEditor } from './UrlParameterEditor';
|
import { UrlParametersEditor } from './UrlParameterEditor';
|
||||||
|
|
||||||
|
const GraphQLEditor = lazy(() =>
|
||||||
|
import('./GraphQLEditor').then((m) => ({ default: m.GraphQLEditor })),
|
||||||
|
);
|
||||||
|
const MarkdownEditor = lazy(() =>
|
||||||
|
import('./MarkdownEditor').then((m) => ({ default: m.MarkdownEditor })),
|
||||||
|
);
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
style: CSSProperties;
|
style: CSSProperties;
|
||||||
fullHeight: boolean;
|
fullHeight: boolean;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { HttpResponse } from '@yaakapp-internal/models';
|
import type { HttpResponse } from '@yaakapp-internal/models';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import type { CSSProperties, ReactNode } from 'react';
|
import type { CSSProperties, ReactNode } from 'react';
|
||||||
import React, { useCallback, useMemo } from 'react';
|
import React, { lazy , useCallback, useMemo } from 'react';
|
||||||
import { useLocalStorage } from 'react-use';
|
import { useLocalStorage } from 'react-use';
|
||||||
import { usePinnedHttpResponse } from '../hooks/usePinnedHttpResponse';
|
import { usePinnedHttpResponse } from '../hooks/usePinnedHttpResponse';
|
||||||
import { useResponseViewMode } from '../hooks/useResponseViewMode';
|
import { useResponseViewMode } from '../hooks/useResponseViewMode';
|
||||||
@@ -27,7 +27,10 @@ import { CsvViewer } from './responseViewers/CsvViewer';
|
|||||||
import { EventStreamViewer } from './responseViewers/EventStreamViewer';
|
import { EventStreamViewer } from './responseViewers/EventStreamViewer';
|
||||||
import { HTMLOrTextViewer } from './responseViewers/HTMLOrTextViewer';
|
import { HTMLOrTextViewer } from './responseViewers/HTMLOrTextViewer';
|
||||||
import { ImageViewer } from './responseViewers/ImageViewer';
|
import { ImageViewer } from './responseViewers/ImageViewer';
|
||||||
import { PdfViewer } from './responseViewers/PdfViewer';
|
|
||||||
|
const PdfViewer = lazy(() =>
|
||||||
|
import('./responseViewers/PdfViewer').then((m) => ({ default: m.PdfViewer })),
|
||||||
|
);
|
||||||
import { SvgViewer } from './responseViewers/SvgViewer';
|
import { SvgViewer } from './responseViewers/SvgViewer';
|
||||||
import { VideoViewer } from './responseViewers/VideoViewer';
|
import { VideoViewer } from './responseViewers/VideoViewer';
|
||||||
import { ErrorBoundary } from './ErrorBoundary';
|
import { ErrorBoundary } from './ErrorBoundary';
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { appInfo } from '../hooks/useAppInfo';
|
|||||||
import { useLicenseConfirmation } from '../hooks/useLicenseConfirmation';
|
import { useLicenseConfirmation } from '../hooks/useLicenseConfirmation';
|
||||||
import { BadgeButton } from './core/BadgeButton';
|
import { BadgeButton } from './core/BadgeButton';
|
||||||
import type { ButtonProps } from './core/Button';
|
import type { ButtonProps } from './core/Button';
|
||||||
import { SettingsTab } from './Settings/SettingsTab';
|
|
||||||
|
|
||||||
const details: Record<
|
const details: Record<
|
||||||
LicenseCheckStatus['type'],
|
LicenseCheckStatus['type'],
|
||||||
@@ -28,7 +27,7 @@ export function LicenseBadge() {
|
|||||||
|
|
||||||
if (check.error) {
|
if (check.error) {
|
||||||
return (
|
return (
|
||||||
<BadgeButton color="danger" onClick={() => openSettings.mutate(SettingsTab.License)}>
|
<BadgeButton color="danger" onClick={() => openSettings.mutate('license')}>
|
||||||
License Error
|
License Error
|
||||||
</BadgeButton>
|
</BadgeButton>
|
||||||
);
|
);
|
||||||
@@ -64,7 +63,7 @@ export function LicenseBadge() {
|
|||||||
hasDismissedTrial: true,
|
hasDismissedTrial: true,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
openSettings.mutate(SettingsTab.License);
|
openSettings.mutate('license');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{detail.label}
|
{detail.label}
|
||||||
|
|||||||
@@ -13,24 +13,23 @@ import { SettingsGeneral } from './SettingsGeneral';
|
|||||||
import { SettingsLicense } from './SettingsLicense';
|
import { SettingsLicense } from './SettingsLicense';
|
||||||
import { SettingsPlugins } from './SettingsPlugins';
|
import { SettingsPlugins } from './SettingsPlugins';
|
||||||
import { SettingsProxy } from './SettingsProxy';
|
import { SettingsProxy } from './SettingsProxy';
|
||||||
import { SettingsTab } from './SettingsTab';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
hide?: () => void;
|
hide?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const tabs = [
|
const TAB_GENERAL = 'general';
|
||||||
SettingsTab.General,
|
const TAB_APPEARANCE = 'appearance';
|
||||||
SettingsTab.Appearance,
|
const TAB_PROXY = 'proxy';
|
||||||
SettingsTab.Proxy,
|
const TAB_PLUGINS = 'plugins';
|
||||||
SettingsTab.Plugins,
|
const TAB_LICENSE = 'license';
|
||||||
SettingsTab.License,
|
const tabs = [TAB_GENERAL, TAB_APPEARANCE, TAB_PROXY, TAB_PLUGINS, TAB_LICENSE] as const;
|
||||||
];
|
export type SettingsTab = (typeof tabs)[number];
|
||||||
|
|
||||||
export default function Settings({ hide }: Props) {
|
export default function Settings({ hide }: Props) {
|
||||||
const osInfo = useOsInfo();
|
const osInfo = useOsInfo();
|
||||||
const { tab: tabFromQuery } = useSearch({ from: '/workspaces/$workspaceId/settings' });
|
const { tab: tabFromQuery } = useSearch({ from: '/workspaces/$workspaceId/settings' });
|
||||||
const [tab, setTab] = useState<string>(tabFromQuery ?? SettingsTab.General);
|
const [tab, setTab] = useState<string | undefined>(tabFromQuery);
|
||||||
|
|
||||||
// Close settings window on escape
|
// Close settings window on escape
|
||||||
// TODO: Could this be put in a better place? Eg. in Rust key listener when creating the window
|
// TODO: Could this be put in a better place? Eg. in Rust key listener when creating the window
|
||||||
@@ -74,19 +73,19 @@ export default function Settings({ hide }: Props) {
|
|||||||
onChangeValue={setTab}
|
onChangeValue={setTab}
|
||||||
tabs={tabs.map((value) => ({ value, label: capitalize(value) }))}
|
tabs={tabs.map((value) => ({ value, label: capitalize(value) }))}
|
||||||
>
|
>
|
||||||
<TabContent value={SettingsTab.General} className="pt-3 overflow-y-auto h-full px-4">
|
<TabContent value={TAB_GENERAL} className="pt-3 overflow-y-auto h-full px-4">
|
||||||
<SettingsGeneral />
|
<SettingsGeneral />
|
||||||
</TabContent>
|
</TabContent>
|
||||||
<TabContent value={SettingsTab.Appearance} className="pt-3 overflow-y-auto h-full px-4">
|
<TabContent value={TAB_APPEARANCE} className="pt-3 overflow-y-auto h-full px-4">
|
||||||
<SettingsAppearance />
|
<SettingsAppearance />
|
||||||
</TabContent>
|
</TabContent>
|
||||||
<TabContent value={SettingsTab.Plugins} className="pt-3 overflow-y-auto h-full px-4">
|
<TabContent value={TAB_PLUGINS} className="pt-3 overflow-y-auto h-full px-4">
|
||||||
<SettingsPlugins />
|
<SettingsPlugins />
|
||||||
</TabContent>
|
</TabContent>
|
||||||
<TabContent value={SettingsTab.Proxy} className="pt-3 overflow-y-auto h-full px-4">
|
<TabContent value={TAB_PROXY} className="pt-3 overflow-y-auto h-full px-4">
|
||||||
<SettingsProxy />
|
<SettingsProxy />
|
||||||
</TabContent>
|
</TabContent>
|
||||||
<TabContent value={SettingsTab.License} className="pt-3 overflow-y-auto h-full px-4">
|
<TabContent value={TAB_LICENSE} className="pt-3 overflow-y-auto h-full px-4">
|
||||||
<SettingsLicense />
|
<SettingsLicense />
|
||||||
</TabContent>
|
</TabContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
|
|
||||||
export enum SettingsTab {
|
|
||||||
General = 'general',
|
|
||||||
Proxy = 'proxy',
|
|
||||||
Appearance = 'appearance',
|
|
||||||
Plugins = 'plugins',
|
|
||||||
License = 'license',
|
|
||||||
}
|
|
||||||
@@ -13,7 +13,6 @@ import { Dropdown } from './core/Dropdown';
|
|||||||
import { Icon } from './core/Icon';
|
import { Icon } from './core/Icon';
|
||||||
import { IconButton } from './core/IconButton';
|
import { IconButton } from './core/IconButton';
|
||||||
import { KeyboardShortcutsDialog } from './KeyboardShortcutsDialog';
|
import { KeyboardShortcutsDialog } from './KeyboardShortcutsDialog';
|
||||||
import { SettingsTab } from './Settings/SettingsTab';
|
|
||||||
|
|
||||||
export function SettingsDropdown() {
|
export function SettingsDropdown() {
|
||||||
const importData = useImportData();
|
const importData = useImportData();
|
||||||
@@ -64,7 +63,7 @@ export function SettingsDropdown() {
|
|||||||
color: 'success',
|
color: 'success',
|
||||||
hidden: check.data == null || check.data.type === 'commercial_use',
|
hidden: check.data == null || check.data.type === 'commercial_use',
|
||||||
leftSlot: <Icon icon="circle_dollar_sign" />,
|
leftSlot: <Icon icon="circle_dollar_sign" />,
|
||||||
onSelect: () => openSettings.mutate(SettingsTab.License),
|
onSelect: () => openSettings.mutate('license'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Check for Updates',
|
label: 'Check for Updates',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import type { EditorView } from '@codemirror/view';
|
||||||
import type { HttpRequest } from '@yaakapp-internal/models';
|
import type { HttpRequest } from '@yaakapp-internal/models';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import type { EditorView } from 'codemirror';
|
|
||||||
import type { FormEvent, ReactNode } from 'react';
|
import type { FormEvent, ReactNode } from 'react';
|
||||||
import { memo, useRef, useState } from 'react';
|
import { memo, useRef, useState } from 'react';
|
||||||
import { useHotKey } from '../hooks/useHotKey';
|
import { useHotKey } from '../hooks/useHotKey';
|
||||||
@@ -8,7 +8,7 @@ import type { IconProps } from './core/Icon';
|
|||||||
import { IconButton } from './core/IconButton';
|
import { IconButton } from './core/IconButton';
|
||||||
import type { InputProps } from './core/Input';
|
import type { InputProps } from './core/Input';
|
||||||
import { Input } from './core/Input';
|
import { Input } from './core/Input';
|
||||||
import {HStack} from "./core/Stacks";
|
import { HStack } from './core/Stacks';
|
||||||
import { RequestMethodDropdown } from './RequestMethodDropdown';
|
import { RequestMethodDropdown } from './RequestMethodDropdown';
|
||||||
|
|
||||||
type Props = Pick<HttpRequest, 'url'> & {
|
type Props = Pick<HttpRequest, 'url'> & {
|
||||||
|
|||||||
@@ -194,12 +194,18 @@ function WorkspaceBody() {
|
|||||||
|
|
||||||
if (activeWorkspace == null) {
|
if (activeWorkspace == null) {
|
||||||
return (
|
return (
|
||||||
<div className="m-auto">
|
<m.div
|
||||||
|
className="m-auto"
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
// Delay the entering because the workspaces might load after a slight delay
|
||||||
|
transition={{ delay: 0.5 }}
|
||||||
|
>
|
||||||
<Banner color="warning" className="max-w-[30rem]">
|
<Banner color="warning" className="max-w-[30rem]">
|
||||||
The active workspace was not found. Select a workspace from the header menu or report this
|
The active workspace was not found. Select a workspace from the header menu or report this
|
||||||
bug to <FeedbackLink />
|
bug to <FeedbackLink />
|
||||||
</Banner>
|
</Banner>
|
||||||
</div>
|
</m.div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,16 +2,15 @@ import { defaultKeymap, historyField, indentWithTab } from '@codemirror/commands
|
|||||||
import { foldState, forceParsing } from '@codemirror/language';
|
import { foldState, forceParsing } from '@codemirror/language';
|
||||||
import type { EditorStateConfig, Extension } from '@codemirror/state';
|
import type { EditorStateConfig, Extension } from '@codemirror/state';
|
||||||
import { Compartment, EditorState } from '@codemirror/state';
|
import { Compartment, EditorState } from '@codemirror/state';
|
||||||
import { keymap, placeholder as placeholderExt, tooltips } from '@codemirror/view';
|
import { EditorView, keymap, placeholder as placeholderExt, tooltips } from '@codemirror/view';
|
||||||
import { emacs } from '@replit/codemirror-emacs';
|
import { emacs } from '@replit/codemirror-emacs';
|
||||||
import { vim } from '@replit/codemirror-vim';
|
|
||||||
import { vscodeKeymap } from '@replit/codemirror-vscode-keymap';
|
import { vscodeKeymap } from '@replit/codemirror-vscode-keymap';
|
||||||
import type { EditorKeymap, EnvironmentVariable } from '@yaakapp-internal/models';
|
import type { EditorKeymap, EnvironmentVariable } from '@yaakapp-internal/models';
|
||||||
import { settingsAtom } from '@yaakapp-internal/models';
|
import { settingsAtom } from '@yaakapp-internal/models';
|
||||||
import type { EditorLanguage, TemplateFunction } from '@yaakapp-internal/plugins';
|
import type { EditorLanguage, TemplateFunction } from '@yaakapp-internal/plugins';
|
||||||
import { parseTemplate } from '@yaakapp-internal/templates';
|
import { parseTemplate } from '@yaakapp-internal/templates';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { EditorView } from 'codemirror';
|
|
||||||
import { useAtomValue } from 'jotai';
|
import { useAtomValue } from 'jotai';
|
||||||
import { md5 } from 'js-md5';
|
import { md5 } from 'js-md5';
|
||||||
import type { MutableRefObject, ReactNode } from 'react';
|
import type { MutableRefObject, ReactNode } from 'react';
|
||||||
@@ -48,6 +47,8 @@ import {
|
|||||||
import type { GenericCompletionConfig } from './genericCompletion';
|
import type { GenericCompletionConfig } from './genericCompletion';
|
||||||
import { singleLineExtensions } from './singleLine';
|
import { singleLineExtensions } from './singleLine';
|
||||||
|
|
||||||
|
const { vim } = await import('@replit/codemirror-vim');
|
||||||
|
|
||||||
// VSCode's Tab actions mess with the single-line editor tab actions, so remove it.
|
// VSCode's Tab actions mess with the single-line editor tab actions, so remove it.
|
||||||
const vsCodeWithoutTab = vscodeKeymap.filter((k) => k.key !== 'Tab');
|
const vsCodeWithoutTab = vscodeKeymap.filter((k) => k.key !== 'Tab');
|
||||||
|
|
||||||
@@ -365,7 +366,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (cm.current === null) return;
|
if (cm.current === null) return;
|
||||||
const { view, languageCompartment } = cm.current;
|
const { view, languageCompartment } = cm.current;
|
||||||
const ext = getLanguageExtension({
|
getLanguageExtension({
|
||||||
useTemplating,
|
useTemplating,
|
||||||
language,
|
language,
|
||||||
environmentVariables,
|
environmentVariables,
|
||||||
@@ -374,8 +375,9 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
|
|||||||
onClickVariable,
|
onClickVariable,
|
||||||
onClickMissingVariable,
|
onClickMissingVariable,
|
||||||
onClickPathParameter,
|
onClickPathParameter,
|
||||||
|
}).then((ext) => {
|
||||||
|
view.dispatch({ effects: languageCompartment.reconfigure(ext) });
|
||||||
});
|
});
|
||||||
view.dispatch({ effects: languageCompartment.reconfigure(ext) });
|
|
||||||
}, [
|
}, [
|
||||||
language,
|
language,
|
||||||
autocomplete,
|
autocomplete,
|
||||||
@@ -399,7 +401,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const languageCompartment = new Compartment();
|
const languageCompartment = new Compartment();
|
||||||
const langExt = getLanguageExtension({
|
getLanguageExtension({
|
||||||
useTemplating,
|
useTemplating,
|
||||||
language,
|
language,
|
||||||
completionOptions,
|
completionOptions,
|
||||||
@@ -408,57 +410,57 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
|
|||||||
onClickVariable,
|
onClickVariable,
|
||||||
onClickMissingVariable,
|
onClickMissingVariable,
|
||||||
onClickPathParameter,
|
onClickPathParameter,
|
||||||
|
}).then((langExt) => {
|
||||||
|
const extensions = [
|
||||||
|
languageCompartment.of(langExt),
|
||||||
|
placeholderCompartment.current.of(placeholderExt(placeholderElFromText(placeholder))),
|
||||||
|
wrapLinesCompartment.current.of(wrapLines ? EditorView.lineWrapping : emptyExtension),
|
||||||
|
tabIndentCompartment.current.of(
|
||||||
|
!disableTabIndent ? keymap.of([indentWithTab]) : emptyExtension,
|
||||||
|
),
|
||||||
|
keymapCompartment.current.of(
|
||||||
|
keymapExtensions[settings.editorKeymap] ?? keymapExtensions['default'],
|
||||||
|
),
|
||||||
|
...getExtensions({
|
||||||
|
container,
|
||||||
|
readOnly,
|
||||||
|
singleLine,
|
||||||
|
hideGutter,
|
||||||
|
stateKey,
|
||||||
|
onChange: handleChange,
|
||||||
|
onPaste: handlePaste,
|
||||||
|
onPasteOverwrite: handlePasteOverwrite,
|
||||||
|
onFocus: handleFocus,
|
||||||
|
onBlur: handleBlur,
|
||||||
|
onKeyDown: handleKeyDown,
|
||||||
|
}),
|
||||||
|
...(extraExtensions ?? []),
|
||||||
|
];
|
||||||
|
|
||||||
|
const cachedJsonState = getCachedEditorState(defaultValue ?? '', stateKey);
|
||||||
|
|
||||||
|
const doc = `${defaultValue ?? ''}`;
|
||||||
|
const config: EditorStateConfig = { extensions, doc };
|
||||||
|
|
||||||
|
const state = cachedJsonState
|
||||||
|
? EditorState.fromJSON(cachedJsonState, config, stateFields)
|
||||||
|
: EditorState.create(config);
|
||||||
|
|
||||||
|
const view = new EditorView({ state, parent: container });
|
||||||
|
|
||||||
|
// For large documents, the parser may parse the max number of lines and fail to add
|
||||||
|
// things like fold markers because of it.
|
||||||
|
// This forces it to parse more but keeps the timeout to the default of 100 ms.
|
||||||
|
forceParsing(view, 9e6, 100);
|
||||||
|
|
||||||
|
cm.current = { view, languageCompartment };
|
||||||
|
if (autoFocus) {
|
||||||
|
view.focus();
|
||||||
|
}
|
||||||
|
if (autoSelect) {
|
||||||
|
view.dispatch({ selection: { anchor: 0, head: view.state.doc.length } });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const extensions = [
|
|
||||||
languageCompartment.of(langExt),
|
|
||||||
placeholderCompartment.current.of(placeholderExt(placeholderElFromText(placeholder))),
|
|
||||||
wrapLinesCompartment.current.of(wrapLines ? EditorView.lineWrapping : emptyExtension),
|
|
||||||
tabIndentCompartment.current.of(
|
|
||||||
!disableTabIndent ? keymap.of([indentWithTab]) : emptyExtension,
|
|
||||||
),
|
|
||||||
keymapCompartment.current.of(
|
|
||||||
keymapExtensions[settings.editorKeymap] ?? keymapExtensions['default'],
|
|
||||||
),
|
|
||||||
...getExtensions({
|
|
||||||
container,
|
|
||||||
readOnly,
|
|
||||||
singleLine,
|
|
||||||
hideGutter,
|
|
||||||
stateKey,
|
|
||||||
onChange: handleChange,
|
|
||||||
onPaste: handlePaste,
|
|
||||||
onPasteOverwrite: handlePasteOverwrite,
|
|
||||||
onFocus: handleFocus,
|
|
||||||
onBlur: handleBlur,
|
|
||||||
onKeyDown: handleKeyDown,
|
|
||||||
}),
|
|
||||||
...(extraExtensions ?? []),
|
|
||||||
];
|
|
||||||
|
|
||||||
const cachedJsonState = getCachedEditorState(defaultValue ?? '', stateKey);
|
|
||||||
|
|
||||||
const doc = `${defaultValue ?? ''}`;
|
|
||||||
const config: EditorStateConfig = { extensions, doc };
|
|
||||||
|
|
||||||
const state = cachedJsonState
|
|
||||||
? EditorState.fromJSON(cachedJsonState, config, stateFields)
|
|
||||||
: EditorState.create(config);
|
|
||||||
|
|
||||||
const view = new EditorView({ state, parent: container });
|
|
||||||
|
|
||||||
// For large documents, the parser may parse the max number of lines and fail to add
|
|
||||||
// things like fold markers because of it.
|
|
||||||
// This forces it to parse more but keeps the timeout to the default of 100 ms.
|
|
||||||
forceParsing(view, 9e6, 100);
|
|
||||||
|
|
||||||
cm.current = { view, languageCompartment };
|
|
||||||
if (autoFocus) {
|
|
||||||
view.focus();
|
|
||||||
}
|
|
||||||
if (autoSelect) {
|
|
||||||
view.dispatch({ selection: { anchor: 0, head: view.state.doc.length } });
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Failed to initialize Codemirror', e);
|
console.log('Failed to initialize Codemirror', e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,6 @@ import {
|
|||||||
completionKeymap,
|
completionKeymap,
|
||||||
} from '@codemirror/autocomplete';
|
} from '@codemirror/autocomplete';
|
||||||
import { history, historyKeymap } from '@codemirror/commands';
|
import { history, historyKeymap } from '@codemirror/commands';
|
||||||
import { javascript } from '@codemirror/lang-javascript';
|
|
||||||
import { json } from '@codemirror/lang-json';
|
|
||||||
import { markdown } from '@codemirror/lang-markdown';
|
|
||||||
import { xml } from '@codemirror/lang-xml';
|
|
||||||
import type { LanguageSupport } from '@codemirror/language';
|
import type { LanguageSupport } from '@codemirror/language';
|
||||||
import {
|
import {
|
||||||
codeFolding,
|
codeFolding,
|
||||||
@@ -27,6 +23,7 @@ import {
|
|||||||
crosshairCursor,
|
crosshairCursor,
|
||||||
drawSelection,
|
drawSelection,
|
||||||
dropCursor,
|
dropCursor,
|
||||||
|
EditorView,
|
||||||
highlightActiveLineGutter,
|
highlightActiveLineGutter,
|
||||||
highlightSpecialChars,
|
highlightSpecialChars,
|
||||||
keymap,
|
keymap,
|
||||||
@@ -36,15 +33,11 @@ import {
|
|||||||
import { tags as t } from '@lezer/highlight';
|
import { tags as t } from '@lezer/highlight';
|
||||||
import type { EnvironmentVariable } from '@yaakapp-internal/models';
|
import type { EnvironmentVariable } from '@yaakapp-internal/models';
|
||||||
import { graphql } from 'cm6-graphql';
|
import { graphql } from 'cm6-graphql';
|
||||||
import { EditorView } from 'codemirror';
|
|
||||||
import { pluralizeCount } from '../../../lib/pluralize';
|
import { pluralizeCount } from '../../../lib/pluralize';
|
||||||
import type { EditorProps } from './Editor';
|
import type { EditorProps } from './Editor';
|
||||||
import { pairs } from './pairs/extension';
|
|
||||||
import { text } from './text/extension';
|
import { text } from './text/extension';
|
||||||
import type { TwigCompletionOption } from './twig/completion';
|
import type { TwigCompletionOption } from './twig/completion';
|
||||||
import { twig } from './twig/extension';
|
|
||||||
import { pathParametersPlugin } from './twig/pathParameters';
|
import { pathParametersPlugin } from './twig/pathParameters';
|
||||||
import { url } from './url/extension';
|
|
||||||
|
|
||||||
export const syntaxHighlightStyle = HighlightStyle.define([
|
export const syntaxHighlightStyle = HighlightStyle.define([
|
||||||
{
|
{
|
||||||
@@ -75,21 +68,25 @@ const syntaxTheme = EditorView.theme({}, { dark: true });
|
|||||||
|
|
||||||
const closeBracketsExtensions: Extension = [closeBrackets(), keymap.of([...closeBracketsKeymap])];
|
const closeBracketsExtensions: Extension = [closeBrackets(), keymap.of([...closeBracketsKeymap])];
|
||||||
|
|
||||||
const syntaxExtensions: Record<NonNullable<EditorProps['language']>, LanguageSupport | null> = {
|
const syntaxExtensions: Record<
|
||||||
|
NonNullable<EditorProps['language']>,
|
||||||
|
null | (() => Promise<LanguageSupport>)
|
||||||
|
> = {
|
||||||
graphql: null,
|
graphql: null,
|
||||||
json: json(),
|
json: () => import('@codemirror/lang-json').then((m) => m.json()),
|
||||||
javascript: javascript(),
|
javascript: () => import('@codemirror/lang-javascript').then((m) => m.javascript()),
|
||||||
html: xml(), // HTML as XML because HTML is oddly slow
|
// HTML as XML because HTML is oddly slow
|
||||||
xml: xml(),
|
html: () => import('@codemirror/lang-xml').then((m) => m.xml()),
|
||||||
url: url(),
|
xml: () => import('@codemirror/lang-xml').then((m) => m.xml()),
|
||||||
pairs: pairs(),
|
url: () => import('./url/extension').then((m) => m.url()),
|
||||||
text: text(),
|
pairs: () => import('./pairs/extension').then((m) => m.pairs()),
|
||||||
markdown: markdown(),
|
text: () => import('./text/extension').then((m) => m.text()),
|
||||||
|
markdown: () => import('@codemirror/lang-markdown').then((m) => m.markdown()),
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeBracketsFor: (keyof typeof syntaxExtensions)[] = ['json', 'javascript', 'graphql'];
|
const closeBracketsFor: (keyof typeof syntaxExtensions)[] = ['json', 'javascript', 'graphql'];
|
||||||
|
|
||||||
export function getLanguageExtension({
|
export async function getLanguageExtension({
|
||||||
useTemplating,
|
useTemplating,
|
||||||
language = 'text',
|
language = 'text',
|
||||||
environmentVariables,
|
environmentVariables,
|
||||||
@@ -122,12 +119,14 @@ export function getLanguageExtension({
|
|||||||
return [graphql(), extraExtensions];
|
return [graphql(), extraExtensions];
|
||||||
}
|
}
|
||||||
|
|
||||||
const base = syntaxExtensions[language ?? 'text'] ?? text();
|
const base_ = syntaxExtensions[language ?? 'text'] ?? text();
|
||||||
|
const base = typeof base_ === 'function' ? await base_() : text();
|
||||||
|
|
||||||
if (!useTemplating) {
|
if (!useTemplating) {
|
||||||
return [base, extraExtensions];
|
return [base, extraExtensions];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { twig } = await import('./twig/extension');
|
||||||
return twig({
|
return twig({
|
||||||
base,
|
base,
|
||||||
environmentVariables,
|
environmentVariables,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import type { DecorationSet, ViewUpdate } from '@codemirror/view';
|
import type { DecorationSet, ViewUpdate } from '@codemirror/view';
|
||||||
import { Decoration, hoverTooltip, MatchDecorator, ViewPlugin } from '@codemirror/view';
|
import { Decoration, EditorView, hoverTooltip, MatchDecorator, ViewPlugin } from '@codemirror/view';
|
||||||
import { EditorView } from 'codemirror';
|
|
||||||
|
|
||||||
const REGEX =
|
const REGEX =
|
||||||
/(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+*~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+*.~#?&/={}[\]]*))/g;
|
/(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+*~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+*.~#?&/={}[\]]*))/g;
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { syntaxTree } from '@codemirror/language';
|
import { syntaxTree } from '@codemirror/language';
|
||||||
import type { Range } from '@codemirror/state';
|
import type { Range } from '@codemirror/state';
|
||||||
import type { DecorationSet, ViewUpdate } from '@codemirror/view';
|
import type { DecorationSet, ViewUpdate } from '@codemirror/view';
|
||||||
import { Decoration, ViewPlugin, WidgetType } from '@codemirror/view';
|
import { Decoration, ViewPlugin, WidgetType, EditorView } from '@codemirror/view';
|
||||||
import { EditorView } from 'codemirror';
|
|
||||||
|
|
||||||
class PathPlaceholderWidget extends WidgetType {
|
class PathPlaceholderWidget extends WidgetType {
|
||||||
readonly #clickListenerCallback: () => void;
|
readonly #clickListenerCallback: () => void;
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
import { syntaxTree } from '@codemirror/language';
|
import { syntaxTree } from '@codemirror/language';
|
||||||
import type { Range } from '@codemirror/state';
|
import type { Range } from '@codemirror/state';
|
||||||
import type { DecorationSet, ViewUpdate } from '@codemirror/view';
|
import type { DecorationSet, ViewUpdate } from '@codemirror/view';
|
||||||
import { Decoration, ViewPlugin, WidgetType } from '@codemirror/view';
|
import { Decoration, ViewPlugin, WidgetType, EditorView } from '@codemirror/view';
|
||||||
import type { SyntaxNodeRef } from '@lezer/common';
|
import type { SyntaxNodeRef } from '@lezer/common';
|
||||||
import { EditorView } from 'codemirror';
|
|
||||||
import type { TwigCompletionOption } from './completion';
|
import type { TwigCompletionOption } from './completion';
|
||||||
|
|
||||||
class TemplateTagWidget extends WidgetType {
|
class TemplateTagWidget extends WidgetType {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
|
import type { EditorView } from '@codemirror/view';
|
||||||
import type { Color } from '@yaakapp/api';
|
import type { Color } from '@yaakapp/api';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import type { EditorView } from 'codemirror';
|
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import {
|
import {
|
||||||
forwardRef,
|
forwardRef,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
import type { EditorView } from '@codemirror/view';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import type { EditorView } from 'codemirror';
|
|
||||||
import {
|
import {
|
||||||
forwardRef,
|
forwardRef,
|
||||||
Fragment,
|
Fragment,
|
||||||
|
|||||||
@@ -7,6 +7,13 @@ import React, { useRef, useState } from 'react';
|
|||||||
import { Document, Page } from 'react-pdf';
|
import { Document, Page } from 'react-pdf';
|
||||||
import { useContainerSize } from '../../hooks/useContainerQuery';
|
import { useContainerSize } from '../../hooks/useContainerQuery';
|
||||||
|
|
||||||
|
import('react-pdf').then(({ pdfjs }) => {
|
||||||
|
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
|
||||||
|
'pdfjs-dist/build/pdf.worker.min.mjs',
|
||||||
|
import.meta.url,
|
||||||
|
).toString();
|
||||||
|
});
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
bodyPath: string;
|
bodyPath: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,6 @@ import { initSync } from './init/sync';
|
|||||||
import { jotaiStore } from './lib/jotai';
|
import { jotaiStore } from './lib/jotai';
|
||||||
import { router } from './lib/router';
|
import { router } from './lib/router';
|
||||||
|
|
||||||
import('react-pdf').then(({ pdfjs }) => {
|
|
||||||
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
|
|
||||||
'pdfjs-dist/build/pdf.worker.min.mjs',
|
|
||||||
import.meta.url,
|
|
||||||
).toString();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Hide decorations here because it doesn't work in Rust for some reason (bug?)
|
// Hide decorations here because it doesn't work in Rust for some reason (bug?)
|
||||||
const osType = type();
|
const osType = type();
|
||||||
if (osType !== 'macos') {
|
if (osType !== 'macos') {
|
||||||
|
|||||||
@@ -9,23 +9,23 @@
|
|||||||
"lint": "tsc --noEmit && eslint . --ext .ts,.tsx"
|
"lint": "tsc --noEmit && eslint . --ext .ts,.tsx"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/commands": "6.7.0",
|
"@codemirror/commands": "^6.8.1",
|
||||||
"@codemirror/lang-javascript": "^6.2.2",
|
"@codemirror/lang-javascript": "^6.2.4",
|
||||||
"@codemirror/lang-json": "^6.0.1",
|
"@codemirror/lang-json": "^6.0.1",
|
||||||
"@codemirror/lang-markdown": "^6.3.1",
|
"@codemirror/lang-markdown": "^6.3.2",
|
||||||
"@codemirror/lang-xml": "^6.0.2",
|
"@codemirror/lang-xml": "^6.1.0",
|
||||||
"@codemirror/language": "^6.6.0",
|
"@codemirror/language": "^6.11.0",
|
||||||
"@codemirror/search": "^6.2.3",
|
"@codemirror/search": "^6.5.11",
|
||||||
"@gilbarbara/deep-equal": "^0.3.1",
|
"@gilbarbara/deep-equal": "^0.3.1",
|
||||||
"@lezer/highlight": "^1.1.3",
|
"@lezer/highlight": "^1.1.3",
|
||||||
"@lezer/lr": "^1.3.3",
|
"@lezer/lr": "^1.3.3",
|
||||||
"@replit/codemirror-emacs": "^6.1.0",
|
"@replit/codemirror-emacs": "^6.1.0",
|
||||||
"@replit/codemirror-vim": "^6.2.1",
|
"@replit/codemirror-vim": "^6.3.0",
|
||||||
"@replit/codemirror-vscode-keymap": "^6.0.2",
|
"@replit/codemirror-vscode-keymap": "^6.0.2",
|
||||||
"@tailwindcss/container-queries": "^0.1.1",
|
"@tailwindcss/container-queries": "^0.1.1",
|
||||||
"@tanstack/react-query": "^5.66.9",
|
"@tanstack/react-query": "^5.76.1",
|
||||||
"@tanstack/react-router": "^1.111.3",
|
"@tanstack/react-router": "^1.120.3",
|
||||||
"@tanstack/react-virtual": "^3.13.0",
|
"@tanstack/react-virtual": "^3.13.8",
|
||||||
"@tauri-apps/api": "^2.4.1",
|
"@tauri-apps/api": "^2.4.1",
|
||||||
"@tauri-apps/plugin-clipboard-manager": "^2.2.2",
|
"@tauri-apps/plugin-clipboard-manager": "^2.2.2",
|
||||||
"@tauri-apps/plugin-dialog": "^2.2.1",
|
"@tauri-apps/plugin-dialog": "^2.2.1",
|
||||||
@@ -36,9 +36,8 @@
|
|||||||
"@tauri-apps/plugin-shell": "^2.2.1",
|
"@tauri-apps/plugin-shell": "^2.2.1",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"classnames": "^2.5.1",
|
"classnames": "^2.5.1",
|
||||||
"cm6-graphql": "^0.0.9",
|
"cm6-graphql": "^0.2.1",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror-json-schema": "0.6.1",
|
||||||
"codemirror-json-schema": "^0.6.1",
|
|
||||||
"date-fns": "^3.6.0",
|
"date-fns": "^3.6.0",
|
||||||
"deep-equal": "^2.2.3",
|
"deep-equal": "^2.2.3",
|
||||||
"eventemitter3": "^5.0.1",
|
"eventemitter3": "^5.0.1",
|
||||||
@@ -72,8 +71,6 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lezer/generator": "^1.7.1",
|
"@lezer/generator": "^1.7.1",
|
||||||
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
||||||
"@tanstack/react-query-devtools": "^5.62.8",
|
|
||||||
"@tanstack/router-devtools": "^1.91.3",
|
|
||||||
"@tanstack/router-plugin": "^1.91.1",
|
"@tanstack/router-plugin": "^1.91.1",
|
||||||
"@types/node": "^22.5.4",
|
"@types/node": "^22.5.4",
|
||||||
"@types/papaparse": "^5.3.14",
|
"@types/papaparse": "^5.3.14",
|
||||||
@@ -90,7 +87,6 @@
|
|||||||
"internal-ip": "^8.0.0",
|
"internal-ip": "^8.0.0",
|
||||||
"postcss": "^8.4.45",
|
"postcss": "^8.4.45",
|
||||||
"postcss-nesting": "^13.0.0",
|
"postcss-nesting": "^13.0.0",
|
||||||
"react-devtools": "^5.3.1",
|
|
||||||
"tailwindcss": "^3.4.10",
|
"tailwindcss": "^3.4.10",
|
||||||
"vite": "6.2.6",
|
"vite": "6.2.6",
|
||||||
"vite-plugin-static-copy": "^2.2.0",
|
"vite-plugin-static-copy": "^2.2.0",
|
||||||
|
|||||||
@@ -15,26 +15,6 @@ import { useOsInfo } from '../hooks/useOsInfo';
|
|||||||
import { jotaiStore } from '../lib/jotai';
|
import { jotaiStore } from '../lib/jotai';
|
||||||
import { queryClient } from '../lib/queryClient';
|
import { queryClient } from '../lib/queryClient';
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
const TanStackRouterDevtools =
|
|
||||||
process.env.NODE_ENV === 'production'
|
|
||||||
? () => null // Render nothing in production
|
|
||||||
: React.lazy(() =>
|
|
||||||
import('@tanstack/router-devtools').then((res) => ({
|
|
||||||
default: res.TanStackRouterDevtools,
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
const ReactQueryDevtools =
|
|
||||||
process.env.NODE_ENV === 'production'
|
|
||||||
? () => null // Render nothing in production
|
|
||||||
: React.lazy(() =>
|
|
||||||
import('@tanstack/react-query-devtools').then((res) => ({
|
|
||||||
default: res.ReactQueryDevtools,
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
|
|
||||||
export const Route = createRootRoute({
|
export const Route = createRootRoute({
|
||||||
component: RouteComponent,
|
component: RouteComponent,
|
||||||
errorComponent: RouteError,
|
errorComponent: RouteError,
|
||||||
@@ -66,8 +46,6 @@ function RouteComponent() {
|
|||||||
</HelmetProvider>
|
</HelmetProvider>
|
||||||
</MotionConfig>
|
</MotionConfig>
|
||||||
</LazyMotion>
|
</LazyMotion>
|
||||||
{/*<ReactQueryDevtools initialIsOpen />*/}
|
|
||||||
{/*<TanStackRouterDevtools initialIsOpen />*/}
|
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
</JotaiProvider>
|
</JotaiProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import { createFileRoute } from '@tanstack/react-router'
|
import { createFileRoute } from '@tanstack/react-router';
|
||||||
import Settings from '../../../components/Settings/Settings'
|
import type { SettingsTab } from '../../../components/Settings/Settings';
|
||||||
import { SettingsTab } from '../../../components/Settings/SettingsTab'
|
import Settings from '../../../components/Settings/Settings';
|
||||||
|
|
||||||
interface SettingsSearchSchema {
|
interface SettingsSearchSchema {
|
||||||
tab?: SettingsTab
|
tab?: SettingsTab;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Route = createFileRoute('/workspaces/$workspaceId/settings')({
|
export const Route = createFileRoute('/workspaces/$workspaceId/settings')({
|
||||||
component: RouteComponent,
|
component: RouteComponent,
|
||||||
validateSearch: (search: Record<string, unknown>): SettingsSearchSchema => ({
|
validateSearch: (search: Record<string, unknown>): SettingsSearchSchema => ({
|
||||||
tab: (search.tab ?? SettingsTab.General) as SettingsTab,
|
tab: (search.tab ?? 'general') as SettingsTab,
|
||||||
}),
|
}),
|
||||||
})
|
});
|
||||||
|
|
||||||
function RouteComponent() {
|
function RouteComponent() {
|
||||||
return <Settings />
|
return <Settings />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import {TanStackRouterVite} from '@tanstack/router-plugin/vite';
|
import { TanStackRouterVite } from '@tanstack/router-plugin/vite';
|
||||||
import react from '@vitejs/plugin-react';
|
import react from '@vitejs/plugin-react';
|
||||||
import reactRefresh from 'eslint-plugin-react-refresh';
|
import reactRefresh from 'eslint-plugin-react-refresh';
|
||||||
import {internalIpV4} from 'internal-ip';
|
import { internalIpV4 } from 'internal-ip';
|
||||||
import {createRequire} from 'node:module';
|
import { createRequire } from 'node:module';
|
||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import {defineConfig, normalizePath} from 'vite';
|
import { defineConfig, normalizePath } from 'vite';
|
||||||
import {viteStaticCopy} from 'vite-plugin-static-copy';
|
import { viteStaticCopy } from 'vite-plugin-static-copy';
|
||||||
import svgr from 'vite-plugin-svgr';
|
import svgr from 'vite-plugin-svgr';
|
||||||
import topLevelAwait from 'vite-plugin-top-level-await';
|
import topLevelAwait from 'vite-plugin-top-level-await';
|
||||||
import wasm from 'vite-plugin-wasm';
|
import wasm from 'vite-plugin-wasm';
|
||||||
|
|||||||
Reference in New Issue
Block a user