Skip to content

Commit

Permalink
Merge branch 'main' into catjohnson/expression-resize
Browse files Browse the repository at this point in the history
  • Loading branch information
catandthemachines committed Aug 27, 2024
2 parents 52104be + 873f107 commit 16af110
Show file tree
Hide file tree
Showing 16 changed files with 352 additions and 99 deletions.
5 changes: 5 additions & 0 deletions .changeset/heavy-falcons-bathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@khanacademy/perseus-editor": minor
---

Remove 'strings' prop from ContentPreview (we'll pull it from context)
6 changes: 6 additions & 0 deletions .changeset/little-badgers-share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@khanacademy/perseus": patch
"@khanacademy/perseus-editor": patch
---

Update dependency on wonder-blocks-form
5 changes: 5 additions & 0 deletions .changeset/rude-snails-kneel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@khanacademy/perseus-editor": patch
---

Ensure 'React' is imported in ContentPreview component.
5 changes: 3 additions & 2 deletions packages/perseus-editor/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
},
"dependencies": {
"@khanacademy/kas": "^0.3.12",
"@khanacademy/keypad-context": "^1.0.0",
"@khanacademy/kmath": "^0.1.13",
"@khanacademy/math-input": "^21.0.1",
"@khanacademy/perseus": "^31.0.1",
Expand All @@ -47,7 +48,7 @@
"@khanacademy/wonder-blocks-clickable": "4.2.1",
"@khanacademy/wonder-blocks-core": "6.4.0",
"@khanacademy/wonder-blocks-dropdown": "5.3.0",
"@khanacademy/wonder-blocks-form": "^4.7.1",
"@khanacademy/wonder-blocks-form": "^4.9.0",
"@khanacademy/wonder-blocks-icon": "4.1.0",
"@khanacademy/wonder-blocks-icon-button": "5.2.1",
"@khanacademy/wonder-blocks-switch": "1.1.16",
Expand Down Expand Up @@ -75,7 +76,7 @@
"@khanacademy/wonder-blocks-clickable": "4.2.1",
"@khanacademy/wonder-blocks-core": "6.4.0",
"@khanacademy/wonder-blocks-dropdown": "5.3.0",
"@khanacademy/wonder-blocks-form": "^4.7.1",
"@khanacademy/wonder-blocks-form": "^4.9.0",
"@khanacademy/wonder-blocks-icon": "4.1.0",
"@khanacademy/wonder-blocks-icon-button": "5.2.1",
"@khanacademy/wonder-blocks-switch": "1.1.16",
Expand Down
103 changes: 103 additions & 0 deletions packages/perseus-editor/src/__stories__/content-preview.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import {
PerseusI18nContextProvider,
type DeviceType,
} from "@khanacademy/perseus";
import {View} from "@khanacademy/wonder-blocks-core";
import {spacing} from "@khanacademy/wonder-blocks-tokens";
import {useState} from "react";

import {articleWithImages} from "../../../perseus/src/__testdata__/article-renderer.testdata";
import {mockStrings} from "../../../perseus/src/strings";
import {question} from "../../../perseus/src/widgets/__testdata__/radio.testdata";
import DeviceFramer from "../components/device-framer";
import ViewportResizer from "../components/viewport-resizer";
import ContentPreview from "../content-preview";

import type {Meta, StoryObj} from "@storybook/react";

import "../styles/perseus-editor.less";

const PreviewWrapper = (props) => {
const [previewDevice, setPreviewDevice] = useState<DeviceType>("phone");

return (
<View>
<ViewportResizer
deviceType={previewDevice}
onViewportSizeChanged={setPreviewDevice}
/>
<DeviceFramer nochrome={false} deviceType={previewDevice}>
<ContentPreview {...props} />
</DeviceFramer>
</View>
);
};

const meta: Meta<typeof ContentPreview> = {
title: "PerseusEditor/Content Preview",
component: ContentPreview,
decorators: [
(Story) => (
<View style={{margin: spacing.xxSmall_6}}>
<PerseusI18nContextProvider strings={mockStrings} locale="en">
<Story />
</PerseusI18nContextProvider>
</View>
),
],
render: (props) => <PreviewWrapper {...props} />,
};

export default meta;
type Story = StoryObj<typeof ContentPreview>;

export const Exercise: Story = {
args: {
question,
},
};

export const Article: Story = {
args: {
question: articleWithImages,
},
};

export const WithLintErrors: Story = {
args: {
linterContext: {
contentType: "exercise",
highlightLint: true,
stack: [],
paths: [],
},
question: {
content: `# H1s bad
Here is some unclosed math: $1+1=3
We should use \`\\dfrac{}\` instead of \`\\frac{}\`: $\\frac{3}{5}$
What is the best color in the world?
[[☃ radio 1]]`,
widgets: {
"radio 1": {
type: "radio",
options: {
choices: [
{content: "Red"},
{content: "# Green"},
{content: "Blue", correct: true},
{
content: "None of these!",
isNoneOfTheAbove: true,
},
],
},
},
},
images: {},
},
},
};
91 changes: 91 additions & 0 deletions packages/perseus-editor/src/content-preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import {
KeypadContext,
StatefulKeypadContextProvider,
} from "@khanacademy/keypad-context";
import {MobileKeypad} from "@khanacademy/math-input";
import {
Renderer,
constants,
usePerseusI18n,
type APIOptions,
type DeviceType,
type PerseusRenderer,
} from "@khanacademy/perseus";
import {View} from "@khanacademy/wonder-blocks-core";
import {spacing} from "@khanacademy/wonder-blocks-tokens";
import {StyleSheet} from "aphrodite";
import * as React from "react";

import type {LinterContextProps} from "@khanacademy/perseus-linter";

/**
* The `ContentPreview` component provides a simple preview system for Perseus
* Content. Due to how Persus styles are built, the preview styling matches the
* current device based on the viewport width (using `@media` queries for
* `min-width` and `max-width`).
*
* The preview will render the mobile variant (styling and layout) when the
* `previewDevice` is phone or tablet. Note that the styling cannot be matched
* 100% due to the above `@media` query limitation.
*/
function ContentPreview({
question,
apiOptions,
seamless,
linterContext,
legacyPerseusLint,
previewDevice,
}: {
question?: PerseusRenderer;
apiOptions?: APIOptions;
seamless?: boolean;
linterContext?: LinterContextProps;
legacyPerseusLint?: ReadonlyArray<string>;
previewDevice: DeviceType;
}) {
const i18n = usePerseusI18n();
const isMobile = previewDevice !== "desktop";

const className = isMobile ? "perseus-mobile" : "";

return (
<View
className={`framework-perseus ${className}`}
style={[styles.container, !seamless ? styles.gutter : undefined]}
>
<StatefulKeypadContextProvider>
<KeypadContext.Consumer>
{({setKeypadActive, keypadElement, setKeypadElement}) => (
<>
<Renderer
strings={i18n.strings}
apiOptions={{...apiOptions, isMobile}}
keypadElement={keypadElement}
linterContext={linterContext}
legacyPerseusLint={legacyPerseusLint}
{...question}
/>

<MobileKeypad
onAnalyticsEvent={() => Promise.resolve()}
onDismiss={() => setKeypadActive(false)}
onElementMounted={setKeypadElement}
/>
</>
)}
</KeypadContext.Consumer>
</StatefulKeypadContextProvider>
</View>
);
}

const styles = StyleSheet.create({
container: {
padding: spacing.xxxSmall_4,
containerType: "inline-size",
containerName: "perseus-root",
},
gutter: {marginRight: constants.lintGutterWidth},
});

export default ContentPreview;
4 changes: 2 additions & 2 deletions packages/perseus/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"@khanacademy/wonder-blocks-core": "6.4.0",
"@khanacademy/wonder-blocks-data": "13.0.7",
"@khanacademy/wonder-blocks-dropdown": "5.3.0",
"@khanacademy/wonder-blocks-form": "^4.7.1",
"@khanacademy/wonder-blocks-form": "^4.9.0",
"@khanacademy/wonder-blocks-icon": "4.1.0",
"@khanacademy/wonder-blocks-icon-button": "5.2.1",
"@khanacademy/wonder-blocks-layout": "2.0.32",
Expand Down Expand Up @@ -94,7 +94,7 @@
"@khanacademy/wonder-blocks-core": "6.4.0",
"@khanacademy/wonder-blocks-data": "13.0.7",
"@khanacademy/wonder-blocks-dropdown": "5.3.0",
"@khanacademy/wonder-blocks-form": "^4.7.1",
"@khanacademy/wonder-blocks-form": "^4.9.0",
"@khanacademy/wonder-blocks-icon": "4.1.0",
"@khanacademy/wonder-blocks-icon-button": "5.2.1",
"@khanacademy/wonder-blocks-layout": "2.0.32",
Expand Down
90 changes: 90 additions & 0 deletions packages/perseus/src/__testdata__/article-renderer.testdata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,93 @@ export const multiSectionArticleWithExpression: ReadonlyArray<PerseusRenderer> =
},
},
];

