Skip to content

Commit

Permalink
Merge pull request #40 from Pkcarreno/fix/2
Browse files Browse the repository at this point in the history
fixes and feats
  • Loading branch information
Pkcarreno authored Oct 6, 2024
2 parents 301c4a0 + f47885c commit 162d3a9
Show file tree
Hide file tree
Showing 28 changed files with 590 additions and 216 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"@radix-ui/react-progress": "^1.1.0",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.1",
"@radix-ui/react-toggle": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2",
"@uiw/codemirror-extensions-basic-setup": "^4.23.3",
Expand Down
70 changes: 70 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/components/loading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Spinner } from './ui/spinner';

export const Loading = () => {
return (
<div className="flex h-screen w-screen items-center justify-center">
<div className="flex size-full items-center justify-center">
<Spinner />
</div>
);
Expand Down
33 changes: 17 additions & 16 deletions src/components/ui/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const DialogOverlay = React.forwardRef<
<DialogPrimitive.Overlay
ref={ref}
className={cn(
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80',
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 grid place-items-center overflow-y-auto bg-black/30 py-16 backdrop-blur-sm',
className,
)}
{...props}
Expand All @@ -32,21 +32,22 @@ const DialogContent = React.forwardRef<
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<DialogPortal>
<DialogOverlay />
<DialogPrimitive.Content
ref={ref}
className={cn(
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg',
className,
)}
{...props}
>
{children}
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none">
<Cross2Icon className="size-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
<DialogOverlay>
<DialogPrimitive.Content
ref={ref}
className={cn(
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 relative z-50 grid w-full max-w-lg gap-4 p-6 shadow-lg duration-200 sm:rounded-lg md:w-full',
className,
)}
{...props}
>
{children}
<DialogPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none">
<Cross2Icon className="size-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</DialogOverlay>
</DialogPortal>
));
DialogContent.displayName = DialogPrimitive.Content.displayName;
Expand Down
53 changes: 53 additions & 0 deletions src/components/ui/tabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import * as TabsPrimitive from '@radix-ui/react-tabs';
import * as React from 'react';

import { cn } from '@/lib/utils';

const Tabs = TabsPrimitive.Root;

const TabsList = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.List>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
>(({ className, ...props }, ref) => (
<TabsPrimitive.List
ref={ref}
className={cn(
'bg-muted text-muted-foreground inline-flex h-10 items-center justify-center rounded-md p-1',
className,
)}
{...props}
/>
));
TabsList.displayName = TabsPrimitive.List.displayName;

const TabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Trigger
ref={ref}
className={cn(
'ring-offset-background focus-visible:ring-ring data-[state=active]:bg-background data-[state=active]:text-foreground inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm',
className,
)}
{...props}
/>
));
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;

const TabsContent = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
>(({ className, ...props }, ref) => (
<TabsPrimitive.Content
ref={ref}
className={cn(
'ring-offset-background focus-visible:ring-ring mt-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2',
className,
)}
{...props}
/>
));
TabsContent.displayName = TabsPrimitive.Content.displayName;

export { Tabs, TabsContent, TabsList, TabsTrigger };
45 changes: 45 additions & 0 deletions src/features/editor/components/editor/cm-extensions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { esLint, javascript } from '@codemirror/lang-javascript';
import { linter, lintGutter } from '@codemirror/lint';
import { basicSetup } from '@uiw/codemirror-extensions-basic-setup';
import type { ReactCodeMirrorProps } from '@uiw/react-codemirror';
import { worker as globalsWorker } from 'globals';

const EsLintConfig = {
languageOptions: {
globals: {
...globalsWorker,
console: true,
},
parserOptions: {
ecmaVersion: 2023,
sourceType: 'module',
},
},
rules: {
semi: ['error', 'never'],
},
};

const newLinter = async () => {
const { ...eslint } = await import('eslint-linter-browserify');
return new eslint.Linter();
};

