-
Notifications
You must be signed in to change notification settings - Fork 30
Initial commit of component render classes. #8
Changes from all commits
0638019
e5d96a8
8500f7e
dad1c8b
3c4c4fe
2a0e894
6bc9a3e
db0fa11
939dbf7
f5d12f7
9ff18a0
2840c31
9bde50b
be4a5d8
bef5a8e
5d548ad
f791971
95e2423
fffa746
e1ea4fc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/** @license | ||
* Copyright 2016 Google Inc. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
* use this file except in compliance with the License. You may obtain a copy | ||
* of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import * as React from "react"; | ||
import { KeyCode, KeyEvent, CSS } from "../lib/Constants"; | ||
import { Messaging } from "../lib/Messaging"; | ||
import { Overlay } from "./overlay/Overlay"; | ||
import { Variable } from "../core/variables/Variable"; | ||
|
||
/** | ||
* Interface for the properties assigned to the DOMController component. | ||
* @interface | ||
*/ | ||
interface ControllerProps { | ||
wrapperElement: HTMLElement; | ||
variables: Array<Variable>; | ||
updateVariable(variable: Variable, selectedValue: any): void; | ||
} | ||
|
||
/** | ||
* Renders an MDL card-styled overlay containing a child control for each | ||
* variable. | ||
* @class | ||
* @extends React.Component | ||
*/ | ||
export class DOMController extends React.Component<ControllerProps, void> { | ||
|
||
/** @override */ | ||
componentDidMount() { | ||
// Register for messaging and key events. | ||
Messaging.register(this.onMessageReceived.bind(this)); | ||
this.addKeyListener(); | ||
} | ||
|
||
/** @override */ | ||
componentWillUnmount() { | ||
// Unregister for messaging and key events. | ||
Messaging.unregister(); | ||
this.removeKeyListener(); | ||
} | ||
|
||
/** | ||
* Handles receiving of window message. | ||
* @param {MessageEvent} event The received message event. | ||
*/ | ||
onMessageReceived(event: MessageEvent): void { | ||
if (event.data === Messaging.type.ToggleVisibility) { | ||
this.toggleVisibility(); | ||
} | ||
} | ||
|
||
/** Adds a key listener. */ | ||
addKeyListener(): void { | ||
document.addEventListener(KeyEvent.DOWN, (e: KeyboardEvent) => { | ||
if (e.keyCode === KeyCode.ESC) { | ||
this.toggleVisibility(); | ||
} | ||
}); | ||
} | ||
|
||
/** Removes a key listener. */ | ||
removeKeyListener(): void { | ||
document.removeEventListener(KeyEvent.DOWN); | ||
} | ||
|
||
/** Toggles the Remixer overlay visibility. */ | ||
toggleVisibility() { | ||
this.props.wrapperElement.classList.toggle(CSS.RMX_VISIBLE); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like I've asked this in every review and haven't seen any comments/changes. Maybe the comments got lost in the GitHub UI? Why are you mutating the DOM of an element this component doesn't control? Couldn't this just be: toggleVisibility() {
this.setState({
isVisible: !this.props.isVisible,
}})
}
render() {
const {
isVisible,
variables,
updateVariable,
} = this.props;
if (this.props.isVisible) {
return (
// your DOM tree
)
} else {
return <div />;
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah we chatted about this. Its part of #12. Just never made that change. |
||
} | ||
|
||
/** @override */ | ||
render() { | ||
return ( | ||
<div className="mdl-card mdl-shadow--6dp"> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you use string literals in some places and groups of |
||
<div className="mdl-card__title" ref="myInput"> | ||
<h2 className="mdl-card__title-text">Remixer</h2> | ||
</div> | ||
<div className="mdl-card__supporting-text mdl-card__actions mdl-card--border"> | ||
<Overlay | ||
variables={this.props.variables} | ||
updateVariable={this.props.updateVariable} | ||
/> | ||
</div> | ||
</div> | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
/** @license | ||
* Copyright 2016 Google Inc. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
* use this file except in compliance with the License. You may obtain a copy | ||
* of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import * as React from "react"; | ||
import { ColorControlProps } from "./controlProps"; | ||
import { CSS, VariableType } from "../../lib/Constants"; | ||
|
||
/** | ||
* A color swatch picker control consisting of a single color swatch for each | ||
* possible value. | ||
* @class | ||
* @extends React.Component | ||
*/ | ||
export class ColorSwatchControl extends React.Component<ColorControlProps, void> { | ||
|
||
/** Handles the update event for this control. */ | ||
onClick = (event: React.FormEvent<HTMLElement>): void => { | ||
this.props.updateVariable( | ||
this.props.variable, | ||
(event.target as HTMLElement).dataset["value"] | ||
); | ||
} | ||
|
||
/** @override */ | ||
shouldComponentUpdate(nextProps: ColorControlProps) { | ||
return nextProps.variable !== this.props.variable; | ||
} | ||
|
||
/** @override */ | ||
render() { | ||
const { | ||
title, | ||
possibleValues, | ||
selectedValue | ||
} = this.props.variable; | ||
|
||
return ( | ||
<div className={`${CSS.RMX_COLOR_SWATCH} ${CSS.MDL_LIST_ITEM} ${CSS.MDL_TWO_LINE}`}> | ||
<span className={CSS.MDL_PRIMARY}> | ||
<span>{title} | ||
<span className={CSS.RMX_SELECTED_VALUE}>{selectedValue}</span> | ||
</span> | ||
<span className={CSS.MDL_SECONDARY}> | ||
{possibleValues.map((value: string) => ( | ||
<ColorSwatch color={value} key={value} | ||
isSelected={selectedValue === value} | ||
onClick={this.onClick} | ||
/> | ||
))} | ||
</span> | ||
</span> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
/** | ||
* Interface containing properties for a single color swatch. | ||
* @interface | ||
*/ | ||
interface ColorSwatchProps { | ||
color: string; | ||
isSelected: boolean; | ||
onClick: any; | ||
} | ||
|
||
/** | ||
* Returns a single color swatch displayed within the `ColorSwatchControl`. | ||
* @param {ColorSwatchProps} props The color swatch properties. | ||
*/ | ||
function ColorSwatch(props: ColorSwatchProps) { | ||
const { | ||
color, | ||
isSelected, | ||
onClick, | ||
} = props; | ||
return ( | ||
<div | ||
className={CSS.RMX_COLOR_SWATCH_ITEM} | ||
style={{backgroundColor: color}} | ||
data-value={color} | ||
onClick={onClick} | ||
> | ||
{isSelected ? <i className="material-icons">check</i> : ""} | ||
</div> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/** @license | ||
* Copyright 2016 Google Inc. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
* use this file except in compliance with the License. You may obtain a copy | ||
* of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import * as React from "react"; | ||
import { CSS } from "../../lib/Constants"; | ||
import { StringControlProps } from "./controlProps"; | ||
|
||
/** | ||
* A dropdown control. | ||
* @class | ||
* @extends React.Component | ||
*/ | ||
export class DropdownControl extends React.Component<StringControlProps, void> { | ||
|
||
/** Handles the update event for this control. */ | ||
onClick = (event: React.FormEvent<HTMLElement>): void => { | ||
this.props.updateVariable( | ||
this.props.variable, | ||
(event.target as HTMLElement).dataset["value"] | ||
); | ||
} | ||
|
||
/** @override */ | ||
shouldComponentUpdate(nextProps: StringControlProps) { | ||
return nextProps.variable !== this.props.variable; | ||
} | ||
|
||
/** @override */ | ||
render() { | ||
const { | ||
title, | ||
key, | ||
possibleValues, | ||
selectedValue | ||
} = this.props.variable; | ||
const id = `${CSS.RMX_DROPDOWN}-${key}`; | ||
|
||
return ( | ||
<div className={`${CSS.RMX_DROPDOWN} ${CSS.MDL_LIST_ITEM}`}> | ||
<span className={CSS.MDL_PRIMARY}>{title}</span> | ||
<span className={CSS.MDL_SECONDARY}> | ||
<button id={id} className="mdl-button mdl-js-button"> | ||
<span> | ||
{selectedValue}<i className="material-icons">arrow_drop_down</i> | ||
</span> | ||
</button> | ||
<ul | ||
className="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect" | ||
htmlFor={id} | ||
> | ||
{possibleValues.map((value: string) => ( | ||
<li className="mdl-menu__item" key={value} | ||
onClick={this.onClick} | ||
data-value={value}>{value} | ||
</li> | ||
))} | ||
</ul> | ||
</span> | ||
</div> | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/** @license | ||
* Copyright 2016 Google Inc. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not | ||
* use this file except in compliance with the License. You may obtain a copy | ||
* of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
* License for the specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import * as React from "react"; | ||
import { CSS, VariableType } from "../../lib/Constants"; | ||
import { StringControlProps } from "./controlProps"; | ||
|
||
/** | ||
* A radio list control. | ||
* @class | ||
* @extends React.Component | ||
*/ | ||
export class RadioListControl extends React.Component<StringControlProps, void> { | ||
|
||
/** Handles the update event for this control. */ | ||
onChange = (event: React.FormEvent<HTMLInputElement>): void => { | ||
this.props.updateVariable( | ||
this.props.variable, | ||
(event.target as HTMLInputElement).value | ||
); | ||
} | ||
|
||
/** @override */ | ||
shouldComponentUpdate(nextProps: StringControlProps) { | ||
return nextProps.variable !== this.props.variable; | ||
} | ||
|
||
/** @override */ | ||
render() { | ||
const { | ||
title, | ||
key, | ||
possibleValues, | ||
selectedValue | ||
} = this.props.variable; | ||
const id = `${CSS.RMX_RADIO_LIST_ITEM}-${key}`; | ||
|
||
return ( | ||
<div className={`${CSS.RMX_RADIO_LIST} ${CSS.MDL_LIST_ITEM}`}> | ||
<span className={CSS.MDL_PRIMARY}>{title}</span> | ||
<span className={CSS.MDL_SECONDARY}> | ||
{possibleValues.map((value: string, i: number) => ( | ||
<label className={`${CSS.RMX_RADIO_LIST_ITEM} mdl-radio mdl-js-radio mdl-js-ripple-effect`} | ||
htmlFor={`${id}-${i}`} key={value} | ||
> | ||
<input type="radio" id={`${id}-${i}`} | ||
className="mdl-radio__button" | ||
name="options" value={value} | ||
checked={selectedValue === value} | ||
onChange={this.onChange} | ||
/> | ||
<span className="mdl-radio__label">{value}</span> | ||
</label> | ||
))} | ||
</span> | ||
</div> | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's weird that you are specifying
variables
externally butonUpdate
internally. What you really want to do is have every call toupdateVariable
updatevariables
and then re-render with the updated version. That would remove the need forsetState
/forceUpdate
inside your controls and let them be pure functions.The idiomatic way to do that would be to have
variables
(and its values) be immutable, so each control could say