diff --git a/packages/mini-editor/src/editor-frame.tsx b/packages/mini-editor/src/editor-frame.tsx index ac817e28..464ddfdc 100644 --- a/packages/mini-editor/src/editor-frame.tsx +++ b/packages/mini-editor/src/editor-frame.tsx @@ -1,8 +1,5 @@ import React from "react" -import { - MiniFrame, - FrameButtons, -} from "@code-hike/mini-frame" +import { FrameButtons } from "@code-hike/mini-frame" import { useClasser, Classes } from "@code-hike/classer" import { EditorTheme } from "@code-hike/smooth-code/dist/themes" import { getColor, ColorName } from "./theme-colors" @@ -58,20 +55,21 @@ export const EditorFrame = React.forwardRef< ref ) { const c = useClasser("ch-editor") + return ( - +
- } - {...rest} - > +
{southPanel && ( -
+ <>
-
+ )} - {terminalPanel} - +
) }) diff --git a/packages/mini-editor/src/editor-shift.tsx b/packages/mini-editor/src/editor-shift.tsx index a8625b7e..f7254c45 100644 --- a/packages/mini-editor/src/editor-shift.tsx +++ b/packages/mini-editor/src/editor-shift.tsx @@ -61,20 +61,25 @@ export function useTransition( backward: boolean, codeConfig: CodeConfig ): Transition { + // prevSnapshot has the dimensions of the editor for t=0 + // nextSnapshot has the dimensions of the editor for t=1 const { prevSnapshot, nextSnapshot } = useSnapshots( ref, prev, next ) + // we return the default styles for t=0 until we measure the dimensions if (!prevSnapshot) { return startingPosition(prev, next, codeConfig) } + // and the same for t=1 if (!nextSnapshot) { return endingPosition(prev, next, codeConfig) } + // TODO this should be commented // if (t === 0) { // return startingPosition(prev, next, codeConfig) // } @@ -114,7 +119,10 @@ export function useTransition( prevFile={prevNorthFile} nextFile={nextNorthFile} t={t} - parentHeight={northStyle.height as string} + parentHeight={ + (northStyle.height || + northStyle.minHeight) as string + } /> ), }, @@ -127,7 +135,10 @@ export function useTransition( prevFile={prevSouthFile!} nextFile={nextSouthFile!} t={t} - parentHeight={southStyle?.height as string} + parentHeight={ + (southStyle?.height || + southStyle?.minHeight) as string + } /> ), }, @@ -150,12 +161,6 @@ function startingPosition( nextSouthFile, } = getStepFiles(prev, next, true) - const northHeight = inputSouthPanel - ? `calc((100% - var(--ch-title-bar-height)) * ${inputNorthPanel.heightRatio})` - : "100%" - - const southHeight = `calc((100% - var(--ch-title-bar-height)) * ${inputSouthPanel?.heightRatio} + var(--ch-title-bar-height))` - return { northPanel: { tabs: inputNorthPanel.tabs.map(title => ({ @@ -164,15 +169,16 @@ function startingPosition( style: {}, })), style: { - height: northHeight, + flexGrow: 1, + overflow: "hidden", }, children: ( ), }, @@ -183,15 +189,16 @@ function startingPosition( style: {}, })), style: { - height: `calc((100% - var(--ch-title-bar-height)) * ${inputSouthPanel.heightRatio} + var(--ch-title-bar-height))`, + flexGrow: 1, + overflow: "hidden", }, children: ( ), }, @@ -221,12 +228,6 @@ function endingPosition( nextNorthFile = nextSouthFile! } - const northHeight = inputSouthPanel - ? `calc((100% - var(--ch-title-bar-height)) * ${inputNorthPanel.heightRatio})` - : "100%" - - const southHeight = `calc((100% - var(--ch-title-bar-height)) * ${inputSouthPanel?.heightRatio} + var(--ch-title-bar-height))` - return { northPanel: { tabs: inputNorthPanel.tabs.map(title => ({ @@ -235,15 +236,16 @@ function endingPosition( style: {}, })), style: { - height: northHeight, + flexGrow: 1, + overflow: "hidden", }, children: ( ), }, @@ -254,15 +256,16 @@ function endingPosition( style: {}, })), style: { - height: southHeight, + flexGrow: 1, + overflow: "hidden", }, children: ( ), }, @@ -285,7 +288,7 @@ function CodeTransition({ const htmlProps = { ...codeConfig?.htmlProps, style: { - height: "unset", + height: "100%", ...codeConfig?.htmlProps?.style, }, } @@ -403,7 +406,7 @@ function getPanelStyles( ) { return { northStyle: { - height: prev.northHeight, + minHeight: prev.northHeight, }, } } @@ -420,14 +423,14 @@ function getPanelStyles( ) { return { northStyle: { - height: tween( + minHeight: tween( prev.northHeight, next.northHeight, t ), }, southStyle: { - height: prev.southHeight, + minHeight: prev.southHeight, }, } } @@ -444,13 +447,13 @@ function getPanelStyles( ) { return { northStyle: { - height: prev.northHeight, + minHeight: prev.northHeight, }, southStyle: { position: "relative", - height: tween( + minHeight: tween( prev.southHeight, - next.northHeight + next.titleBarHeight, + next.northHeight, t ), transform: `translateY(${tween( @@ -474,7 +477,7 @@ function getPanelStyles( ) { return { northStyle: { - height: tween( + minHeight: tween( prev.northHeight, next.northHeight, t @@ -482,7 +485,7 @@ function getPanelStyles( }, southStyle: { position: "relative", - height: next.southHeight!, + minHeight: next.southHeight!, }, } } @@ -499,12 +502,12 @@ function getPanelStyles( ) { return { northStyle: { - height: next.northHeight, + minHeight: next.northHeight, }, southStyle: { position: "relative", - height: tween( - prev.northHeight + prev.titleBarHeight, + minHeight: tween( + prev.northHeight, next.southHeight!, t ), @@ -524,10 +527,14 @@ function getPanelStyles( // +---+---+ return { northStyle: { - height: tween(prev.northHeight, next.northHeight, t), + minHeight: tween( + prev.northHeight, + next.northHeight, + t + ), }, southStyle: { - height: tween( + minHeight: tween( prev.southHeight!, next.southHeight!, t @@ -775,6 +782,7 @@ function useSnapshots( useLayoutEffect(() => { if (!prevSnapshot) { + // debugger setState(s => ({ ...s, prevSnapshot: { @@ -783,6 +791,7 @@ function useSnapshots( }, })) } else if (!nextSnapshot) { + // debugger setState(s => ({ ...s, nextSnapshot: { diff --git a/packages/mini-editor/src/editor-tween.tsx b/packages/mini-editor/src/editor-tween.tsx index bfa1c29e..71e9e31a 100644 --- a/packages/mini-editor/src/editor-tween.tsx +++ b/packages/mini-editor/src/editor-tween.tsx @@ -14,6 +14,11 @@ export { EditorTweenProps, } +const useLayoutEffect = + typeof window !== "undefined" + ? React.useLayoutEffect + : React.useEffect + type EditorTransitionProps = { prev?: EditorStep next?: EditorStep @@ -65,17 +70,30 @@ function EditorTween({ codeConfig ) - const defaultHeight = useDefaultHeight(prev) + const [frozenHeight, freezeHeight] = React.useState< + number | undefined + >(undefined) + + useLayoutEffect(() => { + const height = ref.current?.getBoundingClientRect() + .height + freezeHeight(height) + }, []) + const framePropsWithHeight = { ...frameProps, ...divProps, style: { - height: defaultHeight, ...frameProps?.style, ...divProps?.style, }, } + if (frozenHeight) { + framePropsWithHeight.style.height = frozenHeight + framePropsWithHeight.style.maxHeight = frozenHeight + } + const terminalPanel = ( ) } - -function useDefaultHeight({ - files, - northPanel, - southPanel, -}: EditorStep): string { - return React.useMemo(() => { - const northFile = files.find( - ({ name }) => name === northPanel.active - ) - const southFile = files.find( - ({ name }) => name === southPanel?.active - ) - let focusedLines = getFocusedLineCount(northFile!) + 3.9 - if (southFile) { - focusedLines += getFocusedLineCount(southFile!) + 3.9 - } - const emHeight = focusedLines * 1.5 - return `${emHeight}em` - }, []) -} - -function getFocusedLineCount({ - code, - focus, -}: EditorStep["files"][0]): number { - return code.lines.length -} diff --git a/packages/mini-editor/src/index.scss b/packages/mini-editor/src/index.scss index 0b387d58..130d42eb 100644 --- a/packages/mini-editor/src/index.scss +++ b/packages/mini-editor/src/index.scss @@ -40,36 +40,16 @@ } .ch-editor-frame { - --ch-content-background: rgb(37, 37, 38); -} - -/** body */ - -.ch-editor-body { - // background-color: rgb(30, 30, 30); - // color: #cccccc; - // font-size: 15px; - // padding: 5px 10px; - // line-height: 1.1rem; - box-sizing: border-box; + display: flex; + flex-direction: column; position: relative; + overflow: hidden; } -.ch-editor-body pre { - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - // padding: 0 16px; - margin: 0; - overflow: auto; +.ch-editor-frame .ch-frame-title-bar { + background: none; } -// .ch-editor-body code { -// line-height: 1.2rem; -// } - /** terminal */ .ch-editor-terminal { diff --git a/packages/playground/content/scrollycoding.mdx b/packages/playground/content/scrollycoding.mdx index d5f0182c..40bb91a5 100644 --- a/packages/playground/content/scrollycoding.mdx +++ b/packages/playground/content/scrollycoding.mdx @@ -1,5 +1,3 @@ -import { CH } from "@code-hike/mdx" - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. diff --git a/packages/playground/content/simple-code.mdx b/packages/playground/content/simple-code.mdx index 867cb49f..78cfc2d1 100644 --- a/packages/playground/content/simple-code.mdx +++ b/packages/playground/content/simple-code.mdx @@ -1,5 +1,3 @@ -import { CH } from "@code-hike/mdx" - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ```js diff --git a/packages/playground/content/spotlight-demo.mdx b/packages/playground/content/spotlight-demo.mdx index d783d969..c4943882 100644 --- a/packages/playground/content/spotlight-demo.mdx +++ b/packages/playground/content/spotlight-demo.mdx @@ -4,8 +4,6 @@ This is how to use the `` component. Lorem ipsum dolor sit amet co - - ```js app.js function lorem(ipsum, dolor = 1) { const sit = ipsum == null && 0 @@ -14,14 +12,6 @@ function lorem(ipsum, dolor = 1) { } ``` -```css styles.css -.lorem { - color: red; -} -``` - - - --- Change focus @@ -53,13 +43,7 @@ Or change the file -```js app.js focus=6:10 -function lorem(ipsum, dolor = 1) { - const sit = ipsum == null && 0 - dolor = sit - amet(dolor) - return sit ? consectetur(ipsum) : [] -} - +```js app.js focus=1:4 function adipiscing(...elit) { console.log(elit) return elit.map(ipsum => ipsum.sit) diff --git a/packages/storybook/src/editor-spring.story.js b/packages/storybook/src/editor-spring.story.js index ead0577e..fec03735 100644 --- a/packages/storybook/src/editor-spring.story.js +++ b/packages/storybook/src/editor-spring.story.js @@ -135,21 +135,24 @@ function SingleEditor({ }).then(code => setCode(code)) }, [inputCode]) - const step = { - files: [ - { - name: "index.js", - code, - focus, - annotations, + const step = React.useMemo( + () => ({ + files: [ + { + name: "index.js", + code, + focus, + annotations, + }, + ], + northPanel: { + tabs: ["index.js"], + active: "index.js", + heightRatio: 1, }, - ], - northPanel: { - tabs: ["index.js"], - active: "index.js", - heightRatio: 1, - }, - } + }), + [code, focus] + ) return code ? ( diff --git a/packages/storybook/src/editor-tween-two.story.js b/packages/storybook/src/editor-tween-two.story.js new file mode 100644 index 00000000..f08fcc54 --- /dev/null +++ b/packages/storybook/src/editor-tween-two.story.js @@ -0,0 +1,129 @@ +import React from "react" +import { EditorTween } from "@code-hike/mini-editor" +import { WithProgress } from "./utils" +import "@code-hike/mini-editor/dist/index.css" +import theme from "shiki/themes/github-light.json" +import { highlight } from "@code-hike/highlighter" + +export default { + title: "Test/Editor Tween Two", +} + +export const smartHeight = () => { + const prev = { + files: [ + { + name: "app.js", + code: ` +function lorem(ipsum, dolor = 1) { + const sit = ipsum == null && 0 + dolor = sit - amet(dolor) + return sit ? consectetur(ipsum) : [] +} + +function adipiscing(...elit) { + console.log(elit) + return elit.map(ipsum => ipsum.sit) +}`.trim(), + lang: "js", + focus: "6:10", + annotations: [], + }, + ], + northPanel: { + tabs: ["app.js"], + active: "app.js", + heightRatio: 1, + }, + southPanel: undefined, + } + const next = { + files: [ + { + name: "app.js", + code: ` +function adipiscing(...elit) { + console.log(elit) + return elit.map(ipsum => ipsum.sit) +}`.trim(), + lang: "js", + focus: "1:4", + annotations: [], + }, + { + name: "styles.css", + code: ` +.lorem { + color: #fff; + padding: 10px; + background: #000; +}`.trim(), + lang: "css", + focus: "", + annotations: [], + }, + ], + northPanel: { + tabs: ["app.js"], + active: "app.js", + heightRatio: 1, + }, + southPanel: { + tabs: ["styles.css"], + active: "styles.css", + heightRatio: 1, + }, + } + return +} + +function TestTransition({ prev, next }) { + const [data, setData] = React.useState(null) + React.useEffect(() => { + const prevFilePromises = prev.files.map( + ({ code, lang, ...rest }) => + highlight({ code, lang, theme }).then(code => ({ + code, + ...rest, + })) + ) + const nextFilePromises = next.files.map( + ({ code, lang, ...rest }) => + highlight({ code, lang, theme }).then(code => ({ + code, + ...rest, + })) + ) + + Promise.all([ + Promise.all(prevFilePromises), + Promise.all(nextFilePromises), + ]).then(([prevFiles, nextFiles]) => + setData({ + prev: { ...prev, files: prevFiles }, + next: { ...next, files: nextFiles }, + }) + ) + }, []) + + if (!data) { + return "Loading..." + } + + return ( + + {(progress, backward) => ( + <> + + + )} + + ) +}