<commit_before>/** @jsx React.DOM */
(function(Perseus) {

require("./core.js");
var Util = require("./util.js");

var Widgets = require("./widgets.js");
var PropCheckBox = require("./components/prop-check-box.jsx");

// like [[snowman input-number 1]]
var rWidgetSplit = /(\[\[\u2603 [a-z-]+ [0-9]+\]\])/g;

/* This component makes its children a drag target. Example:
 *
 *     <DragTarget onDrop={this.handleDrop}>Drag to me</DragTarget>
 *
 *     ...
 *
 *     handleDrop: function(e) {
 *         this.addImages(e.nativeEvent.dataTransfer.files);
 *     }
 *
 * Now "Drag to me" will be a drag target - when something is dragged over it,
 * the element will become partially transparent as a visual indicator that
 * it's a target.
 */
// TODO(joel) - indicate before the hover is over the target that it's possible
// to drag into the target. This would (I think) require a high level handler -
// like on Perseus itself, waiting for onDragEnter, then passing down the
// event. Sounds like a pain. Possible workaround - create a div covering the
// entire page...
//
// Other extensions:
// * custom styles for global drag and dragOver
// * only respond to certain types of drags (only images for instance)!
var DragTarget = React.createClass({
    propTypes: {
        onDrop: React.PropTypes.func.isRequired,
        component: React.PropTypes.component,
        shouldDragHighlight: React.PropTypes.func
    },
    render: function() {
        // This is the only property of the returned component we need to
        // calculate here because it will be overwritten by transferPropsTo.
        var opacity = this.state.dragHover ? { "opacity": 0.3 } : {};

        var component = this.props.component;
        return this.transferPropsTo(
            <component style={opacity}
                       onDrop={this.handleDrop}
                       onDragEnd={this.handleDragEnd}
                       onDragOver={this.handleDragOver}
                       onDragEnter={this.handleDragEnter}
                       onDragLeave={this.handleDragLeave}>
                {this.props.children}
            </component>
        );
    },
    getInitialState: function() {
        return { dragHover: false };
    },
    getDefaultProps: function() {
        return {
            component: React.DOM.div,
            shouldDragHighlight: function() { return true; }
        };
    },
    handleDrop: function(e) {
        e.stopPropagation();
        e.preventDefault();
        this.setState({ dragHover: false });
        this.props.onDrop(e);
    },
    handleDragEnd: function() {
        this.setState({ dragHover: false });
    },
    handleDragOver: function(e) {
        e.preventDefault();
    },
    handleDragLeave: function() {
        this.setState({ dragHover: false });
    },
    handleDragEnter: function(e) {
        this.setState({ dragHover: this.props.shouldDragHighlight(e) });
    }
});

var WidgetSelect = React.createClass({
    handleChange: function(e) {
        var widgetType = e.target.value;
        if (widgetType === "") {
            // TODO(alpert): Not sure if change will trigger here
            // but might as well be safe
            return;
        }
        e.target.value = "";
        if (this.props.onChange) {
            this.props.onChange(widgetType);
        }
    },
    shouldComponentUpdate: function() {
        return false;
    },
    render: function() {
        return <select onChange={this.handleChange}>
            <option value="">Add a widget{"\u2026"}</option>
            <option disabled>--</option>
            <option value="input-number">
                    Text input (number)</option>
            <option value="expression">
                    Expression / Equation</option>
            <option value="radio">
                    Multiple choice</option>
            <option value="interactive-graph">
                    Interactive graph</option>
            <option value="number-line">
                    Number line</option>
            <option value="categorization">
                    Categorization</option>
            <option value="plotter">
                    Plotter</option>
            <option value="table">
                    Table of values</option>
            <option value="dropdown">
                    Drop down</option>
            <option value="orderer">
                    Orderer</option>
            <option value="measurer">
                    Measurer</option>
            <option value="transformer">
                    Transformer</option>
            <option value="matcher">
                    Two column matcher</option>
            <option value="sorter">
                    Sorter</option>
        </select>;
    }
});


var WidgetEditor = React.createClass({
    getDefaultProps: function() {
        return {
            graded: true
        };
    },

    getInitialState: function() {
        return {
            showWidget: true
        };
    },

    render: function() {
        var cls = Widgets.get(this.props.type + "-editor");

        var isUngradedEnabled = (this.props.type === "transformer");
        var direction = this.state.showWidget ? "down" : "right";

        var gradedPropBox = <PropCheckBox label="Graded:"
                                graded={this.props.graded}
                                onChange={this.props.onChange} />;

        return <div className="perseus-widget-editor">
            <a href="#" className={"perseus-widget-editor-title " +<commit_msg>Add propTypes to WidgetEditor<commit_after>/** @jsx React.DOM */
(function(Perseus) {

require("./core.js");
var Util = require("./util.js");

var Widgets = require("./widgets.js");
var PropCheckBox = require("./components/prop-check-box.jsx");

// like [[snowman input-number 1]]
var rWidgetSplit = /(\[\[\u2603 [a-z-]+ [0-9]+\]\])/g;

/* This component makes its children a drag target. Example:
 *
 *     <DragTarget onDrop={this.handleDrop}>Drag to me</DragTarget>
 *
 *     ...
 *
 *     handleDrop: function(e) {
 *         this.addImages(e.nativeEvent.dataTransfer.files);
 *     }
 *
 * Now "Drag to me" will be a drag target - when something is dragged over it,
 * the element will become partially transparent as a visual indicator that
 * it's a target.
 */
// TODO(joel) - indicate before the hover is over the target that it's possible
// to drag into the target. This would (I think) require a high level handler -
// like on Perseus itself, waiting for onDragEnter, then passing down the
// event. Sounds like a pain. Possible workaround - create a div covering the
// entire page...
//
// Other extensions:
// * custom styles for global drag and dragOver
// * only respond to certain types of drags (only images for instance)!
var DragTarget = React.createClass({
    propTypes: {
        onDrop: React.PropTypes.func.isRequired,
        component: React.PropTypes.component,
        shouldDragHighlight: React.PropTypes.func
    },
    render: function() {
        // This is the only property of the returned component we need to
        // calculate here because it will be overwritten by transferPropsTo.
        var opacity = this.state.dragHover ? { "opacity": 0.3 } : {};

        var component = this.props.component;
        return this.transferPropsTo(
            <component style={opacity}
                       onDrop={this.handleDrop}
                       onDragEnd={this.handleDragEnd}
                       onDragOver={this.handleDragOver}
                       onDragEnter={this.handleDragEnter}
                       onDragLeave={this.handleDragLeave}>
                {this.props.children}
            </component>
        );
    },
    getInitialState: function() {
        return { dragHover: false };
    },
    getDefaultProps: function() {
        return {
            component: React.DOM.div,
            shouldDragHighlight: function() { return true; }
        };
    },
    handleDrop: function(e) {
        e.stopPropagation();
        e.preventDefault();
        this.setState({ dragHover: false });
        this.props.onDrop(e);
    },
    handleDragEnd: function() {
        this.setState({ dragHover: false });
    },
    handleDragOver: function(e) {
        e.preventDefault();
    },
    handleDragLeave: function() {
        this.setState({ dragHover: false });
    },
    handleDragEnter: function(e) {
        this.setState({ dragHover: this.props.shouldDragHighlight(e) });
    }
});

var WidgetSelect = React.createClass({
    handleChange: function(e) {
        var widgetType = e.target.value;
        if (widgetType === "") {
            // TODO(alpert): Not sure if change will trigger here
            // but might as well be safe
            return;
        }
        e.target.value = "";
        if (this.props.onChange) {
            this.props.onChange(widgetType);
        }
    },
    shouldComponentUpdate: function() {
        return false;
    },
    render: function() {
        return <select onChange={this.handleChange}>
            <option value="">Add a widget{"\u2026"}</option>
            <option disabled>--</option>
            <option value="input-number">
                    Text input (number)</option>
            <option value="expression">
                    Expression / Equation</option>
            <option value="radio">
                    Multiple choice</option>
            <option value="interactive-graph">
                    Interactive graph</option>
            <option value="number-line">
                    Number line</option>
            <option value="categorization">
                    Categorization</option>
            <option value="plotter">
                    Plotter</option>
            <option value="table">
                    Table of values</option>
            <option value="dropdown">
                    Drop down</option>
            <option value="orderer">
                    Orderer</option>
            <option value="measurer">
                    Measurer</option>
            <option value="transformer">
                    Transformer</option>
            <option value="matcher">
                    Two column matcher</option>
            <option value="sorter">
                    Sorter</option>
        </select>;
    }
});


var WidgetEditor = React.createClass({
    propTypes: {
        type: React.PropTypes.string,
        id: React.PropTypes.string,
        graded: React.PropTypes.bool,
        onChange: React.PropTypes.func
    },

    getDefaultProps: function() {
        return {
            graded: true
        };
    },

    getInitialState: function() {
        return {
            showWidget: true
        };
    },

    render: function() {
        var cls = Widgets.get(this.props.type + "-editor");

        var isUngradedEnabled = (this.props.type === "transformer");
        var direction = this.state.showWidget ? "down" : "right";

        var gradedPropBox = <PropCheckBox label="Graded:"
                                graded={this.props.graded}
                                onChange={this.props.onChange} />;

        return <div className="perseus-widget-editor">
            <a href="#" className={"perseus-widget-editor-title " +
{'fraction_non_alphanumeric': 0.1219100124488707, 'fraction_numerical': 0.0023119331317801887, 'mean_word_length': 1.8720633299284986, 'pattern_counts': {'":': 2, '<': 85, '<?xml version=': 0, '>': 83, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4575436', 'n_tokens_mistral': 3014, 'n_tokens_neox': 2931, 'n_words': 750}