diff --git a/.changeset/chilly-singers-decide.md b/.changeset/chilly-singers-decide.md new file mode 100644 index 0000000000..d6c5c3bced --- /dev/null +++ b/.changeset/chilly-singers-decide.md @@ -0,0 +1,5 @@ +--- +"@khanacademy/perseus": patch +--- + +Add features to support show-your-work widget diff --git a/packages/perseus/src/components/math-input.tsx b/packages/perseus/src/components/math-input.tsx index 3cc852a31c..6e356d3de5 100644 --- a/packages/perseus/src/components/math-input.tsx +++ b/packages/perseus/src/components/math-input.tsx @@ -71,6 +71,8 @@ type Props = { * - `never` means that the keypad is **never shown**. */ buttonsVisible?: ButtonsVisibleType; + disabled?: boolean; + noBackground?: boolean; onAnalyticsEvent: AnalyticsEventHandlerFn; }; @@ -168,6 +170,13 @@ class InnerMathInput extends React.Component { input?.focus(); }; + // TODO(kevinb): Port this to @khanacademy/math-input + setValue = (value: string) => { + const input = this.mathField(); + input?.select(); + input?.write(value); + }; + mathField: () => MathFieldInterface | null = () => { if (!this.__mathField && this.__mathFieldWrapperRef) { const {locale} = this.context; @@ -306,8 +315,10 @@ class InnerMathInput extends React.Component {
{ onFocus={() => this.focus()} onBlur={() => this.blur()} /> - this.closeKeypad()} - dismissEnabled - aria-label={this.context.strings.mathInputTitle} - aria-describedby={`popover-content-${popoverContentUniqueId}`} - content={() => ( - <> - - {this.context.strings.mathInputDescription} - - - this.closeKeypad()} + dismissEnabled + aria-label={this.context.strings.mathInputTitle} + aria-describedby={`popover-content-${popoverContentUniqueId}`} + content={() => ( + <> + + { + this.context.strings + .mathInputDescription } - {...(this.props.keypadButtonSets ?? - mapButtonSets( - this.props?.buttonSets, - ))} - /> - - - )} - > - {this.props.buttonsVisible === "never" ? ( - - ) : ( - - this.state.keypadOpen - ? this.closeKeypad() - : this.openKeypad() - } - > - {(props) => ( - - )} - - )} - + + + + + + )} + > + {this.props.buttonsVisible === "never" ? ( + + ) : ( + + this.state.keypadOpen + ? this.closeKeypad() + : this.openKeypad() + } + > + {(props) => ( + + )} + + )} + + )}
); @@ -538,9 +556,11 @@ const styles = StyleSheet.create({ borderWidth: 1, borderColor: color.offBlack50, borderRadius: 3, - background: color.white, ":hover": inputFocused, }, + outerWrapperBackground: { + background: color.white, + }, wrapperFocused: inputFocused, wrapperError: { borderColor: color.red, @@ -554,6 +574,9 @@ const styles = StyleSheet.create({ paddingBottom: spacing.xxSmall_6, maxWidth: "initial", }, + disabled: { + pointerEvents: "none", + }, }); export default MathInput; diff --git a/packages/perseus/src/widgets/expression/expression.tsx b/packages/perseus/src/widgets/expression/expression.tsx index 91f1e24c5e..aefc2e8285 100644 --- a/packages/perseus/src/widgets/expression/expression.tsx +++ b/packages/perseus/src/widgets/expression/expression.tsx @@ -86,6 +86,9 @@ export type Props = ExternalProps & visibleLabel: PerseusExpressionWidgetOptions["visibleLabel"]; ariaLabel: PerseusExpressionWidgetOptions["ariaLabel"]; value: string; + disabled?: boolean; + noBackground?: boolean; + noWrapper?: boolean; }; export type ExpressionState = { @@ -115,6 +118,7 @@ export class Expression _textareaId = `expression_textarea_${Date.now()}`; _isMounted = false; + _mathInput: React.MutableRefObject = React.createRef(); static getUserInputFromProps(props: Props): PerseusExpressionUserInput { return normalizeTex(props.value); @@ -294,6 +298,13 @@ export class Expression }, cb, ); + + if (this._mathInput.current) { + const inputRef = this._mathInput.current.inputRef; + if (inputRef.current) { + inputRef.current.setValue(newValue); + } + } } render() { @@ -342,7 +353,13 @@ export class Expression const {ERROR_MESSAGE, ERROR_TITLE} = this.context.strings; return ( - + {!!this.props.visibleLabel && ( {this.props.visibleLabel} @@ -378,13 +395,14 @@ export class Expression content={ERROR_MESSAGE} >