Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "@uifabric/utilities",
"comment": "Added resetIds for predictable jest tests",
"type": "minor"
}
],
"packageName": "@uifabric/utilities",
"email": "adrum@microsoft.com"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"packageName": "office-ui-fabric-react",
"comment": "ChoiceGroup getStyles conversion",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we are targeting the 6.0 branch, we should rename all the changefiles to 6_0_choiceGroupGetStyles.json manually

"type": "minor"
}
],
"packageName": "office-ui-fabric-react",
"email": "adrum@microsoft.com"
}
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,8 @@
"license": "MIT",
"devDependencies": {
"@microsoft/rush": "4.3.0"
},
"dependencies": {
"npm": "^6.0.0"
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually unintentional. npm told me at some point to run a command, which I diligently obeyed, and this edit got auto-added. Commentary is welcome on why npm thought this was necessary... ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe npm was telling you that a new version of npm is available and prompting you to upgrade :) But.. you might have entered incorrectly (specifically, missed the -g option so it became a local install that was written to package.json)

You probably want to revert this.

}
}
1 change: 1 addition & 0 deletions packages/office-ui-fabric-react/src/ChoiceGroupOption.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './components/ChoiceGroupOption/index';
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import * as React from 'react';
import { Label } from '../../Label';
import { ChoiceGroupOption, OnFocusCallback, OnChangeCallback } from '../../ChoiceGroupOption';
import { IChoiceGroupOption, IChoiceGroupProps, IChoiceGroupStyleProps, IChoiceGroupStyles } from './ChoiceGroup.types';
import {
BaseComponent,
customizable,
classNamesFunction,
createRef,
getId
} from '../../Utilities';

const getClassNames = classNamesFunction<IChoiceGroupStyleProps, IChoiceGroupStyles>();

export interface IChoiceGroupState {
keyChecked: string | number;

/** Is true when the control has focus. */
keyFocused?: string | number;
}

@customizable('ChoiceGroup', ['theme'])
export class ChoiceGroupBase extends BaseComponent<IChoiceGroupProps, IChoiceGroupState> {
public static defaultProps: IChoiceGroupProps = {
options: []
};

private _id: string;
private _labelId: string;
private _inputElement = createRef<HTMLInputElement>();
private focusedVars: { [key: string]: OnFocusCallback } = {};
private changedVars: { [key: string]: OnChangeCallback } = {};

constructor(props: IChoiceGroupProps, ) {
super(props);

this._warnDeprecations({ 'onChanged': 'onChange' });
this._warnMutuallyExclusive({
selectedKey: 'defaultSelectedKey'
});

this.state = {
keyChecked: (props.defaultSelectedKey === undefined) ?
this._getKeyChecked(props)! :
props.defaultSelectedKey,
keyFocused: undefined
};

this._id = getId('ChoiceGroup');
this._labelId = getId('ChoiceGroupLabel');
}

public componentWillReceiveProps(newProps: IChoiceGroupProps): void {
const newKeyChecked = this._getKeyChecked(newProps);
const oldKeyCheched = this._getKeyChecked(this.props);

if (newKeyChecked !== oldKeyCheched) {
this.setState({
keyChecked: newKeyChecked!,
});
}
}

public render(): JSX.Element {
const {
className,
theme,
getStyles,
options,
label,
required,
disabled,
name
} = this.props;
const { keyChecked, keyFocused } = this.state;

const classNames = getClassNames(getStyles!, {
theme: theme!,
className,
optionsContainIconOrImage: options!.some(option => Boolean(option.iconProps || option.imageSrc))
});

return (
// Need to assign role application on containing div because JAWS doesn't call OnKeyDown without this role
<div role='application' className={ classNames.applicationRole }>
<div
className={ classNames.root }
role='radiogroup'
aria-labelledby={ `${this.props.label ? this._id + '-label' : ''} ${(this.props as any)['aria-labelledby'] || ''}` }
>
{ label && (<Label className={ classNames.label } required={ required } id={ this._id + '-label' }>{ label }</Label>) }
<div className={ classNames.flexContainer }>
{ options!.map((option: IChoiceGroupOption) => {

const innerOptionProps = {
...option,
focused: option.key === keyFocused,
checked: option.key === keyChecked,
disabled: option.disabled || disabled,
id: `${this._id}-${option.key}`,
labelId: `${this._labelId}-${option.key}`,
name: name || this._id,
required
};

return (
<ChoiceGroupOption
key={ option.key }
onBlur={ this._onBlur }
onFocus={ this._onFocus(option.key) }
onChange={ this._onChange(option.key) }
{ ...innerOptionProps }
/>
);
}) }
</div>
</div>
</div>
);

}

public focus() {
if (this._inputElement.current) {
this._inputElement.current.focus();
}
}

private _onFocus = (key: string) =>
this.focusedVars[key] ? this.focusedVars[key] : this.focusedVars[key] =
(ev: React.FocusEvent<HTMLElement>, option: IChoiceGroupOption) => {
this.setState({
keyFocused: key,
keyChecked: this.state.keyChecked
});
}

private _onBlur = (ev: React.FocusEvent<HTMLElement>, option: IChoiceGroupOption) => {
this.setState({
keyFocused: undefined,
keyChecked: this.state.keyChecked
});
}

private _onChange = (key: string) =>
this.changedVars[key] ? this.changedVars[key] : this.changedVars[key] =
(evt, option: IChoiceGroupOption) => {
const { onChanged, onChange, selectedKey, options } = this.props;

// Only manage state in uncontrolled scenarios.
if (selectedKey === undefined) {
this.setState({
keyChecked: key
});
}

const originalOption = options!.find((value: IChoiceGroupOption) => value.key === key);

// TODO: onChanged deprecated, remove else if after 07/17/2017 when onChanged has been removed.
if (onChange) {
onChange(evt, originalOption);
} else if (onChanged) {
onChanged(originalOption!);
}
}

private _getKeyChecked(props: IChoiceGroupProps): string | number | undefined {
if (props.selectedKey !== undefined) {
return props.selectedKey;
}

const optionsChecked = props.options!.filter((option: IChoiceGroupOption) => {
return option.checked;
});

if (optionsChecked.length === 0) {
return undefined;
} else {
return optionsChecked[0].key;
}
}

}
Loading