Skip to content

Commit

Permalink
Creating react-focus package and copying FocusZone code there (#11765)
Browse files Browse the repository at this point in the history
* Populating react-focus as an initial package.

* Fixing build errors

* Re-export react-focus's FocusZone from OUFR

* Change files

* api extractor, tsx-editor, and script updates

* Change files

* fix conformance test

* Remove unused test config from test-utilities

* Change files

* Prevent component examples test from eating errors

* fix uifabric/react-focus references

* revert componentexamples changes

* update test

* Revert "Remove unused test config from test-utilities"

This reverts commit e154f87.

* Fixing tslint issues.

* Disabling linter and reverting deprecation-related changes.

* Updating API.

* Updating package.json dependencies to match those of oufr package.

* Reverting deletion from OUFR package and importing from OUFR again until focus-react package is officially published.

Co-authored-by: Elizabeth Craig <ecraig12345@gmail.com>
Co-authored-by: Makoto Morimoto <Humberto.Morimoto@microsoft.com>
  • Loading branch information
3 people authored Feb 11, 2020
1 parent 00b6694 commit da8f232
Show file tree
Hide file tree
Showing 38 changed files with 4,034 additions and 29 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"type": "patch",
"comment": "Initial package check-in",
"packageName": "@fluentui/react-focus",
"email": "dzearing@microsoft.com",
"commit": "4f2d8efea3622ba8c9d844c68e5ed5088b858f6f",
"dependentChangeType": "patch",
"date": "2020-01-30T00:53:36.322Z"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"type": "patch",
"comment": "Add react-focus support",
"packageName": "@uifabric/api-docs",
"email": "elcraig@microsoft.com",
"commit": "5e6d8c691d23f7881afe569ec1f19edd56242656",
"dependentChangeType": "patch",
"date": "2020-01-30T02:32:06.772Z"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"type": "patch",
"comment": "Add react-focus support",
"packageName": "@uifabric/tsx-editor",
"email": "elcraig@microsoft.com",
"commit": "5e6d8c691d23f7881afe569ec1f19edd56242656",
"dependentChangeType": "patch",
"date": "2020-01-30T02:32:10.527Z"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"type": "minor",
"comment": "Re-export react-focus's FocusZone from OUFR",
"packageName": "office-ui-fabric-react",
"email": "elcraig@microsoft.com",
"commit": "4f2d8efea3622ba8c9d844c68e5ed5088b858f6f",
"dependentChangeType": "patch",
"date": "2020-01-30T00:53:11.772Z"
}
1 change: 1 addition & 0 deletions packages/api-docs/config/api-docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
path.resolve(__dirname, '../../styling/dist/styling.api.json'),
path.resolve(__dirname, '../../utilities/dist/utilities.api.json'),
path.resolve(__dirname, '../../merge-styles/dist/merge-styles.api.json'),
path.resolve(__dirname, '../../react-focus/dist/react-focus.api.json'),
path.resolve(__dirname, '../../office-ui-fabric-react/dist/office-ui-fabric-react.api.json'),
path.resolve(__dirname, '../../react-cards/dist/react-cards.api.json')
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1262,7 +1262,7 @@ export class FocusZone extends React.Component<IFocusZoneProps> implements IFocu
focusElement(element: HTMLElement): boolean;
static getOuterZones(): number;
// (undocumented)
render(): JSX.Element;
render(): React.ReactNode;
setFocusAlignment(point: IPoint): void;
}

