code-surfer
Version:
Rad code slides
1,987 lines (1,765 loc) • 62.1 kB
JavaScript
import React from 'react';
import { applyPatch, diffLines } from 'diff';
import Prism from 'prismjs';
import flat from 'array.prototype.flat';
import { useThemeUI, jsx, ThemeProvider } from 'theme-ui';
import 'prismjs/components/prism-markup';
import 'prismjs/components/prism-bash';
import 'prismjs/components/prism-clike';
import 'prismjs/components/prism-c';
import 'prismjs/components/prism-cpp';
import 'prismjs/components/prism-css';
import 'prismjs/components/prism-css-extras';
import 'prismjs/components/prism-javascript';
import 'prismjs/components/prism-jsx';
import 'prismjs/components/prism-js-extras';
import 'prismjs/components/prism-coffeescript';
import 'prismjs/components/prism-diff';
import 'prismjs/components/prism-git';
import 'prismjs/components/prism-go';
import 'prismjs/components/prism-graphql';
import 'prismjs/components/prism-json';
import 'prismjs/components/prism-less';
import 'prismjs/components/prism-makefile';
import 'prismjs/components/prism-markdown';
import 'prismjs/components/prism-objectivec';
import 'prismjs/components/prism-ocaml';
import 'prismjs/components/prism-python';
import 'prismjs/components/prism-reason';
import 'prismjs/components/prism-sass';
import 'prismjs/components/prism-scss';
import 'prismjs/components/prism-sql';
import 'prismjs/components/prism-stylus';
import 'prismjs/components/prism-typescript';
import 'prismjs/components/prism-wasm';
import 'prismjs/components/prism-yaml';
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _inheritsLoose(subClass, superClass) {
subClass.prototype = Object.create(superClass.prototype);
subClass.prototype.constructor = subClass;
subClass.__proto__ = superClass;
}
function _objectWithoutPropertiesLoose(source, excluded) {
if (source == null) return {};
var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (i = 0; i < sourceKeys.length; i++) {
key = sourceKeys[i];
if (excluded.indexOf(key) >= 0) continue;
target[key] = source[key];
}
return target;
}
function grammarNotFound(_ref2) {
var lang = _ref2.lang;
return {
element: React.createElement(ErrorBox, {
header: "Oops, there's a problem",
body: React.createElement(React.Fragment, null, "Syntax highlighter for ", React.createElement(Mark, null, "\"", lang, "\""), " not found.", React.createElement("p", null, "You can try importing it from prismjs with: ", React.createElement("br", null), React.createElement(Mark, null, "import \"prismjs/components/prism-", lang, "\"")), "(See", " ", React.createElement("a", {
href: "https://prismjs.com/#supported-languages",
style: {
color: "grey"
}
}, "all the supported languages"), ")")
})
};
}
function invalidFocusNumber(n) {
return {
withFocusString: function withFocusString(focusString) {
return {
withStepIndex: function withStepIndex(stepIndex) {
return {
element: React.createElement(ErrorBox, {
header: React.createElement(StepErrorHeader, {
stepIndex: stepIndex
}),
body: React.createElement(React.Fragment, null, React.createElement(Mark, null, "\"", n, "\""), " isn't a valid number", " ", n != focusString && React.createElement(Mark, null, " (in \"", focusString, "\")"))
})
};
}
};
}
};
}
function invalidLineOrColumnNumber() {
return {
withFocusString: function withFocusString(focusString) {
return {
withStepIndex: function withStepIndex(stepIndex) {
return {
element: React.createElement(ErrorBox, {
header: React.createElement(StepErrorHeader, {
stepIndex: stepIndex
}),
body: React.createElement(React.Fragment, null, "Are you using \"0\" as a line or column number", " ", React.createElement(Mark, null, "in \"", focusString, "\""), "?", React.createElement("br", null), "(Line and column numbers should start at 1, not 0) ", React.createElement("br", null))
})
};
}
};
}
};
}
function ErrorBox(_ref3) {
var header = _ref3.header,
body = _ref3.body;
return React.createElement("div", {
style: {
background: "#290000",
color: "#b96f70",
border: "2px solid #b96f70",
padding: "10px 30px",
maxWidth: "90vw",
margin: "0 auto",
fontFamily: "monospace",
fontSize: "1rem"
}
}, React.createElement("h3", null, header), React.createElement("p", null, body));
}
function StepErrorHeader(_ref4) {
var stepIndex = _ref4.stepIndex;
return React.createElement(React.Fragment, null, "Oops, there's a problem with the", " ", React.createElement(Mark, null, stepIndex + 1, React.createElement("sup", null, ordinal(stepIndex + 1)), " step"));
}
function Mark(_ref5) {
var children = _ref5.children;
return React.createElement("mark", {
style: {
background: "none",
color: "pink",
fontWeight: "bolder"
}
}, children);
}
function ordinal(i) {
var j = i % 10,
k = i % 100;
if (j == 1 && k != 11) {
return "st";
}
if (j == 2 && k != 12) {
return "nd";
}
if (j == 3 && k != 13) {
return "rd";
}
return "th";
}
var newlineRe = /\r\n|\r|\n/; // Take a list of nested tokens
// (token.content may contain an array of tokens)
// and flatten it so content is always a string
// and type the type of the leaf
function flattenTokens(tokens) {
var flatList = [];
tokens.forEach(function (token) {
var type = token.type,
content = token.content;
if (Array.isArray(content)) {
flatList.push.apply(flatList, flattenTokens(content));
} else {
flatList.push({
type: type,
content: content
});
}
});
return flatList;
}
function wrapToken(prismToken, parentType) {
if (parentType === void 0) {
parentType = "plain";
}
if (typeof prismToken === "string") {
return {
type: parentType,
content: prismToken
};
}
if (Array.isArray(prismToken.content)) {
return {
type: prismToken.type,
content: tokenizeStrings(prismToken.content, prismToken.type)
};
}
return wrapToken(prismToken.content, prismToken.type);
} // Wrap strings in tokens
function tokenizeStrings(prismTokens, parentType) {
if (parentType === void 0) {
parentType = "plain";
}
return prismTokens.map(function (prismToken) {
return wrapToken(prismToken, parentType);
});
}
function tokenize(code, language) {
if (language === void 0) {
language = "javascript";
}
var grammar = Prism.languages[language];
if (!grammar) {
throw grammarNotFound({
lang: language
});
}
var prismTokens = Prism.tokenize(code, Prism.languages[language]);
var nestedTokens = tokenizeStrings(prismTokens);
var tokens = flattenTokens(nestedTokens);
var currentLine = [];
var lines = [currentLine];
tokens.forEach(function (token) {
var contentLines = token.content.split(newlineRe);
var firstContent = contentLines.shift();
if (firstContent !== undefined && firstContent !== "") {
currentLine.push({
type: token.type,
content: firstContent
});
}
contentLines.forEach(function (content) {
currentLine = [];
lines.push(currentLine);
if (content !== "") {
currentLine.push({
type: token.type,
content: content
});
}
});
});
return lines;
}
var newlineRe$1 = /\r\n|\r|\n/;
function myDiff(oldCode, newCode) {
var changes = diffLines(oldCode || "", newCode);
var oldIndex = -1;
return changes.map(function (_ref) {
var value = _ref.value,
count = _ref.count,
removed = _ref.removed,
added = _ref.added;
var lines = value.split(newlineRe$1); // check if last line is empty, if it is, remove it
var lastLine = lines.pop();
if (lastLine) {
lines.push(lastLine);
}
var result = {
oldIndex: oldIndex,
lines: lines,
count: count,
removed: removed,
added: added
};
if (!added) {
oldIndex += count || 0;
}
return result;
});
}
function insert(array, index, elements) {
return array.splice.apply(array, [index, 0].concat(elements));
}
function slideDiff(lines, codes, slideIndex, language) {
var prevLines = lines.filter(function (l) {
return l.slides.includes(slideIndex - 1);
});
var prevCode = codes[slideIndex - 1] || "";
var currCode = codes[slideIndex];
var changes = myDiff(prevCode, currCode);
changes.forEach(function (change) {
if (change.added) {
var prevLine = prevLines[change.oldIndex];
var addAtIndex = lines.indexOf(prevLine) + 1;
var addLines = change.lines.map(function (content) {
return {
content: content,
slides: [slideIndex],
tokens: []
};
});
insert(lines, addAtIndex, addLines);
} else if (!change.removed) {
for (var j = 1; j <= (change.count || 0); j++) {
prevLines[change.oldIndex + j].slides.push(slideIndex);
}
}
});
var tokenLines = tokenize(currCode, language);
var currLines = lines.filter(function (l) {
return l.slides.includes(slideIndex);
});
currLines.forEach(function (line, index) {
return line.tokens = tokenLines[index];
});
}
function parseLines(codes, language) {
var lines = [];
for (var slideIndex = 0; slideIndex < codes.length; slideIndex++) {
slideDiff(lines, codes, slideIndex, language);
}
return lines;
}
function getSlides(codes, language) {
// codes are in reverse cronological order
var lines = parseLines(codes, language); // console.log("lines", lines);
return codes.map(function (_, slideIndex) {
return lines.map(function (line, lineIndex) {
return {
content: line.content,
tokens: line.tokens,
isNew: !line.slides.includes(slideIndex + 1),
show: line.slides.includes(slideIndex),
key: lineIndex
};
}).filter(function (line) {
return line.show;
});
});
}
function getCodes(rawSteps) {
var codes = [];
rawSteps.forEach(function (s, i) {
if (s.lang === "diff" && i > 0) {
codes[i] = applyPatch(codes[i - 1], s.code);
} else {
codes[i] = s.code;
}
});
return codes;
}
function parseFocus(focus) {
if (!focus) {
throw new Error("Focus cannot be empty");
}
try {
var parts = focus.split(/,(?![^\[]*\])/g).map(parsePart);
return new Map(flat(parts));
} catch (error) {
if (error.withFocusString) {
throw error.withFocusString(focus);
} else {
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 line = columnsMatch[1],
columns = columnsMatch[2];
var columnsList = columns.split(",").map(expandString);
var lineIndex = Number(line) - 1;
var columnIndexes = flat(columnsList).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 _part$split = part.split(":"),
start = _part$split[0],
end = _part$split[1]; // todo check if start is 0, line numbers and column numbers start at 1
if (!isNaturalNumber(start)) {
throw invalidFocusNumber(start);
}
var startNumber = Number(start);
if (startNumber < 1) {
throw invalidLineOrColumnNumber();
}
if (!end) {
return [startNumber];
} else {
if (!isNaturalNumber(end)) {
throw invalidFocusNumber(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;
}
function parseSteps(rawSteps, lang) {
var codes = getCodes(rawSteps);
var stepsLines = getSlides(codes.reverse(), lang).reverse();
var steps = rawSteps.map(function (step, i) {
var lines = stepsLines[i];
try {
return parseStep(step, lines);
} catch (e) {
if (e.withStepIndex) {
throw e.withStepIndex(i);
} else {
throw e;
}
}
});
steps.forEach(function (step) {
var lines = step.lines,
focusMap = step.focusMap;
lines.forEach(function (line, index) {
line.focus = focusMap.has(index);
var columnFocus = focusMap.get(index);
line.focusPerToken = Array.isArray(columnFocus);
if (Array.isArray(columnFocus)) {
// this mutates the tokens array in order to change it to the same line in other steps
splitTokensToColumns(line.tokens);
line.tokens = setTokenFocus(line.tokens, columnFocus);
}
});
});
return steps;
}
function parseStep(step, lines) {
var focus = step.focus,
rest = _objectWithoutPropertiesLoose(step, ["focus"]);
var focusMap = focus ? parseFocus(focus) : getDefaultFocus(lines);
var focusIndexes = Array.from(focusMap.keys());
var focusStart = Math.min.apply(Math, focusIndexes);
var focusEnd = Math.max.apply(Math, focusIndexes);
return _extends({
lines: lines,
focusMap: focusMap,
focusStart: focusStart,
focusEnd: focusEnd,
focusCenter: (focusStart + focusEnd + 1) / 2,
focusCount: focusEnd - focusStart + 1
}, rest);
}
function getDefaultFocus(lines) {
var indexes = lines.map(function (line, index) {
return line.isNew ? index : -1;
}).filter(function (index) {
return index !== -1;
});
return new Map(indexes.map(function (i) {
return [i, true];
}));
}
function splitTokensToColumns(tokenArray) {
var tokens = Array.from(tokenArray);
var key = 0;
tokenArray.splice(0, tokenArray.length);
tokens.forEach(function (token) {
var chars = Array.from(token.content);
chars.forEach(function (_char) {
return tokenArray.push(_extends({}, token, {
content: _char,
key: key++
}));
});
});
}
function setTokenFocus(tokens, focusColumns) {
// Assumes that tokens are already splitted in columns
// Return new token objects to avoid changing other steps tokens
return tokens.map(function (token, i) {
return _extends({}, token, {
focus: focusColumns.includes(i)
});
});
}
var Tuple =
/*#__PURE__*/
function () {
function Tuple(prev, next) {
this.prev = prev;
this.next = next;
}
var _proto = Tuple.prototype;
_proto.spread = function spread() {
var prev = this.prev;
var next = this.next;
return [prev, next];
};
_proto.select = function select(selector) {
var _this$spread = this.spread(),
prev = _this$spread[0],
next = _this$spread[1];
var newPrev = prev === null ? null : prev === undefined ? undefined : selector(prev),
newNext = next === null ? null : next === undefined ? undefined : selector(next);
return new Tuple(newPrev, newNext);
};
_proto.selectMany = function selectMany(selector) {
var _this$spread2 = this.spread(),
prev = _this$spread2[0],
next = _this$spread2[1];
var newPrev = prev === null ? null : prev === undefined ? undefined : selector(prev),
newNext = next === null ? null : next === undefined ? undefined : selector(next);
return new ArrayTuple(newPrev, newNext);
};
_proto.get = function get(_key) {
throw Error("Get only supported in ArrayTuple");
};
_proto.map = function map(_mapper) {
throw Error("Map only supported in ArrayTuple");
};
return Tuple;
}();
var ArrayTuple =
/*#__PURE__*/
function (_Tuple) {
_inheritsLoose(ArrayTuple, _Tuple);
function ArrayTuple() {
return _Tuple.apply(this, arguments) || this;
}
var _proto2 = ArrayTuple.prototype;
_proto2._getChildrenMap = function _getChildrenMap() {
if (!this._dict) {
var _this$spread3 = this.spread(),
maybePrevs = _this$spread3[0],
maybeNexts = _this$spread3[1];
var prevs = maybePrevs || [];
var nexts = maybeNexts || [];
var unsortedMap = new Map(prevs.map(function (prev) {
return [prev.key, {
prev: prev
}];
}));
nexts.forEach(function (next) {
var _ref = unsortedMap.get(next.key) || {
prev: undefined
},
prev = _ref.prev;
unsortedMap.set(next.key, {
prev: prev,
next: next
});
});
var sortedKeys = Array.from(unsortedMap.keys());
sortedKeys.sort(function (a, b) {
return a < b ? -1 : a > b ? 1 : 0;
});
this._dict = new Map(sortedKeys.map(function (key) {
var _ref2 = unsortedMap.get(key) || {},
_ref2$prev = _ref2.prev,
prev = _ref2$prev === void 0 ? undefined : _ref2$prev,
_ref2$next = _ref2.next,
next = _ref2$next === void 0 ? undefined : _ref2$next;
return [key, new Tuple(prev, next)];
}));
}
return this._dict;
};
_proto2.get = function get(key) {
var childrenMap = this._getChildrenMap();
return childrenMap.get(key);
};
_proto2.map = function map(mapper) {
var _this = this;
var childrenMap = this._getChildrenMap();
var result = [];
childrenMap.forEach(function (tuple, key) {
return result.push(mapper(tuple, key, _this));
});
return result;
};
return ArrayTuple;
}(Tuple);
var Context =
/*#__PURE__*/
function () {
function Context(tuple, t, parent) {
this.tuple = tuple;
this.t = t;
this.parent = parent;
}
var _proto = Context.prototype;
_proto.useSelect = function useSelect(selector) {
var _this = this;
var newTuple = React.useMemo(function () {
return _this.tuple.select(selector);
}, [this.tuple]);
return new Context(newTuple, this.t);
};
_proto.useSelectMany = function useSelectMany(selector) {
var _this2 = this;
var newTuple = React.useMemo(function () {
return _this2.tuple.selectMany(selector);
}, [this.tuple]);
return new ListContext(newTuple, this.t);
};
_proto.spread = function spread() {
return this.tuple.spread();
};
_proto.animate = function animate(animation, config) {
if (config === void 0) {
config = {};
}
var _this$tuple$spread = this.tuple.spread(),
prev = _this$tuple$spread[0],
next = _this$tuple$spread[1];
if (config.when && !config.when(prev, next)) {
return {};
}
var staggeredT = this.t;
if (config.stagger) {
if (!this.parent) {
throw Error("Can't use stagger without a parent context");
}
var items = this.parent.map(function (childCtx) {
var _childCtx$spread = childCtx.spread(),
prevChild = _childCtx$spread[0],
nextChild = _childCtx$spread[1];
return {
isSelected: !config.when || config.when(prevChild, nextChild),
isThisChild: prevChild === prev && nextChild === next
};
}).filter(function (x) {
return x.isSelected;
});
var N = items.length;
if (N > 1) {
var currentIndex = items.findIndex(function (x) {
return x.isThisChild;
});
var duration = 1 - config.stagger;
var tick = config.stagger / (N - 1);
staggeredT = Math.min(1, Math.max(0, (this.t - currentIndex * tick) / duration));
}
}
return animation(prev, next, staggeredT);
};
_proto.animations = function animations(_animations) {
var _this3 = this;
var results = _animations.map(function (_ref) {
var animation = _ref.animation,
config = _objectWithoutPropertiesLoose(_ref, ["animation"]);
return _this3.animate(animation, config);
});
return merge(results);
};
return Context;
}();
var ListContext =
/*#__PURE__*/
function (_Context) {
_inheritsLoose(ListContext, _Context);
function ListContext(tuple, t) {
var _this4;
_this4 = _Context.call(this, tuple, t) || this;
_this4.tuple = tuple;
return _this4;
}
var _proto2 = ListContext.prototype;
_proto2.map = function map(mapper) {
var _this5 = this;
return this.tuple.map(function (childTuple, key) {
return mapper(new Context(childTuple, _this5.t, _this5), key);
});
};
return ListContext;
}(Context);
function useAnimationContext(items, playhead) {
var prev = items[Math.floor(playhead)];
var next = items[Math.floor(playhead) + 1];
var tuple = React.useMemo(function () {
return new Tuple(prev, next);
}, [prev, next]);
return new Context(tuple, playhead % 1);
}
var MULTIPLY = "multiply";
function merge(results, composite) {
if (composite === void 0) {
composite = MULTIPLY;
}
var firstResult = results[0];
if (results.length < 2) {
return firstResult;
}
if (Array.isArray(firstResult)) {
return mergeArrays(results, composite);
} else {
return mergeObjects(results, composite);
}
}
function mergeObjects(results, composite) {
var merged = Object.assign.apply(Object, [{}].concat(results));
if (composite === MULTIPLY) {
var opacities = results.map(function (x) {
return x.opacity;
}).filter(function (x) {
return x != null;
});
if (opacities.length !== 0) {
merged.opacity = opacities.reduce(function (a, b) {
return a * b;
});
}
}
return merged;
}
function mergeArrays(results, composite) {
var firstResult = results[0];
return firstResult.map(function (_, i) {
return merge(results.map(function (result) {
return result[i];
}), composite);
});
}
var easing = {
// no easing, no acceleration
linear: function linear(t) {
return t;
},
// accelerating from zero velocity
easeInQuad: function easeInQuad(t) {
return t * t;
},
// decelerating to zero velocity
easeOutQuad: function easeOutQuad(t) {
return t * (2 - t);
},
// acceleration until halfway, then deceleration
easeInOutQuad: function easeInOutQuad(t) {
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
},
// accelerating from zero velocity
easeInCubic: function easeInCubic(t) {
return t * t * t;
},
// decelerating to zero velocity
easeOutCubic: function easeOutCubic(t) {
return --t * t * t + 1;
},
// acceleration until halfway, then deceleration
easeInOutCubic: function easeInOutCubic(t) {
return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
},
// accelerating from zero velocity
easeInQuart: function easeInQuart(t) {
return t * t * t * t;
},
// decelerating to zero velocity
easeOutQuart: function easeOutQuart(t) {
return 1 - --t * t * t * t;
},
// acceleration until halfway, then deceleration
easeInOutQuart: function easeInOutQuart(t) {
return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;
},
// accelerating from zero velocity
easeInQuint: function easeInQuint(t) {
return t * t * t * t * t;
},
// decelerating to zero velocity
easeOutQuint: function easeOutQuint(t) {
return 1 + --t * t * t * t * t;
},
// acceleration until halfway, then deceleration
easeInOutQuint: function easeInOutQuint(t) {
return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
}
};
var MULTIPLY$1 = "multiply";
/* eslint-disable */
function mergeResults(results, composite) {
if (composite === void 0) {
composite = null;
}
var firstResult = results[0];
if (results.length < 2) {
return firstResult;
}
if (Array.isArray(firstResult)) {
return firstResult.map(function (_, i) {
return mergeResults(results.map(function (result) {
return result[i];
}), composite);
});
} else {
var merged = Object.assign.apply(Object, [{}].concat(results));
if (composite === MULTIPLY$1) {
var opacities = results.map(function (x) {
return x.opacity;
}).filter(function (x) {
return x != null;
});
if (opacities.length !== 0) {
merged.opacity = opacities.reduce(function (a, b) {
return a * b;
});
}
}
return merged;
}
}
var playhead = {
always: function always(props, context) {
return function (t) {
return props.value;
};
},
step: function step(props, context) {
return function (t) {
var from = props.from,
to = props.to;
return t < 0.5 ? from : to;
};
},
tween: function tween(props, context) {
return function (t) {
var from = props.from,
to = props.to,
_props$ease = props.ease,
ease = _props$ease === void 0 ? easing.linear : _props$ease;
var style = {};
Object.keys(from).forEach(function (key) {
var value = from[key] + (to[key] - from[key]) * ease(t);
if (key === "x") {
style["transform"] = "translateX(" + value + "px)";
} else {
style[key] = value;
}
});
return style;
};
},
chain: function chain(_ref, ctx) {
var fns = _ref.children,
durations = _ref.durations;
return function (t) {
var style = run(fns[0], 0, ctx);
var lowerDuration = 0;
for (var i = 0; i < fns.length; i++) {
var fn = fns[i];
var thisDuration = durations[i];
var upperDuration = lowerDuration + thisDuration;
if (lowerDuration <= t && t <= upperDuration) {
var innerT = (t - lowerDuration) / thisDuration;
style = mergeResults([style, run(fn, innerT, ctx)]);
} else if (upperDuration < t) {
// merge the end of previous animation
style = mergeResults([style, run(fn, 1, ctx)]);
} else if (t < lowerDuration) {
// merge the start of future animation
style = mergeResults([run(fn, 0, ctx), style]);
}
lowerDuration = upperDuration;
}
return style;
};
},
delay: function delay() {
return function () {
return {};
};
},
parallel: function parallel(_ref2, ctx) {
var fns = _ref2.children;
return function (t) {
var styles = fns.map(function (fn) {
return run(fn, t, ctx);
});
var result = mergeResults(styles, MULTIPLY$1);
return result;
};
},
list: function list(_ref3, ctx) {
var items = _ref3.forEach,
children = _ref3.children;
return function (t) {
var mapper = children[0];
var results = items.map(mapper);
return results.map(function (element) {
return run(element, t, ctx);
});
};
}
};
function createAnimation(type, config) {
for (var _len = arguments.length, children = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
children[_key - 2] = arguments[_key];
}
var props = _extends({}, config, {
children: children
});
return {
type: typeof type === "string" ? playhead[type] : type,
props: props
};
}
function Context$1() {
throw Error("shouldnt run Context");
}
function run(node, t, context) {
if (context === void 0) {
context = {};
}
if (node.type === Context$1) {
var _node$props = node.props,
children = _node$props.children,
patch = _objectWithoutPropertiesLoose(_node$props, ["children"]);
var newContext = _extends({}, context, {}, patch);
return run(children[0], t, newContext);
}
var result = node.type(node.props, context);
if (result.type) {
return run(result, t, context);
} else {
return result(t);
}
}
/* @jsx createAnimation */
function FadeIn() {
return createAnimation("tween", {
from: {
opacity: 0
},
to: {
opacity: 1
}
});
}
function FadeOut() {
return createAnimation("tween", {
from: {
opacity: 1
},
to: {
opacity: 0
}
});
}
function FadeOutIn() {
return createAnimation("chain", {
durations: [0.5, 0.5]
}, createAnimation(FadeOut, null), createAnimation(FadeIn, null));
}
var dx = 250;
var offOpacity = 0.3;
var outOpacity = 0;
var outHieght = 0;
var lineDurations = [0.2, 0.6, 0.2];
var SlideToLeft = function SlideToLeft() {
return createAnimation("chain", {
durations: lineDurations
}, createAnimation("tween", {
from: {
x: 0,
opacity: 1
},
to: {
x: -dx,
opacity: outOpacity
},
ease: easing.easeInQuad
}), createAnimation("delay", null), createAnimation("delay", null));
};
var SlideFromRight = function SlideFromRight() {
return createAnimation("chain", {
durations: lineDurations
}, createAnimation("delay", null), createAnimation("delay", null), createAnimation("tween", {
from: {
x: dx,
opacity: outOpacity
},
to: {
x: 0,
opacity: 1
},
ease: easing.easeOutQuad
}));
};
function ShrinkHeight(_ref) {
var lineHeight = _ref.lineHeight;
if (!lineHeight) {
return createAnimation("step", {
from: {
height: null
},
to: {
height: 0
}
});
}
return createAnimation("tween", {
from: {
height: lineHeight
},
to: {
height: outHieght
},
ease: easing.easeInOutQuad
});
}
function ExitLine(_ref2) {
var lineHeight = _ref2.lineHeight;
return createAnimation("chain", {
durations: lineDurations
}, createAnimation("delay", null), createAnimation(ShrinkHeight, {
lineHeight: lineHeight
}));
}
function GrowHeight(_ref3) {
var lineHeight = _ref3.lineHeight;
if (!lineHeight) {
return createAnimation("step", {
from: {
height: 0
},
to: {
height: null
}
});
}
return createAnimation("tween", {
from: {
height: outHieght
},
to: {
height: lineHeight
},
ease: easing.easeInOutQuad
});
}
function EnterLine(_ref4) {
var lineHeight = _ref4.lineHeight;
return createAnimation("chain", {
durations: lineDurations
}, createAnimation("delay", null), createAnimation(GrowHeight, {
lineHeight: lineHeight
}), createAnimation("delay", null));
}
var fadeIn = function fadeIn(t) {
return run(createAnimation(FadeIn, null), t);
};
var fadeOut = function fadeOut(t) {
return run(createAnimation(FadeOut, null), t);
};
var fadeOutIn = function fadeOutIn(t) {
return run(createAnimation(FadeOutIn, null), t);
};
function switchText(prev, next, t) {
// TODO merge with fadeBackground and fadeText
if (t < 0.5) {
return prev && prev.value;
} else {
return next && next.value;
}
}
function any(prev, next) {
return prev || next;
}
var exitLine = function exitLine(prev, next, t) {
var dimensions = any(prev, next).dimensions;
return run(createAnimation(ExitLine, {
lineHeight: dimensions && dimensions.lineHeight
}), t);
};
var enterLine = function enterLine(prev, next, t) {
var dimensions = any(prev, next).dimensions;
return run(createAnimation(EnterLine, {
lineHeight: dimensions && dimensions.lineHeight
}), t);
};
var slideToLeft = function slideToLeft(prev, next, t) {
return run(createAnimation(SlideToLeft, null), t);
};
var slideFromRight = function slideFromRight(prev, next, t) {
return run(createAnimation(SlideFromRight, null), t);
};
var focusLine = function focusLine(prev, next, t) {
return run(createAnimation("tween", {
from: {
opacity: prev && prev.focus ? 1 : offOpacity
},
to: {
opacity: next && next.focus ? 1 : offOpacity
}
}), t);
};
var focusToken = function focusToken(prev, next, t) {
var from = prev && prev.focus === false ? offOpacity : 1;
var to = next && next.focus === false ? offOpacity : 1;
return run(createAnimation("tween", {
from: {
opacity: from
},
to: {
opacity: to
}
}), t);
};
var scaleToFocus = function scaleToFocus(prev, next, t) {
var dimensions = any(prev, next).dimensions;
if (!dimensions) {
return function (_) {
return {
scale: 1
};
};
}
var prevZoom = getZoom(prev);
var nextZoom = getZoom(next);
return run(createAnimation("tween", {
from: {
scale: prevZoom || nextZoom
},
to: {
scale: nextZoom || prevZoom
},
ease: easing.easeInOutQuad
}), t);
};
var scrollToFocus = function scrollToFocus(prevStep, nextStep, t) {
var dimensions = any(prevStep, nextStep).dimensions;
if (!dimensions) {
return function (_) {
return {
scrollTop: 0
};
};
}
var prevCenter = prevStep ? prevStep.focusCenter * dimensions.lineHeight : 0;
var nextCenter = nextStep ? nextStep.focusCenter * dimensions.lineHeight : 0;
return run(createAnimation("chain", {
durations: lineDurations
}, createAnimation("delay", null), createAnimation("tween", {
from: {
scrollTop: prevCenter
},
to: {
scrollTop: nextCenter
},
ease: easing.easeInOutQuad
}), createAnimation("delay", null)), t);
};
function getZoom(step) {
if (!step) return null;
var _step$dimensions = step.dimensions,
paddingBottom = _step$dimensions.paddingBottom,
paddingTop = _step$dimensions.paddingTop,
containerHeight = _step$dimensions.containerHeight,
containerWidth = _step$dimensions.containerWidth,
contentWidth = _step$dimensions.contentWidth,
lineHeight = _step$dimensions.lineHeight;
var contentHeight = step.focusCount * lineHeight;
var availableHeight = containerHeight - Math.max(paddingBottom, paddingTop) * 2;
var yZoom = availableHeight / contentHeight; // if there are lines that are too long for the container
var xZoom = 0.9 * containerWidth / contentWidth;
return Math.min(yZoom, 1, xZoom); // return 1;
}
var baseTheme = {
colors: {
background: "rgb(246, 248, 250)",
text: "rgb(57, 58, 52)",
primary: "rgb(0, 164, 219)"
},
styles: {
CodeSurfer: {
pre: {
color: "text",
backgroundColor: "background"
},
code: {
color: "text",
backgroundColor: "background"
},
tokens: {
"comment cdata doctype": {
fontStyle: "italic"
},
"builtin changed keyword punctuation operator tag deleted string attr-value char number inserted": {
color: "primary"
}
},
title: {
backgroundColor: "background"
},
subtitle: {
color: "#d6deeb",
backgroundColor: "rgba(10,10,10,0.9)"
},
container: {}
}
}
};
function StylesProvider(_ref) {
var _ref$theme = _ref.theme,
theme = _ref$theme === void 0 ? {} : _ref$theme,
children = _ref.children;
var _useThemeUI = useThemeUI(),
outer = _useThemeUI.theme;
var base = _extends({}, baseTheme, {}, outer, {
styles: _extends({}, baseTheme.styles, {}, outer.styles)
});
return jsx(ThemeProvider, {
theme: base
}, jsx(ThemeProvider, {
theme: theme
}, children));
}
function useStyles() {
var _useThemeUI2 = useThemeUI(),
theme = _useThemeUI2.theme;
return theme.styles.CodeSurfer;
}
function getClassFromTokenType(type) {
return "token-" + type;
}
function usePreStyle() {
var styles = useStyles();
var preSx = React.useMemo(function () {
var sx = _extends({}, styles.pre);
Object.keys(styles.tokens).forEach(function (key) {
var classList = key.split(/\s/).map(function (type) {
return "." + getClassFromTokenType(type);
}).join(", ");
sx[classList] = styles.tokens[key];
});
return sx;
}, [styles]);
return preSx;
}
var baseTitle = {
position: "absolute",
top: 0,
width: "100%",
margin: 0,
padding: "1em 0",
textAlign: "center"
};
var baseSubtitle = {
position: "absolute",
bottom: 0,
width: "calc(100% - 2em)",
boxSizing: "border-box",
margin: "0.3em 1em",
padding: "0.5em",
background: "rgba(2,2,2,0.9)",
textAlign: "center"
};
var Styled = {
Code: function Code(props) {
return jsx("code", Object.assign({}, props, {
sx: useStyles().code
}));
},
Pre:
/*#__PURE__*/
React.forwardRef(function (props, ref) {
return jsx("pre", Object.assign({}, props, {
sx: usePreStyle(),
ref: ref
}));
}),
Title: function Title(props) {
return jsx("h4", Object.assign({}, props, {
sx: _extends({}, baseTitle, {}, useStyles().title)
}));
},
Subtitle: function Subtitle(props) {
return jsx("p", Object.assign({}, props, {
sx: _extends({}, baseSubtitle, {}, useStyles().subtitle)
}));
}
};
function CodeSurferContainer(_ref) {
var stepPlayhead = _ref.stepPlayhead,
dimensions = _ref.dimensions,
steps = _ref.steps;
var ctx = useAnimationContext(steps, stepPlayhead);
return React.createElement("div", {
className: "cs-container",
style: {
width: "100%",
height: dimensions ? dimensions.containerHeight : "100%",
maxHeight: "100%",
position: "relative"
}
}, React.createElement(CodeSurferContent, {
dimensions: dimensions,
ctx: ctx
}), React.createElement(Title, {
ctx: ctx.useSelect(function (step) {
return step.title;
})
}), React.createElement(Subtitle, {
ctx: ctx.useSelect(function (step) {
return step.subtitle;
})
}));
}
var heightChangingAnimations = [{
animation: slideToLeft,
when: function when(prev, next) {
return prev && !next;
},
stagger: 0.15
}, {
animation: slideFromRight,
when: function when(prev, next) {
return next && !prev;
},
stagger: 0.15
}, {
animation: exitLine,
when: function when(prev, next) {
return prev && !next;
}
}, {
animation: enterLine,
when: function when(prev, next) {
return next && !prev;
}
}];
function CodeSurferContent(_ref2) {
var dimensions = _ref2.dimensions,
ctx = _ref2.ctx;
var ref = React.useRef(null);
var _ctx$animate = ctx.animate(scrollToFocus),
scrollTop = _ctx$animate.scrollTop;
React.useLayoutEffect(function () {
if (ref.current == null) return;
ref.current.scrollTop = scrollTop;
}, [scrollTop]);
var _ctx$animate2 = ctx.animate(scaleToFocus),
scale = _ctx$animate2.scale;
var verticalOrigin = dimensions ? dimensions.containerHeight / 2 + scrollTop : 0;
var linesCtx = ctx.useSelectMany(function (step) {
return step.lines;
});
return React.createElement(Styled.Pre, {
className: "cs-content",
ref: ref,
style: {
margin: 0,
height: "100%",
overflow: "hidden"
}
}, React.createElement(Styled.Code, {
className: "cs-scaled-content",
style: {
display: "block",
height: dimensions ? dimensions.contentHeight : "100%",
width: dimensions && dimensions.contentWidth,
margin: dimensions && "0 " + (dimensions.containerWidth - dimensions.contentWidth) / 2 + "px",
transform: "scale(" + scale + ")",
transformOrigin: "center " + verticalOrigin + "px"
}
}, React.createElement("div", {
style: {
height: dimensions && dimensions.containerHeight / 2
}
}), linesCtx.map(function (ctx, key) {
return React.createElement(Line, {
ctx: ctx,
key: key
});
}), React.createElement("div", {
style: {
height: dimensions && dimensions.containerHeight / 2
}
})));
}
function Line(_ref3) {
var ctx = _ref3.ctx;
var lineStyle = ctx.animations([].concat(heightChangingAnimations, [{
animation: focusLine
}]));
var _ctx$animate3 = ctx.animate(function (prev, next) {
var line = prev || next;
return {
lineTokens: line.tokens,
key: line.key,
focusPerToken: prev && prev.focusPerToken || next && next.focusPerToken
};
}),
lineTokens = _ctx$animate3.lineTokens,
key = _ctx$animate3.key,
focusPerToken = _ctx$animate3.focusPerToken;
var tokens = [];
var tokensCtx = ctx.useSelectMany(function (line) {
return line.tokens;
});
if (focusPerToken) {
tokens = tokensCtx.map(function (tokenCtx) {
return _extends({}, tokenCtx.animate(function (prev, next) {
return prev || next;
}), {
animatedStyle: tokenCtx.animate(focusToken)
});
});
} else {
tokens = lineTokens.map(function (token) {
return _extends({}, token, {
animatedStyle: {}
});
});
}
return React.createElement("div", {
style: _extends({
overflow: "hidden"
}, lineStyle)
}, React.createElement("div", {
style: {
display: "inline-block"
},
className: "cs-line cs-line-" + key
}, tokens.map(function (token, i) {
return React.createElement("span", {
key: i,
style: token.animatedStyle,
className: getClassFromTokenType(token.type)
}, token.content);
})));
}
function Title(_ref4) {
var ctx = _ref4.ctx;
var text = ctx.animate(switchText);
var bgStyle = ctx.animate(fadeBackground);
var textStyle = ctx.animate(fadeText);
if (!text) return null;
return React.createElement(Styled.Title, {
className: "cs-title",
style: bgStyle
}, React.createElement("span", {
style: textStyle
}, text));
}
function Subtitle(_ref5) {
var ctx = _ref5.ctx;
var text = ctx.animate(switchText);
var bgStyle = ctx.animate(fadeBackground);
var textStyle = ctx.animate(fadeText);
if (!text) return null;
return React.createElement(Styled.Subtitle, {
className: "cs-subtitle",
style: bgStyle
}, React.createElement("span", {
style: textStyle
}, text));
}
var fadeBackground = function fadeBackground(prev, next, t) {
var opacity = 1;
if (!prev) {
opacity = t;
}
if (!next) {
opacity = 1 - t;
}
return {
opacity: opacity
};
};
var fadeText = function fadeText(prev, next, t) {
if (prev && next && prev.value !== next.value) {
return fadeOutIn(t);
}
if (!prev) {
return fadeIn(t);
}
if (!next) {
return fadeOut(t);
}
return {
opacity: 1
};
};
function useWindowResize(handler, deps) {
React.useEffect(function () {
window.addEventListener("resize", handler);
return function () {
window.removeEventListener("resize", handler);
};
}, deps);
}
function useDimensions(ref, steps) {
var _React$useState = React.useState(null),
result = _React$useState[0],
setResult = _React$useState[1];
useWindowResize(function () {
return setResult(null);
}, [setResult]);
React.useLayoutEffect(function () {
if (!ref.current) return;
if (result) return;
var containers = ref.current.querySelectorAll(".cs-container");
var stepsDimensions = Array.from(containers).map(function (container, i) {
return getStepDimensions(container, steps[i]);
});
var containerHeight = Math.max.apply(Math, stepsDimensions.map(function (d) {
return d.containerHeight;
}));
var containerWidth = Math.max.apply(Math, stepsDimensions.map(function (d) {
return d.containerWidth;
}));
var contentWidth = Math.max.apply(Math, stepsDimensions.map(function (d) {
return d.contentWidth;
}));
var lineHeight = Math.max.apply(Math, stepsDimensions.map(function (d) {
return d.lineHeight;
}));
setResult({
dimensions: {
lineHeight: lineHeight,
contentWidth: contentWidth,
containerHeight: containerHeight,
containerWidth: containerWidth
},
steps: steps.map(function (step, i) {
return _extends({}, step, {
lines: step.lines.map(function (l) {
return _extends({}, l, {
dimensions: {
lineHeight: stepsDimensions[i].lineHeight
}
});
}),
dimensions: {
paddingTop: stepsDimensions[i].paddingTop,
paddingBottom: stepsDimensions[i].paddingBottom,
lineHeight: stepsDimensions[i].lineHeight,
contentWidth: contentWidth,
containerHeight: containerHeight,
containerWidth: containerWidth
}
});
})
});
}, [result]);
return result || {};
}
function getStepDimensions(container, step) {
var longestLine = getLongestLine(step);
var longestLineKey = longestLine && longestLine.key;
var longestLineSpan = container.querySelector(".cs-line-" + longestLineKey);
var containerParent = container.parentElement;
var title = container.querySelector(".cs-title");
var subtitle = container.querySelector(".cs-subtitle");
var lineCount = step.lines.length;
var heightOverflow = containerParent.scrollHeight - containerParent.clientHeight;
var avaliableHeight = container.scrollHeight - heightOverflow;
var lineHeight = longestLineSpan ? longestLineSpan.clientHeight : 0;
var paddingTop = title ? outerHeight(title) : lineHeight;
var paddingBottom = subtitle ? outerHeight(subtitle) : lineHeight;
var codeHeight = lineCount * lineHeight * 2; // const maxContentHeight = codeHeight + paddingTop + paddingBottom;
// const containerHeight = Math.min(maxContentHeight, avaliableHeight);
var containerHeight = avaliableHeight;
var containerWidth = container.clientWidth;
var contentHeight = codeHeight + containerHeight;
var contentWidth = longestLineSpan ? longestLineSpan.clientWidth : 0;
return {
lineHeight: lineHeight,
contentHeight: contentHeight,
contentWidth: contentWidth,
paddingTop: paddingTop,
paddingBottom: paddingBottom,
containerHeight: containerHeight,
containerWidth: containerWidth
};
}
function outerHeight(element) {
var styles = window.getComputedStyle(element);
var margin = parseFloat(styles["marginTop"] || "0") + parseFloat(styles["marginBottom"] || "0");
return element.offsetHeight + margin;
}
function getLongestLine(step) {
if (!step || step.lines.length === 0) {
return null;
}
return step.lines.reduce(function (a, b) {
return a.content.length > b.content.length ? a : b;
});
}
function makeTheme(prismTheme, override) {
if (override === void 0) {
override = {};
}
var tokens = {};
prismTheme.styles.forEach(function (s) {
tokens[s.types.join(" ")] = s.style;
});
return {
styles: {
CodeSurfer: _extends({
tokens: tokens,
title: {
backgroundColor: prismTheme.plain.backgroundColor
},
subtitle: {
color: "#d6deeb",
backgroundColor: "rgba(10,10,10,0.9)"
},
pre: {
color: prismTheme.plain.color,
backgroundColor: prismTheme.plain.backgroundColor
},
code: {
color: prismTheme.plain.color,
backgroundColor: prismTheme.plain.backgroundColor
}
}, override)
}
};
}
var prismTheme = {
plain: {
color: "#393A34",
backgroundColor: "#f6f8fa"
},
styles: [{
types: ["comment", "prolog", "doctype", "cdata"],
style: {
color: "#999988",
fontStyle: "italic"
}
}, {
types: ["namespace"],
style: {
opacity: 0.7
}
}, {
types: ["string", "attr-value"],
style: {
color: "#e3116c"
}
}, {
types: ["punctuation", "operator"],
style: {
color: "#393A34"
}
}, {
types: ["entity", "url", "symbol", "number", "boolean", "variable", "constant", "property", "regex", "inserted"],
style: {
color: "#36acaa"
}
}, {
types: ["atrule", "keyword", "attr-name", "selector"],
style: {
color: "#00a4db"
}
}, {
types: ["function", "deleted", "tag"],
style: {
color: "#d73a49"
}
}, {
types: ["function-variable"],
style: {
color: "#6f42c1"
}
}, {
types: ["tag", "selector"],
style: {
color: "#00009f"
}
}]
};
var theme =
/*#__PURE__*/
makeTheme(prismTheme);
var prismTheme$1 = {
plain: {
color: "#F8F8F2",
backgroundColor: "#282A36"
},
styles: [{
types: ["prolog", "constant", "builtin"],
style: {
color: "rgb(189, 147, 249)"
}
}, {
types: ["inserted", "function"],
style: {
color: "rgb(80, 250, 123)"
}
}, {
types: ["deleted"],
style: {
color: "rgb(255, 85, 85)"
}
}, {
types: ["changed"],
style: {
color: "rgb(255, 184, 108)"
}
}, {
types: ["punctuation", "symbol"],
style: {
color: "rgb(248, 248, 242)"
}
}, {
types: ["string", "char", "tag", "selector"],
style: {
color: "rgb(255, 121, 198)"
}
}, {
types: ["keyword", "variable"],
style: {
color: "rgb(189, 147, 249)",
fontStyle: "italic"
}
}, {
types: ["comment"],
style: {
color: "rgb(98, 114, 164)"
}
}, {
types: ["attr-name"],
style: {
color: "rgb(241, 250, 140)"
}
}]
};
var theme$1 =
/*#__PURE__*/
makeTheme(prismTheme$1);
var prismTheme$2 = {
plain: {
backgroundColor: "#2a2734",
color: "#9a86fd"
},
styles: [{
types: ["comment", "prolog", "doctype", "cdata", "punctuation"],
style: {
color: "#6c6783"
}
}, {
types: ["namespace"],
style: {
opacity: 0.7
}
}, {
types: ["tag", "operator", "number"],
style: {
color: "#e09142"
}
}, {
types: ["property", "function"],
style: {
color: "#9a86fd"
}
}, {
types: ["tag-id", "selector", "atrule-id"],
style: {