Skip to content

Commit

Permalink
frontend: Implement MFM transform functions (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
tirr-c committed Aug 25, 2023
1 parent eb5501a commit e61c0b6
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 17 deletions.
63 changes: 46 additions & 17 deletions frontend/src/components/mfm/MfmFunction.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,63 @@
import { MfmFn, MfmNode } from "mfm-js";
import { MfmFn } from "mfm-js";
import type { CSSProperties } from "react";

import { CustomEmojiMapper } from "./Mfm";
import MfmRenderer from "./MfmRenderer";

function parseFloatWithDefault(value: string | true | undefined, defaultValue: string): string {
if (typeof value !== "string" || !/^\d+(:?\.\d+)?$/.test(value)) {
return defaultValue;
}
return value;
}

export default function MfmFunction(
{ props, children, customEmojiMapper }: MfmFn & { customEmojiMapper?: CustomEmojiMapper },
) {
let className;
let style: CSSProperties | undefined;
switch (props.name) {
case "x2":
return <MfmFnZoom scale={2} nodes={children} customEmojiMapper={customEmojiMapper} />;
className = "text-[2em]";
break;
case "x3":
return <MfmFnZoom scale={3} nodes={children} customEmojiMapper={customEmojiMapper} />;
className = "text-[3em]";
break;
case "x4":
return <MfmFnZoom scale={4} nodes={children} customEmojiMapper={customEmojiMapper} />;
default:
return <MfmRenderer nodes={children} customEmojiMapper={customEmojiMapper} />;
className = "text-[4em]";
break;
case "flip":
className = "inline-block -scale-x-100";
break;
case "scale": {
const x = parseFloatWithDefault(props.args.x, "1");
const y = parseFloatWithDefault(props.args.y, "1");
className = "inline-block";
style = { transform: `scale(${x}, ${y})` };
break;
}
case "position": {
const x = parseFloatWithDefault(props.args.x, "0");
const y = parseFloatWithDefault(props.args.y, "0");
className = "inline-block";
style = { transform: `translate(${x}em, ${y}em)` };
break;
}
case "rotate": {
const degrees = parseFloatWithDefault(props.args.deg, "90");
className = "inline-block";
style = { transform: `rotate(${degrees}deg)` };
break;
}
}

if (!className && !style) {
return <MfmRenderer nodes={children} customEmojiMapper={customEmojiMapper} />;
}
}

function MfmFnZoom(
{ scale, nodes, customEmojiMapper }: {
scale: number;
nodes: MfmNode[];
customEmojiMapper?: CustomEmojiMapper;
},
) {
const classNameMap = ["", "", "text-[2em]", "text-[3em]", "text-[4em]"];
return (
<span className={classNameMap[scale]}>
<MfmRenderer nodes={nodes} customEmojiMapper={customEmojiMapper} />
<span className={className} style={style}>
<MfmRenderer nodes={children} customEmojiMapper={customEmojiMapper} />
</span>
);
}
5 changes: 5 additions & 0 deletions frontend/src/stories/Mfm.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from "react";

import Mfm from "@/components/mfm/Mfm";

import transformsTestdata from "./assets/mfm-transforms.json";
import plachta from "./assets/plachta.png";
import recruitSimulatorTestdata from "./assets/recruit.json";
import sendMoney from "./assets/send-money.png";
Expand Down Expand Up @@ -67,6 +68,10 @@ export const EmojiZoom: Story = {
},
};

export const Transforms: Story = {
args: transformsTestdata,
};

export const RecruitSimulator: Story = {
args: recruitSimulatorTestdata,
};
1 change: 1 addition & 0 deletions frontend/src/stories/assets/mfm-transforms.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"content": "$[position.x=2.25 $[rotate.deg=45 🟦]$[scale.y=1.4 🟦]$[rotate.deg=45 🟦]]\n$[x2 $[rotate.deg=45 🟦]$[position.y=0.3 🟦]$[rotate.deg=45 🟦]]"}

0 comments on commit e61c0b6

Please sign in to comment.