Skip to content

Commit

Permalink
Merge branch 'main' into feat-better-runtime-error-handling-99
Browse files Browse the repository at this point in the history
  • Loading branch information
saimeunt authored Mar 28, 2024
2 parents 884e69b + 6ac51cc commit 4f6cc68
Show file tree
Hide file tree
Showing 15 changed files with 296 additions and 171 deletions.
80 changes: 6 additions & 74 deletions components/Editor/EditorControls.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { useMemo, useRef, useState } from 'react'
import { useRef } from 'react'

import { RiLinksLine, RiQuestionLine, RiFileCodeLine } from '@remixicon/react'
import { RiLinksLine, RiQuestionLine } from '@remixicon/react'
import cn from 'classnames'
import { Priority, useRegisterActions } from 'kbar'
import { OnChangeValue } from 'react-select'

import examples from 'components/Editor/examples'
import { Button, Input } from 'components/ui'

import ExampleSelector from './ExampleSelector'

type SelectOption = {
value: number
label: string
Expand All @@ -17,7 +18,6 @@ type EditorControlsProps = {
isCompileDisabled: boolean
programArguments: string
areProgramArgumentsValid: boolean
exampleName: number
handleChangeExampleOption: (
option: OnChangeValue<SelectOption, false>,
) => void
Expand All @@ -31,15 +31,13 @@ const EditorControls = ({
isCompileDisabled,
programArguments,
areProgramArgumentsValid,
exampleName,
handleChangeExampleOption,
onCopyPermalink,
onCompileRun,
onProgramArgumentsUpdate,
onShowArgumentsHelper,
}: EditorControlsProps) => {
const inputRef = useRef<HTMLInputElement>(null)
const [isExampleSelectorOpen, setIsExampleSelectorOpen] = useState(false)

const actions = [
{
Expand Down Expand Up @@ -70,27 +68,7 @@ const EditorControls = ({

useRegisterActions(actions, [onCompileRun, onCopyPermalink])

const CairoNameExamples = useMemo(
() => [
'Simple',
'Variables & mutability',
'Type casting',
'Control flow',
'Functions',
'Arrays',
'Dictionaries',
'Ownership',
],
[],
)

const examplesOptions = examples.Cairo.map((example, i) => ({
value: i,
label: CairoNameExamples[i],
}))

const onExampleSelectorItemClick = (option: SelectOption) => {
setIsExampleSelectorOpen(false)
const onExampleChange = (option: SelectOption | null) => {
handleChangeExampleOption(option)
}

Expand All @@ -108,53 +86,7 @@ const EditorControls = ({
<RiLinksLine size={16} />
</Button>

<div className="relative">
<Button
onClick={() => setIsExampleSelectorOpen((prev) => !prev)}
transparent
padded={false}
tooltip="Change Cairo code example"
tooltipId="change-cairo-example"
className={`p-2 text-indigo-500 hover:text-indigo-600 focus:outline-none ${cn(
{
'bg-indigo-100': isExampleSelectorOpen,
},
)}`}
>
<RiFileCodeLine size={16} />
</Button>

{isExampleSelectorOpen && (
<ul
className="absolute left-0 bottom-0 z-20 mb-10 w-72 border-0 border-slate-200 origin-top-right overflow-hidden rounded-md bg-white shadow-lg ring-1 ring-gray-200 focus:outline-none"
tabIndex={-1}
role="listbox"
aria-labelledby="listbox-label"
aria-activedescendant="listbox-option-0"
>
<li className="p-4 border-l-2 border-white text-2xs text-gray-400 uppercase dark:text-gray-600">
Cairo Examples
</li>
{examplesOptions.map((option, idx) => (
<li
key={option.value}
className="text-gray-900 dark:text-gray-200 border-l-2 border-white cursor-pointer select-none p-4 text-sm hover:bg-gray-50 dark:hover:bg-black-50 hover:border-indigo-500"
id={`listbox-option-${idx}`}
role="option"
aria-selected={option.value === exampleName}
onKeyDown={(e) =>
e.key === 'Enter' && onExampleSelectorItemClick(option)
}
onClick={() => onExampleSelectorItemClick(option)}
>
<div className="flex flex-col">
<p>{option.label}</p>
</div>
</li>
))}
</ul>
)}
</div>
<ExampleSelector onExampleChange={onExampleChange} />
</div>

<div className="flex flex-row grow gap-x-2 items-center justify-end">
Expand Down
53 changes: 53 additions & 0 deletions components/Editor/EditorFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useContext } from 'react'

import cn from 'classnames'

import { AppUiContext } from '../../context/appUiContext'
import { CairoVMApiContext } from '../../context/cairoVMApiContext'
import KBarButton from '../KBar/Button'
import ThemeSelector from '../ThemeSelector'
import ToggleFullScreen from '../ToggleFullScreen'
import ToggleThreeColumnLayout from '../ToggleThreeColumnLayout'

function EditorFooter() {
const { cairoLangCompilerVersion } = useContext(CairoVMApiContext)
const { isFullScreen } = useContext(AppUiContext)
return (
<div
className={cn(
'px-5 bg-gray-100 dark:bg-black-700 border-t border-gray-200 dark:border-black-500 text-xs h-[42px] items-center text-gray-600 ml-auto flex justify-between',
!isFullScreen && 'rounded-b-lg',
)}
>
<span>
{cairoLangCompilerVersion !== ''
? `Cairo Compiler v${cairoLangCompilerVersion}`
: ' '}
</span>

{isFullScreen && (
<div className="flex items-center justify-end divide-x divide-gray-200 dark:divide-black-500">
<span className="pr-4">
Made with ❤️ by{' '}
<a
className="underline font-medium"
href="https://walnut.dev"
target="_blank"
rel="noreferrer"
>
Walnut
</a>
</span>
<div className="items-center flex">
<KBarButton />
<ToggleFullScreen />
<ToggleThreeColumnLayout />
<ThemeSelector />
</div>
</div>
)}
</div>
)
}

export default EditorFooter
87 changes: 87 additions & 0 deletions components/Editor/ExampleSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import React, { useId } from 'react'

import { RiFileCodeLine } from '@remixicon/react'
import cn from 'classnames'
import Select, {
components,
DropdownIndicatorProps,
StylesConfig,
GroupBase,
} from 'react-select'

import { Button } from '../ui'

import { Examples, CairoExampleNames } from './examples'

type SelectOption = {
value: number
label: string
}

type Props = {
onExampleChange: (option: SelectOption | null) => void
}

const examplesOptions = Examples.Cairo.map((_, i) => ({
value: i,
label: CairoExampleNames[i],
}))

function ExampleSelector({ onExampleChange }: Props) {
return (
<Select
onChange={onExampleChange}
options={examplesOptions}
components={{
DropdownIndicator,
}}
controlShouldRenderValue={false}
classNamePrefix="select"
styles={reactSelectStyles}
menuPlacement="top"
isSearchable={false}
instanceId={useId()}
/>
)
}

export default ExampleSelector

const reactSelectStyles: StylesConfig<
SelectOption,
false,
GroupBase<SelectOption>
> = {
// as we dont want to show value field in react-select
// and just want to show an icon, but input field takes some space
// so we hide the valueContainer with css properties
// Question: Why not remove the ValueContainer completely from 'components' prop in react-select?
// Ans: react-select needs a valuefield
// as many features like click outside to close drop down etc depends on it
// so we just add display none (it doesn't hurt)
valueContainer: (styles) => ({
...styles,
width: '0',
opacity: 0,
padding: '0 !important',
}),
}

const DropdownIndicator = (props: DropdownIndicatorProps<SelectOption>) => {
return (
<components.DropdownIndicator {...props}>
<Button
transparent
padded={false}
tooltip="Cairo Examples"
tooltipId="cairo-examples"
className={cn(
'p-2 text-indigo-500 hover:text-indigo-600 focus:outline-none',
props.selectProps.menuIsOpen ? 'bg-black-900/5 dark:bg-white/5' : '',
)}
>
<RiFileCodeLine size={16} />
</Button>
</components.DropdownIndicator>
)
}
9 changes: 2 additions & 7 deletions components/Editor/ExtraColumn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,12 @@ import Header from './Header'
import { InstructionsTable } from './InstructionsTable'

type ExtraColumnProps = {
cairoEditorHeight: number
cairoCode: string
highlightCode: (value: string, codeType: string | undefined) => string
isBytecode: boolean
}

const ExtraColumn = ({
cairoEditorHeight,
cairoCode,
highlightCode,
isBytecode,
Expand All @@ -35,17 +33,14 @@ const ExtraColumn = ({

return (
<div className="w-full md:w-1/3 flex flex-col">
<div className="border-b border-gray-200 dark:border-black-500 flex items-center pl-6 pr-2 h-14 md:border-r">
<div className="border-b border-gray-200 dark:border-black-500 flex items-center pl-6 pr-2 h-14 md:border-r flex-none">
<Header
codeType={codeType}
onCodeTypeChange={({ value }) => setCodeType(value)}
onlyDropDown
/>
</div>
<div
className="relative pane grow pane-light overflow-auto md:border-r bg-gray-50 dark:bg-black-600 border-gray-200 dark:border-black-500"
style={{ height: cairoEditorHeight }}
>
<div className="relative pane grow pane-light overflow-auto md:border-r bg-gray-50 dark:bg-black-600 border-gray-200 dark:border-black-500">
{codeType === CodeType.CASM ? (
<InstructionsTable
instructions={casmInstructions}
Expand Down
49 changes: 30 additions & 19 deletions components/Editor/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useMemo, useId } from 'react'

import Image from 'next/image'
import cairoLogo from 'public/cairo_logo.png'
import Select, { OnChangeValue } from 'react-select'

import { CodeType } from '../../context/appUiContext'
Expand All @@ -8,6 +10,7 @@ type Props = {
codeType: string | undefined
onCodeTypeChange: (option: OnChangeValue<any, any>) => void
onlyDropDown?: boolean
withLogo?: boolean
}

const codeLangOptions = Object.keys(CodeType).map((lang) => ({
Expand All @@ -19,6 +22,7 @@ const EditorHeader = ({
codeType,
onCodeTypeChange,
onlyDropDown = false,
withLogo = false,
}: Props) => {
const codeTypeValue = useMemo(
() => ({
Expand All @@ -27,28 +31,35 @@ const EditorHeader = ({
}),
[codeType],
)

return (
<div className="flex justify-between items-center w-full">
{!onlyDropDown && (
<h3 className="font-semibold text-md hidden xl:inline-flex items-center">
<span>Cairo VM Playground</span>
</h3>
)}
<>
<div className={'flex justify-between items-center w-full'}>
{!onlyDropDown &&
(withLogo ? (
<div className="flex items-center text-lg font-semibold tracking-tight text-gray-900 dark:text-white">
<span className="pr-2">cairovm</span>
<Image src={cairoLogo} width={20} height={20} alt="cairo" />
<span className="pl-2">codes</span>
</div>
) : (
<h3 className="font-semibold text-md hidden xl:inline-flex items-center">
<span>Cairo VM Playground</span>
</h3>
))}

<div className="flex items-center justify-between w-full xl:w-auto z-20">
<Select
onChange={onCodeTypeChange}
options={codeLangOptions}
value={codeTypeValue}
isSearchable={false}
classNamePrefix="select"
menuPlacement="auto"
instanceId={useId()}
/>
<div className="flex items-center ">
<Select
onChange={onCodeTypeChange}
options={codeLangOptions}
value={codeTypeValue}
isSearchable={false}
classNamePrefix="select"
menuPlacement="auto"
instanceId={useId()}
/>
</div>
</div>
</div>
</>
)
}

export default EditorHeader
Loading

0 comments on commit 4f6cc68

Please sign in to comment.