export const getExtensions = async () => {
const extensions: ReactCodeMirrorProps['extensions'] = [
basicSetup({
foldGutter: false,
dropCursor: false,
allowMultipleSelections: true,
indentOnInput: true,
autocompletion: true,
closeBrackets: true,
bracketMatching: true,
}),
javascript(),
lintGutter(),
linter(esLint(await newLinter(), EsLintConfig)),
];

return extensions;
};
88 changes: 38 additions & 50 deletions src/features/editor/components/editor/index.tsx
Original file line number Diff line number Diff line change
@@ -1,58 +1,42 @@
import { esLint, javascript } from '@codemirror/lang-javascript';
import { linter, lintGutter } from '@codemirror/lint';
import { basicSetup } from '@uiw/codemirror-extensions-basic-setup';
import type { ReactCodeMirrorProps } from '@uiw/react-codemirror';
import CodeMirror from '@uiw/react-codemirror';
import * as eslint from 'eslint-linter-browserify';
import { worker as globalsWorker } from 'globals';
import { useMemo, useRef } from 'react';
import { lazy, Suspense, useEffect, useMemo, useRef, useState } from 'react';

import { Loading } from '@/components/loading';
import { useTheme } from '@/hooks/use-theme';
import { debounce } from '@/lib/debounce';

import { useUntrustedMode } from '../../hooks/use-untrusted-mode';
import { useCodeStore } from '../../stores/editor';
import { themeInit } from './theme';

const CodeMirror = lazy(() => import('@uiw/react-codemirror'));

const darkTheme = themeInit({ theme: 'dark' });
const lightTheme = themeInit({ theme: 'light' });

const EsLintConfig = {
languageOptions: {
globals: {
...globalsWorker,
console: true,
},
parserOptions: {
ecmaVersion: 2023,
sourceType: 'module',
},
},
rules: {
semi: ['error', 'never'],
},
};

const extensions: ReactCodeMirrorProps['extensions'] = [
basicSetup({
foldGutter: false,
dropCursor: false,
allowMultipleSelections: true,
indentOnInput: true,
autocompletion: true,
closeBrackets: true,
bracketMatching: true,
}),
javascript(),
lintGutter(),
linter(esLint(new eslint.Linter(), EsLintConfig)),
];

export const CodemirrorEditor = () => {
const { themeMode } = useTheme();
const { code, setCode } = useCodeStore();
const { isUntrustedMode, isUnedited, setUnedited } = useUntrustedMode();
const codeRef = useRef<string | null>(null);
const [extensions, setExtensions] = useState<
ReactCodeMirrorProps['extensions']
>([]);

const getMemoExtensions = useMemo(async () => {
const lib = await import('./cm-extensions');
const res = await lib.getExtensions();
return res;
}, []);

const loadExtensions = async () => {
const ext = await getMemoExtensions;
setExtensions(ext);
};

useEffect(() => {
loadExtensions();
}, []);

codeRef.current = code;

Expand All @@ -77,17 +61,21 @@ export const CodemirrorEditor = () => {
}, [themeMode]);

return (
<CodeMirror
value={codeRef.current ?? ''}
theme={getCurrentTheme}
lang="javascript"
height="100%"
style={{ height: '100%', overflow: 'auto', fontSize: '.9rem' }}
readOnly={isUntrustedMode}
extensions={extensions}
onChange={handleEditorChange}
spellCheck={false}
translate="no"
/>
<Suspense fallback={<Loading />}>
<CodeMirror
value={codeRef.current ?? ''}
theme={getCurrentTheme}
lang="javascript"
height="100%"
style={{ height: '100%', overflow: 'auto', fontSize: '.9rem' }}
readOnly={isUntrustedMode}
extensions={extensions}
onChange={handleEditorChange}
spellCheck={false}
translate="no"
/>
</Suspense>
);
};

export default CodemirrorEditor;
Loading

0 comments on commit 162d3a9

Please sign in to comment.