Grabbed dndbeyond's source code

```
~/go/bin/sourcemapper -output ddb -jsurl https://media.dndbeyond.com/character-app/static/js/main.90aa78c5.js
```
This commit is contained in:
2025-05-28 11:50:03 -07:00
commit 8df9031d27
3592 changed files with 319051 additions and 0 deletions
@@ -0,0 +1,357 @@
import React from "react";
import {
Constants,
EntityAdjustmentConstraintContract,
RuleData,
RuleDataUtils,
} from "@dndbeyond/character-rules-engine/es";
import {
SIGNED_32BIT_INT_MAX_VALUE,
SIGNED_32BIT_INT_MIN_VALUE,
} from "~/subApps/sheet/constants";
import ValueEditorCheckboxProperty from "./ValueEditorCheckboxProperty";
import ValueEditorNumberProperty from "./ValueEditorNumberProperty";
import ValueEditorSelectProperty from "./ValueEditorSelectProperty";
import ValueEditorTextProperty from "./ValueEditorTextProperty";
interface ConstraintProps {
minimumValue?: number;
maximumValue?: number;
}
interface Props {
dataLookup: Partial<Record<Constants.AdjustmentTypeEnum, any>>;
valueEditors: Array<number>; // TODO deal with enums not working with switch statement
labelOverrides: Partial<Record<Constants.AdjustmentTypeEnum, string>>;
optionRestrictions: Partial<Record<Constants.AdjustmentTypeEnum, Array<any>>>;
defaultValues: Partial<Record<Constants.AdjustmentTypeEnum, any>>;
layoutType: "standard" | "compact";
onDataUpdate?: (
propertyKey: Constants.AdjustmentTypeEnum,
value: any,
source: any
) => void;
ruleData: RuleData;
className: string;
}
interface State {
dataLookup: Partial<Record<Constants.AdjustmentTypeEnum, any>>;
}
export default class ValueEditor extends React.PureComponent<Props, State> {
static defaultProps = {
className: "",
labelOverrides: {},
optionRestrictions: {},
defaultValues: {},
layoutType: "standard",
};
constructor(props: Props) {
super(props);
this.state = this.generateStateData(props);
}
componentDidUpdate(
prevProps: Readonly<Props>,
prevState: Readonly<State>
): void {
const { dataLookup } = this.props;
if (dataLookup !== prevProps.dataLookup) {
this.setState(this.generateStateData(this.props));
}
}
generateStateData = (props: Props): State => {
const { dataLookup } = props;
return {
dataLookup,
};
};
getNumberConstraintProps = (
constraintLookup: Record<number, EntityAdjustmentConstraintContract>
): ConstraintProps => {
let constraintProps: ConstraintProps = {};
if (constraintLookup[Constants.AdjustmentConstraintTypeEnum.MINIMUM]) {
constraintProps.minimumValue = this.getConstraintValue(
Constants.AdjustmentConstraintTypeEnum.MINIMUM,
constraintLookup
);
} else {
constraintProps.minimumValue = SIGNED_32BIT_INT_MIN_VALUE;
}
if (constraintLookup[Constants.AdjustmentConstraintTypeEnum.MAXIMUM]) {
constraintProps.maximumValue = this.getConstraintValue(
Constants.AdjustmentConstraintTypeEnum.MAXIMUM,
constraintLookup
);
} else {
constraintProps.maximumValue = SIGNED_32BIT_INT_MAX_VALUE;
}
return constraintProps;
};
getConstraintValue = (
constraintTypeId: Constants.AdjustmentConstraintTypeEnum,
constraintLookup: Record<number, EntityAdjustmentConstraintContract>,
fallback: any = null
): any => {
let constraint = constraintLookup[constraintTypeId];
if (constraint) {
return constraint.value;
}
return fallback;
};
getPropertyValue = (key: Constants.AdjustmentTypeEnum): any => {
const { dataLookup, defaultValues } = this.props;
let property = dataLookup[key];
if (property) {
return property.value;
}
let defaultValue = defaultValues[key];
if (defaultValue) {
return defaultValue;
}
return null;
};
getPropertySource = (key: Constants.AdjustmentTypeEnum): string | null => {
const { dataLookup } = this.state;
let property = dataLookup[key];
if (property) {
return property.notes;
}
return null;
};
restrictOptions = <T extends any>(
key: Constants.AdjustmentTypeEnum,
options: Array<T>
): Array<T> => {
const { optionRestrictions } = this.props;
let typeOptionRestrictions = optionRestrictions[key];
if (!typeOptionRestrictions || typeOptionRestrictions.length === 0) {
return options;
}
return options.filter((option) => {
if (!typeOptionRestrictions) {
return true;
}
// @ts-ignore
return typeOptionRestrictions.includes(option.value);
});
};
handleDataUpdate = (
key: Constants.AdjustmentTypeEnum,
value: any,
source: any
): void => {
const { onDataUpdate } = this.props;
this.setState((prevState: State): State => {
let processedSource: string | null = source === "" ? null : source;
if (
onDataUpdate &&
(this.getPropertyValue(key) !== value ||
this.getPropertySource(key) !== processedSource)
) {
onDataUpdate(key, value, processedSource);
}
return {
...prevState,
dataLookup: {
...prevState.dataLookup,
[key]: {
value,
notes: processedSource,
},
},
};
});
};
render() {
const { valueEditors, className, ruleData, labelOverrides, layoutType } =
this.props;
let enableSource: boolean = layoutType === "standard";
let layoutClass: string = layoutType === "compact" ? "compact" : "standard";
let classNames: Array<string> = [
"ct-value-editor",
`ct-value-editor--${layoutClass}`,
className,
];
return (
<div className={classNames.join(" ")}>
{valueEditors.map((valueTypeId) => {
let valueDataTypeId = RuleDataUtils.getAdjustmentDataType(
valueTypeId,
ruleData
);
let constraintLookup = RuleDataUtils.getAdjustmentConstraintLookup(
valueTypeId,
ruleData
);
let valueName: string = "";
if (labelOverrides.hasOwnProperty(valueTypeId)) {
valueName = labelOverrides[valueTypeId];
} else {
let adjustmentName = RuleDataUtils.getAdjustmentName(
valueTypeId,
ruleData
);
if (adjustmentName) {
valueName = adjustmentName;
}
}
switch (valueDataTypeId) {
case Constants.AdjustmentDataTypeEnum.STRING:
return (
<ValueEditorTextProperty
key={valueTypeId}
propertyKey={valueTypeId}
defaultValue={this.getPropertyValue(valueTypeId)}
label={valueName}
onUpdate={this.handleDataUpdate}
enableSource={enableSource}
initialFocus={
valueTypeId === Constants.AdjustmentTypeEnum.NAME_OVERRIDE
}
/>
);
case Constants.AdjustmentDataTypeEnum.BOOLEAN:
return (
<ValueEditorCheckboxProperty
key={valueTypeId}
propertyKey={valueTypeId}
initiallyEnabled={this.getPropertyValue(valueTypeId)}
defaultSource={this.getPropertySource(valueTypeId)}
label={valueName}
onUpdate={this.handleDataUpdate}
enableSource={enableSource}
/>
);
case Constants.AdjustmentDataTypeEnum.INTEGER:
let baseProps = {
key: valueTypeId,
propertyKey: valueTypeId,
defaultValue: this.getPropertyValue(valueTypeId),
defaultSource: this.getPropertySource(valueTypeId),
label: valueName,
onUpdate: this.handleDataUpdate,
enableSource: enableSource,
};
switch (valueTypeId) {
case Constants.AdjustmentTypeEnum.SKILL_STAT_OVERRIDE:
return (
<ValueEditorSelectProperty
{...baseProps}
options={RuleDataUtils.getStatOptions(ruleData)}
/>
);
case Constants.AdjustmentTypeEnum.DICE_TYPE_OVERRIDE:
return (
<ValueEditorSelectProperty
{...baseProps}
options={RuleDataUtils.getDieTypeOptions(ruleData)}
/>
);
case Constants.AdjustmentTypeEnum.SKILL_PROFICIENCY_LEVEL:
case Constants.AdjustmentTypeEnum
.SAVING_THROW_PROFICIENCY_LEVEL:
return (
<ValueEditorSelectProperty
{...baseProps}
options={RuleDataUtils.getProficiencyLevelOptions(
ruleData
)}
/>
);
case Constants.AdjustmentTypeEnum.CREATURE_ALIGNMENT:
return (
<ValueEditorSelectProperty
{...baseProps}
options={RuleDataUtils.getAlignmentOptions(ruleData)}
/>
);
case Constants.AdjustmentTypeEnum.CREATURE_SIZE:
return (
<ValueEditorSelectProperty
{...baseProps}
options={RuleDataUtils.getCreatureSizeOptions(ruleData)}
/>
);
case Constants.AdjustmentTypeEnum.CREATURE_TYPE_OVERRIDE:
return (
<ValueEditorSelectProperty
{...baseProps}
options={this.restrictOptions(
valueTypeId,
RuleDataUtils.getMonsterTypeOptions(ruleData)
)}
/>
);
default:
let constraintProps =
this.getNumberConstraintProps(constraintLookup);
return (
<ValueEditorNumberProperty
{...baseProps}
{...constraintProps}
/>
);
}
case Constants.AdjustmentDataTypeEnum.DECIMAL:
let constraintProps =
this.getNumberConstraintProps(constraintLookup);
return (
<ValueEditorNumberProperty
key={valueTypeId}
step={0.01}
propertyKey={valueTypeId}
defaultValue={this.getPropertyValue(valueTypeId)}
defaultSource={this.getPropertySource(valueTypeId)}
label={valueName}
onUpdate={this.handleDataUpdate}
enableSource={enableSource}
{...constraintProps}
/>
);
default:
// not implemented
}
return null;
})}
</div>
);
}
}
@@ -0,0 +1,112 @@
import React from "react";
import { Checkbox } from "@dndbeyond/character-components/es";
import { Constants } from "@dndbeyond/character-rules-engine/es";
import ValueEditorProperty from "../ValueEditorProperty";
import ValueEditorPropertySource from "../ValueEditorPropertySource";
import ValueEditorPropertyValue from "../ValueEditorPropertyValue";
interface Props {
label: string;
propertyKey: Constants.AdjustmentTypeEnum;
initiallyEnabled: boolean;
defaultSource: string | null;
onUpdate?: (
propertyKey: Constants.AdjustmentTypeEnum,
isEnabled: boolean,
source: string | null
) => void;
enableSource: boolean;
}
interface State {
value: boolean;
source: string | null;
}
export default class ValueEditorCheckboxProperty extends React.PureComponent<
Props,
State
> {
static defaultProps = {
enableSource: true,
};
constructor(props: Props) {
super(props);
this.state = {
value: props.initiallyEnabled,
source: props.defaultSource,
};
}
componentDidUpdate(
prevProps: Readonly<Props>,
prevState: Readonly<State>
): void {
const { initiallyEnabled } = this.props;
const { value } = this.state;
if (
initiallyEnabled !== prevProps.initiallyEnabled &&
initiallyEnabled !== value
) {
this.setState({
value: initiallyEnabled,
});
}
}
handleChange = (isEnabled: boolean): void => {
const { source } = this.state;
const { propertyKey, onUpdate } = this.props;
if (onUpdate) {
onUpdate(propertyKey, isEnabled, source);
}
};
handleSourceUpdate = (source: string | null): void => {
const { value } = this.state;
const { propertyKey, onUpdate } = this.props;
if (onUpdate) {
onUpdate(propertyKey, value, source);
}
this.setState({
source,
});
};
render() {
const {
propertyKey,
label,
initiallyEnabled,
defaultSource,
enableSource,
} = this.props;
return (
<ValueEditorProperty
className="ct-value-editor__property--checkbox"
propertyKey={propertyKey}
>
<ValueEditorPropertyValue>
<Checkbox
stopPropagation={true}
label={label}
initiallyEnabled={initiallyEnabled}
onChange={this.handleChange}
/>
</ValueEditorPropertyValue>
{enableSource && (
<ValueEditorPropertySource
onUpdate={this.handleSourceUpdate}
defaultValue={defaultSource}
/>
)}
</ValueEditorProperty>
);
}
}
@@ -0,0 +1,4 @@
import ValueEditorCheckboxProperty from "./ValueEditorCheckboxProperty";
export default ValueEditorCheckboxProperty;
export { ValueEditorCheckboxProperty };
@@ -0,0 +1,152 @@
import React from "react";
import { Constants, HelperUtils } from "@dndbeyond/character-rules-engine/es";
import ValueEditorProperty from "../ValueEditorProperty";
import ValueEditorPropertyLabel from "../ValueEditorPropertyLabel";
import ValueEditorPropertySource from "../ValueEditorPropertySource";
import ValueEditorPropertyValue from "../ValueEditorPropertyValue";
interface Props {
label: string;
propertyKey: Constants.AdjustmentTypeEnum;
defaultValue: number | null;
defaultSource: string | null;
minimumValue?: number;
maximumValue?: number;
onUpdate?: (
propertyKey: Constants.AdjustmentTypeEnum,
value: number | null,
source: string | null
) => void;
enableSource: boolean;
step: number;
}
interface State {
value: number | null;
source: string | null;
}
export default class ValueEditorNumberProperty extends React.PureComponent<
Props,
State
> {
static defaultProps = {
enableSource: true,
step: 1,
};
constructor(props: Props) {
super(props);
this.state = {
value: props.defaultValue,
source: props.defaultSource,
};
}
componentDidUpdate(
prevProps: Readonly<Props>,
prevState: Readonly<State>
): void {
const { defaultValue } = this.props;
const { value } = this.state;
if (defaultValue !== prevProps.defaultValue && defaultValue !== value) {
this.setState({
value: defaultValue,
});
}
}
getDataValue = (value: number | null): number | null => {
const { minimumValue, maximumValue } = this.props;
if (value === null) {
return null;
}
return HelperUtils.clampInt(
value,
minimumValue ? minimumValue : null,
maximumValue
);
};
handleBlur = (evt: React.FocusEvent<HTMLInputElement>): void => {
const { source } = this.state;
const { propertyKey, onUpdate, step } = this.props;
let newValue = this.getDataValue(
step < 1
? HelperUtils.parseInputFloat(evt.target.value)
: HelperUtils.parseInputInt(evt.target.value)
);
if (onUpdate) {
onUpdate(propertyKey, newValue, source);
}
this.setState({
value: newValue,
});
};
handleChange = (evt: React.ChangeEvent<HTMLInputElement>): void => {
const { step } = this.props;
this.setState({
value:
step < 1
? HelperUtils.parseInputFloat(evt.target.value)
: HelperUtils.parseInputInt(evt.target.value),
});
};
handleSourceUpdate = (source: string | null): void => {
const { value } = this.state;
const { propertyKey, onUpdate } = this.props;
if (onUpdate) {
onUpdate(propertyKey, this.getDataValue(value), source);
}
this.setState({
source,
});
};
render() {
const { value } = this.state;
const {
propertyKey,
label,
minimumValue,
maximumValue,
defaultSource,
enableSource,
step,
} = this.props;
return (
<ValueEditorProperty
className="ct-value-editor__property--number"
propertyKey={propertyKey}
>
<ValueEditorPropertyLabel>{label}</ValueEditorPropertyLabel>
<ValueEditorPropertyValue>
<input
className="ct-value-editor__property-input"
type="number"
min={minimumValue}
max={maximumValue}
step={step}
value={value === null ? "" : value}
onBlur={this.handleBlur}
onChange={this.handleChange}
/>
</ValueEditorPropertyValue>
{enableSource && (
<ValueEditorPropertySource
onUpdate={this.handleSourceUpdate}
defaultValue={defaultSource}
/>
)}
</ValueEditorProperty>
);
}
}
@@ -0,0 +1,4 @@
import ValueEditorNumberProperty from "./ValueEditorNumberProperty";
export default ValueEditorNumberProperty;
export { ValueEditorNumberProperty };
@@ -0,0 +1,28 @@
import React from "react";
interface Props {
isBlock: boolean;
propertyKey: number;
className: string;
}
export default class ValueEditorProperty extends React.PureComponent<Props> {
static defaultProps = {
isBlock: false,
className: "",
};
render() {
const { className, isBlock, propertyKey } = this.props;
let classNames: Array<string> = [
className,
"ct-value-editor__property",
`ct-value-editor__property--${propertyKey}`,
];
if (isBlock) {
classNames.push("ct-value-editor__property--block");
}
return <div className={classNames.join(" ")}>{this.props.children}</div>;
}
}
@@ -0,0 +1,4 @@
import ValueEditorProperty from "./ValueEditorProperty";
export default ValueEditorProperty;
export { ValueEditorProperty };
@@ -0,0 +1,11 @@
import React from "react";
export default class ValueEditorPropertyLabel extends React.PureComponent {
render() {
return (
<div className="ct-value-editor__property-label">
{this.props.children}
</div>
);
}
}
@@ -0,0 +1,4 @@
import ValueEditorPropertyLabel from "./ValueEditorPropertyLabel";
export default ValueEditorPropertyLabel;
export { ValueEditorPropertyLabel };
@@ -0,0 +1,76 @@
import React from "react";
interface Props {
defaultValue: string | null;
placeholder: string;
onUpdate?: (value: string) => void;
}
interface State {
value: string | null;
}
export default class ValueEditorPropertySource extends React.PureComponent<
Props,
State
> {
static defaultProps = {
placeholder: "Enter Source Notes...",
};
constructor(props) {
super(props);
this.state = {
value: props.defaultValue,
};
}
componentDidUpdate(
prevProps: Readonly<Props>,
prevState: Readonly<State>
): void {
const { defaultValue } = this.props;
const { value } = this.state;
if (defaultValue !== prevProps.defaultValue && defaultValue !== value) {
this.setState({
value: defaultValue,
});
}
}
handleChange = (evt: React.ChangeEvent<HTMLInputElement>): void => {
this.setState({
value: evt.target.value,
});
};
handleBlur = (evt: React.FocusEvent<HTMLInputElement>): void => {
const { onUpdate } = this.props;
let value = evt.target.value;
if (onUpdate) {
onUpdate(value);
}
this.setState({
value,
});
};
render() {
const { value } = this.state;
const { placeholder } = this.props;
return (
<div className="ct-value-editor__property-source">
<input
className="ct-value-editor__property-input"
type="text"
placeholder={placeholder}
onChange={this.handleChange}
onBlur={this.handleBlur}
value={value === null ? "" : value}
/>
</div>
);
}
}
@@ -0,0 +1,4 @@
import ValueEditorPropertySource from "./ValueEditorPropertySource";
export default ValueEditorPropertySource;
export { ValueEditorPropertySource };
@@ -0,0 +1,11 @@
import React from "react";
export default class ValueEditorPropertyValue extends React.PureComponent {
render() {
return (
<div className="ct-value-editor__property-value">
{this.props.children}
</div>
);
}
}
@@ -0,0 +1,4 @@
import ValueEditorPropertyValue from "./ValueEditorPropertyValue";
export default ValueEditorPropertyValue;
export { ValueEditorPropertyValue };
@@ -0,0 +1,122 @@
import React from "react";
import { Select } from "@dndbeyond/character-components/es";
import { HelperUtils, Constants } from "@dndbeyond/character-rules-engine/es";
import ValueEditorProperty from "../ValueEditorProperty";
import ValueEditorPropertyLabel from "../ValueEditorPropertyLabel";
import ValueEditorPropertySource from "../ValueEditorPropertySource";
import ValueEditorPropertyValue from "../ValueEditorPropertyValue";
interface Props {
label: string;
propertyKey: Constants.AdjustmentTypeEnum;
defaultValue: number | null;
defaultSource: string | null;
options: Array<any>; // TODO figure out type
selectProps: any; // TODO use Partial<Select.props> somehow
onUpdate?: (
propertyKey: Constants.AdjustmentTypeEnum,
value: number | null,
source: string | null
) => void;
enableSource: boolean;
}
interface State {
value: number | null;
source: string | null;
}
export default class ValueEditorSelectProperty extends React.PureComponent<
Props,
State
> {
static defaultProps = {
selectProps: {},
enableSource: true,
};
constructor(props: Props) {
super(props);
this.state = {
value: props.defaultValue,
source: props.defaultSource,
};
}
componentDidUpdate(
prevProps: Readonly<Props>,
prevState: Readonly<State>
): void {
const { defaultValue } = this.props;
const { value } = this.state;
if (defaultValue !== prevProps.defaultValue && defaultValue !== value) {
this.setState({
value: defaultValue,
});
}
}
handleSelectChange = (value: string): void => {
const { source } = this.state;
const { propertyKey, onUpdate } = this.props;
let parsedValue = HelperUtils.parseInputInt(value);
if (onUpdate) {
onUpdate(propertyKey, parsedValue, source);
}
this.setState({
value: parsedValue,
});
};
handleSourceUpdate = (source: string | null): void => {
const { value } = this.state;
const { propertyKey, onUpdate } = this.props;
if (onUpdate) {
onUpdate(propertyKey, value, source);
}
this.setState({
source,
});
};
render() {
const { value } = this.state;
const {
propertyKey,
label,
options,
selectProps,
defaultSource,
enableSource,
} = this.props;
return (
<ValueEditorProperty
className="ct-value-editor__property--select"
propertyKey={propertyKey}
>
<ValueEditorPropertyLabel>{label}</ValueEditorPropertyLabel>
<ValueEditorPropertyValue>
<Select
placeholder="--"
{...selectProps}
options={options}
value={value}
onChange={this.handleSelectChange}
/>
</ValueEditorPropertyValue>
{enableSource && (
<ValueEditorPropertySource
onUpdate={this.handleSourceUpdate}
defaultValue={defaultSource}
/>
)}
</ValueEditorProperty>
);
}
}
@@ -0,0 +1,4 @@
import ValueEditorSelectProperty from "./ValueEditorSelectProperty";
export default ValueEditorSelectProperty;
export { ValueEditorSelectProperty };
@@ -0,0 +1,105 @@
import React from "react";
import { Constants } from "@dndbeyond/character-rules-engine/es";
import ValueEditorProperty from "../ValueEditorProperty";
import ValueEditorPropertyLabel from "../ValueEditorPropertyLabel";
import ValueEditorPropertyValue from "../ValueEditorPropertyValue";
interface Props {
label: string;
propertyKey: Constants.AdjustmentTypeEnum;
defaultValue: string | null;
onUpdate?: (
propertyKey: Constants.AdjustmentTypeEnum,
value: string | null,
source: string | null
) => void;
enableSource: boolean;
initialFocus?: boolean;
}
interface State {
value: string | null;
}
export default class ValueEditorTextProperty extends React.PureComponent<
Props,
State
> {
static defaultProps = {
enableSource: true,
};
constructor(props: Props) {
super(props);
this.state = {
value: props.defaultValue,
};
}
inputRef = React.createRef<HTMLInputElement>();
componentDidMount() {
if (this.inputRef.current && this.props.initialFocus) {
this.inputRef.current.focus();
}
}
componentDidUpdate(
prevProps: Readonly<Props>,
prevState: Readonly<State>
): void {
const { defaultValue } = this.props;
const { value } = this.state;
if (defaultValue !== prevProps.defaultValue && defaultValue !== value) {
this.setState({
value: defaultValue,
});
}
}
handleBlur = (evt: React.FocusEvent<HTMLInputElement>): void => {
const { propertyKey, onUpdate } = this.props;
if (onUpdate) {
let value: string | null = evt.target.value ? evt.target.value : null;
onUpdate(propertyKey, value, null);
}
};
handleChange = (evt: React.FocusEvent<HTMLInputElement>): void => {
const { value } = this.state;
if (value !== evt.target.value) {
this.setState({
value: evt.target.value,
});
}
};
render() {
const { propertyKey, label } = this.props;
const { value } = this.state;
return (
<ValueEditorProperty
className="ct-value-editor__property--text"
propertyKey={propertyKey}
isBlock={true}
>
<ValueEditorPropertyValue>
<input
type="text"
value={value === null ? "" : value}
onBlur={this.handleBlur}
onChange={this.handleChange}
className="ct-value-editor__property-input"
ref={this.inputRef}
/>
</ValueEditorPropertyValue>
<ValueEditorPropertyLabel>{label}</ValueEditorPropertyLabel>
</ValueEditorProperty>
);
}
}
@@ -0,0 +1,4 @@
import ValueEditorTextProperty from "./ValueEditorTextProperty";
export default ValueEditorTextProperty;
export { ValueEditorTextProperty };
@@ -0,0 +1,95 @@
import React from "react";
import { Constants } from "@dndbeyond/character-rules-engine/es";
import ValueEditorProperty from "../ValueEditorProperty";
import ValueEditorPropertyLabel from "../ValueEditorPropertyLabel";
import ValueEditorPropertyValue from "../ValueEditorPropertyValue";
interface Props {
label: string;
propertyKey: Constants.AdjustmentTypeEnum;
defaultValue: string | null;
onUpdate?: (
propertyKey: Constants.AdjustmentTypeEnum,
value: string | null,
source: string | null
) => void;
enableSource: boolean;
}
interface State {
value: string | null;
}
export default class ValueEditorTextareaProperty extends React.PureComponent<
Props,
State
> {
static defaultProps = {
enableSource: true,
};
constructor(props: Props) {
super(props);
this.state = {
value: props.defaultValue,
};
}
componentDidUpdate(
prevProps: Readonly<Props>,
prevState: Readonly<State>
): void {
const { defaultValue } = this.props;
const { value } = this.state;
if (defaultValue !== prevProps.defaultValue && defaultValue !== value) {
this.setState({
value: defaultValue,
});
}
}
handleChange = (evt: React.FocusEvent<HTMLTextAreaElement>): void => {
const { value } = this.state;
if (value !== evt.target.value) {
this.setState({
value: evt.target.value,
});
}
};
handleBlur = (evt: React.FocusEvent<HTMLTextAreaElement>): void => {
const { propertyKey, onUpdate } = this.props;
if (onUpdate) {
let value: string | null = evt.target.value ? evt.target.value : null;
onUpdate(propertyKey, value, null);
}
};
render() {
const { propertyKey, label } = this.props;
const { value } = this.state;
return (
<ValueEditorProperty
className="ct-value-editor__property--textarea"
propertyKey={propertyKey}
isBlock={true}
>
<ValueEditorPropertyLabel>{label}</ValueEditorPropertyLabel>
<ValueEditorPropertyValue>
<textarea
className="ct-value-editor__property-input"
value={value === null ? "" : value}
onBlur={this.handleBlur}
onChange={this.handleChange}
/>
</ValueEditorPropertyValue>
</ValueEditorProperty>
);
}
}
@@ -0,0 +1,4 @@
import ValueEditorTextareaProperty from "./ValueEditorTextareaProperty";
export default ValueEditorTextareaProperty;
export { ValueEditorTextareaProperty };
@@ -0,0 +1,24 @@
import ValueEditor from "./ValueEditor";
import ValueEditorCheckboxProperty from "./ValueEditorCheckboxProperty";
import ValueEditorNumberProperty from "./ValueEditorNumberProperty";
import ValueEditorProperty from "./ValueEditorProperty";
import ValueEditorPropertyLabel from "./ValueEditorPropertyLabel";
import ValueEditorPropertySource from "./ValueEditorPropertySource";
import ValueEditorPropertyValue from "./ValueEditorPropertyValue";
import ValueEditorSelectProperty from "./ValueEditorSelectProperty";
import ValueEditorTextProperty from "./ValueEditorTextProperty";
import ValueEditorTextareaProperty from "./ValueEditorTextareaProperty";
export default ValueEditor;
export {
ValueEditor,
ValueEditorCheckboxProperty,
ValueEditorNumberProperty,
ValueEditorProperty,
ValueEditorPropertyLabel,
ValueEditorPropertySource,
ValueEditorPropertyValue,
ValueEditorSelectProperty,
ValueEditorTextareaProperty,
ValueEditorTextProperty,
};