@code-hike/mini-editor
Advanced tools
Comparing version 0.2.1 to 0.3.0--canary.32.323f72f.0
import React from "react"; | ||
import "./editor-frame.css"; | ||
import { Classes } from "@code-hike/classer"; | ||
import "./index.scss"; | ||
export { EditorFrame, TerminalPanel }; | ||
@@ -7,5 +8,8 @@ declare type EditorFrameProps = { | ||
active: string; | ||
height?: number; | ||
terminalPanel: React.ReactNode; | ||
button?: React.ReactNode; | ||
classes?: Classes; | ||
} & React.PropsWithoutRef<JSX.IntrinsicElements["div"]>; | ||
declare function EditorFrame({ files, active, children, terminalPanel, ...rest }: EditorFrameProps): JSX.Element; | ||
declare function EditorFrame({ files, active, children, terminalPanel, height, style, button, classes, ...rest }: EditorFrameProps): JSX.Element; | ||
declare type TerminalPanelProps = { | ||
@@ -15,2 +19,2 @@ height?: number; | ||
}; | ||
declare function TerminalPanel({ height, children }: TerminalPanelProps): JSX.Element | null; | ||
declare function TerminalPanel({ height, children, }: TerminalPanelProps): JSX.Element | null; |
@@ -5,10 +5,14 @@ 'use strict'; | ||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } | ||
var React = _interopDefault(require('react')); | ||
var React = require('react'); | ||
var miniFrame = require('@code-hike/mini-frame'); | ||
var standalone = require('@code-surfer/standalone'); | ||
var themes = require('@code-surfer/themes'); | ||
var classer = require('@code-hike/classer'); | ||
var miniTerminal = require('@code-hike/mini-terminal'); | ||
var codeDiff = require('@code-hike/code-diff'); | ||
var smoothLines = require('@code-hike/smooth-lines'); | ||
var useSpring = require('use-spring'); | ||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
var React__default = /*#__PURE__*/_interopDefaultLegacy(React); | ||
/*! ***************************************************************************** | ||
@@ -28,3 +32,17 @@ Copyright (c) Microsoft Corporation. | ||
***************************************************************************** */ | ||
/* global Reflect, Promise */ | ||
var extendStatics = function(d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
function __extends(d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
} | ||
var __assign = function() { | ||
@@ -76,31 +94,445 @@ __assign = Object.assign || function __assign(t) { | ||
var e=[],t=[];function injector_1a6c3c54(n,r){if(n&&"undefined"!=typeof document){void 0===r&&(r={});var d,a=!0===r.prepend?"prepend":"append",i="undefined"!=typeof r.singleTag&&r.singleTag,s="undefined"!=typeof r.container?document.querySelector(r.container):document.getElementsByTagName("head")[0];if(i){var u=e.indexOf(s);-1===u&&(u=e.push(s)-1,t[u]={}),d=t[u]&&t[u][a]?t[u][a]:t[u][a]=o();}else d=o();65279===n.charCodeAt(0)&&(n=n.substring(1)),d.styleSheet?d.styleSheet.cssText+=n:d.appendChild(document.createTextNode(n));}function o(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),r.attributes)for(var t=Object.keys(r.attributes),n=0;n<t.length;n++)e.setAttribute(t[n],r.attributes[t[n]]);var d="prepend"===a?"afterbegin":"beforeend";return s.insertAdjacentElement(d,e),e}} | ||
const css_f2c17fbd = ".ch-editor-tab{border-right:1px solid #252526;width:120px;min-width:-webkit-fit-content;min-width:-moz-fit-content;min-width:fit-content;flex-shrink:0;position:relative;display:flex;white-space:nowrap;cursor:pointer;height:100%;box-sizing:border-box;padding-left:15px;padding-right:15px;background-color:#2d2d2d;color:hsla(0,0%,100%,.5)}.ch-editor-tab[data-active]{background-color:#1e1e1e;color:#fff}.ch-editor-tab>div{margin-top:auto;margin-bottom:auto;font-size:12px;line-height:1.4em;text-overflow:ellipsis}.ch-editor-body{background-color:#1e1e1e;height:100%;color:#ccc;font-size:15px;padding:5px 10px;line-height:1.1rem;box-sizing:border-box}.ch-editor-body code{line-height:20px}.ch-editor-terminal{position:absolute;overflow:hidden;bottom:0;width:100%;background-color:#1e1e1e;color:#e7e7e7;border-top:1px solid hsla(0,0%,50.2%,.35);padding:0 8px;box-sizing:border-box}.ch-editor-terminal-tab{text-transform:uppercase;padding:4px 10px 3px;font-size:11px;line-height:24px;display:flex}.ch-editor-terminal-tab>span{border-bottom:1px solid #e7e7e7}.ch-editor-terminal-content{margin-top:8px;height:calc(100% - 40px);box-sizing:border-box}.ch-editor-terminal-content .ch-terminal{font-size:12px;margin:0}"; | ||
injector_1a6c3c54(css_f2c17fbd,{"singleTag":true}); | ||
var DEFAULT_HEIGHT = 200; | ||
function EditorFrame(_a) { | ||
var files = _a.files, active = _a.active, children = _a.children, terminalPanel = _a.terminalPanel, rest = __rest(_a, ["files", "active", "children", "terminalPanel"]); | ||
return (React.createElement(miniFrame.MiniFrame, __assign({ titleBar: React.createElement(TabsContainer, { files: files, active: active }) }, rest), | ||
React.createElement("div", { className: "ch-editor-body" }, children), | ||
var files = _a.files, active = _a.active, children = _a.children, terminalPanel = _a.terminalPanel, height = _a.height, style = _a.style, button = _a.button, classes = _a.classes, rest = __rest(_a, ["files", "active", "children", "terminalPanel", "height", "style", "button", "classes"]); | ||
var c = classer.useClasser("ch-editor"); | ||
return (React__default['default'].createElement(miniFrame.MiniFrame, __assign({ titleBar: React__default['default'].createElement(TabsContainer, { files: files, active: active, button: button, classes: classes }), classes: classes, style: __assign({ height: height !== null && height !== void 0 ? height : DEFAULT_HEIGHT }, style) }, rest), | ||
React__default['default'].createElement("div", { className: c("body") }, children), | ||
terminalPanel)); | ||
} | ||
function TabsContainer(_a) { | ||
var files = _a.files, active = _a.active; | ||
return (React.createElement(React.Fragment, null, | ||
React.createElement(miniFrame.FrameButtons, null), | ||
files.map(function (fileName) { return (React.createElement("div", { key: fileName, className: "ch-editor-tab", "data-active": fileName === active || undefined }, | ||
React.createElement("div", null, fileName))); }), | ||
React.createElement("div", { style: { flex: 1 } }))); | ||
var files = _a.files, active = _a.active, button = _a.button, classes = _a.classes; | ||
var c = classer.useClasser("ch-editor-tab"); | ||
return (React__default['default'].createElement(React__default['default'].Fragment, null, | ||
React__default['default'].createElement(miniFrame.FrameButtons, null), | ||
files.map(function (fileName) { return (React__default['default'].createElement("div", { key: fileName, className: c("", fileName === active ? "active" : "inactive") }, | ||
React__default['default'].createElement("div", null, fileName))); }), | ||
React__default['default'].createElement("div", { style: { flex: 1 } }), | ||
button)); | ||
} | ||
function TerminalPanel(_a) { | ||
var height = _a.height, children = _a.children; | ||
return !height ? null : (React.createElement("div", { className: "ch-editor-terminal", style: { height: height } }, | ||
React.createElement("div", { className: "ch-editor-terminal-tab" }, | ||
React.createElement("span", null, "Terminal")), | ||
React.createElement("div", { className: "ch-editor-terminal-content" }, children))); | ||
return !height ? null : (React__default['default'].createElement("div", { className: "ch-editor-terminal", style: { height: height } }, | ||
React__default['default'].createElement("div", { className: "ch-editor-terminal-tab" }, | ||
React__default['default'].createElement("span", null, "Terminal")), | ||
React__default['default'].createElement("div", { className: "ch-editor-terminal-content" }, children))); | ||
} | ||
function MiniEditor(_a) { | ||
var _b = _a.progress, progress = _b === void 0 ? 0 : _b, _c = _a.backward, backward = _c === void 0 ? false : _c, code = _a.code, focus = _a.focus, lang = _a.lang, file = _a.file, ogSteps = _a.steps, rest = __rest(_a, ["progress", "backward", "code", "focus", "lang", "file", "steps"]); | ||
var useLayoutEffect = typeof window !== "undefined" | ||
? React__default['default'].useLayoutEffect | ||
: React__default['default'].useEffect; | ||
var DEFAULT_WIDTH = 200; | ||
function useDimensions(deps) { | ||
var ref = React__default['default'].useRef(null); | ||
var _a = __read(React__default['default'].useState(null), 2), dimensions = _a[0], setDimensions = _a[1]; | ||
var windowWidth = useWindowWidth(); | ||
var fullDeps = __spread(deps, [windowWidth]); | ||
useLayoutEffect(function () { | ||
var _a, _b, _c, _d, _e, _f, _g, _h; | ||
if (ref.current) { | ||
var rect = ref.current.getBoundingClientRect(); | ||
var pll = ref.current.querySelector(".prev-longest-line"); | ||
var nll = ref.current.querySelector(".next-longest-line"); | ||
// TODO is it clientWidth or clientRect? | ||
var plw = (_a = pll === null || pll === void 0 ? void 0 : pll.firstElementChild) === null || _a === void 0 ? void 0 : _a.clientWidth; | ||
var nlw = (_b = nll === null || nll === void 0 ? void 0 : nll.firstElementChild) === null || _b === void 0 ? void 0 : _b.clientWidth; | ||
var plh = (_d = (_c = pll === null || pll === void 0 ? void 0 : pll.firstElementChild) === null || _c === void 0 ? void 0 : _c.clientHeight) !== null && _d !== void 0 ? _d : 20; | ||
var nlh = (_f = (_e = nll === null || nll === void 0 ? void 0 : nll.firstElementChild) === null || _e === void 0 ? void 0 : _e.clientHeight) !== null && _f !== void 0 ? _f : 20; | ||
var colWidth = pll | ||
? plw / (((_g = pll.textContent) === null || _g === void 0 ? void 0 : _g.length) || 1) | ||
: nlw / (((_h = nll.textContent) === null || _h === void 0 ? void 0 : _h.length) || 1); | ||
setDimensions({ | ||
width: rect.width, | ||
height: rect.height, | ||
lineWidths: [ | ||
plw || nlw || DEFAULT_WIDTH, | ||
nlw || plw || DEFAULT_WIDTH, | ||
], | ||
lineHeight: Math.max(plh, nlh), | ||
colWidth: colWidth, | ||
deps: fullDeps, | ||
}); | ||
} | ||
}, fullDeps); | ||
if (!dimensions || | ||
depsChanged(dimensions.deps, fullDeps)) { | ||
return [ref, null]; | ||
} | ||
else { | ||
return [ref, dimensions]; | ||
} | ||
} | ||
function depsChanged(oldDeps, newDeps) { | ||
for (var i = 0; i < oldDeps.length; i++) { | ||
if (oldDeps[i] !== newDeps[i]) | ||
return true; | ||
} | ||
return false; | ||
} | ||
function useWindowWidth() { | ||
var _a = __read(React__default['default'].useState(undefined), 2), width = _a[0], setWidth = _a[1]; | ||
React__default['default'].useEffect(function () { | ||
function handleResize() { | ||
setWidth(window.innerWidth); | ||
} | ||
window.addEventListener("resize", handleResize); | ||
return function () { | ||
return window.removeEventListener("resize", handleResize); | ||
}; | ||
}, []); | ||
return width; | ||
} | ||
function getFocusIndexes(focus, lines) { | ||
if (!focus) { | ||
return __spread(lines.keys()); | ||
} | ||
else { | ||
var parsed = parseFocus(focus); | ||
var focusedIndexes = Object.keys(parsed).map(function (i) { | ||
return parseInt(i, 10); | ||
}); | ||
return focusedIndexes; | ||
} | ||
} | ||
function getFocusByKey(focus, keys) { | ||
if (!focus) { | ||
// focus all lines | ||
return fromEntries(keys.map(function (key) { return [key, true]; })); | ||
} | ||
else { | ||
var parsed_1 = parseFocus(focus); | ||
var byKey_1 = {}; | ||
Object.keys(parsed_1).forEach(function (i) { | ||
var key = keys[parseInt(i, 10)]; | ||
byKey_1[key] = parsed_1[parseInt(i, 10)]; | ||
}); | ||
return byKey_1; | ||
} | ||
} | ||
function parseFocus(focus) { | ||
if (!focus) { | ||
throw new Error("Focus cannot be empty"); | ||
} | ||
try { | ||
var parts = focus | ||
.split(/,(?![^\[]*\])/g) | ||
.map(parsePart); | ||
return fromEntries(parts.flat()); | ||
} | ||
catch (error) { | ||
// TODO enhance error | ||
throw error; | ||
} | ||
} | ||
function parsePart(part) { | ||
// a part could be | ||
// - a line number: "2" | ||
// - a line range: "5:9" | ||
// - a line number with a column selector: "2[1,3:5,9]" | ||
var columnsMatch = part.match(/(\d+)\[(.+)\]/); | ||
if (columnsMatch) { | ||
var _a = __read(columnsMatch, 3), line = _a[1], columns = _a[2]; | ||
var columnsList = columns.split(",").map(expandString); | ||
var lineIndex = Number(line) - 1; | ||
var columnIndexes = columnsList.flat().map(function (c) { return c - 1; }); | ||
return [[lineIndex, columnIndexes]]; | ||
} | ||
else { | ||
return expandString(part).map(function (lineNumber) { return [ | ||
lineNumber - 1, | ||
true, | ||
]; }); | ||
} | ||
} | ||
function expandString(part) { | ||
// Transforms something like | ||
// - "1:3" to [1,2,3] | ||
// - "4" to [4] | ||
var _a = __read(part.split(":"), 2), start = _a[0], end = _a[1]; | ||
if (!isNaturalNumber(start)) { | ||
throw new FocusNumberError(start); | ||
} | ||
var startNumber = Number(start); | ||
if (startNumber < 1) { | ||
throw new LineOrColumnNumberError(); | ||
} | ||
if (!end) { | ||
return [startNumber]; | ||
} | ||
else { | ||
if (!isNaturalNumber(end)) { | ||
throw new FocusNumberError(end); | ||
} | ||
var list = []; | ||
for (var i = startNumber; i <= +end; i++) { | ||
list.push(i); | ||
} | ||
return list; | ||
} | ||
} | ||
function isNaturalNumber(n) { | ||
n = n.toString(); // force the value in case it is not | ||
var n1 = Math.abs(n), n2 = parseInt(n, 10); | ||
return !isNaN(n1) && n2 === n1 && n1.toString() === n; | ||
} | ||
var LineOrColumnNumberError = /** @class */ (function (_super) { | ||
__extends(LineOrColumnNumberError, _super); | ||
function LineOrColumnNumberError() { | ||
var _newTarget = this.constructor; | ||
var _this = _super.call(this, "Invalid line or column number in focus string") || this; | ||
Object.setPrototypeOf(_this, _newTarget.prototype); | ||
return _this; | ||
} | ||
return LineOrColumnNumberError; | ||
}(Error)); | ||
var FocusNumberError = /** @class */ (function (_super) { | ||
__extends(FocusNumberError, _super); | ||
function FocusNumberError(number) { | ||
var _newTarget = this.constructor; | ||
var _this = _super.call(this, "Invalid number \"" + number + "\" in focus string") || this; | ||
_this.number = number; | ||
Object.setPrototypeOf(_this, _newTarget.prototype); | ||
return _this; | ||
} | ||
return FocusNumberError; | ||
}(Error)); | ||
function fromEntries(pairs) { | ||
var result = {}; | ||
var index = -1, length = pairs == null ? 0 : pairs.length; | ||
while (++index < length) { | ||
var pair = pairs[index]; | ||
result[pair[0]] = pair[1]; | ||
} | ||
return result; | ||
} | ||
function Code(_a) { | ||
var prevCode = _a.prevCode, prevFocus = _a.prevFocus, nextCode = _a.nextCode, nextFocus = _a.nextFocus, progress = _a.progress, language = _a.language, parentHeight = _a.parentHeight, minColumns = _a.minColumns; | ||
var _b = useLineProps(prevCode, nextCode, language, prevFocus, nextFocus), prevLines = _b.prevLines, nextLines = _b.nextLines, prevFocusIndexes = _b.prevFocusIndexes, nextFocusIndexes = _b.nextFocusIndexes, prevLongestLine = _b.prevLongestLine, nextLongestLine = _b.nextLongestLine; | ||
var _c = __read(useDimensions([ | ||
parentHeight, | ||
prevLongestLine, | ||
nextLongestLine, | ||
]), 2), ref = _c[0], dimensions = _c[1]; | ||
return (React__default['default'].createElement("pre", { ref: ref, className: "language-" + language, style: { | ||
position: "absolute", | ||
top: 0, | ||
bottom: 0, | ||
right: 16, | ||
left: 16, | ||
padding: 0, | ||
margin: 0, | ||
overflow: "hidden", | ||
opacity: dimensions ? 1 : 0, | ||
} }, | ||
React__default['default'].createElement("code", null, dimensions ? (React__default['default'].createElement(smoothLines.SmoothLines, { center: false, progress: progress, containerWidth: dimensions.width, containerHeight: dimensions.height, prevLines: prevLines, nextLines: nextLines, lineHeight: dimensions.lineHeight, lineWidth: dimensions.lineWidths.map(function (lw) { | ||
return Math.max(lw, dimensions.colWidth * minColumns); | ||
}), prevFocus: prevFocusIndexes, nextFocus: nextFocusIndexes, maxZoom: 1 })) : (React__default['default'].createElement(React__default['default'].Fragment, null, | ||
React__default['default'].createElement("div", { className: "prev-longest-line" }, prevLongestLine), | ||
React__default['default'].createElement("div", { className: "next-longest-line" }, nextLongestLine)))))); | ||
} | ||
function useLineProps(prevCode, nextCode, language, prevFocus, nextFocus) { | ||
return React__default['default'].useMemo(function () { | ||
var _a, _b; | ||
var _c = codeDiff.codeDiff({ | ||
prevCode: prevCode, | ||
nextCode: nextCode, | ||
lang: language, | ||
}), prevKeys = _c.prevKeys, nextKeys = _c.nextKeys, codeMap = _c.codeMap; | ||
var prevFocusByKey = getFocusByKey(prevFocus, prevKeys); | ||
var prevFocusIndexes = getFocusIndexes(prevFocus, prevKeys); | ||
var prevLongestLineIndex = longestLineIndex(prevCode, prevFocusIndexes); | ||
var nextFocusByKey = getFocusByKey(nextFocus, nextKeys); | ||
var nextFocusIndexes = getFocusIndexes(nextFocus, nextKeys); | ||
var nextLongestLineIndex = longestLineIndex(nextCode, nextFocusIndexes); | ||
var prevLines = prevKeys.map(function (key) { | ||
var prevFocus = prevFocusByKey[key]; | ||
var nextFocus = nextFocusByKey[key]; | ||
var focusPerColumn = Array.isArray(prevFocus) || Array.isArray(nextFocus); | ||
if (!focusPerColumn) { | ||
return { | ||
key: key, | ||
element: React__default['default'].createElement(Line, { line: codeMap[key] }), | ||
}; | ||
} | ||
else { | ||
return { | ||
key: key, | ||
element: React__default['default'].createElement(Line, { line: codeMap[key] }), | ||
elementWithProgress: function (progress) { return (React__default['default'].createElement(ColumnedLine, { line: codeMap[key], progress: progress, prevFocus: prevFocus, nextFocus: nextFocus })); }, | ||
}; | ||
} | ||
}); | ||
var prevLongestLine = prevLongestLineIndex == null | ||
? null | ||
: (_a = prevLines[prevLongestLineIndex]) === null || _a === void 0 ? void 0 : _a.element; | ||
var nextLines = nextKeys.map(function (key) { | ||
var prevFocus = prevFocusByKey[key]; | ||
var nextFocus = nextFocusByKey[key]; | ||
var focusPerColumn = Array.isArray(prevFocus) || Array.isArray(nextFocus); | ||
if (!focusPerColumn) { | ||
return { | ||
key: key, | ||
element: React__default['default'].createElement(Line, { line: codeMap[key] }), | ||
}; | ||
} | ||
else { | ||
return { | ||
key: key, | ||
element: React__default['default'].createElement(Line, { line: codeMap[key] }), | ||
elementWithProgress: function (progress) { return (React__default['default'].createElement(ColumnedLine, { line: codeMap[key], progress: progress, prevFocus: prevFocus, nextFocus: nextFocus })); }, | ||
}; | ||
} | ||
}); | ||
var nextLongestLine = nextLongestLineIndex == null | ||
? null | ||
: (_b = nextLines[nextLongestLineIndex]) === null || _b === void 0 ? void 0 : _b.element; | ||
return { | ||
prevLines: prevLines, | ||
nextLines: nextLines, | ||
prevFocusIndexes: prevFocusIndexes, | ||
nextFocusIndexes: nextFocusIndexes, | ||
prevLongestLine: prevLongestLine, | ||
nextLongestLine: nextLongestLine, | ||
}; | ||
}, [prevCode, nextCode, language, prevFocus, nextFocus]); | ||
} | ||
function Line(_a) { | ||
var line = _a.line; | ||
return (React__default['default'].createElement("div", { style: { | ||
display: "inline-block", | ||
} }, line.map(function (_a, i) { | ||
var _b = __read(_a, 2), token = _b[0], type = _b[1]; | ||
return (React__default['default'].createElement("span", { className: "token " + type, key: i + 1 }, token)); | ||
}))); | ||
} | ||
var OFF_OPACITY = 0.33; | ||
function ColumnedLine(_a) { | ||
var line = _a.line, progress = _a.progress, prevFocus = _a.prevFocus, nextFocus = _a.nextFocus; | ||
var columns = React__default['default'].useMemo(function () { | ||
var chars = flatMap(line, function (_a) { | ||
var _b = __read(_a, 2), token = _b[0], type = _b[1]; | ||
return token.split("").map(function (char) { return [char, type]; }); | ||
}); | ||
return chars.map(function (_a, i) { | ||
var _b = __read(_a, 2), char = _b[0], type = _b[1]; | ||
return ({ | ||
char: char, | ||
type: type, | ||
fromOpacity: !prevFocus | ||
? 0.99 // because the line is already transparent | ||
: prevFocus === true || prevFocus.includes(i) | ||
? 0.99 | ||
: OFF_OPACITY, | ||
toOpacity: !nextFocus | ||
? 0.99 // because the line is already transparent | ||
: nextFocus === true || nextFocus.includes(i) | ||
? 0.99 | ||
: OFF_OPACITY, | ||
}); | ||
}); | ||
}, [line, prevFocus, nextFocus]); | ||
return (React__default['default'].createElement("div", { style: { | ||
display: "inline-block", | ||
width: "100%", | ||
} }, columns.map(function (_a, i) { | ||
var char = _a.char, type = _a.type, fromOpacity = _a.fromOpacity, toOpacity = _a.toOpacity; | ||
return (React__default['default'].createElement("span", { className: "token " + type, key: i + 1, style: { | ||
opacity: tween(fromOpacity, toOpacity, progress), | ||
} }, char)); | ||
}))); | ||
} | ||
function tween(p, n, t) { | ||
return (n - p) * t + p; | ||
} | ||
var newlineRe = /\r\n|\r|\n/; | ||
function longestLineIndex(code, focusIndexes) { | ||
var first = Math.min.apply(Math, __spread(focusIndexes)); | ||
var last = Math.max.apply(Math, __spread(focusIndexes)); | ||
var focusedLines = code == null | ||
? [] | ||
: code.split(newlineRe).slice(first, last + 1); | ||
if (!focusedLines.length) { | ||
return null; | ||
} | ||
var longestIndex = 0; | ||
for (var i = 1; i < focusedLines.length; i++) { | ||
if (focusedLines[i].length > | ||
focusedLines[longestIndex].length) { | ||
longestIndex = i; | ||
} | ||
} | ||
return first + longestIndex; | ||
} | ||
function flatMap(array, callbackfn) { | ||
var _a; | ||
return (_a = Array.prototype).concat.apply(_a, __spread(array.map(callbackfn))); | ||
} | ||
function useForwardTransitions(steps) { | ||
return React__default['default'].useMemo(function () { | ||
var transitions = steps.map(function (step, i) { | ||
var prevStepForFile = null; | ||
for (var j = i - 1; j >= 0; j--) { | ||
if (steps[j].file === step.file) { | ||
prevStepForFile = steps[j]; | ||
break; | ||
} | ||
} | ||
return { | ||
prevCode: prevStepForFile && prevStepForFile.code, | ||
prevFocus: prevStepForFile && prevStepForFile.focus, | ||
nextCode: step.code, | ||
nextFocus: step.focus, | ||
file: step.file, | ||
lang: step.lang, | ||
}; | ||
}); | ||
var lastStep = steps[steps.length - 1]; | ||
transitions.push({ | ||
file: lastStep.file, | ||
prevCode: lastStep.code, | ||
prevFocus: lastStep.focus, | ||
nextCode: null, | ||
nextFocus: null, | ||
lang: lastStep.lang, | ||
}); | ||
return transitions; | ||
}, [steps]); | ||
} | ||
function useBackwardTransitions(steps) { | ||
return React__default['default'].useMemo(function () { | ||
var transitions = []; | ||
transitions.push({ | ||
prevCode: null, | ||
prevFocus: null, | ||
nextCode: steps[0].code, | ||
nextFocus: steps[0].focus, | ||
lang: steps[0].lang, | ||
file: steps[0].file, | ||
}); | ||
steps.forEach(function (step, i) { | ||
var nextStepForFile = null; | ||
for (var j = i + 1; j < steps.length; j++) { | ||
if (steps[j].file === step.file) { | ||
nextStepForFile = steps[j]; | ||
break; | ||
} | ||
} | ||
transitions.push({ | ||
prevCode: step.code, | ||
prevFocus: step.focus, | ||
nextCode: nextStepForFile && nextStepForFile.code, | ||
nextFocus: nextStepForFile && nextStepForFile.focus, | ||
lang: step.lang, | ||
file: step.file, | ||
}); | ||
}); | ||
return transitions; | ||
}, [steps]); | ||
} | ||
function MiniEditor(props) { | ||
var _a = props.progress, progress = _a === void 0 ? 0 : _a, _b = props.backward, backward = _b === void 0 ? false : _b, code = props.code, focus = props.focus, lang = props.lang, file = props.file, ogSteps = props.steps, ogTabs = props.tabs, _c = props.minColumns, minColumns = _c === void 0 ? 50 : _c, height = props.height, rest = __rest(props, ["progress", "backward", "code", "focus", "lang", "file", "steps", "tabs", "minColumns", "height"]); | ||
var _d = useSteps(ogSteps, { | ||
@@ -111,23 +543,56 @@ code: code, | ||
file: file, | ||
tabs: ogTabs, | ||
}), steps = _d.steps, files = _d.files, stepsByFile = _d.stepsByFile; | ||
var activeStepIndex = backward ? Math.floor(progress) : Math.ceil(progress); | ||
var activeStepIndex = backward | ||
? Math.floor(progress) | ||
: Math.ceil(progress); | ||
var activeStep = steps[activeStepIndex]; | ||
var activeFile = (activeStep && activeStep.file) || ""; | ||
var activeSteps = stepsByFile[activeFile] || []; | ||
var index = activeSteps.indexOf(activeStep); | ||
var activeProgress = Math.min(Math.max(progress - activeStepIndex + index, 0), activeSteps.length - 1); | ||
var tabs = activeStep.tabs || files; | ||
var terminalHeight = getTerminalHeight(steps, progress); | ||
var terminalSteps = steps.map(function (s) { return ({ text: (s && s.terminal) || "" }); }); | ||
return (React.createElement(EditorFrame, __assign({ files: tabs, active: activeFile, terminalPanel: React.createElement(TerminalPanel, { height: terminalHeight }, | ||
React.createElement(miniTerminal.InnerTerminal, { steps: terminalSteps, progress: progress })) }, rest), activeSteps.length > 0 && (React.createElement(standalone.CodeSurfer, { key: activeFile, progress: activeProgress, steps: activeSteps, theme: themes.vsDark, nonblocking: true })))); | ||
var terminalSteps = steps.map(function (s) { return ({ | ||
text: (s && s.terminal) || "", | ||
}); }); | ||
var contentSteps = useStepsWithDefaults({ code: code, focus: focus, lang: lang, file: file }, ogSteps || []); | ||
return (React__default['default'].createElement(EditorFrame, __assign({ files: tabs, active: activeFile, terminalPanel: React__default['default'].createElement(TerminalPanel, { height: terminalHeight }, | ||
React__default['default'].createElement(miniTerminal.InnerTerminal, { steps: terminalSteps, progress: progress })), height: height }, rest), activeSteps.length > 0 && (React__default['default'].createElement(EditorContent, { key: activeFile, backward: backward, progress: progress, steps: contentSteps, parentHeight: height, minColumns: minColumns })))); | ||
} | ||
function useStepsWithDefaults(defaults, steps) { | ||
var files = __spread(new Set(steps.map(function (s) { return coalesce(s.file, defaults.file, ""); }))); | ||
return steps.map(function (step) { | ||
return { | ||
code: coalesce(step.code, defaults.code, ""), | ||
file: coalesce(step.file, defaults.file, ""), | ||
focus: coalesce(step.focus, defaults.focus, ""), | ||
lang: coalesce(step.lang, defaults.lang, "javascript"), | ||
tabs: coalesce(step.tabs, defaults.tabs, files), | ||
terminal: step.terminal || defaults.terminal, | ||
}; | ||
}); | ||
} | ||
function coalesce(a, b, c) { | ||
return a != null ? a : b != null ? b : c; | ||
} | ||
function EditorContent(_a) { | ||
var progress = _a.progress, backward = _a.backward, steps = _a.steps, parentHeight = _a.parentHeight, minColumns = _a.minColumns; | ||
var fwdTransitions = useForwardTransitions(steps); | ||
var bwdTransitions = useBackwardTransitions(steps); | ||
var transitionIndex = Math.ceil(progress); | ||
var _b = backward | ||
? bwdTransitions[transitionIndex] | ||
: fwdTransitions[transitionIndex], prevCode = _b.prevCode, nextCode = _b.nextCode, prevFocus = _b.prevFocus, nextFocus = _b.nextFocus, lang = _b.lang; | ||
return (React__default['default'].createElement(Code, { prevCode: prevCode || nextCode, nextCode: nextCode || prevCode, prevFocus: prevFocus, nextFocus: nextFocus, language: lang, progress: progress - transitionIndex + 1, parentHeight: parentHeight, minColumns: minColumns })); | ||
} | ||
function useSteps(ogSteps, _a) { | ||
var _b = _a.code, code = _b === void 0 ? "" : _b, focus = _a.focus, lang = _a.lang, file = _a.file; | ||
return React.useMemo(function () { | ||
var _b = _a.code, code = _b === void 0 ? "" : _b, focus = _a.focus, lang = _a.lang, file = _a.file, tabs = _a.tabs; | ||
return React__default['default'].useMemo(function () { | ||
var steps = (ogSteps === null || ogSteps === void 0 ? void 0 : ogSteps.map(function (s) { return (__assign({ code: code, | ||
focus: focus, | ||
lang: lang, | ||
file: file }, s)); })) || [{ code: code, focus: focus, lang: lang, file: file }]; | ||
var files = __spread(new Set(steps.map(function (s) { return s.file; }).filter(function (f) { return f != null; }))); | ||
file: file, | ||
tabs: tabs }, s)); })) || [{ code: code, focus: focus, lang: lang, file: file, tabs: tabs }]; | ||
var files = __spread(new Set(steps | ||
.map(function (s) { return s.file; }) | ||
.filter(function (f) { return f != null; }))); | ||
var stepsByFile = {}; | ||
@@ -143,3 +608,3 @@ steps.forEach(function (s) { | ||
return { steps: steps, files: files, stepsByFile: stepsByFile }; | ||
}, [ogSteps, code, focus, lang, file]); | ||
}, [ogSteps, code, focus, lang, file, tabs]); | ||
} | ||
@@ -164,2 +629,31 @@ var MAX_HEIGHT = 150; | ||
function MiniEditorWithState(_a) { | ||
var focus = _a.focus, code = _a.code, rest = __rest(_a, ["focus", "code"]); | ||
var _b = __read(usePrevFocus(code, focus), 2), steps = _b[0], progress = _b[1]; | ||
return (React__default['default'].createElement(MiniEditor, __assign({ progress: progress, steps: steps }, rest))); | ||
} | ||
function usePrevFocus(code, focus) { | ||
var _a = __read(React__default['default'].useState({ | ||
target: 0, | ||
steps: [{ focus: focus, code: code }], | ||
}), 2), state = _a[0], setState = _a[1]; | ||
React__default['default'].useEffect(function () { | ||
var last = state.steps[state.steps.length - 1]; | ||
if (last.focus !== focus || last.code !== code) { | ||
setState(function (s) { return ({ | ||
target: s.target + 1, | ||
steps: __spread(s.steps, [{ focus: focus, code: code }]), | ||
}); }); | ||
} | ||
}, [focus, code]); | ||
var _b = __read(useSpring.useSpring(state.target, { | ||
stiffness: 256, | ||
damping: 24, | ||
mass: 0.2, | ||
decimals: 3, | ||
}), 1), progress = _b[0]; | ||
return [state.steps, progress]; | ||
} | ||
exports.MiniEditor = MiniEditor; | ||
exports.MiniEditorWithState = MiniEditorWithState; |
@@ -1,2 +0,4 @@ | ||
import { MiniEditor } from "./mini-editor"; | ||
export { MiniEditor }; | ||
import "./index.scss"; | ||
import { MiniEditor, MiniEditorProps } from "./mini-editor"; | ||
import { MiniEditorWithState, StatefulEditorProps } from "./stateful-editor"; | ||
export { MiniEditor, MiniEditorWithState, MiniEditorProps, StatefulEditorProps, }; |
import React from 'react'; | ||
import { MiniFrame, FrameButtons } from '@code-hike/mini-frame'; | ||
import { CodeSurfer } from '@code-surfer/standalone'; | ||
import { vsDark } from '@code-surfer/themes'; | ||
import { useClasser } from '@code-hike/classer'; | ||
import { InnerTerminal } from '@code-hike/mini-terminal'; | ||
import { codeDiff } from '@code-hike/code-diff'; | ||
import { SmoothLines } from '@code-hike/smooth-lines'; | ||
import { useSpring } from 'use-spring'; | ||
@@ -21,3 +23,17 @@ /*! ***************************************************************************** | ||
***************************************************************************** */ | ||
/* global Reflect, Promise */ | ||
var extendStatics = function(d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
function __extends(d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
} | ||
var __assign = function() { | ||
@@ -69,20 +85,19 @@ __assign = Object.assign || function __assign(t) { | ||
var e=[],t=[];function injector_1a6c3c54(n,r){if(n&&"undefined"!=typeof document){void 0===r&&(r={});var d,a=!0===r.prepend?"prepend":"append",i="undefined"!=typeof r.singleTag&&r.singleTag,s="undefined"!=typeof r.container?document.querySelector(r.container):document.getElementsByTagName("head")[0];if(i){var u=e.indexOf(s);-1===u&&(u=e.push(s)-1,t[u]={}),d=t[u]&&t[u][a]?t[u][a]:t[u][a]=o();}else d=o();65279===n.charCodeAt(0)&&(n=n.substring(1)),d.styleSheet?d.styleSheet.cssText+=n:d.appendChild(document.createTextNode(n));}function o(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),r.attributes)for(var t=Object.keys(r.attributes),n=0;n<t.length;n++)e.setAttribute(t[n],r.attributes[t[n]]);var d="prepend"===a?"afterbegin":"beforeend";return s.insertAdjacentElement(d,e),e}} | ||
const css_f2c17fbd = ".ch-editor-tab{border-right:1px solid #252526;width:120px;min-width:-webkit-fit-content;min-width:-moz-fit-content;min-width:fit-content;flex-shrink:0;position:relative;display:flex;white-space:nowrap;cursor:pointer;height:100%;box-sizing:border-box;padding-left:15px;padding-right:15px;background-color:#2d2d2d;color:hsla(0,0%,100%,.5)}.ch-editor-tab[data-active]{background-color:#1e1e1e;color:#fff}.ch-editor-tab>div{margin-top:auto;margin-bottom:auto;font-size:12px;line-height:1.4em;text-overflow:ellipsis}.ch-editor-body{background-color:#1e1e1e;height:100%;color:#ccc;font-size:15px;padding:5px 10px;line-height:1.1rem;box-sizing:border-box}.ch-editor-body code{line-height:20px}.ch-editor-terminal{position:absolute;overflow:hidden;bottom:0;width:100%;background-color:#1e1e1e;color:#e7e7e7;border-top:1px solid hsla(0,0%,50.2%,.35);padding:0 8px;box-sizing:border-box}.ch-editor-terminal-tab{text-transform:uppercase;padding:4px 10px 3px;font-size:11px;line-height:24px;display:flex}.ch-editor-terminal-tab>span{border-bottom:1px solid #e7e7e7}.ch-editor-terminal-content{margin-top:8px;height:calc(100% - 40px);box-sizing:border-box}.ch-editor-terminal-content .ch-terminal{font-size:12px;margin:0}"; | ||
injector_1a6c3c54(css_f2c17fbd,{"singleTag":true}); | ||
var DEFAULT_HEIGHT = 200; | ||
function EditorFrame(_a) { | ||
var files = _a.files, active = _a.active, children = _a.children, terminalPanel = _a.terminalPanel, rest = __rest(_a, ["files", "active", "children", "terminalPanel"]); | ||
return (React.createElement(MiniFrame, __assign({ titleBar: React.createElement(TabsContainer, { files: files, active: active }) }, rest), | ||
React.createElement("div", { className: "ch-editor-body" }, children), | ||
var files = _a.files, active = _a.active, children = _a.children, terminalPanel = _a.terminalPanel, height = _a.height, style = _a.style, button = _a.button, classes = _a.classes, rest = __rest(_a, ["files", "active", "children", "terminalPanel", "height", "style", "button", "classes"]); | ||
var c = useClasser("ch-editor"); | ||
return (React.createElement(MiniFrame, __assign({ titleBar: React.createElement(TabsContainer, { files: files, active: active, button: button, classes: classes }), classes: classes, style: __assign({ height: height !== null && height !== void 0 ? height : DEFAULT_HEIGHT }, style) }, rest), | ||
React.createElement("div", { className: c("body") }, children), | ||
terminalPanel)); | ||
} | ||
function TabsContainer(_a) { | ||
var files = _a.files, active = _a.active; | ||
var files = _a.files, active = _a.active, button = _a.button, classes = _a.classes; | ||
var c = useClasser("ch-editor-tab"); | ||
return (React.createElement(React.Fragment, null, | ||
React.createElement(FrameButtons, null), | ||
files.map(function (fileName) { return (React.createElement("div", { key: fileName, className: "ch-editor-tab", "data-active": fileName === active || undefined }, | ||
files.map(function (fileName) { return (React.createElement("div", { key: fileName, className: c("", fileName === active ? "active" : "inactive") }, | ||
React.createElement("div", null, fileName))); }), | ||
React.createElement("div", { style: { flex: 1 } }))); | ||
React.createElement("div", { style: { flex: 1 } }), | ||
button)); | ||
} | ||
@@ -97,4 +112,419 @@ function TerminalPanel(_a) { | ||
function MiniEditor(_a) { | ||
var _b = _a.progress, progress = _b === void 0 ? 0 : _b, _c = _a.backward, backward = _c === void 0 ? false : _c, code = _a.code, focus = _a.focus, lang = _a.lang, file = _a.file, ogSteps = _a.steps, rest = __rest(_a, ["progress", "backward", "code", "focus", "lang", "file", "steps"]); | ||
var useLayoutEffect = typeof window !== "undefined" | ||
? React.useLayoutEffect | ||
: React.useEffect; | ||
var DEFAULT_WIDTH = 200; | ||
function useDimensions(deps) { | ||
var ref = React.useRef(null); | ||
var _a = __read(React.useState(null), 2), dimensions = _a[0], setDimensions = _a[1]; | ||
var windowWidth = useWindowWidth(); | ||
var fullDeps = __spread(deps, [windowWidth]); | ||
useLayoutEffect(function () { | ||
var _a, _b, _c, _d, _e, _f, _g, _h; | ||
if (ref.current) { | ||
var rect = ref.current.getBoundingClientRect(); | ||
var pll = ref.current.querySelector(".prev-longest-line"); | ||
var nll = ref.current.querySelector(".next-longest-line"); | ||
// TODO is it clientWidth or clientRect? | ||
var plw = (_a = pll === null || pll === void 0 ? void 0 : pll.firstElementChild) === null || _a === void 0 ? void 0 : _a.clientWidth; | ||
var nlw = (_b = nll === null || nll === void 0 ? void 0 : nll.firstElementChild) === null || _b === void 0 ? void 0 : _b.clientWidth; | ||
var plh = (_d = (_c = pll === null || pll === void 0 ? void 0 : pll.firstElementChild) === null || _c === void 0 ? void 0 : _c.clientHeight) !== null && _d !== void 0 ? _d : 20; | ||
var nlh = (_f = (_e = nll === null || nll === void 0 ? void 0 : nll.firstElementChild) === null || _e === void 0 ? void 0 : _e.clientHeight) !== null && _f !== void 0 ? _f : 20; | ||
var colWidth = pll | ||
? plw / (((_g = pll.textContent) === null || _g === void 0 ? void 0 : _g.length) || 1) | ||
: nlw / (((_h = nll.textContent) === null || _h === void 0 ? void 0 : _h.length) || 1); | ||
setDimensions({ | ||
width: rect.width, | ||
height: rect.height, | ||
lineWidths: [ | ||
plw || nlw || DEFAULT_WIDTH, | ||
nlw || plw || DEFAULT_WIDTH, | ||
], | ||
lineHeight: Math.max(plh, nlh), | ||
colWidth: colWidth, | ||
deps: fullDeps, | ||
}); | ||
} | ||
}, fullDeps); | ||
if (!dimensions || | ||
depsChanged(dimensions.deps, fullDeps)) { | ||
return [ref, null]; | ||
} | ||
else { | ||
return [ref, dimensions]; | ||
} | ||
} | ||
function depsChanged(oldDeps, newDeps) { | ||
for (var i = 0; i < oldDeps.length; i++) { | ||
if (oldDeps[i] !== newDeps[i]) | ||
return true; | ||
} | ||
return false; | ||
} | ||
function useWindowWidth() { | ||
var _a = __read(React.useState(undefined), 2), width = _a[0], setWidth = _a[1]; | ||
React.useEffect(function () { | ||
function handleResize() { | ||
setWidth(window.innerWidth); | ||
} | ||
window.addEventListener("resize", handleResize); | ||
return function () { | ||
return window.removeEventListener("resize", handleResize); | ||
}; | ||
}, []); | ||
return width; | ||
} | ||
function getFocusIndexes(focus, lines) { | ||
if (!focus) { | ||
return __spread(lines.keys()); | ||
} | ||
else { | ||
var parsed = parseFocus(focus); | ||
var focusedIndexes = Object.keys(parsed).map(function (i) { | ||
return parseInt(i, 10); | ||
}); | ||
return focusedIndexes; | ||
} | ||
} | ||
function getFocusByKey(focus, keys) { | ||
if (!focus) { | ||
// focus all lines | ||
return fromEntries(keys.map(function (key) { return [key, true]; })); | ||
} | ||
else { | ||
var parsed_1 = parseFocus(focus); | ||
var byKey_1 = {}; | ||
Object.keys(parsed_1).forEach(function (i) { | ||
var key = keys[parseInt(i, 10)]; | ||
byKey_1[key] = parsed_1[parseInt(i, 10)]; | ||
}); | ||
return byKey_1; | ||
} | ||
} | ||
function parseFocus(focus) { | ||
if (!focus) { | ||
throw new Error("Focus cannot be empty"); | ||
} | ||
try { | ||
var parts = focus | ||
.split(/,(?![^\[]*\])/g) | ||
.map(parsePart); | ||
return fromEntries(parts.flat()); | ||
} | ||
catch (error) { | ||
// TODO enhance error | ||
throw error; | ||
} | ||
} | ||
function parsePart(part) { | ||
// a part could be | ||
// - a line number: "2" | ||
// - a line range: "5:9" | ||
// - a line number with a column selector: "2[1,3:5,9]" | ||
var columnsMatch = part.match(/(\d+)\[(.+)\]/); | ||
if (columnsMatch) { | ||
var _a = __read(columnsMatch, 3), line = _a[1], columns = _a[2]; | ||
var columnsList = columns.split(",").map(expandString); | ||
var lineIndex = Number(line) - 1; | ||
var columnIndexes = columnsList.flat().map(function (c) { return c - 1; }); | ||
return [[lineIndex, columnIndexes]]; | ||
} | ||
else { | ||
return expandString(part).map(function (lineNumber) { return [ | ||
lineNumber - 1, | ||
true, | ||
]; }); | ||
} | ||
} | ||
function expandString(part) { | ||
// Transforms something like | ||
// - "1:3" to [1,2,3] | ||
// - "4" to [4] | ||
var _a = __read(part.split(":"), 2), start = _a[0], end = _a[1]; | ||
if (!isNaturalNumber(start)) { | ||
throw new FocusNumberError(start); | ||
} | ||
var startNumber = Number(start); | ||
if (startNumber < 1) { | ||
throw new LineOrColumnNumberError(); | ||
} | ||
if (!end) { | ||
return [startNumber]; | ||
} | ||
else { | ||
if (!isNaturalNumber(end)) { | ||
throw new FocusNumberError(end); | ||
} | ||
var list = []; | ||
for (var i = startNumber; i <= +end; i++) { | ||
list.push(i); | ||
} | ||
return list; | ||
} | ||
} | ||
function isNaturalNumber(n) { | ||
n = n.toString(); // force the value in case it is not | ||
var n1 = Math.abs(n), n2 = parseInt(n, 10); | ||
return !isNaN(n1) && n2 === n1 && n1.toString() === n; | ||
} | ||
var LineOrColumnNumberError = /** @class */ (function (_super) { | ||
__extends(LineOrColumnNumberError, _super); | ||
function LineOrColumnNumberError() { | ||
var _newTarget = this.constructor; | ||
var _this = _super.call(this, "Invalid line or column number in focus string") || this; | ||
Object.setPrototypeOf(_this, _newTarget.prototype); | ||
return _this; | ||
} | ||
return LineOrColumnNumberError; | ||
}(Error)); | ||
var FocusNumberError = /** @class */ (function (_super) { | ||
__extends(FocusNumberError, _super); | ||
function FocusNumberError(number) { | ||
var _newTarget = this.constructor; | ||
var _this = _super.call(this, "Invalid number \"" + number + "\" in focus string") || this; | ||
_this.number = number; | ||
Object.setPrototypeOf(_this, _newTarget.prototype); | ||
return _this; | ||
} | ||
return FocusNumberError; | ||
}(Error)); | ||
function fromEntries(pairs) { | ||
var result = {}; | ||
var index = -1, length = pairs == null ? 0 : pairs.length; | ||
while (++index < length) { | ||
var pair = pairs[index]; | ||
result[pair[0]] = pair[1]; | ||
} | ||
return result; | ||
} | ||
function Code(_a) { | ||
var prevCode = _a.prevCode, prevFocus = _a.prevFocus, nextCode = _a.nextCode, nextFocus = _a.nextFocus, progress = _a.progress, language = _a.language, parentHeight = _a.parentHeight, minColumns = _a.minColumns; | ||
var _b = useLineProps(prevCode, nextCode, language, prevFocus, nextFocus), prevLines = _b.prevLines, nextLines = _b.nextLines, prevFocusIndexes = _b.prevFocusIndexes, nextFocusIndexes = _b.nextFocusIndexes, prevLongestLine = _b.prevLongestLine, nextLongestLine = _b.nextLongestLine; | ||
var _c = __read(useDimensions([ | ||
parentHeight, | ||
prevLongestLine, | ||
nextLongestLine, | ||
]), 2), ref = _c[0], dimensions = _c[1]; | ||
return (React.createElement("pre", { ref: ref, className: "language-" + language, style: { | ||
position: "absolute", | ||
top: 0, | ||
bottom: 0, | ||
right: 16, | ||
left: 16, | ||
padding: 0, | ||
margin: 0, | ||
overflow: "hidden", | ||
opacity: dimensions ? 1 : 0, | ||
} }, | ||
React.createElement("code", null, dimensions ? (React.createElement(SmoothLines, { center: false, progress: progress, containerWidth: dimensions.width, containerHeight: dimensions.height, prevLines: prevLines, nextLines: nextLines, lineHeight: dimensions.lineHeight, lineWidth: dimensions.lineWidths.map(function (lw) { | ||
return Math.max(lw, dimensions.colWidth * minColumns); | ||
}), prevFocus: prevFocusIndexes, nextFocus: nextFocusIndexes, maxZoom: 1 })) : (React.createElement(React.Fragment, null, | ||
React.createElement("div", { className: "prev-longest-line" }, prevLongestLine), | ||
React.createElement("div", { className: "next-longest-line" }, nextLongestLine)))))); | ||
} | ||
function useLineProps(prevCode, nextCode, language, prevFocus, nextFocus) { | ||
return React.useMemo(function () { | ||
var _a, _b; | ||
var _c = codeDiff({ | ||
prevCode: prevCode, | ||
nextCode: nextCode, | ||
lang: language, | ||
}), prevKeys = _c.prevKeys, nextKeys = _c.nextKeys, codeMap = _c.codeMap; | ||
var prevFocusByKey = getFocusByKey(prevFocus, prevKeys); | ||
var prevFocusIndexes = getFocusIndexes(prevFocus, prevKeys); | ||
var prevLongestLineIndex = longestLineIndex(prevCode, prevFocusIndexes); | ||
var nextFocusByKey = getFocusByKey(nextFocus, nextKeys); | ||
var nextFocusIndexes = getFocusIndexes(nextFocus, nextKeys); | ||
var nextLongestLineIndex = longestLineIndex(nextCode, nextFocusIndexes); | ||
var prevLines = prevKeys.map(function (key) { | ||
var prevFocus = prevFocusByKey[key]; | ||
var nextFocus = nextFocusByKey[key]; | ||
var focusPerColumn = Array.isArray(prevFocus) || Array.isArray(nextFocus); | ||
if (!focusPerColumn) { | ||
return { | ||
key: key, | ||
element: React.createElement(Line, { line: codeMap[key] }), | ||
}; | ||
} | ||
else { | ||
return { | ||
key: key, | ||
element: React.createElement(Line, { line: codeMap[key] }), | ||
elementWithProgress: function (progress) { return (React.createElement(ColumnedLine, { line: codeMap[key], progress: progress, prevFocus: prevFocus, nextFocus: nextFocus })); }, | ||
}; | ||
} | ||
}); | ||
var prevLongestLine = prevLongestLineIndex == null | ||
? null | ||
: (_a = prevLines[prevLongestLineIndex]) === null || _a === void 0 ? void 0 : _a.element; | ||
var nextLines = nextKeys.map(function (key) { | ||
var prevFocus = prevFocusByKey[key]; | ||
var nextFocus = nextFocusByKey[key]; | ||
var focusPerColumn = Array.isArray(prevFocus) || Array.isArray(nextFocus); | ||
if (!focusPerColumn) { | ||
return { | ||
key: key, | ||
element: React.createElement(Line, { line: codeMap[key] }), | ||
}; | ||
} | ||
else { | ||
return { | ||
key: key, | ||
element: React.createElement(Line, { line: codeMap[key] }), | ||
elementWithProgress: function (progress) { return (React.createElement(ColumnedLine, { line: codeMap[key], progress: progress, prevFocus: prevFocus, nextFocus: nextFocus })); }, | ||
}; | ||
} | ||
}); | ||
var nextLongestLine = nextLongestLineIndex == null | ||
? null | ||
: (_b = nextLines[nextLongestLineIndex]) === null || _b === void 0 ? void 0 : _b.element; | ||
return { | ||
prevLines: prevLines, | ||
nextLines: nextLines, | ||
prevFocusIndexes: prevFocusIndexes, | ||
nextFocusIndexes: nextFocusIndexes, | ||
prevLongestLine: prevLongestLine, | ||
nextLongestLine: nextLongestLine, | ||
}; | ||
}, [prevCode, nextCode, language, prevFocus, nextFocus]); | ||
} | ||
function Line(_a) { | ||
var line = _a.line; | ||
return (React.createElement("div", { style: { | ||
display: "inline-block", | ||
} }, line.map(function (_a, i) { | ||
var _b = __read(_a, 2), token = _b[0], type = _b[1]; | ||
return (React.createElement("span", { className: "token " + type, key: i + 1 }, token)); | ||
}))); | ||
} | ||
var OFF_OPACITY = 0.33; | ||
function ColumnedLine(_a) { | ||
var line = _a.line, progress = _a.progress, prevFocus = _a.prevFocus, nextFocus = _a.nextFocus; | ||
var columns = React.useMemo(function () { | ||
var chars = flatMap(line, function (_a) { | ||
var _b = __read(_a, 2), token = _b[0], type = _b[1]; | ||
return token.split("").map(function (char) { return [char, type]; }); | ||
}); | ||
return chars.map(function (_a, i) { | ||
var _b = __read(_a, 2), char = _b[0], type = _b[1]; | ||
return ({ | ||
char: char, | ||
type: type, | ||
fromOpacity: !prevFocus | ||
? 0.99 // because the line is already transparent | ||
: prevFocus === true || prevFocus.includes(i) | ||
? 0.99 | ||
: OFF_OPACITY, | ||
toOpacity: !nextFocus | ||
? 0.99 // because the line is already transparent | ||
: nextFocus === true || nextFocus.includes(i) | ||
? 0.99 | ||
: OFF_OPACITY, | ||
}); | ||
}); | ||
}, [line, prevFocus, nextFocus]); | ||
return (React.createElement("div", { style: { | ||
display: "inline-block", | ||
width: "100%", | ||
} }, columns.map(function (_a, i) { | ||
var char = _a.char, type = _a.type, fromOpacity = _a.fromOpacity, toOpacity = _a.toOpacity; | ||
return (React.createElement("span", { className: "token " + type, key: i + 1, style: { | ||
opacity: tween(fromOpacity, toOpacity, progress), | ||
} }, char)); | ||
}))); | ||
} | ||
function tween(p, n, t) { | ||
return (n - p) * t + p; | ||
} | ||
var newlineRe = /\r\n|\r|\n/; | ||
function longestLineIndex(code, focusIndexes) { | ||
var first = Math.min.apply(Math, __spread(focusIndexes)); | ||
var last = Math.max.apply(Math, __spread(focusIndexes)); | ||
var focusedLines = code == null | ||
? [] | ||
: code.split(newlineRe).slice(first, last + 1); | ||
if (!focusedLines.length) { | ||
return null; | ||
} | ||
var longestIndex = 0; | ||
for (var i = 1; i < focusedLines.length; i++) { | ||
if (focusedLines[i].length > | ||
focusedLines[longestIndex].length) { | ||
longestIndex = i; | ||
} | ||
} | ||
return first + longestIndex; | ||
} | ||
function flatMap(array, callbackfn) { | ||
var _a; | ||
return (_a = Array.prototype).concat.apply(_a, __spread(array.map(callbackfn))); | ||
} | ||
function useForwardTransitions(steps) { | ||
return React.useMemo(function () { | ||
var transitions = steps.map(function (step, i) { | ||
var prevStepForFile = null; | ||
for (var j = i - 1; j >= 0; j--) { | ||
if (steps[j].file === step.file) { | ||
prevStepForFile = steps[j]; | ||
break; | ||
} | ||
} | ||
return { | ||
prevCode: prevStepForFile && prevStepForFile.code, | ||
prevFocus: prevStepForFile && prevStepForFile.focus, | ||
nextCode: step.code, | ||
nextFocus: step.focus, | ||
file: step.file, | ||
lang: step.lang, | ||
}; | ||
}); | ||
var lastStep = steps[steps.length - 1]; | ||
transitions.push({ | ||
file: lastStep.file, | ||
prevCode: lastStep.code, | ||
prevFocus: lastStep.focus, | ||
nextCode: null, | ||
nextFocus: null, | ||
lang: lastStep.lang, | ||
}); | ||
return transitions; | ||
}, [steps]); | ||
} | ||
function useBackwardTransitions(steps) { | ||
return React.useMemo(function () { | ||
var transitions = []; | ||
transitions.push({ | ||
prevCode: null, | ||
prevFocus: null, | ||
nextCode: steps[0].code, | ||
nextFocus: steps[0].focus, | ||
lang: steps[0].lang, | ||
file: steps[0].file, | ||
}); | ||
steps.forEach(function (step, i) { | ||
var nextStepForFile = null; | ||
for (var j = i + 1; j < steps.length; j++) { | ||
if (steps[j].file === step.file) { | ||
nextStepForFile = steps[j]; | ||
break; | ||
} | ||
} | ||
transitions.push({ | ||
prevCode: step.code, | ||
prevFocus: step.focus, | ||
nextCode: nextStepForFile && nextStepForFile.code, | ||
nextFocus: nextStepForFile && nextStepForFile.focus, | ||
lang: step.lang, | ||
file: step.file, | ||
}); | ||
}); | ||
return transitions; | ||
}, [steps]); | ||
} | ||
function MiniEditor(props) { | ||
var _a = props.progress, progress = _a === void 0 ? 0 : _a, _b = props.backward, backward = _b === void 0 ? false : _b, code = props.code, focus = props.focus, lang = props.lang, file = props.file, ogSteps = props.steps, ogTabs = props.tabs, _c = props.minColumns, minColumns = _c === void 0 ? 50 : _c, height = props.height, rest = __rest(props, ["progress", "backward", "code", "focus", "lang", "file", "steps", "tabs", "minColumns", "height"]); | ||
var _d = useSteps(ogSteps, { | ||
@@ -105,17 +535,47 @@ code: code, | ||
file: file, | ||
tabs: ogTabs, | ||
}), steps = _d.steps, files = _d.files, stepsByFile = _d.stepsByFile; | ||
var activeStepIndex = backward ? Math.floor(progress) : Math.ceil(progress); | ||
var activeStepIndex = backward | ||
? Math.floor(progress) | ||
: Math.ceil(progress); | ||
var activeStep = steps[activeStepIndex]; | ||
var activeFile = (activeStep && activeStep.file) || ""; | ||
var activeSteps = stepsByFile[activeFile] || []; | ||
var index = activeSteps.indexOf(activeStep); | ||
var activeProgress = Math.min(Math.max(progress - activeStepIndex + index, 0), activeSteps.length - 1); | ||
var tabs = activeStep.tabs || files; | ||
var terminalHeight = getTerminalHeight(steps, progress); | ||
var terminalSteps = steps.map(function (s) { return ({ text: (s && s.terminal) || "" }); }); | ||
var terminalSteps = steps.map(function (s) { return ({ | ||
text: (s && s.terminal) || "", | ||
}); }); | ||
var contentSteps = useStepsWithDefaults({ code: code, focus: focus, lang: lang, file: file }, ogSteps || []); | ||
return (React.createElement(EditorFrame, __assign({ files: tabs, active: activeFile, terminalPanel: React.createElement(TerminalPanel, { height: terminalHeight }, | ||
React.createElement(InnerTerminal, { steps: terminalSteps, progress: progress })) }, rest), activeSteps.length > 0 && (React.createElement(CodeSurfer, { key: activeFile, progress: activeProgress, steps: activeSteps, theme: vsDark, nonblocking: true })))); | ||
React.createElement(InnerTerminal, { steps: terminalSteps, progress: progress })), height: height }, rest), activeSteps.length > 0 && (React.createElement(EditorContent, { key: activeFile, backward: backward, progress: progress, steps: contentSteps, parentHeight: height, minColumns: minColumns })))); | ||
} | ||
function useStepsWithDefaults(defaults, steps) { | ||
var files = __spread(new Set(steps.map(function (s) { return coalesce(s.file, defaults.file, ""); }))); | ||
return steps.map(function (step) { | ||
return { | ||
code: coalesce(step.code, defaults.code, ""), | ||
file: coalesce(step.file, defaults.file, ""), | ||
focus: coalesce(step.focus, defaults.focus, ""), | ||
lang: coalesce(step.lang, defaults.lang, "javascript"), | ||
tabs: coalesce(step.tabs, defaults.tabs, files), | ||
terminal: step.terminal || defaults.terminal, | ||
}; | ||
}); | ||
} | ||
function coalesce(a, b, c) { | ||
return a != null ? a : b != null ? b : c; | ||
} | ||
function EditorContent(_a) { | ||
var progress = _a.progress, backward = _a.backward, steps = _a.steps, parentHeight = _a.parentHeight, minColumns = _a.minColumns; | ||
var fwdTransitions = useForwardTransitions(steps); | ||
var bwdTransitions = useBackwardTransitions(steps); | ||
var transitionIndex = Math.ceil(progress); | ||
var _b = backward | ||
? bwdTransitions[transitionIndex] | ||
: fwdTransitions[transitionIndex], prevCode = _b.prevCode, nextCode = _b.nextCode, prevFocus = _b.prevFocus, nextFocus = _b.nextFocus, lang = _b.lang; | ||
return (React.createElement(Code, { prevCode: prevCode || nextCode, nextCode: nextCode || prevCode, prevFocus: prevFocus, nextFocus: nextFocus, language: lang, progress: progress - transitionIndex + 1, parentHeight: parentHeight, minColumns: minColumns })); | ||
} | ||
function useSteps(ogSteps, _a) { | ||
var _b = _a.code, code = _b === void 0 ? "" : _b, focus = _a.focus, lang = _a.lang, file = _a.file; | ||
var _b = _a.code, code = _b === void 0 ? "" : _b, focus = _a.focus, lang = _a.lang, file = _a.file, tabs = _a.tabs; | ||
return React.useMemo(function () { | ||
@@ -125,4 +585,7 @@ var steps = (ogSteps === null || ogSteps === void 0 ? void 0 : ogSteps.map(function (s) { return (__assign({ code: code, | ||
lang: lang, | ||
file: file }, s)); })) || [{ code: code, focus: focus, lang: lang, file: file }]; | ||
var files = __spread(new Set(steps.map(function (s) { return s.file; }).filter(function (f) { return f != null; }))); | ||
file: file, | ||
tabs: tabs }, s)); })) || [{ code: code, focus: focus, lang: lang, file: file, tabs: tabs }]; | ||
var files = __spread(new Set(steps | ||
.map(function (s) { return s.file; }) | ||
.filter(function (f) { return f != null; }))); | ||
var stepsByFile = {}; | ||
@@ -138,3 +601,3 @@ steps.forEach(function (s) { | ||
return { steps: steps, files: files, stepsByFile: stepsByFile }; | ||
}, [ogSteps, code, focus, lang, file]); | ||
}, [ogSteps, code, focus, lang, file, tabs]); | ||
} | ||
@@ -159,2 +622,30 @@ var MAX_HEIGHT = 150; | ||
export { MiniEditor }; | ||
function MiniEditorWithState(_a) { | ||
var focus = _a.focus, code = _a.code, rest = __rest(_a, ["focus", "code"]); | ||
var _b = __read(usePrevFocus(code, focus), 2), steps = _b[0], progress = _b[1]; | ||
return (React.createElement(MiniEditor, __assign({ progress: progress, steps: steps }, rest))); | ||
} | ||
function usePrevFocus(code, focus) { | ||
var _a = __read(React.useState({ | ||
target: 0, | ||
steps: [{ focus: focus, code: code }], | ||
}), 2), state = _a[0], setState = _a[1]; | ||
React.useEffect(function () { | ||
var last = state.steps[state.steps.length - 1]; | ||
if (last.focus !== focus || last.code !== code) { | ||
setState(function (s) { return ({ | ||
target: s.target + 1, | ||
steps: __spread(s.steps, [{ focus: focus, code: code }]), | ||
}); }); | ||
} | ||
}, [focus, code]); | ||
var _b = __read(useSpring(state.target, { | ||
stiffness: 256, | ||
damping: 24, | ||
mass: 0.2, | ||
decimals: 3, | ||
}), 1), progress = _b[0]; | ||
return [state.steps, progress]; | ||
} | ||
export { MiniEditor, MiniEditorWithState }; |
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('@code-hike/mini-frame'), require('@code-surfer/standalone'), require('@code-surfer/themes'), require('@code-hike/mini-terminal')) : | ||
typeof define === 'function' && define.amd ? define(['exports', 'react', '@code-hike/mini-frame', '@code-surfer/standalone', '@code-surfer/themes', '@code-hike/mini-terminal'], factory) : | ||
(global = global || self, factory(global.foo = {}, global.React, global.miniFrame, global.standalone, global.themes, global.miniTerminal)); | ||
}(this, (function (exports, React, miniFrame, standalone, themes, miniTerminal) { 'use strict'; | ||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('@code-hike/mini-frame'), require('@code-hike/classer'), require('@code-hike/mini-terminal'), require('@code-hike/code-diff'), require('@code-hike/smooth-lines'), require('use-spring')) : | ||
typeof define === 'function' && define.amd ? define(['exports', 'react', '@code-hike/mini-frame', '@code-hike/classer', '@code-hike/mini-terminal', '@code-hike/code-diff', '@code-hike/smooth-lines', 'use-spring'], factory) : | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ch = {}, global.React, global.miniFrame, global.classer, global.miniTerminal, global.codeDiff, global.smoothLines, global.useSpring)); | ||
}(this, (function (exports, React, miniFrame, classer, miniTerminal, codeDiff, smoothLines, useSpring) { 'use strict'; | ||
React = React && Object.prototype.hasOwnProperty.call(React, 'default') ? React['default'] : React; | ||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
var React__default = /*#__PURE__*/_interopDefaultLegacy(React); | ||
/*! ***************************************************************************** | ||
@@ -23,3 +25,17 @@ Copyright (c) Microsoft Corporation. | ||
***************************************************************************** */ | ||
/* global Reflect, Promise */ | ||
var extendStatics = function(d, b) { | ||
extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; | ||
return extendStatics(d, b); | ||
}; | ||
function __extends(d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
} | ||
var __assign = function() { | ||
@@ -71,31 +87,445 @@ __assign = Object.assign || function __assign(t) { | ||
var e=[],t=[];function injector_1a6c3c54(n,r){if(n&&"undefined"!=typeof document){void 0===r&&(r={});var d,a=!0===r.prepend?"prepend":"append",i="undefined"!=typeof r.singleTag&&r.singleTag,s="undefined"!=typeof r.container?document.querySelector(r.container):document.getElementsByTagName("head")[0];if(i){var u=e.indexOf(s);-1===u&&(u=e.push(s)-1,t[u]={}),d=t[u]&&t[u][a]?t[u][a]:t[u][a]=o();}else d=o();65279===n.charCodeAt(0)&&(n=n.substring(1)),d.styleSheet?d.styleSheet.cssText+=n:d.appendChild(document.createTextNode(n));}function o(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),r.attributes)for(var t=Object.keys(r.attributes),n=0;n<t.length;n++)e.setAttribute(t[n],r.attributes[t[n]]);var d="prepend"===a?"afterbegin":"beforeend";return s.insertAdjacentElement(d,e),e}} | ||
const css_f2c17fbd = ".ch-editor-tab{border-right:1px solid #252526;width:120px;min-width:-webkit-fit-content;min-width:-moz-fit-content;min-width:fit-content;flex-shrink:0;position:relative;display:flex;white-space:nowrap;cursor:pointer;height:100%;box-sizing:border-box;padding-left:15px;padding-right:15px;background-color:#2d2d2d;color:hsla(0,0%,100%,.5)}.ch-editor-tab[data-active]{background-color:#1e1e1e;color:#fff}.ch-editor-tab>div{margin-top:auto;margin-bottom:auto;font-size:12px;line-height:1.4em;text-overflow:ellipsis}.ch-editor-body{background-color:#1e1e1e;height:100%;color:#ccc;font-size:15px;padding:5px 10px;line-height:1.1rem;box-sizing:border-box}.ch-editor-body code{line-height:20px}.ch-editor-terminal{position:absolute;overflow:hidden;bottom:0;width:100%;background-color:#1e1e1e;color:#e7e7e7;border-top:1px solid hsla(0,0%,50.2%,.35);padding:0 8px;box-sizing:border-box}.ch-editor-terminal-tab{text-transform:uppercase;padding:4px 10px 3px;font-size:11px;line-height:24px;display:flex}.ch-editor-terminal-tab>span{border-bottom:1px solid #e7e7e7}.ch-editor-terminal-content{margin-top:8px;height:calc(100% - 40px);box-sizing:border-box}.ch-editor-terminal-content .ch-terminal{font-size:12px;margin:0}"; | ||
injector_1a6c3c54(css_f2c17fbd,{"singleTag":true}); | ||
var DEFAULT_HEIGHT = 200; | ||
function EditorFrame(_a) { | ||
var files = _a.files, active = _a.active, children = _a.children, terminalPanel = _a.terminalPanel, rest = __rest(_a, ["files", "active", "children", "terminalPanel"]); | ||
return (React.createElement(miniFrame.MiniFrame, __assign({ titleBar: React.createElement(TabsContainer, { files: files, active: active }) }, rest), | ||
React.createElement("div", { className: "ch-editor-body" }, children), | ||
var files = _a.files, active = _a.active, children = _a.children, terminalPanel = _a.terminalPanel, height = _a.height, style = _a.style, button = _a.button, classes = _a.classes, rest = __rest(_a, ["files", "active", "children", "terminalPanel", "height", "style", "button", "classes"]); | ||
var c = classer.useClasser("ch-editor"); | ||
return (React__default['default'].createElement(miniFrame.MiniFrame, __assign({ titleBar: React__default['default'].createElement(TabsContainer, { files: files, active: active, button: button, classes: classes }), classes: classes, style: __assign({ height: height !== null && height !== void 0 ? height : DEFAULT_HEIGHT }, style) }, rest), | ||
React__default['default'].createElement("div", { className: c("body") }, children), | ||
terminalPanel)); | ||
} | ||
function TabsContainer(_a) { | ||
var files = _a.files, active = _a.active; | ||
return (React.createElement(React.Fragment, null, | ||
React.createElement(miniFrame.FrameButtons, null), | ||
files.map(function (fileName) { return (React.createElement("div", { key: fileName, className: "ch-editor-tab", "data-active": fileName === active || undefined }, | ||
React.createElement("div", null, fileName))); }), | ||
React.createElement("div", { style: { flex: 1 } }))); | ||
var files = _a.files, active = _a.active, button = _a.button, classes = _a.classes; | ||
var c = classer.useClasser("ch-editor-tab"); | ||
return (React__default['default'].createElement(React__default['default'].Fragment, null, | ||
React__default['default'].createElement(miniFrame.FrameButtons, null), | ||
files.map(function (fileName) { return (React__default['default'].createElement("div", { key: fileName, className: c("", fileName === active ? "active" : "inactive") }, | ||
React__default['default'].createElement("div", null, fileName))); }), | ||
React__default['default'].createElement("div", { style: { flex: 1 } }), | ||
button)); | ||
} | ||
function TerminalPanel(_a) { | ||
var height = _a.height, children = _a.children; | ||
return !height ? null : (React.createElement("div", { className: "ch-editor-terminal", style: { height: height } }, | ||
React.createElement("div", { className: "ch-editor-terminal-tab" }, | ||
React.createElement("span", null, "Terminal")), | ||
React.createElement("div", { className: "ch-editor-terminal-content" }, children))); | ||
return !height ? null : (React__default['default'].createElement("div", { className: "ch-editor-terminal", style: { height: height } }, | ||
React__default['default'].createElement("div", { className: "ch-editor-terminal-tab" }, | ||
React__default['default'].createElement("span", null, "Terminal")), | ||
React__default['default'].createElement("div", { className: "ch-editor-terminal-content" }, children))); | ||
} | ||
function MiniEditor(_a) { | ||
var _b = _a.progress, progress = _b === void 0 ? 0 : _b, _c = _a.backward, backward = _c === void 0 ? false : _c, code = _a.code, focus = _a.focus, lang = _a.lang, file = _a.file, ogSteps = _a.steps, rest = __rest(_a, ["progress", "backward", "code", "focus", "lang", "file", "steps"]); | ||
var useLayoutEffect = typeof window !== "undefined" | ||
? React__default['default'].useLayoutEffect | ||
: React__default['default'].useEffect; | ||
var DEFAULT_WIDTH = 200; | ||
function useDimensions(deps) { | ||
var ref = React__default['default'].useRef(null); | ||
var _a = __read(React__default['default'].useState(null), 2), dimensions = _a[0], setDimensions = _a[1]; | ||
var windowWidth = useWindowWidth(); | ||
var fullDeps = __spread(deps, [windowWidth]); | ||
useLayoutEffect(function () { | ||
var _a, _b, _c, _d, _e, _f, _g, _h; | ||
if (ref.current) { | ||
var rect = ref.current.getBoundingClientRect(); | ||
var pll = ref.current.querySelector(".prev-longest-line"); | ||
var nll = ref.current.querySelector(".next-longest-line"); | ||
// TODO is it clientWidth or clientRect? | ||
var plw = (_a = pll === null || pll === void 0 ? void 0 : pll.firstElementChild) === null || _a === void 0 ? void 0 : _a.clientWidth; | ||
var nlw = (_b = nll === null || nll === void 0 ? void 0 : nll.firstElementChild) === null || _b === void 0 ? void 0 : _b.clientWidth; | ||
var plh = (_d = (_c = pll === null || pll === void 0 ? void 0 : pll.firstElementChild) === null || _c === void 0 ? void 0 : _c.clientHeight) !== null && _d !== void 0 ? _d : 20; | ||
var nlh = (_f = (_e = nll === null || nll === void 0 ? void 0 : nll.firstElementChild) === null || _e === void 0 ? void 0 : _e.clientHeight) !== null && _f !== void 0 ? _f : 20; | ||
var colWidth = pll | ||
? plw / (((_g = pll.textContent) === null || _g === void 0 ? void 0 : _g.length) || 1) | ||
: nlw / (((_h = nll.textContent) === null || _h === void 0 ? void 0 : _h.length) || 1); | ||
setDimensions({ | ||
width: rect.width, | ||
height: rect.height, | ||
lineWidths: [ | ||
plw || nlw || DEFAULT_WIDTH, | ||
nlw || plw || DEFAULT_WIDTH, | ||
], | ||
lineHeight: Math.max(plh, nlh), | ||
colWidth: colWidth, | ||
deps: fullDeps, | ||
}); | ||
} | ||
}, fullDeps); | ||
if (!dimensions || | ||
depsChanged(dimensions.deps, fullDeps)) { | ||
return [ref, null]; | ||
} | ||
else { | ||
return [ref, dimensions]; | ||
} | ||
} | ||
function depsChanged(oldDeps, newDeps) { | ||
for (var i = 0; i < oldDeps.length; i++) { | ||
if (oldDeps[i] !== newDeps[i]) | ||
return true; | ||
} | ||
return false; | ||
} | ||
function useWindowWidth() { | ||
var _a = __read(React__default['default'].useState(undefined), 2), width = _a[0], setWidth = _a[1]; | ||
React__default['default'].useEffect(function () { | ||
function handleResize() { | ||
setWidth(window.innerWidth); | ||
} | ||
window.addEventListener("resize", handleResize); | ||
return function () { | ||
return window.removeEventListener("resize", handleResize); | ||
}; | ||
}, []); | ||
return width; | ||
} | ||
function getFocusIndexes(focus, lines) { | ||
if (!focus) { | ||
return __spread(lines.keys()); | ||
} | ||
else { | ||
var parsed = parseFocus(focus); | ||
var focusedIndexes = Object.keys(parsed).map(function (i) { | ||
return parseInt(i, 10); | ||
}); | ||
return focusedIndexes; | ||
} | ||
} | ||
function getFocusByKey(focus, keys) { | ||
if (!focus) { | ||
// focus all lines | ||
return fromEntries(keys.map(function (key) { return [key, true]; })); | ||
} | ||
else { | ||
var parsed_1 = parseFocus(focus); | ||
var byKey_1 = {}; | ||
Object.keys(parsed_1).forEach(function (i) { | ||
var key = keys[parseInt(i, 10)]; | ||
byKey_1[key] = parsed_1[parseInt(i, 10)]; | ||
}); | ||
return byKey_1; | ||
} | ||
} | ||
function parseFocus(focus) { | ||
if (!focus) { | ||
throw new Error("Focus cannot be empty"); | ||
} | ||
try { | ||
var parts = focus | ||
.split(/,(?![^\[]*\])/g) | ||
.map(parsePart); | ||
return fromEntries(parts.flat()); | ||
} | ||
catch (error) { | ||
// TODO enhance error | ||
throw error; | ||
} | ||
} | ||
function parsePart(part) { | ||
// a part could be | ||
// - a line number: "2" | ||
// - a line range: "5:9" | ||
// - a line number with a column selector: "2[1,3:5,9]" | ||
var columnsMatch = part.match(/(\d+)\[(.+)\]/); | ||
if (columnsMatch) { | ||
var _a = __read(columnsMatch, 3), line = _a[1], columns = _a[2]; | ||
var columnsList = columns.split(",").map(expandString); | ||
var lineIndex = Number(line) - 1; | ||
var columnIndexes = columnsList.flat().map(function (c) { return c - 1; }); | ||
return [[lineIndex, columnIndexes]]; | ||
} | ||
else { | ||
return expandString(part).map(function (lineNumber) { return [ | ||
lineNumber - 1, | ||
true, | ||
]; }); | ||
} | ||
} | ||
function expandString(part) { | ||
// Transforms something like | ||
// - "1:3" to [1,2,3] | ||
// - "4" to [4] | ||
var _a = __read(part.split(":"), 2), start = _a[0], end = _a[1]; | ||
if (!isNaturalNumber(start)) { | ||
throw new FocusNumberError(start); | ||
} | ||
var startNumber = Number(start); | ||
if (startNumber < 1) { | ||
throw new LineOrColumnNumberError(); | ||
} | ||
if (!end) { | ||
return [startNumber]; | ||
} | ||
else { | ||
if (!isNaturalNumber(end)) { | ||
throw new FocusNumberError(end); | ||
} | ||
var list = []; | ||
for (var i = startNumber; i <= +end; i++) { | ||
list.push(i); | ||
} | ||
return list; | ||
} | ||
} | ||
function isNaturalNumber(n) { | ||
n = n.toString(); // force the value in case it is not | ||
var n1 = Math.abs(n), n2 = parseInt(n, 10); | ||
return !isNaN(n1) && n2 === n1 && n1.toString() === n; | ||
} | ||
var LineOrColumnNumberError = /** @class */ (function (_super) { | ||
__extends(LineOrColumnNumberError, _super); | ||
function LineOrColumnNumberError() { | ||
var _newTarget = this.constructor; | ||
var _this = _super.call(this, "Invalid line or column number in focus string") || this; | ||
Object.setPrototypeOf(_this, _newTarget.prototype); | ||
return _this; | ||
} | ||
return LineOrColumnNumberError; | ||
}(Error)); | ||
var FocusNumberError = /** @class */ (function (_super) { | ||
__extends(FocusNumberError, _super); | ||
function FocusNumberError(number) { | ||
var _newTarget = this.constructor; | ||
var _this = _super.call(this, "Invalid number \"" + number + "\" in focus string") || this; | ||
_this.number = number; | ||
Object.setPrototypeOf(_this, _newTarget.prototype); | ||
return _this; | ||
} | ||
return FocusNumberError; | ||
}(Error)); | ||
function fromEntries(pairs) { | ||
var result = {}; | ||
var index = -1, length = pairs == null ? 0 : pairs.length; | ||
while (++index < length) { | ||
var pair = pairs[index]; | ||
result[pair[0]] = pair[1]; | ||
} | ||
return result; | ||
} | ||
function Code(_a) { | ||
var prevCode = _a.prevCode, prevFocus = _a.prevFocus, nextCode = _a.nextCode, nextFocus = _a.nextFocus, progress = _a.progress, language = _a.language, parentHeight = _a.parentHeight, minColumns = _a.minColumns; | ||
var _b = useLineProps(prevCode, nextCode, language, prevFocus, nextFocus), prevLines = _b.prevLines, nextLines = _b.nextLines, prevFocusIndexes = _b.prevFocusIndexes, nextFocusIndexes = _b.nextFocusIndexes, prevLongestLine = _b.prevLongestLine, nextLongestLine = _b.nextLongestLine; | ||
var _c = __read(useDimensions([ | ||
parentHeight, | ||
prevLongestLine, | ||
nextLongestLine, | ||
]), 2), ref = _c[0], dimensions = _c[1]; | ||
return (React__default['default'].createElement("pre", { ref: ref, className: "language-" + language, style: { | ||
position: "absolute", | ||
top: 0, | ||
bottom: 0, | ||
right: 16, | ||
left: 16, | ||
padding: 0, | ||
margin: 0, | ||
overflow: "hidden", | ||
opacity: dimensions ? 1 : 0, | ||
} }, | ||
React__default['default'].createElement("code", null, dimensions ? (React__default['default'].createElement(smoothLines.SmoothLines, { center: false, progress: progress, containerWidth: dimensions.width, containerHeight: dimensions.height, prevLines: prevLines, nextLines: nextLines, lineHeight: dimensions.lineHeight, lineWidth: dimensions.lineWidths.map(function (lw) { | ||
return Math.max(lw, dimensions.colWidth * minColumns); | ||
}), prevFocus: prevFocusIndexes, nextFocus: nextFocusIndexes, maxZoom: 1 })) : (React__default['default'].createElement(React__default['default'].Fragment, null, | ||
React__default['default'].createElement("div", { className: "prev-longest-line" }, prevLongestLine), | ||
React__default['default'].createElement("div", { className: "next-longest-line" }, nextLongestLine)))))); | ||
} | ||
function useLineProps(prevCode, nextCode, language, prevFocus, nextFocus) { | ||
return React__default['default'].useMemo(function () { | ||
var _a, _b; | ||
var _c = codeDiff.codeDiff({ | ||
prevCode: prevCode, | ||
nextCode: nextCode, | ||
lang: language, | ||
}), prevKeys = _c.prevKeys, nextKeys = _c.nextKeys, codeMap = _c.codeMap; | ||
var prevFocusByKey = getFocusByKey(prevFocus, prevKeys); | ||
var prevFocusIndexes = getFocusIndexes(prevFocus, prevKeys); | ||
var prevLongestLineIndex = longestLineIndex(prevCode, prevFocusIndexes); | ||
var nextFocusByKey = getFocusByKey(nextFocus, nextKeys); | ||
var nextFocusIndexes = getFocusIndexes(nextFocus, nextKeys); | ||
var nextLongestLineIndex = longestLineIndex(nextCode, nextFocusIndexes); | ||
var prevLines = prevKeys.map(function (key) { | ||
var prevFocus = prevFocusByKey[key]; | ||
var nextFocus = nextFocusByKey[key]; | ||
var focusPerColumn = Array.isArray(prevFocus) || Array.isArray(nextFocus); | ||
if (!focusPerColumn) { | ||
return { | ||
key: key, | ||
element: React__default['default'].createElement(Line, { line: codeMap[key] }), | ||
}; | ||
} | ||
else { | ||
return { | ||
key: key, | ||
element: React__default['default'].createElement(Line, { line: codeMap[key] }), | ||
elementWithProgress: function (progress) { return (React__default['default'].createElement(ColumnedLine, { line: codeMap[key], progress: progress, prevFocus: prevFocus, nextFocus: nextFocus })); }, | ||
}; | ||
} | ||
}); | ||
var prevLongestLine = prevLongestLineIndex == null | ||
? null | ||
: (_a = prevLines[prevLongestLineIndex]) === null || _a === void 0 ? void 0 : _a.element; | ||
var nextLines = nextKeys.map(function (key) { | ||
var prevFocus = prevFocusByKey[key]; | ||
var nextFocus = nextFocusByKey[key]; | ||
var focusPerColumn = Array.isArray(prevFocus) || Array.isArray(nextFocus); | ||
if (!focusPerColumn) { | ||
return { | ||
key: key, | ||
element: React__default['default'].createElement(Line, { line: codeMap[key] }), | ||
}; | ||
} | ||
else { | ||
return { | ||
key: key, | ||
element: React__default['default'].createElement(Line, { line: codeMap[key] }), | ||
elementWithProgress: function (progress) { return (React__default['default'].createElement(ColumnedLine, { line: codeMap[key], progress: progress, prevFocus: prevFocus, nextFocus: nextFocus })); }, | ||
}; | ||
} | ||
}); | ||
var nextLongestLine = nextLongestLineIndex == null | ||
? null | ||
: (_b = nextLines[nextLongestLineIndex]) === null || _b === void 0 ? void 0 : _b.element; | ||
return { | ||
prevLines: prevLines, | ||
nextLines: nextLines, | ||
prevFocusIndexes: prevFocusIndexes, | ||
nextFocusIndexes: nextFocusIndexes, | ||
prevLongestLine: prevLongestLine, | ||
nextLongestLine: nextLongestLine, | ||
}; | ||
}, [prevCode, nextCode, language, prevFocus, nextFocus]); | ||
} | ||
function Line(_a) { | ||
var line = _a.line; | ||
return (React__default['default'].createElement("div", { style: { | ||
display: "inline-block", | ||
} }, line.map(function (_a, i) { | ||
var _b = __read(_a, 2), token = _b[0], type = _b[1]; | ||
return (React__default['default'].createElement("span", { className: "token " + type, key: i + 1 }, token)); | ||
}))); | ||
} | ||
var OFF_OPACITY = 0.33; | ||
function ColumnedLine(_a) { | ||
var line = _a.line, progress = _a.progress, prevFocus = _a.prevFocus, nextFocus = _a.nextFocus; | ||
var columns = React__default['default'].useMemo(function () { | ||
var chars = flatMap(line, function (_a) { | ||
var _b = __read(_a, 2), token = _b[0], type = _b[1]; | ||
return token.split("").map(function (char) { return [char, type]; }); | ||
}); | ||
return chars.map(function (_a, i) { | ||
var _b = __read(_a, 2), char = _b[0], type = _b[1]; | ||
return ({ | ||
char: char, | ||
type: type, | ||
fromOpacity: !prevFocus | ||
? 0.99 // because the line is already transparent | ||
: prevFocus === true || prevFocus.includes(i) | ||
? 0.99 | ||
: OFF_OPACITY, | ||
toOpacity: !nextFocus | ||
? 0.99 // because the line is already transparent | ||
: nextFocus === true || nextFocus.includes(i) | ||
? 0.99 | ||
: OFF_OPACITY, | ||
}); | ||
}); | ||
}, [line, prevFocus, nextFocus]); | ||
return (React__default['default'].createElement("div", { style: { | ||
display: "inline-block", | ||
width: "100%", | ||
} }, columns.map(function (_a, i) { | ||
var char = _a.char, type = _a.type, fromOpacity = _a.fromOpacity, toOpacity = _a.toOpacity; | ||
return (React__default['default'].createElement("span", { className: "token " + type, key: i + 1, style: { | ||
opacity: tween(fromOpacity, toOpacity, progress), | ||
} }, char)); | ||
}))); | ||
} | ||
function tween(p, n, t) { | ||
return (n - p) * t + p; | ||
} | ||
var newlineRe = /\r\n|\r|\n/; | ||
function longestLineIndex(code, focusIndexes) { | ||
var first = Math.min.apply(Math, __spread(focusIndexes)); | ||
var last = Math.max.apply(Math, __spread(focusIndexes)); | ||
var focusedLines = code == null | ||
? [] | ||
: code.split(newlineRe).slice(first, last + 1); | ||
if (!focusedLines.length) { | ||
return null; | ||
} | ||
var longestIndex = 0; | ||
for (var i = 1; i < focusedLines.length; i++) { | ||
if (focusedLines[i].length > | ||
focusedLines[longestIndex].length) { | ||
longestIndex = i; | ||
} | ||
} | ||
return first + longestIndex; | ||
} | ||
function flatMap(array, callbackfn) { | ||
var _a; | ||
return (_a = Array.prototype).concat.apply(_a, __spread(array.map(callbackfn))); | ||
} | ||
function useForwardTransitions(steps) { | ||
return React__default['default'].useMemo(function () { | ||
var transitions = steps.map(function (step, i) { | ||
var prevStepForFile = null; | ||
for (var j = i - 1; j >= 0; j--) { | ||
if (steps[j].file === step.file) { | ||
prevStepForFile = steps[j]; | ||
break; | ||
} | ||
} | ||
return { | ||
prevCode: prevStepForFile && prevStepForFile.code, | ||
prevFocus: prevStepForFile && prevStepForFile.focus, | ||
nextCode: step.code, | ||
nextFocus: step.focus, | ||
file: step.file, | ||
lang: step.lang, | ||
}; | ||
}); | ||
var lastStep = steps[steps.length - 1]; | ||
transitions.push({ | ||
file: lastStep.file, | ||
prevCode: lastStep.code, | ||
prevFocus: lastStep.focus, | ||
nextCode: null, | ||
nextFocus: null, | ||
lang: lastStep.lang, | ||
}); | ||
return transitions; | ||
}, [steps]); | ||
} | ||
function useBackwardTransitions(steps) { | ||
return React__default['default'].useMemo(function () { | ||
var transitions = []; | ||
transitions.push({ | ||
prevCode: null, | ||
prevFocus: null, | ||
nextCode: steps[0].code, | ||
nextFocus: steps[0].focus, | ||
lang: steps[0].lang, | ||
file: steps[0].file, | ||
}); | ||
steps.forEach(function (step, i) { | ||
var nextStepForFile = null; | ||
for (var j = i + 1; j < steps.length; j++) { | ||
if (steps[j].file === step.file) { | ||
nextStepForFile = steps[j]; | ||
break; | ||
} | ||
} | ||
transitions.push({ | ||
prevCode: step.code, | ||
prevFocus: step.focus, | ||
nextCode: nextStepForFile && nextStepForFile.code, | ||
nextFocus: nextStepForFile && nextStepForFile.focus, | ||
lang: step.lang, | ||
file: step.file, | ||
}); | ||
}); | ||
return transitions; | ||
}, [steps]); | ||
} | ||
function MiniEditor(props) { | ||
var _a = props.progress, progress = _a === void 0 ? 0 : _a, _b = props.backward, backward = _b === void 0 ? false : _b, code = props.code, focus = props.focus, lang = props.lang, file = props.file, ogSteps = props.steps, ogTabs = props.tabs, _c = props.minColumns, minColumns = _c === void 0 ? 50 : _c, height = props.height, rest = __rest(props, ["progress", "backward", "code", "focus", "lang", "file", "steps", "tabs", "minColumns", "height"]); | ||
var _d = useSteps(ogSteps, { | ||
@@ -106,23 +536,56 @@ code: code, | ||
file: file, | ||
tabs: ogTabs, | ||
}), steps = _d.steps, files = _d.files, stepsByFile = _d.stepsByFile; | ||
var activeStepIndex = backward ? Math.floor(progress) : Math.ceil(progress); | ||
var activeStepIndex = backward | ||
? Math.floor(progress) | ||
: Math.ceil(progress); | ||
var activeStep = steps[activeStepIndex]; | ||
var activeFile = (activeStep && activeStep.file) || ""; | ||
var activeSteps = stepsByFile[activeFile] || []; | ||
var index = activeSteps.indexOf(activeStep); | ||
var activeProgress = Math.min(Math.max(progress - activeStepIndex + index, 0), activeSteps.length - 1); | ||
var tabs = activeStep.tabs || files; | ||
var terminalHeight = getTerminalHeight(steps, progress); | ||
var terminalSteps = steps.map(function (s) { return ({ text: (s && s.terminal) || "" }); }); | ||
return (React.createElement(EditorFrame, __assign({ files: tabs, active: activeFile, terminalPanel: React.createElement(TerminalPanel, { height: terminalHeight }, | ||
React.createElement(miniTerminal.InnerTerminal, { steps: terminalSteps, progress: progress })) }, rest), activeSteps.length > 0 && (React.createElement(standalone.CodeSurfer, { key: activeFile, progress: activeProgress, steps: activeSteps, theme: themes.vsDark, nonblocking: true })))); | ||
var terminalSteps = steps.map(function (s) { return ({ | ||
text: (s && s.terminal) || "", | ||
}); }); | ||
var contentSteps = useStepsWithDefaults({ code: code, focus: focus, lang: lang, file: file }, ogSteps || []); | ||
return (React__default['default'].createElement(EditorFrame, __assign({ files: tabs, active: activeFile, terminalPanel: React__default['default'].createElement(TerminalPanel, { height: terminalHeight }, | ||
React__default['default'].createElement(miniTerminal.InnerTerminal, { steps: terminalSteps, progress: progress })), height: height }, rest), activeSteps.length > 0 && (React__default['default'].createElement(EditorContent, { key: activeFile, backward: backward, progress: progress, steps: contentSteps, parentHeight: height, minColumns: minColumns })))); | ||
} | ||
function useStepsWithDefaults(defaults, steps) { | ||
var files = __spread(new Set(steps.map(function (s) { return coalesce(s.file, defaults.file, ""); }))); | ||
return steps.map(function (step) { | ||
return { | ||
code: coalesce(step.code, defaults.code, ""), | ||
file: coalesce(step.file, defaults.file, ""), | ||
focus: coalesce(step.focus, defaults.focus, ""), | ||
lang: coalesce(step.lang, defaults.lang, "javascript"), | ||
tabs: coalesce(step.tabs, defaults.tabs, files), | ||
terminal: step.terminal || defaults.terminal, | ||
}; | ||
}); | ||
} | ||
function coalesce(a, b, c) { | ||
return a != null ? a : b != null ? b : c; | ||
} | ||
function EditorContent(_a) { | ||
var progress = _a.progress, backward = _a.backward, steps = _a.steps, parentHeight = _a.parentHeight, minColumns = _a.minColumns; | ||
var fwdTransitions = useForwardTransitions(steps); | ||
var bwdTransitions = useBackwardTransitions(steps); | ||
var transitionIndex = Math.ceil(progress); | ||
var _b = backward | ||
? bwdTransitions[transitionIndex] | ||
: fwdTransitions[transitionIndex], prevCode = _b.prevCode, nextCode = _b.nextCode, prevFocus = _b.prevFocus, nextFocus = _b.nextFocus, lang = _b.lang; | ||
return (React__default['default'].createElement(Code, { prevCode: prevCode || nextCode, nextCode: nextCode || prevCode, prevFocus: prevFocus, nextFocus: nextFocus, language: lang, progress: progress - transitionIndex + 1, parentHeight: parentHeight, minColumns: minColumns })); | ||
} | ||
function useSteps(ogSteps, _a) { | ||
var _b = _a.code, code = _b === void 0 ? "" : _b, focus = _a.focus, lang = _a.lang, file = _a.file; | ||
return React.useMemo(function () { | ||
var _b = _a.code, code = _b === void 0 ? "" : _b, focus = _a.focus, lang = _a.lang, file = _a.file, tabs = _a.tabs; | ||
return React__default['default'].useMemo(function () { | ||
var steps = (ogSteps === null || ogSteps === void 0 ? void 0 : ogSteps.map(function (s) { return (__assign({ code: code, | ||
focus: focus, | ||
lang: lang, | ||
file: file }, s)); })) || [{ code: code, focus: focus, lang: lang, file: file }]; | ||
var files = __spread(new Set(steps.map(function (s) { return s.file; }).filter(function (f) { return f != null; }))); | ||
file: file, | ||
tabs: tabs }, s)); })) || [{ code: code, focus: focus, lang: lang, file: file, tabs: tabs }]; | ||
var files = __spread(new Set(steps | ||
.map(function (s) { return s.file; }) | ||
.filter(function (f) { return f != null; }))); | ||
var stepsByFile = {}; | ||
@@ -138,3 +601,3 @@ steps.forEach(function (s) { | ||
return { steps: steps, files: files, stepsByFile: stepsByFile }; | ||
}, [ogSteps, code, focus, lang, file]); | ||
}, [ogSteps, code, focus, lang, file, tabs]); | ||
} | ||
@@ -159,3 +622,32 @@ var MAX_HEIGHT = 150; | ||
function MiniEditorWithState(_a) { | ||
var focus = _a.focus, code = _a.code, rest = __rest(_a, ["focus", "code"]); | ||
var _b = __read(usePrevFocus(code, focus), 2), steps = _b[0], progress = _b[1]; | ||
return (React__default['default'].createElement(MiniEditor, __assign({ progress: progress, steps: steps }, rest))); | ||
} | ||
function usePrevFocus(code, focus) { | ||
var _a = __read(React__default['default'].useState({ | ||
target: 0, | ||
steps: [{ focus: focus, code: code }], | ||
}), 2), state = _a[0], setState = _a[1]; | ||
React__default['default'].useEffect(function () { | ||
var last = state.steps[state.steps.length - 1]; | ||
if (last.focus !== focus || last.code !== code) { | ||
setState(function (s) { return ({ | ||
target: s.target + 1, | ||
steps: __spread(s.steps, [{ focus: focus, code: code }]), | ||
}); }); | ||
} | ||
}, [focus, code]); | ||
var _b = __read(useSpring.useSpring(state.target, { | ||
stiffness: 256, | ||
damping: 24, | ||
mass: 0.2, | ||
decimals: 3, | ||
}), 1), progress = _b[0]; | ||
return [state.steps, progress]; | ||
} | ||
exports.MiniEditor = MiniEditor; | ||
exports.MiniEditorWithState = MiniEditorWithState; | ||
@@ -162,0 +654,0 @@ Object.defineProperty(exports, '__esModule', { value: true }); |
import React from "react"; | ||
import { Classes } from "@code-hike/classer"; | ||
export { MiniEditor }; | ||
@@ -11,3 +12,3 @@ declare type MiniEditorStep = { | ||
}; | ||
declare type MiniEditorProps = { | ||
export declare type MiniEditorProps = { | ||
progress?: number; | ||
@@ -19,4 +20,9 @@ backward?: boolean; | ||
file?: string; | ||
tabs?: string[]; | ||
steps?: MiniEditorStep[]; | ||
height?: number; | ||
minColumns?: number; | ||
button?: React.ReactNode; | ||
classes?: Classes; | ||
} & React.PropsWithoutRef<JSX.IntrinsicElements["div"]>; | ||
declare function MiniEditor({ progress, backward, code, focus, lang, file, steps: ogSteps, ...rest }: MiniEditorProps): JSX.Element; | ||
declare function MiniEditor(props: MiniEditorProps): JSX.Element; |
{ | ||
"name": "@code-hike/mini-editor", | ||
"version": "0.2.1", | ||
"version": "0.3.0--canary.32.323f72f.0", | ||
"main": "dist/index.js", | ||
"typings": "dist/index.d.ts", | ||
"module": "dist/index.esm.js", | ||
"style": "dist/index.css", | ||
"files": [ | ||
@@ -11,7 +12,7 @@ "dist" | ||
"scripts": { | ||
"build": "ch-build", | ||
"watch": "ch-build --watch" | ||
"x": "x", | ||
"publish-canary": "yarn publish --tag canary --access public" | ||
}, | ||
"devDependencies": { | ||
"@code-hike/build": "0.0.1", | ||
"@code-hike/script": "0.3.0--canary.32.323f72f.0", | ||
"@types/react": "^16.9.38", | ||
@@ -21,5 +22,8 @@ "react": "^16.13.1" | ||
"dependencies": { | ||
"@code-hike/mini-terminal": "0.2.1", | ||
"@code-hike/mini-frame": "0.2.1", | ||
"@code-surfer/standalone": "^3.1.1" | ||
"@code-hike/classer": "0.3.0--canary.32.323f72f.0", | ||
"@code-hike/code-diff": "0.3.0--canary.32.323f72f.0", | ||
"@code-hike/mini-frame": "0.3.0--canary.32.323f72f.0", | ||
"@code-hike/mini-terminal": "0.3.0--canary.32.323f72f.0", | ||
"@code-hike/smooth-lines": "0.3.0--canary.32.323f72f.0", | ||
"use-spring": "^0.2.3" | ||
}, | ||
@@ -34,2 +38,3 @@ "peerDependencies": { | ||
"repository": "code-hike/codehike", | ||
"author": "Rodrigo Pombo", | ||
"license": "MIT", | ||
@@ -39,3 +44,4 @@ "funding": { | ||
"url": "https://opencollective.com/codehike" | ||
} | ||
}, | ||
"gitHead": "323f72f61683cacadde7f5396509202ae58a45bc" | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
102697
18
2079
1
1
7
1
+ Addeduse-spring@^0.2.3
+ Added@code-hike/classer@0.3.0--canary.32.323f72f.0(transitive)
+ Added@code-hike/code-diff@0.3.0--canary.32.323f72f.0(transitive)
+ Added@code-hike/mini-frame@0.3.0--canary.32.323f72f.0(transitive)
+ Added@code-hike/mini-terminal@0.3.0--canary.32.323f72f.0(transitive)
+ Added@code-hike/smooth-lines@0.3.0--canary.32.323f72f.0(transitive)
+ Addedreact@18.3.1(transitive)
+ Addedreact-dom@18.3.1(transitive)
+ Addedscheduler@0.23.2(transitive)
+ Addeduse-spring@0.2.4(transitive)
- Removed@code-surfer/standalone@^3.1.1
- Removed@babel/code-frame@7.26.2(transitive)
- Removed@babel/generator@7.26.9(transitive)
- Removed@babel/helper-module-imports@7.25.9(transitive)
- Removed@babel/helper-string-parser@7.25.9(transitive)
- Removed@babel/helper-validator-identifier@7.25.9(transitive)
- Removed@babel/parser@7.26.9(transitive)
- Removed@babel/runtime@7.26.9(transitive)
- Removed@babel/template@7.26.9(transitive)
- Removed@babel/traverse@7.26.9(transitive)
- Removed@babel/types@7.26.9(transitive)
- Removed@code-hike/mini-frame@0.2.1(transitive)
- Removed@code-hike/mini-terminal@0.2.1(transitive)
- Removed@code-surfer/standalone@3.1.1(transitive)
- Removed@code-surfer/step-parser@3.1.1(transitive)
- Removed@code-surfer/themes@3.1.1(transitive)
- Removed@emotion/cache@10.0.29(transitive)
- Removed@emotion/core@10.3.1(transitive)
- Removed@emotion/css@10.0.27(transitive)
- Removed@emotion/hash@0.8.0(transitive)
- Removed@emotion/is-prop-valid@0.8.8(transitive)
- Removed@emotion/memoize@0.7.4(transitive)
- Removed@emotion/serialize@0.11.16(transitive)
- Removed@emotion/sheet@0.9.4(transitive)
- Removed@emotion/stylis@0.8.5(transitive)
- Removed@emotion/unitless@0.7.5(transitive)
- Removed@emotion/utils@0.11.3(transitive)
- Removed@emotion/weak-memoize@0.2.5(transitive)
- Removed@jridgewell/gen-mapping@0.3.8(transitive)
- Removed@jridgewell/resolve-uri@3.1.2(transitive)
- Removed@jridgewell/set-array@1.2.1(transitive)
- Removed@jridgewell/sourcemap-codec@1.5.0(transitive)
- Removed@jridgewell/trace-mapping@0.3.25(transitive)
- Removed@mdx-js/react@1.6.22(transitive)
- Removed@styled-system/css@5.1.5(transitive)
- Removed@types/parse-json@4.0.2(transitive)
- Removed@types/react@19.0.10(transitive)
- Removed@types/styled-system@5.1.23(transitive)
- Removed@types/styled-system__css@5.0.21(transitive)
- Removed@types/table@4.0.7(transitive)
- Removed@types/theme-ui@0.2.8(transitive)
- Removedarray-buffer-byte-length@1.0.2(transitive)
- Removedarray.prototype.flat@1.3.3(transitive)
- Removedarraybuffer.prototype.slice@1.0.4(transitive)
- Removedasync-function@1.0.0(transitive)
- Removedavailable-typed-arrays@1.0.7(transitive)
- Removedbabel-plugin-emotion@10.2.2(transitive)
- Removedbabel-plugin-macros@2.8.0(transitive)
- Removedbabel-plugin-syntax-jsx@6.18.0(transitive)
- Removedcall-bind@1.0.8(transitive)
- Removedcall-bind-apply-helpers@1.0.2(transitive)
- Removedcall-bound@1.0.3(transitive)
- Removedcallsites@3.1.0(transitive)
- Removedconvert-source-map@1.9.0(transitive)
- Removedcosmiconfig@6.0.0(transitive)
- Removedcsstype@2.6.213.1.3(transitive)
- Removeddata-view-buffer@1.0.2(transitive)
- Removeddata-view-byte-length@1.0.2(transitive)
- Removeddata-view-byte-offset@1.0.1(transitive)
- Removeddebug@4.4.0(transitive)
- Removeddeepmerge@4.3.1(transitive)
- Removeddefine-data-property@1.1.4(transitive)
- Removeddefine-properties@1.2.1(transitive)
- Removeddunder-proto@1.0.1(transitive)
- Removederror-ex@1.3.2(transitive)
- Removedes-abstract@1.23.9(transitive)
- Removedes-define-property@1.0.1(transitive)
- Removedes-errors@1.3.0(transitive)
- Removedes-object-atoms@1.1.1(transitive)
- Removedes-set-tostringtag@2.1.0(transitive)
- Removedes-shim-unscopables@1.1.0(transitive)
- Removedes-to-primitive@1.3.0(transitive)
- Removedescape-string-regexp@1.0.5(transitive)
- Removedfind-root@1.1.0(transitive)
- Removedfor-each@0.3.5(transitive)
- Removedfunction-bind@1.1.2(transitive)
- Removedfunction.prototype.name@1.1.8(transitive)
- Removedfunctions-have-names@1.2.3(transitive)
- Removedget-intrinsic@1.3.0(transitive)
- Removedget-proto@1.0.1(transitive)
- Removedget-symbol-description@1.1.0(transitive)
- Removedglobals@11.12.0(transitive)
- Removedglobalthis@1.0.4(transitive)
- Removedgopd@1.2.0(transitive)
- Removedhas-bigints@1.1.0(transitive)
- Removedhas-property-descriptors@1.0.2(transitive)
- Removedhas-proto@1.2.0(transitive)
- Removedhas-symbols@1.1.0(transitive)
- Removedhas-tostringtag@1.0.2(transitive)
- Removedhasown@2.0.2(transitive)
- Removedimport-fresh@3.3.1(transitive)
- Removedinternal-slot@1.1.0(transitive)
- Removedis-array-buffer@3.0.5(transitive)
- Removedis-arrayish@0.2.1(transitive)
- Removedis-async-function@2.1.1(transitive)
- Removedis-bigint@1.1.0(transitive)
- Removedis-boolean-object@1.2.2(transitive)
- Removedis-callable@1.2.7(transitive)
- Removedis-core-module@2.16.1(transitive)
- Removedis-data-view@1.0.2(transitive)
- Removedis-date-object@1.1.0(transitive)
- Removedis-finalizationregistry@1.1.1(transitive)
- Removedis-generator-function@1.1.0(transitive)
- Removedis-map@2.0.3(transitive)
- Removedis-number-object@1.1.1(transitive)
- Removedis-regex@1.2.1(transitive)
- Removedis-set@2.0.3(transitive)
- Removedis-shared-array-buffer@1.0.4(transitive)
- Removedis-string@1.1.1(transitive)
- Removedis-symbol@1.1.1(transitive)
- Removedis-typed-array@1.1.15(transitive)
- Removedis-weakmap@2.0.2(transitive)
- Removedis-weakref@1.1.1(transitive)
- Removedis-weakset@2.0.4(transitive)
- Removedisarray@2.0.5(transitive)
- Removedjsesc@3.1.0(transitive)
- Removedjson-parse-even-better-errors@2.3.1(transitive)
- Removedlines-and-columns@1.2.4(transitive)
- Removedmath-intrinsics@1.1.0(transitive)
- Removedms@2.1.3(transitive)
- Removedobject-assign@4.1.1(transitive)
- Removedobject-inspect@1.13.4(transitive)
- Removedobject-keys@1.1.1(transitive)
- Removedobject.assign@4.1.7(transitive)
- Removedown-keys@1.0.1(transitive)
- Removedparent-module@1.0.1(transitive)
- Removedparse-json@5.2.0(transitive)
- Removedpath-parse@1.0.7(transitive)
- Removedpath-type@4.0.0(transitive)
- Removedpicocolors@1.1.1(transitive)
- Removedpossible-typed-array-names@1.1.0(transitive)
- Removedprop-types@15.8.1(transitive)
- Removedreact@16.14.017.0.2(transitive)
- Removedreact-is@16.13.1(transitive)
- Removedrebound@0.1.0(transitive)
- Removedreflect.getprototypeof@1.0.10(transitive)
- Removedregenerator-runtime@0.14.1(transitive)
- Removedregexp.prototype.flags@1.5.4(transitive)
- Removedresolve@1.22.10(transitive)
- Removedresolve-from@4.0.0(transitive)
- Removedsafe-array-concat@1.1.3(transitive)
- Removedsafe-push-apply@1.0.0(transitive)
- Removedsafe-regex-test@1.1.0(transitive)
- Removedset-function-length@1.2.2(transitive)
- Removedset-function-name@2.0.2(transitive)
- Removedset-proto@1.0.0(transitive)
- Removedshell-quote@1.8.2(transitive)
- Removedside-channel@1.1.0(transitive)
- Removedside-channel-list@1.0.0(transitive)
- Removedside-channel-map@1.0.1(transitive)
- Removedside-channel-weakmap@1.0.2(transitive)
- Removedsource-map@0.5.7(transitive)
- Removedstring.prototype.trim@1.2.10(transitive)
- Removedstring.prototype.trimend@1.0.9(transitive)
- Removedstring.prototype.trimstart@1.0.8(transitive)
- Removedsupports-preserve-symlinks-flag@1.0.0(transitive)
- Removedtheme-ui@0.2.52(transitive)
- Removedtyped-array-buffer@1.0.3(transitive)
- Removedtyped-array-byte-length@1.0.3(transitive)
- Removedtyped-array-byte-offset@1.0.4(transitive)
- Removedtyped-array-length@1.0.7(transitive)
- Removedunbox-primitive@1.1.0(transitive)
- Removedwhich-boxed-primitive@1.1.1(transitive)
- Removedwhich-builtin-type@1.2.1(transitive)
- Removedwhich-collection@1.0.2(transitive)
- Removedwhich-typed-array@1.1.18(transitive)
- Removedyaml@1.10.2(transitive)