@sorrell/code-hike 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ /**
3
+ * @file CodePresentation.Internal.Types.ts
4
+ * @author Gage Sorrell <gage@sorrell.sh>
5
+ * @copyright (c) 2026 Gage Sorrell
6
+ * @license MIT
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MarkdownSchema = exports.StepSchema = void 0;
4
+ exports.Video = Video;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ /**
7
+ * @file CodePresentation.Internal.tsx
8
+ * @author Gage Sorrell <gage@sorrell.sh>
9
+ * @copyright (c) 2026 Gage Sorrell
10
+ * @license MIT
11
+ */
12
+ const remotion_1 = require("remotion");
13
+ const blocks_1 = require("codehike/blocks");
14
+ const code_1 = require("codehike/code");
15
+ const zod_1 = require("zod");
16
+ /* eslint-disable @typescript-eslint/typedef, @typescript-eslint/no-unused-vars, jsdoc/require-jsdoc */
17
+ exports.StepSchema = blocks_1.Block.extend({ code: blocks_1.HighlightedCodeBlock });
18
+ exports.MarkdownSchema = blocks_1.Block.extend({ steps: zod_1.z.array(exports.StepSchema) });
19
+ /* eslint-enable @typescript-eslint/typedef, @typescript-eslint/no-unused-vars */
20
+ function Code({ FrameRate, Handlers, Hook, OldCode, NewCode, Resolution, style }) {
21
+ const { Code, Ref } = Hook(OldCode, NewCode, FrameRate);
22
+ const BaseFontSizeRem = 6;
23
+ const FontSizeScalars = {
24
+ "1296x864": 1296 / 1920,
25
+ "1920x1280": 1,
26
+ "2400x1600": 2400 / 1920
27
+ };
28
+ const Style = {
29
+ fontSize: `${BaseFontSizeRem * FontSizeScalars[Resolution]}rem`,
30
+ ...style
31
+ };
32
+ return ((0, jsx_runtime_1.jsx)(code_1.Pre, { code: Code, handlers: [...Handlers], ref: Ref, style: Style }));
33
+ }
34
+ function VideoStep(Props) {
35
+ var _a;
36
+ const { Duration, FrameRate, Handlers, Hook, Index, Resolution, Steps, style } = Props;
37
+ const Step = Steps[Index];
38
+ const DurationInFrames = Duration * 0.001 * FrameRate;
39
+ return ((0, jsx_runtime_1.jsx)(remotion_1.Sequence, { durationInFrames: DurationInFrames, from: DurationInFrames * Index, layout: "none", name: Step.title, children: (0, jsx_runtime_1.jsx)(Code, { NewCode: Step.code, OldCode: (_a = Steps[Index - 1]) === null || _a === void 0 ? void 0 : _a.code, FrameRate, Handlers, Hook, Resolution, style }) }));
40
+ }
41
+ function MakeToVideoStep(InheritedProps) {
42
+ return function ToVideoStep(Step, Index) {
43
+ return ((0, jsx_runtime_1.jsx)(VideoStep, { ...InheritedProps, Index, ...Step }, Index));
44
+ };
45
+ }
46
+ function Video(Props) {
47
+ return ((0, jsx_runtime_1.jsx)(remotion_1.AbsoluteFill, { style: {
48
+ alignItems: "center",
49
+ background: "#0D1117",
50
+ fontSize: 24
51
+ }, children: Props.Steps.map(MakeToVideoStep(Props)) }));
52
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ /**
3
+ * @file CodePresentation.Types.ts
4
+ * @author Gage Sorrell <gage@sorrell.sh>
5
+ * @copyright (c) 2026 Gage Sorrell
6
+ * @license MIT
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CodePresentation = CodePresentation;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const CodePresentation_Internal_1 = require("./CodePresentation.Internal");
6
+ const react_1 = require("react");
7
+ const TokenTransitions_1 = require("./TokenTransitions");
8
+ const remotion_1 = require("remotion");
9
+ const blocks_1 = require("codehike/blocks");
10
+ /**
11
+ * An animation, made up of {@link FStep | steps}, to explain code.
12
+ *
13
+ * @param Props - The sequence of {@link FStep | steps} that defines an animation.
14
+ *
15
+ * @throws {Error} If {@link PCodePresentation!Durations} is an {@link Array} and there is not
16
+ * precisely one duration assigned to every step, then this will throw.
17
+ *
18
+ * @returns {ReactPortal | null} A {@link Composition} with default values for
19
+ * important props, suitable for code animations.
20
+ */
21
+ function CodePresentation(Props) {
22
+ const { Content, Duration, FrameRate = 90, Handlers: InHandlers, Hook = TokenTransitions_1.UseTokenTransitions, Name, Resolution = "1920x1280", style = {} } = Props;
23
+ const Handlers = (() => {
24
+ if (InHandlers === undefined) {
25
+ return [TokenTransitions_1.TokenTransitions];
26
+ }
27
+ else if (!InHandlers.includes(TokenTransitions_1.TokenTransitions)) {
28
+ return [...InHandlers, TokenTransitions_1.TokenTransitions];
29
+ }
30
+ else {
31
+ return InHandlers;
32
+ }
33
+ })();
34
+ const { steps: Steps } = (0, react_1.useMemo)(
35
+ // @ts-expect-error parseRoot disagrees with the `zod` schema.
36
+ () => (0, blocks_1.parseRoot)(Content, CodePresentation_Internal_1.MarkdownSchema), [Content]);
37
+ const Resolutions = {
38
+ "1296x864": [1296, 864],
39
+ "1920x1280": [1920, 1080],
40
+ "2400x1600": [2400, 1600]
41
+ };
42
+ const VideoProps = {
43
+ Duration,
44
+ FrameRate,
45
+ Handlers,
46
+ Hook,
47
+ Resolution,
48
+ Steps,
49
+ style
50
+ };
51
+ const DurationInFrames = FrameRate * Duration;
52
+ return ((0, jsx_runtime_1.jsx)(remotion_1.Composition, { component: CodePresentation_Internal_1.Video, defaultProps: VideoProps, durationInFrames: DurationInFrames, fps: FrameRate, height: Resolutions[Resolution][1], id: Name, width: Resolutions[Resolution][0] }));
53
+ }
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TokenTransitions = void 0;
4
+ exports.UseTokenTransitions = UseTokenTransitions;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ /**
7
+ * @file TokenTransitions.tsx
8
+ * @author Gage Sorrell <gage@sorrell.sh>
9
+ * @copyright (c) 2026 Gage Sorrell
10
+ * @license MIT
11
+ */
12
+ /* eslint-disable jsdoc/require-jsdoc */
13
+ const code_1 = require("codehike/code");
14
+ const react_1 = require("react");
15
+ const remotion_1 = require("remotion");
16
+ const token_transitions_1 = require("codehike/utils/token-transitions");
17
+ const remotion_2 = require("remotion");
18
+ function UseTokenTransitions(OldCode, NewCode, FrameRate) {
19
+ const Frame = (0, remotion_1.useCurrentFrame)();
20
+ const Ref = (0, react_1.useRef)(null);
21
+ const [Snapshot, SetSnapshot] = (0, react_1.useState)();
22
+ const [Handle] = (0, react_1.useState)(() => (0, remotion_1.delayRender)());
23
+ /* If there is no old code, then transition from empty code. */
24
+ const PreviousCode = OldCode || { ...NewCode, annotations: [], tokens: [] };
25
+ (0, react_1.useLayoutEffect)(() => {
26
+ if (!Snapshot) {
27
+ SetSnapshot((0, token_transitions_1.getStartingSnapshot)(Ref.current));
28
+ return;
29
+ }
30
+ const Transitions = (0, token_transitions_1.calculateTransitions)(Ref.current, Snapshot);
31
+ function ApplyTransition({ element, keyframes, options }) {
32
+ interpolateStyle(element, keyframes, Frame, FrameRate * options.delay, FrameRate * options.duration);
33
+ }
34
+ ;
35
+ Transitions.forEach(ApplyTransition);
36
+ (0, remotion_1.continueRender)(Handle);
37
+ }, [Snapshot, Handle, Frame, FrameRate]);
38
+ const Code = Snapshot
39
+ ? NewCode
40
+ : PreviousCode;
41
+ return { Code, Ref };
42
+ }
43
+ exports.TokenTransitions = {
44
+ Pre: (Props) => ((0, jsx_runtime_1.jsx)(code_1.InnerPre, { merge: Props, style: { position: "relative" } })),
45
+ Token: (Props) => ((0, jsx_runtime_1.jsx)(code_1.InnerToken, { merge: Props, style: { display: "inline-block" } })),
46
+ name: "token-transitions"
47
+ };
48
+ function interpolateStyle(Element, Keyframes, Frame, Delay, Duration) {
49
+ const { color: Color, opacity: Opacity, translateX: TranslateX, translateY: TranslateY } = Keyframes;
50
+ const Progress = (0, remotion_2.interpolate)(Frame, [Delay, Delay + Duration], [0, 1], {
51
+ easing: remotion_1.Easing.inOut(remotion_1.Easing.ease),
52
+ extrapolateLeft: "clamp",
53
+ extrapolateRight: "clamp"
54
+ });
55
+ if (Opacity) {
56
+ Element.style.opacity = (0, remotion_2.interpolate)(Progress, [0, 1], Opacity).toString();
57
+ }
58
+ if (Color) {
59
+ Element.style.color = (0, remotion_2.interpolateColors)(Progress, [0, 1], Color);
60
+ }
61
+ if (TranslateX || TranslateY) {
62
+ const X = (0, remotion_2.interpolate)(Progress, [0, 1], TranslateX);
63
+ const Y = (0, remotion_2.interpolate)(Progress, [0, 1], TranslateY);
64
+ Element.style.translate = `${X}px ${Y}px`;
65
+ }
66
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ /**
3
+ * @file index.ts
4
+ * @author Gage Sorrell <gage@sorrell.sh>
5
+ * @copyright (c) 2026 Gage Sorrell
6
+ * @license MIT
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
20
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ __exportStar(require("./CodePresentation"), exports);
24
+ __exportStar(require("./CodePresentation.Types"), exports);
25
+ __exportStar(require("./TokenTransitions"), exports);
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ReactiveEventIntro = ReactiveEventIntro;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ /**
9
+ * @file index.tsx
10
+ * @author Gage Sorrell <gage@sorrell.sh>
11
+ * @copyright (c) 2026 Gage Sorrell
12
+ * @license MIT
13
+ */
14
+ /* eslint-disable jsdoc/require-jsdoc */
15
+ const code_1 = require("codehike/code");
16
+ const remotion_1 = require("remotion");
17
+ const CodePresentation_1 = require("../CodePresentation/CodePresentation");
18
+ const Content_md_1 = __importDefault(require("./Content.md"));
19
+ const Mark = {
20
+ Block: ({ children, annotation }) => {
21
+ const Delay = +(annotation.query || 0);
22
+ const Frame = (0, remotion_1.useCurrentFrame)();
23
+ const Background = (0, remotion_1.interpolateColors)(Frame, [Delay, Delay + 10], ["#0000", "#F2CC6044"]);
24
+ return (0, jsx_runtime_1.jsx)("div", { style: { background: Background }, children: children });
25
+ },
26
+ /* eslint-disable-next-line @typescript-eslint/typedef */
27
+ Line: (Props) => ((0, jsx_runtime_1.jsx)(code_1.InnerLine, { merge: Props, style: { padding: "0 4px" } })),
28
+ name: "mark"
29
+ };
30
+ const Handlers = [Mark];
31
+ function ReactiveEventIntro() {
32
+ return ((0, jsx_runtime_1.jsx)(CodePresentation_1.CodePresentation, { Duration: 3000, Name: "ReactiveEventIntro", Content: Content_md_1.default, Handlers }));
33
+ }
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ /**
3
+ * @file index.js
4
+ * @author Gage Sorrell <gage@sorrell.sh>
5
+ * @copyright (c) 2026 Gage Sorrell
6
+ * @license MIT
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
20
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.RunStudio = RunStudio;
24
+ const remotion_1 = require("remotion");
25
+ /**
26
+ * This should be called in the Remotion entrypoint, so that Remotion Studio
27
+ * will open the given {@link CodePresentation} component.
28
+ *
29
+ * @param PresentationComponent - The component to open in Remotion Studio.
30
+ */
31
+ function RunStudio(PresentationComponent) {
32
+ (0, remotion_1.registerRoot)(PresentationComponent);
33
+ }
34
+ __exportStar(require("./CodePresentation"), exports);
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@sorrell/code-hike",
3
+ "private": false,
4
+ "version": "1.0.0",
5
+ "description": "A helper library for making animations with Code Hike.",
6
+ "scripts": {
7
+ "build": "tsc -p ./tsconfig.json"
8
+ },
9
+ "keywords": [
10
+ "code-hike",
11
+ "code",
12
+ "hike",
13
+ "sorrell",
14
+ "react",
15
+ "remotion",
16
+ "next"
17
+ ],
18
+ "homepage": "https://github.com/GageSorrell/SorrellWm/tree/Master/Package/CodeHike#ReadMe",
19
+ "bugs": {
20
+ "url": "https://github.com/GageSorrell/SorrellWm/issues"
21
+ },
22
+ "repository": {
23
+ "directory": "Package/CodeHike",
24
+ "type": "git",
25
+ "url": "git+https://github.com/GageSorrell/SorrellWm.git"
26
+ },
27
+ "author": {
28
+ "email": "gage@sorrell.sh",
29
+ "name": "Gage Sorrell",
30
+ "url": "https://sorrell.sh"
31
+ },
32
+ "license": "MIT",
33
+ "devDependencies": {
34
+ "@types/react": "^18.0.0",
35
+ "typescript": "^6.0.3"
36
+ },
37
+ "files":
38
+ [
39
+ "Distribution",
40
+ "Distribution/**/*",
41
+ "remotion.config.ts",
42
+ "tsconfig.remotion.json"
43
+ ],
44
+ "exports": {
45
+ ".": { "default": "./Distribution/index.js", "types": "./Distribution/index.d.ts" },
46
+ "./tsconfig": "./tsconfig.remotion.json",
47
+ "./remotion": "./remotion.config.ts"
48
+ },
49
+ "dependencies": {
50
+ "@mdx-js/loader": "",
51
+ "@mdx-js/react": "",
52
+ "@remotion/cli": "4.0.177",
53
+ "@remotion/zod-types": "4.0.177",
54
+ "codehike": "1.0.0",
55
+ "react": "^18.0.0",
56
+ "react-dom": "^18.0.0",
57
+ "remotion": "4.0.177",
58
+ "twoslash-cdn": "^0.2.9",
59
+ "zod": "^3.21.4"
60
+ }
61
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * @file remotion.config.js
3
+ * @author Gage Sorrell <gage@sorrell.sh>
4
+ * @copyright (c) 2026 Gage Sorrell
5
+ * @license MIT
6
+ */
7
+
8
+ /* eslint-disable @typescript-eslint/typedef, jsdoc/require-jsdoc */
9
+
10
+ import { Config, type WebpackConfiguration } from "@remotion/cli/config";
11
+
12
+ export const DefaultCodeHikeConfig =
13
+ {
14
+ syntaxHighlighting:
15
+ {
16
+ theme: "github-dark"
17
+ }
18
+ };
19
+
20
+ /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
21
+ async function EnableMdx(CurrentConfiguration: any): Promise<WebpackConfiguration>
22
+ {
23
+ const { remarkCodeHike, recmaCodeHike } = await import("codehike/mdx");
24
+
25
+ return {
26
+ ...CurrentConfiguration,
27
+ module:
28
+ {
29
+ ...CurrentConfiguration.module,
30
+ rules:
31
+ [
32
+ ...(CurrentConfiguration.module?.rules
33
+ ? CurrentConfiguration.module.rules
34
+ : [ ]
35
+ ),
36
+ {
37
+ test: /\.mdx?$/,
38
+ use:
39
+ [
40
+ {
41
+ loader: "@mdx-js/loader",
42
+ options:
43
+ {
44
+ recmaPlugins: [ [ recmaCodeHike, DefaultCodeHikeConfig ] ],
45
+ remarkPlugins: [ [ remarkCodeHike, DefaultCodeHikeConfig ] ]
46
+ }
47
+ }
48
+ ]
49
+ }
50
+ ]
51
+ }
52
+ };
53
+ };
54
+
55
+ export function ApplyBaseConfig(): void
56
+ {
57
+ Config.overrideWebpackConfig(EnableMdx);
58
+ }
59
+
60
+ export function ApplyDefaultConfig(EntryPoint: string = "./Source/index.ts"): void
61
+ {
62
+ ApplyBaseConfig();
63
+ Config.setVideoImageFormat("jpeg");
64
+ Config.setEntryPoint(EntryPoint);
65
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions":
3
+ {
4
+ "target": "ES2018",
5
+ "module": "commonjs",
6
+ "jsx": "react-jsx",
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "lib": [ "es2016", "DOM" ],
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "noUnusedLocals": true
14
+ },
15
+ "include": [ "Source" ],
16
+ "exclude": [ "Distribution", "remotion.config.ts" ]
17
+ }