New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@code-hike/mini-editor

Package Overview
Dependencies
Maintainers
1
Versions
131
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@code-hike/mini-editor - npm Package Compare versions

Comparing version 0.2.1 to 0.3.0--canary.32.323f72f.0

dist/code-tween.d.ts

10

dist/editor-frame.d.ts
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"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc