diff --git a/apps/codeimage/src/components/KeyboardShortcuts/KeyboardShortcuts.tsx b/apps/codeimage/src/components/KeyboardShortcuts/KeyboardShortcuts.tsx index 1510b6a43..71a312400 100644 --- a/apps/codeimage/src/components/KeyboardShortcuts/KeyboardShortcuts.tsx +++ b/apps/codeimage/src/components/KeyboardShortcuts/KeyboardShortcuts.tsx @@ -1,13 +1,12 @@ import {useI18n} from '@codeimage/locale'; import {getRootEditorStore} from '@codeimage/store/editor'; -import {dispatchUpdateTheme} from '@codeimage/store/effects/onThemeChange'; import {getFrameState} from '@codeimage/store/editor/frame'; import {getTerminalState} from '@codeimage/store/editor/terminal'; +import {dispatchUpdateTheme} from '@codeimage/store/effects/onThemeChange'; import * as ui from '@codeimage/store/ui'; import { Button, FadeInOutTransition, - HStack, PopoverPanel, PortalHostContext, useFloating, diff --git a/apps/codeimage/src/components/PropertyEditor/EditorStyleForm.tsx b/apps/codeimage/src/components/PropertyEditor/EditorStyleForm.tsx index a98116dcc..4b0565903 100644 --- a/apps/codeimage/src/components/PropertyEditor/EditorStyleForm.tsx +++ b/apps/codeimage/src/components/PropertyEditor/EditorStyleForm.tsx @@ -5,10 +5,12 @@ import {getActiveEditorStore} from '@codeimage/store/editor/activeEditor'; import {SegmentedField, Select, Text} from '@codeimage/ui'; import {SUPPORTED_FONTS} from '@core/configuration/font'; import {useModality} from '@core/hooks/isMobile'; +import {SkeletonLine} from '@ui/Skeleton/Skeleton'; import {createMemo, ParentComponent, Show} from 'solid-js'; import {AppLocaleEntries} from '../../i18n'; import {PanelHeader} from './PanelHeader'; import {PanelRow, TwoColumnPanelRow} from './PanelRow'; +import {SuspenseEditorItem} from './SuspenseEditorItemt'; export const EditorStyleForm: ParentComponent = () => { const languages = SUPPORTED_LANGUAGES; @@ -44,21 +46,25 @@ export const EditorStyleForm: ParentComponent = () => { - ({ + label: label, + value: id, + }))} + value={editor.languageId} + onSelectChange={value => { + const language = value ?? languages[0].id; + setLanguageId(language); + umami.trackEvent(language, 'change-language'); + }} + /> + @@ -67,53 +73,65 @@ export const EditorStyleForm: ParentComponent = () => { label={t('frame.lineNumbers')} > - + } + > + + - ( + + {label} + + )} + onSelectChange={value => setFontId(value?.id ?? fonts[0].id)} + /> + - + setFontWeight(value ?? font()?.types[0].weight ?? 400) + } + /> + diff --git a/apps/codeimage/src/components/PropertyEditor/FrameStyleForm.tsx b/apps/codeimage/src/components/PropertyEditor/FrameStyleForm.tsx index 81500f23e..5bdf46bcd 100644 --- a/apps/codeimage/src/components/PropertyEditor/FrameStyleForm.tsx +++ b/apps/codeimage/src/components/PropertyEditor/FrameStyleForm.tsx @@ -1,12 +1,14 @@ import {useI18n} from '@codeimage/locale'; import {getFrameState} from '@codeimage/store/editor/frame'; import {RangeField, SegmentedField} from '@codeimage/ui'; +import {SkeletonLine, SkeletonVCenter} from '@ui/Skeleton/Skeleton'; import {ParentComponent, Show} from 'solid-js'; import {appEnvironment} from '../../core/configuration'; import {AppLocaleEntries} from '../../i18n'; import {CustomColorPicker} from './controls/CustomColorPicker'; import {PanelHeader} from './PanelHeader'; import {PanelRow, TwoColumnPanelRow} from './PanelRow'; +import {SuspenseEditorItem} from './SuspenseEditorItemt'; export const FrameStyleForm: ParentComponent = () => { const [t] = useI18n(); @@ -19,45 +21,61 @@ export const FrameStyleForm: ParentComponent = () => { - ({ - label: padding.toString(), - value: padding, - }))} - /> + } + > + ({ + label: padding.toString(), + value: padding, + }))} + /> + - + } + > + + - + + + + } + > + + @@ -65,11 +83,15 @@ export const FrameStyleForm: ParentComponent = () => { - frame.setBackground(color)} - value={frame.store.background ?? ''} - /> + } + > + frame.setBackground(color)} + value={frame.store.background ?? ''} + /> + diff --git a/apps/codeimage/src/components/PropertyEditor/SuspenseEditorItemt.tsx b/apps/codeimage/src/components/PropertyEditor/SuspenseEditorItemt.tsx new file mode 100644 index 000000000..d653278f1 --- /dev/null +++ b/apps/codeimage/src/components/PropertyEditor/SuspenseEditorItemt.tsx @@ -0,0 +1,17 @@ +import {getEditorSyncAdapter} from '@codeimage/store/editor/createEditorInit'; +import {JSX, ParentProps, Suspense} from 'solid-js'; + +export function SuspenseEditorItem( + props: ParentProps<{fallback: JSX.Element}>, +) { + const {loadedSnippet} = getEditorSyncAdapter()!; + + const render = () => { + loadedSnippet(); + return true; + }; + + return ( + {render() && props.children} + ); +} diff --git a/apps/codeimage/src/components/PropertyEditor/WindowStyleForm.tsx b/apps/codeimage/src/components/PropertyEditor/WindowStyleForm.tsx index f131386ed..27147d214 100644 --- a/apps/codeimage/src/components/PropertyEditor/WindowStyleForm.tsx +++ b/apps/codeimage/src/components/PropertyEditor/WindowStyleForm.tsx @@ -1,13 +1,17 @@ import {useI18n} from '@codeimage/locale'; import {getTerminalState} from '@codeimage/store/editor/terminal'; -import {SegmentedField, Select} from '@codeimage/ui'; +import {Box, Group, RadioBlock, SegmentedField, Select} from '@codeimage/ui'; import {shadowsLabel, TERMINAL_SHADOWS} from '@core/configuration/shadow'; +import {AVAILABLE_TERMINAL_THEMES} from '@core/configuration/terminal-themes'; import {useModality} from '@core/hooks/isMobile'; -import {createMemo, ParentComponent, Show} from 'solid-js'; +import {SkeletonLine} from '@ui/Skeleton/Skeleton'; +import {createMemo, For, ParentComponent, Show} from 'solid-js'; import {AppLocaleEntries} from '../../i18n'; import {TerminalControlField} from '../TerminalControlField/TerminalControlField'; +import {TerminalControlSkeleton} from '../TerminalControlField/TerminalControlFieldSkeleton'; import {PanelHeader} from './PanelHeader'; import {FullWidthPanelRow, PanelRow, TwoColumnPanelRow} from './PanelRow'; +import {SuspenseEditorItem} from './SuspenseEditorItemt'; export const WindowStyleForm: ParentComponent = () => { const terminal = getTerminalState(); @@ -20,40 +24,67 @@ export const WindowStyleForm: ParentComponent = () => { - + } + > + + - + } + > + + - + { + const terminalThemes = AVAILABLE_TERMINAL_THEMES; + return ( + + + {() => ( + + + + + + )} + + + ); + }} + > + + @@ -78,44 +109,56 @@ export const WindowStyleForm: ParentComponent = () => { - + } + > + + - + } + > + + - { + const shadowSelected = value ?? TERMINAL_SHADOWS.bottom; + umami.trackEvent(shadowSelected, 'change-shadow'); + terminal.setShadow(shadowSelected); + }} + /> + diff --git a/apps/codeimage/src/components/ThemeSwitcher/ThemeBoxSkeleton.tsx b/apps/codeimage/src/components/ThemeSwitcher/ThemeBoxSkeleton.tsx index 7d7fc1d7a..24a33f731 100644 --- a/apps/codeimage/src/components/ThemeSwitcher/ThemeBoxSkeleton.tsx +++ b/apps/codeimage/src/components/ThemeSwitcher/ThemeBoxSkeleton.tsx @@ -6,13 +6,13 @@ export function ThemeBoxSkeleton() { return (
- + - + - + - +
); diff --git a/apps/codeimage/src/components/ThemeSwitcher/ThemeSwitcher.tsx b/apps/codeimage/src/components/ThemeSwitcher/ThemeSwitcher.tsx index 13a81485b..711e11b50 100644 --- a/apps/codeimage/src/components/ThemeSwitcher/ThemeSwitcher.tsx +++ b/apps/codeimage/src/components/ThemeSwitcher/ThemeSwitcher.tsx @@ -1,8 +1,8 @@ import {CustomTheme} from '@codeimage/highlight'; import {useI18n} from '@codeimage/locale'; import {getRootEditorStore} from '@codeimage/store/editor'; -import {dispatchUpdateTheme} from '@codeimage/store/effects/onThemeChange'; import {getTerminalState} from '@codeimage/store/editor/terminal'; +import {dispatchUpdateTheme} from '@codeimage/store/effects/onThemeChange'; import {getThemeStore} from '@codeimage/store/theme/theme.store'; import {useFilteredThemes} from '@codeimage/store/theme/useFilteredThemes'; import {Box, FlexField, TextField} from '@codeimage/ui'; @@ -15,12 +15,12 @@ import { lazy, ParentComponent, Show, - Suspense, SuspenseList, } from 'solid-js'; import {AppLocaleEntries} from '../../i18n'; import {CheckCircle} from '../Icons/CheckCircle'; import {EmptyCircle} from '../Icons/EmptyCircle'; +import {SuspenseEditorItem} from '../PropertyEditor/SuspenseEditorItemt'; import {TerminalHost} from '../Terminal/TerminalHost'; import {ThemeBox} from './ThemeBox'; import {ThemeBoxSkeleton} from './ThemeBoxSkeleton'; @@ -77,7 +77,7 @@ export const ThemeSwitcher: ParentComponent = props => { {theme => { return ( - }> + }> {theme => ( @@ -106,8 +106,8 @@ export const ThemeSwitcher: ParentComponent = props => { > @@ -135,7 +135,7 @@ export const ThemeSwitcher: ParentComponent = props => { )} - + ); }} diff --git a/apps/codeimage/src/components/Toolbar/ToolbarSnippetName.tsx b/apps/codeimage/src/components/Toolbar/ToolbarSnippetName.tsx index b8fd5f7a9..143bc4e45 100644 --- a/apps/codeimage/src/components/Toolbar/ToolbarSnippetName.tsx +++ b/apps/codeimage/src/components/Toolbar/ToolbarSnippetName.tsx @@ -9,10 +9,12 @@ import { TextField, } from '@codeimage/ui'; import clickOutside from '@core/directives/clickOutside'; +import {SkeletonLine} from '@ui/Skeleton/Skeleton'; import {createEffect, createSignal, on, onMount, Show, untrack} from 'solid-js'; import {API} from '../../data-access/api'; import {useHotkey} from '../../hooks/use-hotkey'; import {PencilAlt} from '../Icons/Pencil'; +import {SuspenseEditorItem} from '../PropertyEditor/SuspenseEditorItemt'; import * as styles from './Toolbar.css'; void clickOutside; @@ -49,70 +51,74 @@ export function ToolbarSnippetName() { } return ( - - {value() ?? 'Untitled'}} - > + } + > + - - - {value() ?? 'Untitled'} - - - - } - when={editing()} + when={!readOnly()} + fallback={{value() ?? 'Untitled'}} > -
{ - setEditing(false); - updateSnippetName(value()); - }} + + + + {value() ?? 'Untitled'} + + + + } + when={editing()} > - {() => { - let ref: HTMLInputElement | undefined; - onMount(() => { - ref?.focus(); - ref?.select(); - useHotkey(ref!, { - Enter: () => { - setEditing(false); - updateSnippetName(value()); - }, - Escape: () => { - console.log('esc click'); - setEditing(false); - setValue(value()); - }, +
{ + setEditing(false); + updateSnippetName(value()); + }} + > + {() => { + let ref: HTMLInputElement | undefined; + onMount(() => { + ref?.focus(); + ref?.select(); + useHotkey(ref!, { + Enter: () => { + setEditing(false); + updateSnippetName(value()); + }, + Escape: () => { + console.log('esc click'); + setEditing(false); + setValue(value()); + }, + }); }); - }); - return ( - - setValue(value)} - style={{ - 'text-align': 'center', - }} - /> - - ); - }} -
+ return ( + + setValue(value)} + style={{ + 'text-align': 'center', + }} + /> + + ); + }} +
+
- -
+ + ); } diff --git a/apps/codeimage/src/index.tsx b/apps/codeimage/src/index.tsx index c9056ae0e..4d8209895 100644 --- a/apps/codeimage/src/index.tsx +++ b/apps/codeimage/src/index.tsx @@ -1,6 +1,7 @@ import {createI18nContext, I18nContext, useI18n} from '@codeimage/locale'; import {getAuth0State} from '@codeimage/store/auth/auth0'; import {getRootEditorStore} from '@codeimage/store/editor'; +import {getThemeStore} from '@codeimage/store/theme/theme.store'; import {uiStore} from '@codeimage/store/ui'; import { backgroundColorVar, @@ -26,6 +27,7 @@ import './assets/styles/app.scss'; import {SidebarPopoverHost} from './components/PropertyEditor/SidebarPopoverHost'; import {Scaffold} from './components/Scaffold/Scaffold'; import {locale} from './i18n'; +import {EditorPageSkeleton} from './pages/Editor/components/EditorSkeleton'; import {darkGrayScale} from './theme/dark-theme.css'; import './theme/dark-theme.css'; import './theme/global.css'; @@ -56,7 +58,15 @@ const Dashboard = lazyWithNoLauncher( () => import('./pages/Dashboard/Dashboard'), ); -const Editor = lazyWithNoLauncher(() => import('./pages/Editor/Editor')); +const Editor = () => { + const Page = lazyWithNoLauncher(() => import('./pages/Editor/Editor')); + getThemeStore().loadThemes(); + return ( + }> + + + ); +}; const NotFoundPage = lazyWithNoLauncher( () => import('./pages/NotFound/NotFoundPage'), @@ -74,7 +84,7 @@ export function Bootstrap() { component: () => { const state = getAuth0State(); return ( - } when={state.loggedIn()}> + } when={state.loggedIn()}> ); diff --git a/apps/codeimage/src/pages/Dashboard/components/CreateNewProjectButton/CreateNewProjectButton.tsx b/apps/codeimage/src/pages/Dashboard/components/CreateNewProjectButton/CreateNewProjectButton.tsx index b05bfbfbc..b240f6351 100644 --- a/apps/codeimage/src/pages/Dashboard/components/CreateNewProjectButton/CreateNewProjectButton.tsx +++ b/apps/codeimage/src/pages/Dashboard/components/CreateNewProjectButton/CreateNewProjectButton.tsx @@ -28,14 +28,7 @@ export function CreateNewProjectButton() { } return ( - -
- - - - - + + + + +
+ + + + + - - }> - - - + + }> + + + -