export const articleWithImages: PerseusRenderer = {
content:
"The word \"radiation\" sometimes gets a bad rap. People often associate radiation with something dangerous or scary, without really knowing what it is. In reality, we're surrounded by radiation all the time. \n\n**Radiation** is energy that travels through space (not just \"outer space\"—any space). Radiation can also interact with matter. How radiation interacts with matter depends on the type of radiation and the type of matter.\n\nRadiation comes in many forms, one of which is *electromagnetic radiation*. Without electromagnetic radiation life on Earth would not be possible, nor would most modern technologies.\n\n[[☃ image 13]]\n\nLet's take a closer look at this important and fascinating type of radiation.\n\n##Electromagnetic radiation\n\nAs the name suggests, **electromagnetic (EM) radiation** is energy transferred by *electromagnetic fields* oscillating through space.\n\nEM radiation is strange—it has both wave and particle properties. Let's take a look at both.\n\n###Electromagnetic waves\n\nAn animated model of an EM wave is shown below.\n[[☃ image 1]]\nThe electric field $(\\vec{\\textbf{E}})$ is shown in $\\color{blue}\\textbf{blue}$, and the magnetic field $(\\vec{\\textbf{B}})$ is shown in $\\color{red}\\textbf{red}$. They're perpendicular to each other.\n\nA changing electric field creates a magnetic field, and a changing magnetic field creates an electric field. So, once the EM wave is generated it propagates itself through space!\n\nAs with any wave, EM waves have wavelength, frequency, and speed. The wave model of EM radiation works best on large scales. But what about the atomic scale?\n\n###Photons\n\nAt the quantum level, EM radiation exists as particles. A particle of EM radiation is called a **photon**.\n\nWe can think of photons as wave *packets*—tiny bundles of EM radiation containing specific amounts of energy. Photons are visually represented using the following symbol.\n\n[[☃ image 3]]\n\nAll EM radiation, whether modeled as waves or photons, travels at the **speed of light** $\\textbf{(c)}$ in a vacuum: \n\n$\\text{c}=3\\times10^8\\space\\pu{m/s}=300{,}000{,}000\\space\\pu{m/s}$\n\nBut, EM radiation travels at a slower speed in matter, such as water or glass.",
images: {},
widgets: {
"image 13": {
type: "image",
alignment: "block",
static: false,
graded: true,
options: {
static: false,
title: "",
range: [
[0, 10],
[0, 10],
],
box: [600, 254],
backgroundImage: {
url: "https://cdn.kastatic.org/ka-content-images/358a87c20ab6ee70447f5fcb547010f69986828e.jpg",
width: 600,
height: 254,
},
labels: [],
alt: "From space, the sun appears over Earth's horizon, illuminating the atmosphere as a blue layer above Earth. Above the atmosphere, space appears black.",
caption:
"*Sunrise photo from the International Space Station. Earth's atmosphere scatters electromagnetic radiation from the sun, producing a bright sky during the day.*",
},
version: {
major: 0,
minor: 0,
},
},
"image 1": {
type: "image",
alignment: "block",
static: false,
graded: true,
options: {
static: false,
title: "",
range: [
[0, 10],
[0, 10],
],
box: [627, 522],
backgroundImage: {
url: "https://cdn.kastatic.org/ka-content-images/8100369eaf3b581d4e7bfc9f1062625309def486.gif",
width: 627,
height: 522,
},
labels: [],
alt: "An animation shows a blue electric field arrow oscillating up and down. Connected to the base of the electric field arrow is a magnetic field arrow, which oscillates from side to side. The two fields oscillate in unison: when one extends the other extends too, creating a repeating wave pattern.",
caption: "",
},
version: {
major: 0,
minor: 0,
},
},
"image 3": {
type: "image",
alignment: "block",
static: false,
graded: true,
options: {
static: false,
title: "",
range: [
[0, 10],
[0, 10],
],
box: [350, 130],
backgroundImage: {
url: "https://cdn.kastatic.org/ka-content-images/74edeeb6c6605a4e854e3a3e9db69c01dcf5508f.svg",
width: 350,
height: 130,
},
labels: [],
alt: "A squiggly curve drawn from left to right. The right end of the curve has an arrow point. The curve begins with a small amount of wiggle on the left, which grows in amplitude in the middle and then decreases again on the right. The result is a small wave packet.",
caption: "",
},
version: {
major: 0,
minor: 0,
},
},
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ exports[`server item renderer should snapshot: initial render 1`] = `
autocapitalize="off"
autocomplete="off"
autocorrect="off"
class="input_1t4b01j-o_O-LabelMedium_1rew30o-o_O-default_1r2dwp3-o_O-default_1gznapd-o_O-leftAlign_7jg4r4"
class="input_1t4b01j-o_O-LabelMedium_1rew30o-o_O-default_53h0n9-o_O-default_1gznapd-o_O-leftAlign_7jg4r4"
id="input-with-examples-aW5wdXQtbnVtYmVyIDE"
type="text"
value=""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,7 @@ exports[`multi-item renderer should snapshot: initial render 1`] = `
autocapitalize="off"
autocomplete="off"
autocorrect="off"
class="input_1t4b01j-o_O-LabelMedium_1rew30o-o_O-default_1r2dwp3-o_O-default_1gznapd-o_O-leftAlign_7jg4r4"
class="input_1t4b01j-o_O-LabelMedium_1rew30o-o_O-default_53h0n9-o_O-default_1gznapd-o_O-leftAlign_7jg4r4"
id="input-with-examples-aW5wdXQtbnVtYmVyIDE"
type="text"
value=""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ exports[`graded-group-set should render all graded groups 1`] = `
autocapitalize="off"
autocomplete="off"
autocorrect="off"
class="input_1t4b01j-o_O-LabelMedium_1rew30o-o_O-default_1r2dwp3-o_O-input_19vw1dn"
class="input_1t4b01j-o_O-LabelMedium_1rew30o-o_O-default_53h0n9-o_O-input_19vw1dn"
id="input-with-examples-bnVtZXJpYy1pbnB1dCAx"
type="text"
value=""
Expand Down Expand Up @@ -297,7 +297,7 @@ exports[`graded-group-set should render all graded groups 1`] = `
autocapitalize="off"
autocomplete="off"
autocorrect="off"
class="input_1t4b01j-o_O-LabelMedium_1rew30o-o_O-default_1r2dwp3-o_O-input_19vw1dn"
class="input_1t4b01j-o_O-LabelMedium_1rew30o-o_O-default_53h0n9-o_O-input_19vw1dn"
id="input-with-examples-bnVtZXJpYy1pbnB1dCAx"
type="text"
value=""
Expand Down Expand Up @@ -526,7 +526,7 @@ exports[`graded-group-set should render all graded groups 1`] = `
autocapitalize="off"
autocomplete="off"
autocorrect="off"
class="input_1t4b01j-o_O-LabelMedium_1rew30o-o_O-default_1r2dwp3-o_O-input_19vw1dn"
class="input_1t4b01j-o_O-LabelMedium_1rew30o-o_O-default_53h0n9-o_O-input_19vw1dn"
id="input-with-examples-bnVtZXJpYy1pbnB1dCAx"
type="text"
value=""
Expand Down
Loading

0 comments on commit 16af110

Please sign in to comment.