Expand Down
1 change: 1 addition & 0 deletions packages/office-ui-fabric-react/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const config = createConfig({
setupFiles: [path.resolve(path.join(__dirname, 'config', 'tests.js'))],

moduleNameMapper: {
'@fluentui/react-focus/lib/(.*)$': '@fluentui/react-focus/lib-commonjs/$1',
'@uifabric/react-hooks/lib/(.*)$': '@uifabric/react-hooks/lib-commonjs/$1',
'@uifabric/utilities/lib/(.*)$': '@uifabric/utilities/lib-commonjs/$1',
// These mappings allow Jest to run snapshot tests against Example files.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import * as fs from 'fs';
* Any conditions that Fabric components should fulfill can be added to this test suite.
*/

// Common props required by List-based components in order for tests to pass
/** Common props required by List-based components in order for tests to pass */
const listProps = {
items: [],
skipViewportMeasures: true,
onShouldVirtualize: () => false
};

// Props required by certain components in order for tests to pass
/** Props required by certain components in order for tests to pass */
const requiredProps: { [key: string]: any } = {
PlainCard: {
onRenderPlainCard: () => null
Expand Down Expand Up @@ -92,8 +92,10 @@ const requiredProps: { [key: string]: any } = {
}
};

// Some components inject the className prop on a child DOM element rather than the root,
// so the test needs to look for className on the child props object that has the given class name
/**
* Some components inject the className prop on a child DOM element rather than the root,
* so the test needs to look for className on the child props object that has the given class name
*/
const classNameSelectors: { [key: string]: string } = {
Breadcrumb: 'ms-Breadcrumb',
Callout: 'ms-Callout',
Expand Down Expand Up @@ -137,9 +139,14 @@ const excludedComponents: string[] = [
'ThemeGenerator' // not intended to be tested
];

// Some components require nodes to be mocked when creating the test component (e.g. components that use refs)
/** Some components require nodes to be mocked when creating the test component (e.g. components that use refs) */
const mockNodeComponents = ['ScrollablePane'];

/** Map from component name to alternative package name from which it should import a version file */
const componentPackageMap: { [componentName: string]: string } = {
// FocusZone: '@fluentui/react-focus'
};

/**
* Automatically consume and test any components that are exported
* from a file that matches its parent folder name (e.g. ActivityItem/ActivityItem.tsx)
Expand Down Expand Up @@ -279,11 +286,12 @@ describe('Top Level Component File Conformance', () => {
// make sure that there is a version import in each corresponding top level component file
topLevelComponentFiles.forEach(file => {
const componentName = path.basename(file).split('.')[0];
const packageName = componentPackageMap[componentName] || 'office-ui-fabric-react';

it(componentName + ' imports the OUFR version file', () => {
it(`${componentName} imports the ${packageName} version file`, () => {
(window as any).__packages__ = null;
require(file);
expect((window as any).__packages__['office-ui-fabric-react']).not.toBeUndefined();
expect((window as any).__packages__[packageName]).not.toBeUndefined();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,17 @@ describe('FocusZone', () => {
isVisible?: boolean;
}
): void {
element.getBoundingClientRect = () =>
({
top: clientRect.top,
left: clientRect.left,
bottom: clientRect.bottom,
right: clientRect.right,
width: clientRect.right - clientRect.left,
height: clientRect.bottom - clientRect.top
} as DOMRect);
element.getBoundingClientRect = () => ({
x: clientRect.left,
y: clientRect.top,
top: clientRect.top,
left: clientRect.left,
bottom: clientRect.bottom,
right: clientRect.right,
width: clientRect.right - clientRect.left,
height: clientRect.bottom - clientRect.top,
toJSON: () => clientRect
});

element.setAttribute('data-is-visible', String(isVisible));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class FocusZone extends React.Component<IFocusZoneProps> implements IFocu
};

private _disposables: Function[] = [];
private _root = React.createRef<HTMLElement>();
private _root: React.RefObject<HTMLElement> = React.createRef();
private _id: string;

/** The most recently focused child element. */
Expand Down Expand Up @@ -191,7 +191,7 @@ export class FocusZone extends React.Component<IFocusZoneProps> implements IFocu
}
}

public componentWillUnmount() {
public componentWillUnmount(): void {
delete _allInstances[this._id];

if (!this._isInnerZone) {
Expand All @@ -204,13 +204,14 @@ export class FocusZone extends React.Component<IFocusZoneProps> implements IFocu
}

// Dispose all events.
this._disposables.forEach(d => d());
this._disposables.forEach((d: () => void) => d());

// Clear function references so their closures can be garbage-collected.
delete this._disposables;
}

public render() {
public render(): React.ReactNode {
// tslint:disable:deprecation
const { rootProps, ariaDescribedBy, ariaLabelledBy, className } = this.props;
const divProps = getNativeProps(this.props, htmlElementProperties);

Expand All @@ -232,6 +233,7 @@ export class FocusZone extends React.Component<IFocusZoneProps> implements IFocu
// root props has been deprecated and should get removed.
// it needs to be marked as "any" since root props expects a div element, but really Tag can
// be any native element so typescript rightly flags this as a problem.
// tslint:disable-next-line:no-any
...(rootProps as any)
}
// Once the getClassName correctly memoizes inputs this should
Expand Down Expand Up @@ -428,7 +430,7 @@ export class FocusZone extends React.Component<IFocusZoneProps> implements IFocu
*/
private _onKeyDownCapture = (ev: KeyboardEvent): void => {
if (ev.which === KeyCodes.tab) {
_outerZones.forEach(zone => zone._updateTabIndexes());
_outerZones.forEach((zone: FocusZone) => zone._updateTabIndexes());
}
};

Expand Down Expand Up @@ -1035,7 +1037,8 @@ export class FocusZone extends React.Component<IFocusZoneProps> implements IFocu
}
return changedFocus;
}
private _setFocusAlignment(element: HTMLElement, isHorizontal?: boolean, isVertical?: boolean) {

private _setFocusAlignment(element: HTMLElement, isHorizontal?: boolean, isVertical?: boolean): void {
if (this.props.direction === FocusZoneDirection.bidirectional && (!this._focusAlignment || isHorizontal || isVertical)) {
const rect = element.getBoundingClientRect();
const left = rect.left + rect.width / 2;
Expand Down Expand Up @@ -1076,7 +1079,7 @@ export class FocusZone extends React.Component<IFocusZoneProps> implements IFocu
return parentElement;
}

private _updateTabIndexes(element?: HTMLElement) {
private _updateTabIndexes(element?: HTMLElement): void {
if (!element && this._root.current) {
this._defaultFocusElement = null;
element = this._root.current;
Expand Down Expand Up @@ -1139,7 +1142,7 @@ export class FocusZone extends React.Component<IFocusZoneProps> implements IFocu
return false;
}

private _shouldInputLoseFocus(element: HTMLInputElement, isForward?: boolean) {
private _shouldInputLoseFocus(element: HTMLInputElement, isForward?: boolean): boolean {
// If a tab was used, we want to focus on the next element.
if (!this._processingTabKey && element && element.type && ALLOWED_INPUT_TYPES.indexOf(element.type.toLowerCase()) > -1) {
const selectionStart = element.selectionStart;
Expand Down
31 changes: 31 additions & 0 deletions packages/react-focus/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
*.api.json
*.config.js
*.log
*.nuspec
*.test.*
*.yml
.editorconfig
.gitattributes
.gitignore
.vscode
coverage
dist/*.stats.html
dist/*.stats.json
dist/demo*.*
fabric-test*
gulpfile.js
images
index.html
jsconfig.json
node_modules
results
src/**/*
!src/**/examples/*.tsx
!src/**/docs/**/*.md
!src/**/*.types.ts
temp
tsconfig.json
tsd.json
tslint.json
typings
visualtests
2 changes: 2 additions & 0 deletions packages/react-focus/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
registry=https://registry.npmjs.org/

4 changes: 4 additions & 0 deletions packages/react-focus/CHANGELOG.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "@fluentui/react-focus",
"entries": []
}
3 changes: 3 additions & 0 deletions packages/react-focus/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Change Log - @fluentui/react-focus

This log was last generated on Mon, 13 Jan 2020 19:25:55 GMT and should not be manually modified.
15 changes: 15 additions & 0 deletions packages/react-focus/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@fluentui/react-focus

Copyright (c) Microsoft Corporation

All rights reserved.

MIT License

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Note: Usage of the fonts and icons referenced in Office UI Fabric is subject to the terms listed at https://aka.ms/fabric-assets-license
11 changes: 11 additions & 0 deletions packages/react-focus/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# @fluentui/react-focus

**React Focus components for [Fluent UI](https://fluent.microsoft.com/)**

These are not production-ready components and **should never be used in product**. This space is useful for testing new components whose APIs might change before final release.

To import ReactFocus components:

```js
import { FocusZone } from '@fluentui/react-focus';
```
29 changes: 29 additions & 0 deletions packages/react-focus/config/api-extractor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"mainEntryPointFilePath": "<projectFolder>/lib/index.d.ts",
"apiReport": {
"enabled": true
},
"docModel": {
"enabled": true,
"apiJsonFilePath": "<projectFolder>/dist/<unscopedPackageName>.api.json"
},
"dtsRollup": {
"enabled": true
},
"messages": {
"extractorMessageReporting": {
"ae-missing-release-tag": {
"logLevel": "none"
},
"ae-unresolved-link": {
"logLevel": "none"
}
},
"tsdocMessageReporting": {
"tsdoc-undefined-tag": {
"logLevel": "none"
}
}
}
}
12 changes: 12 additions & 0 deletions packages/react-focus/config/tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/** Jest test setup file. */

const { configure } = require('enzyme');
const Adapter = require('enzyme-adapter-react-16');

// Mock requestAnimationFrame for React 16+.
global.requestAnimationFrame = callback => {
setTimeout(callback, 0);
};

// Configure enzyme.
configure({ adapter: new Adapter() });
Loading

0 comments on commit da8f232

Please sign in to comment.