Add a git attributes file for line ending settings (#180)

* bump beachball version to one with prepublish fix

* update beachball hook to use new prepublish strategy

* add gitattributes for auto text line endings

* update values

* renormalize files

* Change files
This commit is contained in:
Jason Morse 2020-04-24 11:38:36 -07:00 коммит произвёл GitHub
Родитель 4392f30963
Коммит dc062498d6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
71 изменённых файлов: 3258 добавлений и 3102 удалений

2
.gitattributes поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
# Set the default line ending behavior for text, in case people don't have core.autocrlf set.
* text=auto

Просмотреть файл

@ -1,9 +1,9 @@
# Microsoft Open Source Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
Resources:
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
# Microsoft Open Source Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
Resources:
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns

42
LICENSE
Просмотреть файл

@ -1,21 +1,21 @@
MIT License
Copyright (c) Microsoft Corporation. All rights reserved.
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
MIT License
Copyright (c) Microsoft Corporation. All rights reserved.
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

168
README.md
Просмотреть файл

@ -1,84 +1,84 @@
# FluentUI React Native
FluentUI React Native is a javascript component library that provides developers with controls that are part of the [Fluent Design System](https://www.microsoft.com/design/fluent/). These controls are built on [React Native](https://reactnative.dev/) and fully customizable.
## Getting Started
If you have an existing React Native project, it's easy to begin using FluentUI React Native. If you need to setup a new React Native project, please see the [React Native Windows Getting Started documentation](https://microsoft.github.io/react-native-windows/docs/getting-started).
### Prerequisites
- [Standard React Native dependencies](http://facebook.github.io/react-native/docs/getting-started.html#node-python2-jdk)
- [Node.js](https://nodejs.org/en/download/)
### Install FluentUI React Native into an existing project
Navigate to the root folder of your project, and use npm to install the package:
```
npm i @fluentui/react-native
```
After successful installation, you can test the package by importing components at the top of your app's entry file, e.g. `App.js`:
```
import { Checkbox } from '@fluentui/react-native';
```
Once you have the package installed, check out our [Hello World Fluent page](https://github.com/microsoft/fluent-site/blob/master/packages/fluent-website/docs/windows/get-started/Hello-World.mdx) to start writing code (Coming Soon).
## Documentation
### Components and Controls
Our component documentation is hosted in a separate repository, [Microsoft FluentUI Site](https://github.com/Microsoft/fluent-site) that will be published to its own website (Coming Soon).
### Theming framework
Our FluentUI framework documentation is found in this repository alongside the implementation.
- [Theming Overview](./packages/framework/theming-react-native/README.md)
- [StyleSheets](./packages/framework/themed-stylesheet/README.md)
- [Customizing Theme Settings](./packages/framework/themed-settings/README.md)
- [Theme Registry](./packages/framework/theme-registry/README.md)
- [Tokens](./packages/framework/foundation-tokens/README.md)
- [Settings and Slots](./packages/framework/foundation-settings/README.md)
- [Compose](./packages/framework/foundation-compose/README.md) and [Composable](./packages/framework/foundation-composable/README.md)
## Developing in the repo
### Yarn + Lerna
This repo is set up as a monorepo using Lerna + Yarn workspaces. The yarn commands will trigger the lerna commands which will execute yarn commands in each package. To install yarn, please follow instructions in the [Yarn documentation](https://classic.yarnpkg.com/en/docs/install/).
### Setup your development environment
To start developing in the repository you can:
1. `git clone https://github.com/microsoft/fluentui-react-native.git`
1. `cd fluentui-react-native`
1. `yarn`
1. `yarn build`
After a successful yarn build, you can explore FluentUI Tester, our demo application to play with each of the controls. To run FluentUI Tester, please follow instructions in the [FluentUI Tester readme](./apps/fluent-tester/README.md).
### Beachball
This repo manages semantic versioning and publishing using [Beachball](https://github.com/microsoft/beachball). When contributing, make sure to run the following before making a pull request:
1. `yarn change` will take you through a command line wizard to generate change files
2. Make sure to commit and push the newly generated change file
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
# FluentUI React Native
FluentUI React Native is a javascript component library that provides developers with controls that are part of the [Fluent Design System](https://www.microsoft.com/design/fluent/). These controls are built on [React Native](https://reactnative.dev/) and fully customizable.
## Getting Started
If you have an existing React Native project, it's easy to begin using FluentUI React Native. If you need to setup a new React Native project, please see the [React Native Windows Getting Started documentation](https://microsoft.github.io/react-native-windows/docs/getting-started).
### Prerequisites
- [Standard React Native dependencies](http://facebook.github.io/react-native/docs/getting-started.html#node-python2-jdk)
- [Node.js](https://nodejs.org/en/download/)
### Install FluentUI React Native into an existing project
Navigate to the root folder of your project, and use npm to install the package:
```
npm i @fluentui/react-native
```
After successful installation, you can test the package by importing components at the top of your app's entry file, e.g. `App.js`:
```
import { Checkbox } from '@fluentui/react-native';
```
Once you have the package installed, check out our [Hello World Fluent page](https://github.com/microsoft/fluent-site/blob/master/packages/fluent-website/docs/windows/get-started/Hello-World.mdx) to start writing code (Coming Soon).
## Documentation
### Components and Controls
Our component documentation is hosted in a separate repository, [Microsoft FluentUI Site](https://github.com/Microsoft/fluent-site) that will be published to its own website (Coming Soon).
### Theming framework
Our FluentUI framework documentation is found in this repository alongside the implementation.
- [Theming Overview](./packages/framework/theming-react-native/README.md)
- [StyleSheets](./packages/framework/themed-stylesheet/README.md)
- [Customizing Theme Settings](./packages/framework/themed-settings/README.md)
- [Theme Registry](./packages/framework/theme-registry/README.md)
- [Tokens](./packages/framework/foundation-tokens/README.md)
- [Settings and Slots](./packages/framework/foundation-settings/README.md)
- [Compose](./packages/framework/foundation-compose/README.md) and [Composable](./packages/framework/foundation-composable/README.md)
## Developing in the repo
### Yarn + Lerna
This repo is set up as a monorepo using Lerna + Yarn workspaces. The yarn commands will trigger the lerna commands which will execute yarn commands in each package. To install yarn, please follow instructions in the [Yarn documentation](https://classic.yarnpkg.com/en/docs/install/).
### Setup your development environment
To start developing in the repository you can:
1. `git clone https://github.com/microsoft/fluentui-react-native.git`
1. `cd fluentui-react-native`
1. `yarn`
1. `yarn build`
After a successful yarn build, you can explore FluentUI Tester, our demo application to play with each of the controls. To run FluentUI Tester, please follow instructions in the [FluentUI Tester readme](./apps/fluent-tester/README.md).
### Beachball
This repo manages semantic versioning and publishing using [Beachball](https://github.com/microsoft/beachball). When contributing, make sure to run the following before making a pull request:
1. `yarn change` will take you through a command line wizard to generate change files
2. Make sure to commit and push the newly generated change file
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

Просмотреть файл

@ -1,58 +1,58 @@
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"idiom" : "mac",
"scale" : "1x",
"size" : "16x16"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "16x16"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "32x32"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "32x32"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "128x128"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "128x128"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "256x256"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "256x256"
},
{
"idiom" : "mac",
"scale" : "1x",
"size" : "512x512"
},
{
"idiom" : "mac",
"scale" : "2x",
"size" : "512x512"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Просмотреть файл

@ -1,6 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

Просмотреть файл

@ -1,5 +1,5 @@
#import <AppKit/AppKit.h>
@interface FRNAppDelegate : NSObject <NSApplicationDelegate>
@end
#import <AppKit/AppKit.h>
@interface FRNAppDelegate : NSObject <NSApplicationDelegate>
@end

Просмотреть файл

@ -1,5 +1,5 @@
#import "FRNAppDelegate.h"
@implementation FRNAppDelegate
@end
#import "FRNAppDelegate.h"
@implementation FRNAppDelegate
@end

Просмотреть файл

@ -1,5 +1,5 @@
#import <AppKit/AppKit.h>
@interface FRNViewController : NSViewController
@end
#import <AppKit/AppKit.h>
@interface FRNViewController : NSViewController
@end

Просмотреть файл

@ -1,28 +1,28 @@
#import "FRNViewController.h"
#import "FRNAppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTBridge.h>
#import <React/RCTRootView.h>
@interface FRNViewController () <RCTBridgeDelegate>
@end
@implementation FRNViewController
- (void)loadView {
// The delegate must conform to RCTBridgeDelegate to retrieve the JS source file for the packager
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"FluentUITester" initialProperties:nil];
[self setView:rootView];
}
#pragma mark - RCTBridgeDelegate Methods
- (NSURL *)sourceURLForBridge:(__unused RCTBridge *)bridge {
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:@"main"]; // .jsbundle;
}
@end
#import "FRNViewController.h"
#import "FRNAppDelegate.h"
#import <React/RCTBundleURLProvider.h>
#import <React/RCTBridge.h>
#import <React/RCTRootView.h>
@interface FRNViewController () <RCTBridgeDelegate>
@end
@implementation FRNViewController
- (void)loadView {
// The delegate must conform to RCTBridgeDelegate to retrieve the JS source file for the packager
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge moduleName:@"FluentUITester" initialProperties:nil];
[self setView:rootView];
}
#pragma mark - RCTBridgeDelegate Methods
- (NSURL *)sourceURLForBridge:(__unused RCTBridge *)bridge {
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:@"main"]; // .jsbundle;
}
@end

Просмотреть файл

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
</dict>
</plist>

Просмотреть файл

@ -1,47 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
<key>NSMainStoryboardFile</key>
<string>Main</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSSupportsAutomaticTermination</key>
<true/>
<key>NSSupportsSuddenTermination</key>
<true/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
<key>NSMainStoryboardFile</key>
<string>Main</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSSupportsAutomaticTermination</key>
<true/>
<key>NSSupportsSuddenTermination</key>
<true/>
</dict>
</plist>

Просмотреть файл

@ -1,5 +1,5 @@
#import <AppKit/AppKit.h>
int main(int argc, const char *argv[]) {
return NSApplicationMain(argc, argv);
}
#import <AppKit/AppKit.h>
int main(int argc, const char *argv[]) {
return NSApplicationMain(argc, argv);
}

Просмотреть файл

@ -1,36 +1,36 @@
# require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
abstract_target 'Shared' do
# use_native_modules!
pod 'React', :path => "../node_modules/react-native-macos/"
pod 'React-Core', :path => "../node_modules/react-native-macos/React"
pod 'React-fishhook', :path => "../node_modules/react-native-macos/Libraries/fishhook"
pod 'React-RCTActionSheet', :path => "../node_modules/react-native-macos/Libraries/ActionSheetIOS"
pod 'React-RCTAnimation', :path => "../node_modules/react-native-macos/Libraries/NativeAnimation"
pod 'React-RCTBlob', :path => "../node_modules/react-native-macos/Libraries/Blob"
pod 'React-RCTImage', :path => "../node_modules/react-native-macos/Libraries/Image"
pod 'React-RCTLinking', :path => "../node_modules/react-native-macos/Libraries/LinkingIOS"
pod 'React-RCTNetwork', :path => "../node_modules/react-native-macos/Libraries/Network"
pod 'React-RCTSettings', :path => "../node_modules/react-native-macos/Libraries/Settings"
pod 'React-RCTText', :path => "../node_modules/react-native-macos/Libraries/Text"
pod 'React-RCTVibration', :path => "../node_modules/react-native-macos/Libraries/Vibration"
pod 'React-RCTWebSocket', :path => "../node_modules/react-native-macos/Libraries/WebSocket"
pod 'React-cxxreact', :path => "../node_modules/react-native-macos/ReactCommon/cxxreact"
pod 'React-jscallinvoker', :path => "../node_modules/react-native-macos/ReactCommon/jscallinvoker"
pod 'React-jsi', :path => "../node_modules/react-native-macos/ReactCommon/jsi"
pod 'React-jsiexecutor', :path => "../node_modules/react-native-macos/ReactCommon/jsiexecutor"
pod 'React-jsinspector', :path => "../node_modules/react-native-macos/ReactCommon/jsinspector"
pod 'yoga', :path => "../node_modules/react-native-macos/ReactCommon/yoga"
pod 'DoubleConversion', :podspec => "../node_modules/react-native-macos/third-party-podspecs/DoubleConversion.podspec"
pod 'glog', :podspec => "../node_modules/react-native-macos/third-party-podspecs/glog.podspec"
pod 'Folly', :podspec => "../node_modules/react-native-macos/third-party-podspecs/Folly.podspec"
pod 'boost-for-react-native', :podspec => "../node_modules/react-native-macos/third-party-podspecs/boost-for-react-native.podspec"
pod 'React-DevSupport', :path => "../node_modules/react-native-macos/React"
target 'FluentUITester-macOS' do
platform :macos, '10.15'
# Pods specifically for macOS target
end
end
# require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
abstract_target 'Shared' do
# use_native_modules!
pod 'React', :path => "../node_modules/react-native-macos/"
pod 'React-Core', :path => "../node_modules/react-native-macos/React"
pod 'React-fishhook', :path => "../node_modules/react-native-macos/Libraries/fishhook"
pod 'React-RCTActionSheet', :path => "../node_modules/react-native-macos/Libraries/ActionSheetIOS"
pod 'React-RCTAnimation', :path => "../node_modules/react-native-macos/Libraries/NativeAnimation"
pod 'React-RCTBlob', :path => "../node_modules/react-native-macos/Libraries/Blob"
pod 'React-RCTImage', :path => "../node_modules/react-native-macos/Libraries/Image"
pod 'React-RCTLinking', :path => "../node_modules/react-native-macos/Libraries/LinkingIOS"
pod 'React-RCTNetwork', :path => "../node_modules/react-native-macos/Libraries/Network"
pod 'React-RCTSettings', :path => "../node_modules/react-native-macos/Libraries/Settings"
pod 'React-RCTText', :path => "../node_modules/react-native-macos/Libraries/Text"
pod 'React-RCTVibration', :path => "../node_modules/react-native-macos/Libraries/Vibration"
pod 'React-RCTWebSocket', :path => "../node_modules/react-native-macos/Libraries/WebSocket"
pod 'React-cxxreact', :path => "../node_modules/react-native-macos/ReactCommon/cxxreact"
pod 'React-jscallinvoker', :path => "../node_modules/react-native-macos/ReactCommon/jscallinvoker"
pod 'React-jsi', :path => "../node_modules/react-native-macos/ReactCommon/jsi"
pod 'React-jsiexecutor', :path => "../node_modules/react-native-macos/ReactCommon/jsiexecutor"
pod 'React-jsinspector', :path => "../node_modules/react-native-macos/ReactCommon/jsinspector"
pod 'yoga', :path => "../node_modules/react-native-macos/ReactCommon/yoga"
pod 'DoubleConversion', :podspec => "../node_modules/react-native-macos/third-party-podspecs/DoubleConversion.podspec"
pod 'glog', :podspec => "../node_modules/react-native-macos/third-party-podspecs/glog.podspec"
pod 'Folly', :podspec => "../node_modules/react-native-macos/third-party-podspecs/Folly.podspec"
pod 'boost-for-react-native', :podspec => "../node_modules/react-native-macos/third-party-podspecs/boost-for-react-native.podspec"
pod 'React-DevSupport', :path => "../node_modules/react-native-macos/React"
target 'FluentUITester-macOS' do
platform :macos, '10.15'
# Pods specifically for macOS target
end
end

Просмотреть файл

@ -1,19 +1,19 @@
/**
* This cli config is needed for development purposes, e.g. for running
* integration tests during local development or on CI services.
*/
const path = require('path');
const blacklist = require('metro-config/src/defaults/blacklist');
const rnmPath = path.resolve(__dirname, 'node_modules/react-native-macos');
module.exports = {
resolver: {
extraNodeModules: {
'react-native': rnmPath,
},
platforms: ['macos', 'ios'],
blacklistRE: blacklist([/node_modules\/react-native\/.*/]),
},
};
/**
* This cli config is needed for development purposes, e.g. for running
* integration tests during local development or on CI services.
*/
const path = require('path');
const blacklist = require('metro-config/src/defaults/blacklist');
const rnmPath = path.resolve(__dirname, 'node_modules/react-native-macos');
module.exports = {
resolver: {
extraNodeModules: {
'react-native': rnmPath,
},
platforms: ['macos', 'ios'],
blacklistRE: blacklist([/node_modules\/react-native\/.*/]),
},
};

Просмотреть файл

@ -1,33 +1,33 @@
/**
* This cli config is needed for the coexistance of react-native and other
* out-of-tree implementations such react-native-macos.
* The following issue is tracked by
* https://github.com/react-native-community/discussions-and-proposals/issues/182
*
* The work-around involves having a metro.config.js for each out-of-tree
* platform, i.e. metro.config.js for react-native and
* metro.config.macos.js for react-native-macos.
* This react-native.config.js looks for a --use-react-native-macos
* switch and when present pushes --config=metro.config.macos.js
* and specifies reactNativePath: 'node_modules/react-native-macos'.
* The metro.config.js has to blacklist 'node_modules/react-native-macos',
* and conversely metro.config.macos.js has to blacklist 'node_modules/react-native'.
*/
'use strict';
const macSwitch = '--use-react-native-macos';
const windowsSwitch = '--use-react-native-windows';
if (process.argv.includes(macSwitch)) {
process.argv = process.argv.filter(arg => arg !== macSwitch);
process.argv.push('--config=metro.config.macos.js');
module.exports = {
reactNativePath: 'node_modules/react-native-macos',
};
} else if (process.argv.includes(windowsSwitch)) {
process.argv = process.argv.filter(arg => arg !== windowsSwitch);
process.argv.push('--config=metro.config.windows.js');
module.exports = {
reactNativePath: 'node_modules/react-native-windows',
};
}
/**
* This cli config is needed for the coexistance of react-native and other
* out-of-tree implementations such react-native-macos.
* The following issue is tracked by
* https://github.com/react-native-community/discussions-and-proposals/issues/182
*
* The work-around involves having a metro.config.js for each out-of-tree
* platform, i.e. metro.config.js for react-native and
* metro.config.macos.js for react-native-macos.
* This react-native.config.js looks for a --use-react-native-macos
* switch and when present pushes --config=metro.config.macos.js
* and specifies reactNativePath: 'node_modules/react-native-macos'.
* The metro.config.js has to blacklist 'node_modules/react-native-macos',
* and conversely metro.config.macos.js has to blacklist 'node_modules/react-native'.
*/
'use strict';
const macSwitch = '--use-react-native-macos';
const windowsSwitch = '--use-react-native-windows';
if (process.argv.includes(macSwitch)) {
process.argv = process.argv.filter(arg => arg !== macSwitch);
process.argv.push('--config=metro.config.macos.js');
module.exports = {
reactNativePath: 'node_modules/react-native-macos',
};
} else if (process.argv.includes(windowsSwitch)) {
process.argv = process.argv.filter(arg => arg !== windowsSwitch);
process.argv.push('--config=metro.config.windows.js');
module.exports = {
reactNativePath: 'node_modules/react-native-windows',
};
}

Просмотреть файл

@ -1,28 +1,28 @@
import * as React from 'react';
import { undefinedText } from '../PersonaCoin/styles';
import { IconAlignment } from '@fluentui/react-native';
import { Picker, StyleProp, ViewStyle } from 'react-native';
const alignmentValues: Array<typeof undefinedText | IconAlignment> = [undefinedText, 'start', 'center', 'end'];
interface IAlignmentPickerProps {
style?: StyleProp<ViewStyle>;
label: string;
onSelectionChange: (value: IconAlignment | undefined) => void;
}
export const AlignmentPicker: React.FunctionComponent<IAlignmentPickerProps> = (props: IAlignmentPickerProps) => {
const { label, onSelectionChange, style } = props;
return (
<Picker
style={style}
prompt={label}
selectedValue={undefinedText}
onValueChange={(value, index) => onSelectionChange(index == 0 ? undefined : value)}
>
{alignmentValues.map((alignment, index) => (
<Picker.Item label={alignment} key={index} value={alignment} />
))}
</Picker>
);
};
import * as React from 'react';
import { undefinedText } from '../PersonaCoin/styles';
import { IconAlignment } from '@fluentui/react-native';
import { Picker, StyleProp, ViewStyle } from 'react-native';
const alignmentValues: Array<typeof undefinedText | IconAlignment> = [undefinedText, 'start', 'center', 'end'];
interface IAlignmentPickerProps {
style?: StyleProp<ViewStyle>;
label: string;
onSelectionChange: (value: IconAlignment | undefined) => void;
}
export const AlignmentPicker: React.FunctionComponent<IAlignmentPickerProps> = (props: IAlignmentPickerProps) => {
const { label, onSelectionChange, style } = props;
return (
<Picker
style={style}
prompt={label}
selectedValue={undefinedText}
onValueChange={(value, index) => onSelectionChange(index == 0 ? undefined : value)}
>
{alignmentValues.map((alignment, index) => (
<Picker.Item label={alignment} key={index} value={alignment} />
))}
</Picker>
);
};

Просмотреть файл

@ -1,168 +1,168 @@
import * as React from 'react';
import { ViewProps, StyleSheet, StyleProp, ViewStyle, UIManager, Text, findNodeHandle, View } from 'react-native';
import { Separator, Pressable, IPressableState } from '@fluentui/react-native';
const thumbSize = 20;
const defaultMaximumValue = 100;
const defaultMinimumValue = 1;
interface ISliderProps extends ViewProps {
minimum?: number;
maximum?: number;
initialValue?: number;
onChange?: (value: number) => void;
}
const styles = StyleSheet.create({
root: {
flexDirection: 'row',
alignItems: 'center'
},
slider: {
minWidth: thumbSize * 2,
flexDirection: 'row',
alignItems: 'center',
alignContent: 'stretch',
height: thumbSize,
width: 200
},
track: {
flexGrow: 1
},
thumb: {
width: thumbSize,
height: thumbSize,
borderRadius: thumbSize,
borderWidth: 2,
borderColor: '#7A7574',
backgroundColor: '#FFFFFF',
position: 'absolute'
},
label: {
margin: 8,
fontSize: 12
}
});
const Track = Separator.customize({ tokens: { separatorWidth: 4 } });
function onThumbRenderStyle(state: IPressableState, thumbLocation: number): StyleProp<ViewStyle> {
return {
...styles.thumb,
borderColor: state.pressed ? 'black' : state.hovered ? 'red' : '#7A7574',
marginLeft: thumbLocation
};
}
function calculateThumbLocationAndValue(
startTouchThumbLocation: number,
startTouchPosition: number,
currentTouchPosition: number,
trackLength: number,
minimum: number,
maximum: number
): [number, number] {
let newThumbLocation = startTouchThumbLocation + currentTouchPosition - startTouchPosition;
newThumbLocation = Math.max(0, newThumbLocation);
newThumbLocation = Math.min(newThumbLocation, trackLength);
const newValue = minimum + (newThumbLocation / trackLength) * (maximum - minimum);
const intValue = Math.min(maximum, Math.floor(newValue + 0.3)); // snap to nearest integer value
newThumbLocation = (trackLength * (intValue - minimum)) / (maximum - minimum);
return [newThumbLocation, intValue];
}
function verifyProps(initialValue: number, minimum: number, maximum: number) {
if (minimum >= maximum) {
throw new Error(`'minimum' must not be greater than or equal 'maximum'.`);
}
if (initialValue < minimum) {
throw new Error(`'initialValue' must not be less than 'minimum'.`);
}
if (initialValue > maximum) {
throw new Error(`'initialValue' must not be greater than 'maximum'.`);
}
}
export const Slider: React.FunctionComponent<ISliderProps> = (props: ISliderProps) => {
let { minimum, maximum, initialValue } = props;
minimum = minimum || defaultMinimumValue;
maximum = maximum || defaultMaximumValue;
initialValue = initialValue || minimum;
verifyProps(initialValue, minimum, maximum);
const { style: userStyle, onChange } = props;
const [thumbLocation, setThumbLocation] = React.useState<number>(0);
const startTouchPosition = React.useRef<number>(-1);
const startTouchThumbLocation = React.useRef<number>(-1);
const trackLength = React.useRef<number>(-1);
const sliderValue = React.useRef<number>(initialValue);
const ref = React.useRef<View>(null);
React.useEffect(() => {
const parent = findNodeHandle(ref.current);
if (parent) {
UIManager.measure(parent, (_x, _y, width) => {
if (width <= 0) {
return;
}
// track length is the entire view width subtracted by the thumb size.
trackLength.current = Math.max(0, width - thumbSize);
const initialThumbLocation = (trackLength.current * (initialValue! - minimum!)) / (maximum! - minimum!);
setThumbLocation(initialThumbLocation);
});
}
}, [ref.current, initialValue, maximum, minimum]);
return (
<View style={[userStyle, styles.root]}>
<View ref={ref} {...props} style={styles.slider}>
<Track style={styles.track} />
{trackLength.current > 0 && (
<Pressable
renderStyle={state => onThumbRenderStyle(state, thumbLocation)}
onStartShouldSetResponder={() => trackLength.current > 0}
onResponderStart={e => {
startTouchPosition.current = e.nativeEvent.pageX;
startTouchThumbLocation.current = thumbLocation;
}}
onResponderMove={e => {
if (startTouchPosition.current !== -1 && trackLength.current > 0) {
const [newThumbLocation, newValue] = calculateThumbLocationAndValue(
startTouchThumbLocation.current,
startTouchPosition.current,
e.nativeEvent.pageX,
trackLength.current,
minimum || defaultMinimumValue,
maximum || defaultMaximumValue
);
sliderValue.current = newValue;
setThumbLocation(newThumbLocation);
}
}}
onResponderEnd={() => {
startTouchPosition.current = -1;
startTouchThumbLocation.current = -1;
}}
onResponderRelease={() => {
if (onChange) {
onChange(sliderValue.current);
}
}}
/>
)}
</View>
<Text style={styles.label}>{sliderValue.current}</Text>
</View>
);
};
import * as React from 'react';
import { ViewProps, StyleSheet, StyleProp, ViewStyle, UIManager, Text, findNodeHandle, View } from 'react-native';
import { Separator, Pressable, IPressableState } from '@fluentui/react-native';
const thumbSize = 20;
const defaultMaximumValue = 100;
const defaultMinimumValue = 1;
interface ISliderProps extends ViewProps {
minimum?: number;
maximum?: number;
initialValue?: number;
onChange?: (value: number) => void;
}
const styles = StyleSheet.create({
root: {
flexDirection: 'row',
alignItems: 'center'
},
slider: {
minWidth: thumbSize * 2,
flexDirection: 'row',
alignItems: 'center',
alignContent: 'stretch',
height: thumbSize,
width: 200
},
track: {
flexGrow: 1
},
thumb: {
width: thumbSize,
height: thumbSize,
borderRadius: thumbSize,
borderWidth: 2,
borderColor: '#7A7574',
backgroundColor: '#FFFFFF',
position: 'absolute'
},
label: {
margin: 8,
fontSize: 12
}
});
const Track = Separator.customize({ tokens: { separatorWidth: 4 } });
function onThumbRenderStyle(state: IPressableState, thumbLocation: number): StyleProp<ViewStyle> {
return {
...styles.thumb,
borderColor: state.pressed ? 'black' : state.hovered ? 'red' : '#7A7574',
marginLeft: thumbLocation
};
}
function calculateThumbLocationAndValue(
startTouchThumbLocation: number,
startTouchPosition: number,
currentTouchPosition: number,
trackLength: number,
minimum: number,
maximum: number
): [number, number] {
let newThumbLocation = startTouchThumbLocation + currentTouchPosition - startTouchPosition;
newThumbLocation = Math.max(0, newThumbLocation);
newThumbLocation = Math.min(newThumbLocation, trackLength);
const newValue = minimum + (newThumbLocation / trackLength) * (maximum - minimum);
const intValue = Math.min(maximum, Math.floor(newValue + 0.3)); // snap to nearest integer value
newThumbLocation = (trackLength * (intValue - minimum)) / (maximum - minimum);
return [newThumbLocation, intValue];
}
function verifyProps(initialValue: number, minimum: number, maximum: number) {
if (minimum >= maximum) {
throw new Error(`'minimum' must not be greater than or equal 'maximum'.`);
}
if (initialValue < minimum) {
throw new Error(`'initialValue' must not be less than 'minimum'.`);
}
if (initialValue > maximum) {
throw new Error(`'initialValue' must not be greater than 'maximum'.`);
}
}
export const Slider: React.FunctionComponent<ISliderProps> = (props: ISliderProps) => {
let { minimum, maximum, initialValue } = props;
minimum = minimum || defaultMinimumValue;
maximum = maximum || defaultMaximumValue;
initialValue = initialValue || minimum;
verifyProps(initialValue, minimum, maximum);
const { style: userStyle, onChange } = props;
const [thumbLocation, setThumbLocation] = React.useState<number>(0);
const startTouchPosition = React.useRef<number>(-1);
const startTouchThumbLocation = React.useRef<number>(-1);
const trackLength = React.useRef<number>(-1);
const sliderValue = React.useRef<number>(initialValue);
const ref = React.useRef<View>(null);
React.useEffect(() => {
const parent = findNodeHandle(ref.current);
if (parent) {
UIManager.measure(parent, (_x, _y, width) => {
if (width <= 0) {
return;
}
// track length is the entire view width subtracted by the thumb size.
trackLength.current = Math.max(0, width - thumbSize);
const initialThumbLocation = (trackLength.current * (initialValue! - minimum!)) / (maximum! - minimum!);
setThumbLocation(initialThumbLocation);
});
}
}, [ref.current, initialValue, maximum, minimum]);
return (
<View style={[userStyle, styles.root]}>
<View ref={ref} {...props} style={styles.slider}>
<Track style={styles.track} />
{trackLength.current > 0 && (
<Pressable
renderStyle={state => onThumbRenderStyle(state, thumbLocation)}
onStartShouldSetResponder={() => trackLength.current > 0}
onResponderStart={e => {
startTouchPosition.current = e.nativeEvent.pageX;
startTouchThumbLocation.current = thumbLocation;
}}
onResponderMove={e => {
if (startTouchPosition.current !== -1 && trackLength.current > 0) {
const [newThumbLocation, newValue] = calculateThumbLocationAndValue(
startTouchThumbLocation.current,
startTouchPosition.current,
e.nativeEvent.pageX,
trackLength.current,
minimum || defaultMinimumValue,
maximum || defaultMaximumValue
);
sliderValue.current = newValue;
setThumbLocation(newThumbLocation);
}
}}
onResponderEnd={() => {
startTouchPosition.current = -1;
startTouchThumbLocation.current = -1;
}}
onResponderRelease={() => {
if (onChange) {
onChange(sliderValue.current);
}
}}
/>
)}
</View>
<Text style={styles.label}>{sliderValue.current}</Text>
</View>
);
};

Просмотреть файл

@ -1,116 +1,116 @@
import { StyleSheet } from 'react-native';
import { IStackProps } from '@fluentui-react-native/stack';
export const commonTestStyles = StyleSheet.create({
root: {
marginTop: 16,
marginRight: 32,
flexDirection: 'row',
alignItems: 'flex-start'
},
header: {
marginVertical: 6,
fontSize: 12
},
section: {
fontSize: 15,
fontWeight: 'bold',
color: '#0B6A0B',
marginTop: 12
},
separatorStack: {
height: 200,
flexDirection: 'row',
justifyContent: 'space-evenly'
},
settings: {
flexGrow: 1
},
slider: {
marginVertical: 6
},
stack: {
borderWidth: 2,
borderColor: '#bdbdbd',
padding: 12,
margin: 8
},
switch: {
flexDirection: 'row',
alignItems: 'center'
},
textBox: {
borderWidth: 1,
height: 25,
fontSize: 12,
width: 150,
marginBottom: 8
},
view: {
minHeight: 200,
justifyContent: 'space-between'
}
});
export const fabricTesterStyles = StyleSheet.create({
root: {
flex: 1,
flexGrow: 1,
flexDirection: 'row',
minHeight: 550,
minWidth: 300,
justifyContent: 'flex-start',
alignItems: 'stretch',
padding: 4
},
testHeader: {
marginBottom: 8,
fontSize: 14,
fontWeight: 'bold'
},
testList: {
width: 160
},
testListContainerStyle: {
flexDirection: 'column',
alignItems: 'stretch'
},
testListItem: {
width: 150
},
testSection: {
fontSize: 15,
fontWeight: 'bold',
color: '#0B6A0B',
marginTop: 12
},
separator: {
marginHorizontal: 8,
width: 2
},
noTest: {
alignSelf: 'center',
fontSize: 14
}
});
export const stackStyle: IStackProps['style'] = {
borderWidth: 1,
borderColor: '#bdbdbd',
paddingVertical: 8,
paddingHorizontal: 12,
margin: 8
};
export const separatorStackStyle: IStackProps['style'] = {
height: 200,
flexDirection: 'row',
justifyContent: 'space-evenly'
};
import { StyleSheet } from 'react-native';
import { IStackProps } from '@fluentui-react-native/stack';
export const commonTestStyles = StyleSheet.create({
root: {
marginTop: 16,
marginRight: 32,
flexDirection: 'row',
alignItems: 'flex-start'
},
header: {
marginVertical: 6,
fontSize: 12
},
section: {
fontSize: 15,
fontWeight: 'bold',
color: '#0B6A0B',
marginTop: 12
},
separatorStack: {
height: 200,
flexDirection: 'row',
justifyContent: 'space-evenly'
},
settings: {
flexGrow: 1
},
slider: {
marginVertical: 6
},
stack: {
borderWidth: 2,
borderColor: '#bdbdbd',
padding: 12,
margin: 8
},
switch: {
flexDirection: 'row',
alignItems: 'center'
},
textBox: {
borderWidth: 1,
height: 25,
fontSize: 12,
width: 150,
marginBottom: 8
},
view: {
minHeight: 200,
justifyContent: 'space-between'
}
});
export const fabricTesterStyles = StyleSheet.create({
root: {
flex: 1,
flexGrow: 1,
flexDirection: 'row',
minHeight: 550,
minWidth: 300,
justifyContent: 'flex-start',
alignItems: 'stretch',
padding: 4
},
testHeader: {
marginBottom: 8,
fontSize: 14,
fontWeight: 'bold'
},
testList: {
width: 160
},
testListContainerStyle: {
flexDirection: 'column',
alignItems: 'stretch'
},
testListItem: {
width: 150
},
testSection: {
fontSize: 15,
fontWeight: 'bold',
color: '#0B6A0B',
marginTop: 12
},
separator: {
marginHorizontal: 8,
width: 2
},
noTest: {
alignSelf: 'center',
fontSize: 14
}
});
export const stackStyle: IStackProps['style'] = {
borderWidth: 1,
borderColor: '#bdbdbd',
paddingVertical: 8,
paddingHorizontal: 12,
margin: 8
};
export const separatorStackStyle: IStackProps['style'] = {
height: 200,
flexDirection: 'row',
justifyContent: 'space-evenly'
};

Просмотреть файл

@ -1,114 +1,114 @@
import * as React from 'react';
import { View, Text, Switch, TextInput } from 'react-native';
import { IPersonaTokens, Persona } from '@fluentui/react-native';
import { michaelImageUrl } from './styles';
import { commonTestStyles as commonStyles } from '../Common/styles';
import { useTheme } from '@uifabricshared/theming-react-native';
import { Slider } from '../Common/Slider';
export const CustomizeUsage: React.FunctionComponent<{}> = () => {
const [showImage, setShowImage] = React.useState(true);
const [coinColor, setCoinColor] = React.useState<string>();
const [textColor, setTextColor] = React.useState<string>();
const [textSize, setTextSize] = React.useState<number>(23);
const [secondarySize, setSecondarySize] = React.useState<number>(20);
const [tertiarySize, setTertiarySize] = React.useState<number>(17);
const [optionalSize, setOptionalSize] = React.useState<number>(14);
const [horizontalGap, setHorizontalGap] = React.useState<number>();
const [verticalGap, setVerticalGap] = React.useState<number>();
const tokens: Partial<IPersonaTokens> = {};
if (coinColor) {
tokens.coinBackgroundColor = coinColor;
}
if (textColor) {
tokens.color = textColor;
}
if (textSize) {
tokens.textFont = { fontSize: textSize };
}
if (secondarySize) {
tokens.secondaryFont = { fontSize: secondarySize };
}
if (tertiarySize) {
tokens.tertiaryFont = { fontSize: tertiarySize };
}
if (optionalSize) {
tokens.optionalFont = { fontSize: optionalSize };
}
if (horizontalGap !== undefined) {
tokens.horizontalGap = horizontalGap;
}
if (verticalGap !== undefined) {
tokens.verticalGap = verticalGap;
}
const theme = useTheme();
const textBoxBorderStyle = {
borderColor: theme.colors.inputBorder
};
const CustomizedPersona = Persona.customize({ tokens });
return (
<View style={commonStyles.root}>
{/* settings */}
<View style={commonStyles.settings}>
<View style={commonStyles.switch}>
<Text>Show image</Text>
<Switch value={showImage} onValueChange={setShowImage} />
</View>
<TextInput
style={[commonStyles.textBox, textBoxBorderStyle]}
placeholder="Background color"
blurOnSubmit={true}
onSubmitEditing={e => {
setCoinColor(e.nativeEvent.text);
}}
/>
<TextInput
style={[commonStyles.textBox, textBoxBorderStyle]}
placeholder="Initials text color"
blurOnSubmit={true}
onSubmitEditing={e => {
setTextColor(e.nativeEvent.text);
}}
/>
<Text>Primary text size</Text>
<Slider maximum={50} minimum={5} initialValue={textSize} style={commonStyles.slider} onChange={setTextSize} />
<Text>Secondary text size</Text>
<Slider maximum={50} minimum={5} initialValue={secondarySize} style={commonStyles.slider} onChange={setSecondarySize} />
<Text>Tertiary text size</Text>
<Slider maximum={50} minimum={5} initialValue={tertiarySize} style={commonStyles.slider} onChange={setTertiarySize} />
<Text>Optional text size</Text>
<Slider maximum={50} minimum={5} initialValue={optionalSize} style={commonStyles.slider} onChange={setOptionalSize} />
<Text>Horizontal gap</Text>
<Slider maximum={100} initialValue={5} minimum={0} style={commonStyles.slider} onChange={setHorizontalGap} />
<Text>Vertical gap</Text>
<Slider maximum={20} initialValue={5} minimum={0} style={commonStyles.slider} onChange={setVerticalGap} />
</View>
{/* component under test */}
<CustomizedPersona
initials="MJ"
size="size72"
text="Michael Jackson"
secondaryText="Pop singer"
tertiaryText="King of pop"
optionalText="Indiana"
imageDescription="Legendary pop singer"
presence="offline"
imageUrl={showImage ? michaelImageUrl : undefined}
/>
</View>
);
};
import * as React from 'react';
import { View, Text, Switch, TextInput } from 'react-native';
import { IPersonaTokens, Persona } from '@fluentui/react-native';
import { michaelImageUrl } from './styles';
import { commonTestStyles as commonStyles } from '../Common/styles';
import { useTheme } from '@uifabricshared/theming-react-native';
import { Slider } from '../Common/Slider';
export const CustomizeUsage: React.FunctionComponent<{}> = () => {
const [showImage, setShowImage] = React.useState(true);
const [coinColor, setCoinColor] = React.useState<string>();
const [textColor, setTextColor] = React.useState<string>();
const [textSize, setTextSize] = React.useState<number>(23);
const [secondarySize, setSecondarySize] = React.useState<number>(20);
const [tertiarySize, setTertiarySize] = React.useState<number>(17);
const [optionalSize, setOptionalSize] = React.useState<number>(14);
const [horizontalGap, setHorizontalGap] = React.useState<number>();
const [verticalGap, setVerticalGap] = React.useState<number>();
const tokens: Partial<IPersonaTokens> = {};
if (coinColor) {
tokens.coinBackgroundColor = coinColor;
}
if (textColor) {
tokens.color = textColor;
}
if (textSize) {
tokens.textFont = { fontSize: textSize };
}
if (secondarySize) {
tokens.secondaryFont = { fontSize: secondarySize };
}
if (tertiarySize) {
tokens.tertiaryFont = { fontSize: tertiarySize };
}
if (optionalSize) {
tokens.optionalFont = { fontSize: optionalSize };
}
if (horizontalGap !== undefined) {
tokens.horizontalGap = horizontalGap;
}
if (verticalGap !== undefined) {
tokens.verticalGap = verticalGap;
}
const theme = useTheme();
const textBoxBorderStyle = {
borderColor: theme.colors.inputBorder
};
const CustomizedPersona = Persona.customize({ tokens });
return (
<View style={commonStyles.root}>
{/* settings */}
<View style={commonStyles.settings}>
<View style={commonStyles.switch}>
<Text>Show image</Text>
<Switch value={showImage} onValueChange={setShowImage} />
</View>
<TextInput
style={[commonStyles.textBox, textBoxBorderStyle]}
placeholder="Background color"
blurOnSubmit={true}
onSubmitEditing={e => {
setCoinColor(e.nativeEvent.text);
}}
/>
<TextInput
style={[commonStyles.textBox, textBoxBorderStyle]}
placeholder="Initials text color"
blurOnSubmit={true}
onSubmitEditing={e => {
setTextColor(e.nativeEvent.text);
}}
/>
<Text>Primary text size</Text>
<Slider maximum={50} minimum={5} initialValue={textSize} style={commonStyles.slider} onChange={setTextSize} />
<Text>Secondary text size</Text>
<Slider maximum={50} minimum={5} initialValue={secondarySize} style={commonStyles.slider} onChange={setSecondarySize} />
<Text>Tertiary text size</Text>
<Slider maximum={50} minimum={5} initialValue={tertiarySize} style={commonStyles.slider} onChange={setTertiarySize} />
<Text>Optional text size</Text>
<Slider maximum={50} minimum={5} initialValue={optionalSize} style={commonStyles.slider} onChange={setOptionalSize} />
<Text>Horizontal gap</Text>
<Slider maximum={100} initialValue={5} minimum={0} style={commonStyles.slider} onChange={setHorizontalGap} />
<Text>Vertical gap</Text>
<Slider maximum={20} initialValue={5} minimum={0} style={commonStyles.slider} onChange={setVerticalGap} />
</View>
{/* component under test */}
<CustomizedPersona
initials="MJ"
size="size72"
text="Michael Jackson"
secondaryText="Pop singer"
tertiaryText="King of pop"
optionalText="Indiana"
imageDescription="Legendary pop singer"
presence="offline"
imageUrl={showImage ? michaelImageUrl : undefined}
/>
</View>
);
};

Просмотреть файл

@ -1,20 +1,20 @@
import * as React from 'react';
import { View } from 'react-native';
import { Separator, Text } from '@fluentui/react-native';
import { commonTestStyles } from '../Common/styles';
import { StandardUsage } from './StandardUsage';
import { CustomizeUsage } from './CustomizeUsage';
export const PersonaTest: React.FunctionComponent<{}> = () => {
return (
<View>
<Text style={commonTestStyles.section}>Standard Usage</Text>
<Separator />
<StandardUsage />
<Text style={commonTestStyles.section}>Customize Usage</Text>
<Separator />
<CustomizeUsage />
</View>
);
};
import * as React from 'react';
import { View } from 'react-native';
import { Separator, Text } from '@fluentui/react-native';
import { commonTestStyles } from '../Common/styles';
import { StandardUsage } from './StandardUsage';
import { CustomizeUsage } from './CustomizeUsage';
export const PersonaTest: React.FunctionComponent<{}> = () => {
return (
<View>
<Text style={commonTestStyles.section}>Standard Usage</Text>
<Separator />
<StandardUsage />
<Text style={commonTestStyles.section}>Customize Usage</Text>
<Separator />
<CustomizeUsage />
</View>
);
};

Просмотреть файл

@ -1,82 +1,82 @@
import * as React from 'react';
import { Persona, PersonaSize } from '@fluentui/react-native';
import { rajeshImageUrl } from './styles';
import { commonTestStyles as commonStyles } from '../Common/styles';
import { View, Text, Switch, Picker } from 'react-native';
import { undefinedText } from '../PersonaCoin/styles';
type WithUndefined<T> = T | typeof undefinedText;
const allSizes: WithUndefined<PersonaSize>[] = [
undefinedText,
'size8',
'size24',
'size32',
'size40',
'size48',
'size56',
'size72',
'size100',
'size120'
];
interface ISwitchWithLabelProps {
label: string;
value: boolean;
onValueChange: (value: boolean) => void;
}
function SwitchWithLabel(props: ISwitchWithLabelProps): React.ReactElement {
const { label, value, onValueChange } = props;
return (
<View style={commonStyles.switch}>
<Text>{label}</Text>
<Switch value={value} onValueChange={onValueChange} />
</View>
);
}
export const StandardUsage: React.FunctionComponent<{}> = () => {
const [showImage, setShowImage] = React.useState(true);
const [showPrimary, setShowPrimary] = React.useState(true);
const [showSecondary, setShowSecondary] = React.useState(true);
const [showTertiary, setShowTertiary] = React.useState(true);
const [showOptional, setShowOptional] = React.useState(true);
const [imageSize, setImageSize] = React.useState<PersonaSize | undefined>('size72');
return (
<View style={commonStyles.root}>
{/* settings */}
<View style={commonStyles.settings}>
<SwitchWithLabel label="Show image" value={showImage} onValueChange={setShowImage} />
<SwitchWithLabel label="Show primary text" value={showPrimary} onValueChange={setShowPrimary} />
<SwitchWithLabel label="Show secondary text" value={showSecondary} onValueChange={setShowSecondary} />
<SwitchWithLabel label="Show tertiary text" value={showTertiary} onValueChange={setShowTertiary} />
<SwitchWithLabel label="Show optional text" value={showOptional} onValueChange={setShowOptional} />
<Picker
prompt="Size"
style={commonStyles.header}
selectedValue={imageSize || undefinedText}
onValueChange={size => setImageSize(size === undefinedText ? undefined : size)}
>
{allSizes.map((size, index) => (
<Picker.Item label={size} key={index} value={size} />
))}
</Picker>
</View>
<Persona
text={showPrimary ? 'Rajesh Jha' : undefined}
secondaryText={showSecondary ? 'Executive Vice President' : undefined}
tertiaryText={showTertiary ? 'E & D' : undefined}
optionalText={showOptional ? 'Building 36/5600' : undefined}
size={imageSize}
initials="RJ"
imageUrl={showImage ? rajeshImageUrl : undefined}
imageDescription="Profile photo of Rajesh Jha"
presence={'away'}
/>
</View>
);
};
import * as React from 'react';
import { Persona, PersonaSize } from '@fluentui/react-native';
import { rajeshImageUrl } from './styles';
import { commonTestStyles as commonStyles } from '../Common/styles';
import { View, Text, Switch, Picker } from 'react-native';
import { undefinedText } from '../PersonaCoin/styles';
type WithUndefined<T> = T | typeof undefinedText;
const allSizes: WithUndefined<PersonaSize>[] = [
undefinedText,
'size8',
'size24',
'size32',
'size40',
'size48',
'size56',
'size72',
'size100',
'size120'
];
interface ISwitchWithLabelProps {
label: string;
value: boolean;
onValueChange: (value: boolean) => void;
}
function SwitchWithLabel(props: ISwitchWithLabelProps): React.ReactElement {
const { label, value, onValueChange } = props;
return (
<View style={commonStyles.switch}>
<Text>{label}</Text>
<Switch value={value} onValueChange={onValueChange} />
</View>
);
}
export const StandardUsage: React.FunctionComponent<{}> = () => {
const [showImage, setShowImage] = React.useState(true);
const [showPrimary, setShowPrimary] = React.useState(true);
const [showSecondary, setShowSecondary] = React.useState(true);
const [showTertiary, setShowTertiary] = React.useState(true);
const [showOptional, setShowOptional] = React.useState(true);
const [imageSize, setImageSize] = React.useState<PersonaSize | undefined>('size72');
return (
<View style={commonStyles.root}>
{/* settings */}
<View style={commonStyles.settings}>
<SwitchWithLabel label="Show image" value={showImage} onValueChange={setShowImage} />
<SwitchWithLabel label="Show primary text" value={showPrimary} onValueChange={setShowPrimary} />
<SwitchWithLabel label="Show secondary text" value={showSecondary} onValueChange={setShowSecondary} />
<SwitchWithLabel label="Show tertiary text" value={showTertiary} onValueChange={setShowTertiary} />
<SwitchWithLabel label="Show optional text" value={showOptional} onValueChange={setShowOptional} />
<Picker
prompt="Size"
style={commonStyles.header}
selectedValue={imageSize || undefinedText}
onValueChange={size => setImageSize(size === undefinedText ? undefined : size)}
>
{allSizes.map((size, index) => (
<Picker.Item label={size} key={index} value={size} />
))}
</Picker>
</View>
<Persona
text={showPrimary ? 'Rajesh Jha' : undefined}
secondaryText={showSecondary ? 'Executive Vice President' : undefined}
tertiaryText={showTertiary ? 'E & D' : undefined}
optionalText={showOptional ? 'Building 36/5600' : undefined}
size={imageSize}
initials="RJ"
imageUrl={showImage ? rajeshImageUrl : undefined}
imageDescription="Profile photo of Rajesh Jha"
presence={'away'}
/>
</View>
);
};

Просмотреть файл

@ -1,6 +1,6 @@
export * from '../PersonaCoin/styles';
export const rajeshImageUrl =
'https://3er1viui9wo30pkxh1v2nh4w-wpengine.netdna-ssl.com/wp-content/uploads/prod/2016/09/Rajesh-BW-Square.jpg';
export const michaelImageUrl = 'http://www.rap-up.com/app/uploads/2014/12/michael-jackson.jpg';
export * from '../PersonaCoin/styles';
export const rajeshImageUrl =
'https://3er1viui9wo30pkxh1v2nh4w-wpengine.netdna-ssl.com/wp-content/uploads/prod/2016/09/Rajesh-BW-Square.jpg';
export const michaelImageUrl = 'http://www.rap-up.com/app/uploads/2014/12/michael-jackson.jpg';

Просмотреть файл

@ -1,99 +1,99 @@
import * as React from 'react';
import { PersonaCoin, IconAlignment, IPersonaCoinTokens } from '@fluentui/react-native';
import { Switch, View, Text, TextInput } from 'react-native';
import { Slider } from '../Common/Slider';
import { steveBallmerPhotoUrl } from './styles';
import { useTheme } from '@uifabricshared/theming-react-native';
import { AlignmentPicker } from '../Common/AlignmentPicker';
import { commonTestStyles as commonStyles } from '../Common/styles';
export const CustomizeUsage: React.FunctionComponent<{}> = () => {
const [showImage, setShowImage] = React.useState(true);
const [coinColor, setCoinColor] = React.useState<string>();
const [textColor, setTextColor] = React.useState<string>();
const [physicalSize, setPhysicalSize] = React.useState<number>(80);
const [iconSize, setIconSize] = React.useState<number>(24);
const [initialsSize, setInitialsSize] = React.useState<number>(14);
const [horizontalAlignment, setHorizontalAlignment] = React.useState<IconAlignment>();
const [verticalAlignment, setVerticalAlignment] = React.useState<IconAlignment>();
const theme = useTheme();
const textBoxBorderStyle = {
borderColor: theme.colors.inputBorder
};
const tokens: Partial<IPersonaCoinTokens> = {};
if (coinColor) {
tokens.backgroundColor = coinColor;
}
if (textColor) {
tokens.color = textColor;
}
if (horizontalAlignment) {
tokens.horizontalIconAlignment = horizontalAlignment;
}
if (verticalAlignment) {
tokens.verticalIconAlignment = verticalAlignment;
}
if (iconSize) {
tokens.iconSize = iconSize;
}
if (initialsSize) {
tokens.initialsSize = initialsSize;
}
if (physicalSize) {
tokens.coinSize = physicalSize;
}
const CustomizedPersonaCoin = PersonaCoin.customize({ tokens });
return (
<View style={commonStyles.root}>
{/* settings */}
<View style={commonStyles.settings}>
<View style={commonStyles.switch}>
<Text>Show image</Text>
<Switch value={showImage} onValueChange={setShowImage} />
</View>
<TextInput
style={[commonStyles.textBox, textBoxBorderStyle]}
placeholder="Background color"
blurOnSubmit={true}
onSubmitEditing={e => {
setCoinColor(e.nativeEvent.text);
}}
/>
<TextInput
style={[commonStyles.textBox, textBoxBorderStyle]}
placeholder="Initials text color"
blurOnSubmit={true}
onSubmitEditing={e => {
setTextColor(e.nativeEvent.text);
}}
/>
<AlignmentPicker style={commonStyles.header} label="Horizontal icon alignment" onSelectionChange={setHorizontalAlignment} />
<AlignmentPicker style={commonStyles.header} label="Vertical icon alignment" onSelectionChange={setVerticalAlignment} />
<Text>Coin size</Text>
<Slider minimum={8} maximum={200} initialValue={80} style={commonStyles.slider} onChange={setPhysicalSize} />
<Text>Icon size</Text>
<Slider minimum={8} maximum={100} initialValue={24} style={commonStyles.slider} onChange={setIconSize} />
<Text>Font size</Text>
<Slider minimum={5} maximum={50} initialValue={14} style={commonStyles.slider} onChange={setInitialsSize} />
</View>
{/* component under test */}
<CustomizedPersonaCoin
initials="SB"
imageDescription="Former CEO of Microsoft"
presence="blocked"
imageUrl={showImage ? steveBallmerPhotoUrl : undefined}
/>
</View>
);
};
import * as React from 'react';
import { PersonaCoin, IconAlignment, IPersonaCoinTokens } from '@fluentui/react-native';
import { Switch, View, Text, TextInput } from 'react-native';
import { Slider } from '../Common/Slider';
import { steveBallmerPhotoUrl } from './styles';
import { useTheme } from '@uifabricshared/theming-react-native';
import { AlignmentPicker } from '../Common/AlignmentPicker';
import { commonTestStyles as commonStyles } from '../Common/styles';
export const CustomizeUsage: React.FunctionComponent<{}> = () => {
const [showImage, setShowImage] = React.useState(true);
const [coinColor, setCoinColor] = React.useState<string>();
const [textColor, setTextColor] = React.useState<string>();
const [physicalSize, setPhysicalSize] = React.useState<number>(80);
const [iconSize, setIconSize] = React.useState<number>(24);
const [initialsSize, setInitialsSize] = React.useState<number>(14);
const [horizontalAlignment, setHorizontalAlignment] = React.useState<IconAlignment>();
const [verticalAlignment, setVerticalAlignment] = React.useState<IconAlignment>();
const theme = useTheme();
const textBoxBorderStyle = {
borderColor: theme.colors.inputBorder
};
const tokens: Partial<IPersonaCoinTokens> = {};
if (coinColor) {
tokens.backgroundColor = coinColor;
}
if (textColor) {
tokens.color = textColor;
}
if (horizontalAlignment) {
tokens.horizontalIconAlignment = horizontalAlignment;
}
if (verticalAlignment) {
tokens.verticalIconAlignment = verticalAlignment;
}
if (iconSize) {
tokens.iconSize = iconSize;
}
if (initialsSize) {
tokens.initialsSize = initialsSize;
}
if (physicalSize) {
tokens.coinSize = physicalSize;
}
const CustomizedPersonaCoin = PersonaCoin.customize({ tokens });
return (
<View style={commonStyles.root}>
{/* settings */}
<View style={commonStyles.settings}>
<View style={commonStyles.switch}>
<Text>Show image</Text>
<Switch value={showImage} onValueChange={setShowImage} />
</View>
<TextInput
style={[commonStyles.textBox, textBoxBorderStyle]}
placeholder="Background color"
blurOnSubmit={true}
onSubmitEditing={e => {
setCoinColor(e.nativeEvent.text);
}}
/>
<TextInput
style={[commonStyles.textBox, textBoxBorderStyle]}
placeholder="Initials text color"
blurOnSubmit={true}
onSubmitEditing={e => {
setTextColor(e.nativeEvent.text);
}}
/>
<AlignmentPicker style={commonStyles.header} label="Horizontal icon alignment" onSelectionChange={setHorizontalAlignment} />
<AlignmentPicker style={commonStyles.header} label="Vertical icon alignment" onSelectionChange={setVerticalAlignment} />
<Text>Coin size</Text>
<Slider minimum={8} maximum={200} initialValue={80} style={commonStyles.slider} onChange={setPhysicalSize} />
<Text>Icon size</Text>
<Slider minimum={8} maximum={100} initialValue={24} style={commonStyles.slider} onChange={setIconSize} />
<Text>Font size</Text>
<Slider minimum={5} maximum={50} initialValue={14} style={commonStyles.slider} onChange={setInitialsSize} />
</View>
{/* component under test */}
<CustomizedPersonaCoin
initials="SB"
imageDescription="Former CEO of Microsoft"
presence="blocked"
imageUrl={showImage ? steveBallmerPhotoUrl : undefined}
/>
</View>
);
};

Просмотреть файл

@ -1,20 +1,20 @@
import * as React from 'react';
import { View, Text } from 'react-native';
import { Separator } from '@fluentui/react-native';
import { StandardUsage } from './StandardUsage';
import { CustomizeUsage } from './CustomizeUsage';
import { commonTestStyles as commonStyles } from '../Common/styles';
export const PersonaCoinTest: React.FunctionComponent<{}> = () => {
return (
<View>
<Text style={commonStyles.section}>Standard Usage</Text>
<Separator />
<StandardUsage />
<Text style={commonStyles.section}>Customize Usage</Text>
<Separator />
<CustomizeUsage />
</View>
);
};
import * as React from 'react';
import { View, Text } from 'react-native';
import { Separator } from '@fluentui/react-native';
import { StandardUsage } from './StandardUsage';
import { CustomizeUsage } from './CustomizeUsage';
import { commonTestStyles as commonStyles } from '../Common/styles';
export const PersonaCoinTest: React.FunctionComponent<{}> = () => {
return (
<View>
<Text style={commonStyles.section}>Standard Usage</Text>
<Separator />
<StandardUsage />
<Text style={commonStyles.section}>Customize Usage</Text>
<Separator />
<CustomizeUsage />
</View>
);
};

Просмотреть файл

@ -1,96 +1,96 @@
import * as React from 'react';
import { PersonaSize, PersonaCoinColor, PersonaCoin, PersonaPresence } from '@fluentui/react-native';
import { Switch, View, Text, Picker } from 'react-native';
import { satyaPhotoUrl, undefinedText } from './styles';
import { commonTestStyles as commonStyles } from '../Common/styles';
type WithUndefined<T> = T | typeof undefinedText;
const allSizes: WithUndefined<PersonaSize>[] = [
undefinedText,
'size8',
'size24',
'size32',
'size40',
'size48',
'size56',
'size72',
'size100',
'size120'
];
const allColors: WithUndefined<PersonaCoinColor>[] = [
undefinedText,
'lightBlue',
'blue',
'darkBlue',
'teal',
'green',
'darkGreen',
'lightPink',
'pink',
'magenta',
'purple',
'orange',
'darkRed',
'violet',
'lightRed',
'gold',
'burgundy',
'warmGray',
'coolGray',
'cyan',
'rust'
];
const allPresences: WithUndefined<PersonaPresence>[] = [undefinedText, 'none', 'online', 'offline', 'busy', 'dnd', 'blocked', 'away'];
export const StandardUsage: React.FunctionComponent<{}> = () => {
const [showImage, setShowImage] = React.useState(true);
const [imageSize, setImageSize] = React.useState<WithUndefined<PersonaSize>>('size72');
const [coinColor, setCoinColor] = React.useState<WithUndefined<PersonaCoinColor>>('gold');
const [presence, setPresence] = React.useState<WithUndefined<PersonaPresence>>('online');
const onSizeChange = React.useCallback(value => setImageSize(value), []);
const onColorChange = React.useCallback(value => setCoinColor(value), []);
const onPresenceChange = React.useCallback(value => setPresence(value), []);
return (
<View style={commonStyles.root}>
{/* settings */}
<View style={commonStyles.settings}>
<View style={commonStyles.switch}>
<Text>Show image</Text>
<Switch value={showImage} onValueChange={setShowImage} />
</View>
<Picker prompt="Size" style={commonStyles.header} selectedValue={imageSize} onValueChange={onSizeChange}>
{allSizes.map((size, index) => (
<Picker.Item label={size} key={index} value={size} />
))}
</Picker>
<Picker prompt="Coin color" style={commonStyles.header} selectedValue={coinColor} onValueChange={onColorChange}>
{allColors.map((color, index) => (
<Picker.Item label={color} key={index} value={color} />
))}
</Picker>
<Picker prompt="Presence status" style={commonStyles.header} selectedValue={presence} onValueChange={onPresenceChange}>
{allPresences.map((presence, index) => (
<Picker.Item label={presence} key={index} value={presence} />
))}
</Picker>
</View>
{/* component under test */}
<PersonaCoin
size={imageSize === undefinedText ? undefined : imageSize}
initials="SN"
imageDescription="Photo of Satya Nadella"
presence={presence === undefinedText ? undefined : presence}
imageUrl={showImage ? satyaPhotoUrl : undefined}
coinColor={coinColor === undefinedText ? undefined : coinColor}
/>
</View>
);
};
import * as React from 'react';
import { PersonaSize, PersonaCoinColor, PersonaCoin, PersonaPresence } from '@fluentui/react-native';
import { Switch, View, Text, Picker } from 'react-native';
import { satyaPhotoUrl, undefinedText } from './styles';
import { commonTestStyles as commonStyles } from '../Common/styles';
type WithUndefined<T> = T | typeof undefinedText;
const allSizes: WithUndefined<PersonaSize>[] = [
undefinedText,
'size8',
'size24',
'size32',
'size40',
'size48',
'size56',
'size72',
'size100',
'size120'
];
const allColors: WithUndefined<PersonaCoinColor>[] = [
undefinedText,
'lightBlue',
'blue',
'darkBlue',
'teal',
'green',
'darkGreen',
'lightPink',
'pink',
'magenta',
'purple',
'orange',
'darkRed',
'violet',
'lightRed',
'gold',
'burgundy',
'warmGray',
'coolGray',
'cyan',
'rust'
];
const allPresences: WithUndefined<PersonaPresence>[] = [undefinedText, 'none', 'online', 'offline', 'busy', 'dnd', 'blocked', 'away'];
export const StandardUsage: React.FunctionComponent<{}> = () => {
const [showImage, setShowImage] = React.useState(true);
const [imageSize, setImageSize] = React.useState<WithUndefined<PersonaSize>>('size72');
const [coinColor, setCoinColor] = React.useState<WithUndefined<PersonaCoinColor>>('gold');
const [presence, setPresence] = React.useState<WithUndefined<PersonaPresence>>('online');
const onSizeChange = React.useCallback(value => setImageSize(value), []);
const onColorChange = React.useCallback(value => setCoinColor(value), []);
const onPresenceChange = React.useCallback(value => setPresence(value), []);
return (
<View style={commonStyles.root}>
{/* settings */}
<View style={commonStyles.settings}>
<View style={commonStyles.switch}>
<Text>Show image</Text>
<Switch value={showImage} onValueChange={setShowImage} />
</View>
<Picker prompt="Size" style={commonStyles.header} selectedValue={imageSize} onValueChange={onSizeChange}>
{allSizes.map((size, index) => (
<Picker.Item label={size} key={index} value={size} />
))}
</Picker>
<Picker prompt="Coin color" style={commonStyles.header} selectedValue={coinColor} onValueChange={onColorChange}>
{allColors.map((color, index) => (
<Picker.Item label={color} key={index} value={color} />
))}
</Picker>
<Picker prompt="Presence status" style={commonStyles.header} selectedValue={presence} onValueChange={onPresenceChange}>
{allPresences.map((presence, index) => (
<Picker.Item label={presence} key={index} value={presence} />
))}
</Picker>
</View>
{/* component under test */}
<PersonaCoin
size={imageSize === undefinedText ? undefined : imageSize}
initials="SN"
imageDescription="Photo of Satya Nadella"
presence={presence === undefinedText ? undefined : presence}
imageUrl={showImage ? satyaPhotoUrl : undefined}
coinColor={coinColor === undefinedText ? undefined : coinColor}
/>
</View>
);
};

Просмотреть файл

@ -1,14 +1,14 @@
import { StyleSheet } from 'react-native';
export const styles = StyleSheet.create({
oneCoin: {
margin: 8
}
});
export const satyaPhotoUrl =
'https://www.microsoft.com/en-us/CMSImages/satya.jpg?version=0881eb71-4942-b627-d602-84c832b8a0b6&amp;CollectionId=1b46ce2d-c90d-421e-94f1-cfb6bc6ef6ec';
export const steveBallmerPhotoUrl = 'http://www.rmndigital.com/wp-content/uploads/2012/11/stevems.jpg';
export const undefinedText = '(undefined)';
import { StyleSheet } from 'react-native';
export const styles = StyleSheet.create({
oneCoin: {
margin: 8
}
});
export const satyaPhotoUrl =
'https://www.microsoft.com/en-us/CMSImages/satya.jpg?version=0881eb71-4942-b627-d602-84c832b8a0b6&amp;CollectionId=1b46ce2d-c90d-421e-94f1-cfb6bc6ef6ec';
export const steveBallmerPhotoUrl = 'http://www.rmndigital.com/wp-content/uploads/2012/11/stevems.jpg';
export const undefinedText = '(undefined)';

Просмотреть файл

@ -1,48 +1,48 @@
import * as React from 'react';
import { View } from 'react-native';
import { Stack } from '@fluentui-react-native/stack';
import { Text } from '@fluentui-react-native/text';
import { stackStyle } from '../Common/styles';
import { styles } from './styles';
export const CustomizeUsage: React.FunctionComponent<{}> = () => {
const RedCaptionBold = Text.customize({ tokens: { variant: 'captionStandard', fontWeight: 'semiBold', color: '#ff0000' } });
const OrangeSecondaryBold = Text.customize({ tokens: { variant: 'secondaryStandard', fontWeight: 'semiBold', color: '#ff9900' } });
const YellowBodyBold = Text.customize({ tokens: { variant: 'bodyStandard', fontWeight: 'semiBold', color: '#f3ce00' } });
const GreenSubheaderBold = Text.customize({ tokens: { variant: 'subheaderStandard', fontWeight: 'semiBold', color: '#02c440' } });
const BlueHeaderBold = Text.customize({ tokens: { variant: 'headerStandard', fontWeight: 'semiBold', color: '#0229c4' } });
const IndigoHeroBold = Text.customize({ tokens: { variant: 'heroStandard', fontWeight: 'semiBold', color: '#4b0082' } });
const PurpleHeroLargeBold = Text.customize({ tokens: { variant: 'heroLargeStandard', fontWeight: 'semiBold', color: '#8402c4' } });
const ArialBlack = Text.customize({ tokens: { variant: 'heroLargeStandard', fontFamily: 'Arial Black' } });
const BrushScriptMT = Text.customize({ tokens: { variant: 'heroStandard', fontFamily: 'Brush Script MT' } });
const CourierNew = Text.customize({ tokens: { variant: 'headerStandard', fontFamily: 'Courier New' } });
const Georgia = Text.customize({ tokens: { variant: 'subheaderStandard', fontFamily: 'Georgia' } });
const SegoeScript = Text.customize({ tokens: { variant: 'bodyStandard', fontFamily: 'Segoe Script' } });
const TimesNewRoman = Text.customize({ tokens: { variant: 'secondaryStandard', fontFamily: 'Times New Roman' } });
const Wingdings = Text.customize({ tokens: { variant: 'captionStandard', fontFamily: 'Wingdings' } });
return (
<View style={styles.root}>
<Stack style={stackStyle} gap={5}>
<RedCaptionBold>RedCaptionBold</RedCaptionBold>
<OrangeSecondaryBold>OrangeSecondaryBold</OrangeSecondaryBold>
<YellowBodyBold>YellowBodyBold</YellowBodyBold>
<GreenSubheaderBold>GreenSubheaderBold</GreenSubheaderBold>
<BlueHeaderBold>BlueHeaderBold</BlueHeaderBold>
<IndigoHeroBold>IndigoHeroBold</IndigoHeroBold>
<PurpleHeroLargeBold>PurpleHeroLargeBold</PurpleHeroLargeBold>
</Stack>
<Stack style={stackStyle} gap={5}>
<ArialBlack>Arial Black</ArialBlack>
<BrushScriptMT>Brush Script MT</BrushScriptMT>
<CourierNew>Courier New</CourierNew>
<Georgia>Georgia</Georgia>
<SegoeScript>Segoe Script</SegoeScript>
<TimesNewRoman>TimesNewRoman</TimesNewRoman>
<Wingdings>Wingdings</Wingdings>
</Stack>
</View>
);
};
import * as React from 'react';
import { View } from 'react-native';
import { Stack } from '@fluentui-react-native/stack';
import { Text } from '@fluentui-react-native/text';
import { stackStyle } from '../Common/styles';
import { styles } from './styles';
export const CustomizeUsage: React.FunctionComponent<{}> = () => {
const RedCaptionBold = Text.customize({ tokens: { variant: 'captionStandard', fontWeight: 'semiBold', color: '#ff0000' } });
const OrangeSecondaryBold = Text.customize({ tokens: { variant: 'secondaryStandard', fontWeight: 'semiBold', color: '#ff9900' } });
const YellowBodyBold = Text.customize({ tokens: { variant: 'bodyStandard', fontWeight: 'semiBold', color: '#f3ce00' } });
const GreenSubheaderBold = Text.customize({ tokens: { variant: 'subheaderStandard', fontWeight: 'semiBold', color: '#02c440' } });
const BlueHeaderBold = Text.customize({ tokens: { variant: 'headerStandard', fontWeight: 'semiBold', color: '#0229c4' } });
const IndigoHeroBold = Text.customize({ tokens: { variant: 'heroStandard', fontWeight: 'semiBold', color: '#4b0082' } });
const PurpleHeroLargeBold = Text.customize({ tokens: { variant: 'heroLargeStandard', fontWeight: 'semiBold', color: '#8402c4' } });
const ArialBlack = Text.customize({ tokens: { variant: 'heroLargeStandard', fontFamily: 'Arial Black' } });
const BrushScriptMT = Text.customize({ tokens: { variant: 'heroStandard', fontFamily: 'Brush Script MT' } });
const CourierNew = Text.customize({ tokens: { variant: 'headerStandard', fontFamily: 'Courier New' } });
const Georgia = Text.customize({ tokens: { variant: 'subheaderStandard', fontFamily: 'Georgia' } });
const SegoeScript = Text.customize({ tokens: { variant: 'bodyStandard', fontFamily: 'Segoe Script' } });
const TimesNewRoman = Text.customize({ tokens: { variant: 'secondaryStandard', fontFamily: 'Times New Roman' } });
const Wingdings = Text.customize({ tokens: { variant: 'captionStandard', fontFamily: 'Wingdings' } });
return (
<View style={styles.root}>
<Stack style={stackStyle} gap={5}>
<RedCaptionBold>RedCaptionBold</RedCaptionBold>
<OrangeSecondaryBold>OrangeSecondaryBold</OrangeSecondaryBold>
<YellowBodyBold>YellowBodyBold</YellowBodyBold>
<GreenSubheaderBold>GreenSubheaderBold</GreenSubheaderBold>
<BlueHeaderBold>BlueHeaderBold</BlueHeaderBold>
<IndigoHeroBold>IndigoHeroBold</IndigoHeroBold>
<PurpleHeroLargeBold>PurpleHeroLargeBold</PurpleHeroLargeBold>
</Stack>
<Stack style={stackStyle} gap={5}>
<ArialBlack>Arial Black</ArialBlack>
<BrushScriptMT>Brush Script MT</BrushScriptMT>
<CourierNew>Courier New</CourierNew>
<Georgia>Georgia</Georgia>
<SegoeScript>Segoe Script</SegoeScript>
<TimesNewRoman>TimesNewRoman</TimesNewRoman>
<Wingdings>Wingdings</Wingdings>
</Stack>
</View>
);
};

Просмотреть файл

@ -1,24 +1,24 @@
import * as React from 'react';
import { View } from 'react-native';
import { Text } from '@fluentui-react-native/text';
import { styles } from './styles';
export const StandardUsage: React.FunctionComponent<{}> = () => {
return (
<View style={styles.root}>
<Text variant="captionStandard">CaptionStandard</Text>
<Text variant="secondaryStandard">SecondaryStandard</Text>
<Text variant="secondarySemibold">SecondarySemibold</Text>
<Text variant="bodyStandard">BodyStandard</Text>
<Text variant="bodySemibold">BodySemibold</Text>
<Text variant="subheaderStandard">SubheaderStandard</Text>
<Text variant="subheaderSemibold">SubheaderSemibold</Text>
<Text variant="headerStandard">HeaderStandard</Text>
<Text variant="headerSemibold">HeaderSemibold</Text>
<Text variant="heroStandard">HeroStandard</Text>
<Text variant="heroSemibold">HeroSemibold</Text>
<Text variant="heroLargeStandard">HeroLargeStandard</Text>
<Text variant="heroLargeSemibold">HeroLargeSemibold</Text>
</View>
);
};
import * as React from 'react';
import { View } from 'react-native';
import { Text } from '@fluentui-react-native/text';
import { styles } from './styles';
export const StandardUsage: React.FunctionComponent<{}> = () => {
return (
<View style={styles.root}>
<Text variant="captionStandard">CaptionStandard</Text>
<Text variant="secondaryStandard">SecondaryStandard</Text>
<Text variant="secondarySemibold">SecondarySemibold</Text>
<Text variant="bodyStandard">BodyStandard</Text>
<Text variant="bodySemibold">BodySemibold</Text>
<Text variant="subheaderStandard">SubheaderStandard</Text>
<Text variant="subheaderSemibold">SubheaderSemibold</Text>
<Text variant="headerStandard">HeaderStandard</Text>
<Text variant="headerSemibold">HeaderSemibold</Text>
<Text variant="heroStandard">HeroStandard</Text>
<Text variant="heroSemibold">HeroSemibold</Text>
<Text variant="heroLargeStandard">HeroLargeStandard</Text>
<Text variant="heroLargeSemibold">HeroLargeSemibold</Text>
</View>
);
};

Просмотреть файл

@ -1,21 +1,21 @@
import * as React from 'react';
import { View } from 'react-native';
import { Separator } from '@fluentui-react-native/separator';
import { StandardUsage } from './StandardUsage';
import { CustomizeUsage } from './CustomizeUsage';
import { styles } from './styles';
import { Text } from '@fluentui-react-native/text';
export const TextTest: React.FunctionComponent<{}> = () => {
return (
<View>
<Text style={styles.section}>Standard Usage</Text>
<Separator />
<StandardUsage />
<Text style={styles.section}>Customize Usage</Text>
<Separator />
<CustomizeUsage />
</View>
);
};
import * as React from 'react';
import { View } from 'react-native';
import { Separator } from '@fluentui-react-native/separator';
import { StandardUsage } from './StandardUsage';
import { CustomizeUsage } from './CustomizeUsage';
import { styles } from './styles';
import { Text } from '@fluentui-react-native/text';
export const TextTest: React.FunctionComponent<{}> = () => {
return (
<View>
<Text style={styles.section}>Standard Usage</Text>
<Separator />
<StandardUsage />
<Text style={styles.section}>Customize Usage</Text>
<Separator />
<CustomizeUsage />
</View>
);
};

Просмотреть файл

@ -1 +1 @@
export * from './TextTest';
export * from './TextTest';

Просмотреть файл

@ -1,16 +1,16 @@
import { StyleSheet } from 'react-native';
export const styles = StyleSheet.create({
root: {
marginTop: 16,
marginRight: 32,
flexDirection: 'column',
alignItems: 'flex-start'
},
section: {
fontSize: 15,
fontWeight: 'bold',
color: '#0B6A0B',
marginTop: 12
}
});
import { StyleSheet } from 'react-native';
export const styles = StyleSheet.create({
root: {
marginTop: 16,
marginRight: 32,
flexDirection: 'column',
alignItems: 'flex-start'
},
section: {
fontSize: 15,
fontWeight: 'bold',
color: '#0B6A0B',
marginTop: 12
}
});

Просмотреть файл

@ -1,205 +1,207 @@
import * as React from 'react';
import { FlatList, View, ViewStyle, TextStyle, StyleSheet } from 'react-native';
import { getHostSettingsWin32, ThemeProvider, useTheme, IThemeDefinition, ThemingModuleHelper } from '@uifabricshared/theming-react-native';
import { themedStyleSheet } from '@uifabricshared/themed-stylesheet';
import { commonTestStyles } from '../Common/styles';
import { Button, PrimaryButton, Separator, StealthButton, Text, RadioGroup, RadioButton } from '@fluentui/react-native';
import { ITheme, IPartialTheme } from '@uifabricshared/theming-ramp';
import { customRegistry } from './CustomThemes';
let brand = 'Office';
const brandColors = {
Word: ['#E3ECFA', '#A5B9D1', '#7DA3C6', '#4A78B0', '#3C65A4', '#2B579A', '#124078', '#002050'],
Excel: ['#E9F5EE', '#9FCDB3', '#6EB38A', '#4E9668', '#3F8159', '#217346', '#0E5C2F', '#004B1C'],
Powerpoint: ['#FCF0ED', '#FDC9B5', '#ED9583', '#E86E58', '#C75033', '#B7472A', '#A92B1A', '#740912'],
Outlook: ['#CCE3F5', '#B3D6F2', '#69AFE5', '#2488D8', '#0078D7', '#106EBE', '#1664A7', '#135995'],
};
// This IProcessTheme takes the parent theme and shims in the brand colors selected in the RadioGroup
const fakeBrandTheme: IThemeDefinition = (theme: ITheme): IPartialTheme => {
if (brand === 'Office') {
return {};
}
const brandValues = theme.colors.brand.values;
const brandedTheme = { colors: {}, host: { palette: {} } };
Object.keys(theme.colors).forEach((value: string) => {
if (typeof theme.colors[value] === 'string') {
const index = brandValues.indexOf(theme.colors[value].toString());
if (index !== -1) brandedTheme.colors[value] = brandColors[brand][index];
}
});
const hostThemeSettings = getHostSettingsWin32(theme);
if (hostThemeSettings === undefined) return brandedTheme;
Object.keys(hostThemeSettings.palette).forEach((value: string) => {
const index = brandValues.indexOf(hostThemeSettings.palette[value].toString());
if (index !== -1) brandedTheme.host.palette[value] = brandColors[brand][index];
});
return brandedTheme;
};
// this applies the shim to the default theme
customRegistry.setTheme(fakeBrandTheme, 'Default');
// this registers platform white colors
customRegistry.setTheme(ThemingModuleHelper.getPlatformThemeDefinition('WhiteColors'), 'RealWhiteColors');
// this applies the shim to the white colors theme
customRegistry.setTheme(fakeBrandTheme, 'WhiteColors', 'RealWhiteColors');
const getThemedStyles = themedStyleSheet((theme: ITheme) => {
const hostSettings = getHostSettingsWin32(theme);
return {
swatch: {
width: 80,
height: 20,
marginRight: 5,
borderWidth: 2,
borderColor: theme.colors.bodyText,
},
extraLargeStandardEmphasis: {
color: hostSettings ? hostSettings.palette.TextEmphasis : theme.colors.bodyText,
fontSize: theme.typography.sizes.header,
fontWeight: theme.typography.weights.regular,
fontFamily: theme.typography.families.primary,
} as TextStyle,
largeStandard: {
color: theme.colors.bodyText,
fontSize: theme.typography.sizes.body,
fontWeight: theme.typography.weights.regular,
fontFamily: theme.typography.families.primary,
marginBottom: 5,
} as TextStyle,
stackStyle: {
borderWidth: 2,
borderColor: theme.colors.focusBorder,
padding: 12,
margin: 8,
backgroundColor: theme.colors.background,
},
};
});
const styles = StyleSheet.create({
swatchItem: {
flexDirection: 'row',
alignItems: 'center',
marginVertical: 5,
},
pickerContainer: {
flexDirection: 'row',
justifyContent: 'space-evenly',
},
});
const Panel: React.FunctionComponent = () => {
const [disabled, setDisabled] = React.useState(false);
const onClick = React.useCallback(() => setDisabled(!disabled), [disabled, setDisabled]);
const themedStyles = getThemedStyles(useTheme());
return (
<View style={[commonTestStyles.view, themedStyles.stackStyle]}>
<PrimaryButton onClick={onClick} content="Primary Button" disabled={disabled} />
<Button onClick={onClick} content="Default Button" disabled={disabled} />
<StealthButton onClick={onClick} content="Stealth Button" disabled={disabled} />
<Text>This is a text element</Text>
<Button onClick={onClick} content="This button has longer text" disabled={disabled} />
</View>
);
};
const getSwatchColorStyle = (color: string): ViewStyle => {
styles[color] = styles[color] || { backgroundColor: color };
return styles[color];
};
type SemanticColorProps = { color: string; name: string };
const SemanticColor: React.FunctionComponent<SemanticColorProps> = (p: SemanticColorProps) => {
const themedStyles = getThemedStyles(useTheme());
return (
<View style={styles.swatchItem}>
<View style={[getSwatchColorStyle(p.color), themedStyles.swatch]} />
<Text>{p.name}</Text>
</View>
);
};
const SwatchList: React.FunctionComponent = () => {
const hostSettings = getHostSettingsWin32(useTheme());
const themedStyles = getThemedStyles(useTheme());
if (hostSettings === undefined) return <Text>Error</Text>;
const aggregator = React.useCallback(
(key: string) => {
return { name: key + ' (' + hostSettings.palette[key] + ')', color: hostSettings.palette[key] };
},
[hostSettings.palette]
);
const flattenArray = React.useCallback(() => {
return Object.keys(hostSettings.palette).sort().map(aggregator);
}, [hostSettings.palette, aggregator]);
const paletteAsArray = React.useMemo(flattenArray, [flattenArray]);
const renderSwatch = React.useCallback(({ item }) => {
const { color, name } = item;
return <SemanticColor key={name} color={color} name={name} />;
}, []);
return (
<View style={[commonTestStyles.view]}>
<Text style={themedStyles.largeStandard}>getHostSettingsWin32(theme: ITheme).palette</Text>
<View style={themedStyles.stackStyle}>
<FlatList data={paletteAsArray} renderItem={renderSwatch} />
</View>
</View>
);
};
const ThemeTestInner: React.FunctionComponent = () => {
const themedStyles = getThemedStyles(useTheme());
const onAppChange = React.useCallback((app: string) => {
brand = app;
// Invalidate the DAG children of the shimmed brand colors
customRegistry.setTheme(fakeBrandTheme, 'Default');
customRegistry.setTheme(fakeBrandTheme, 'WhiteColors', 'RealWhiteColors');
}, []);
const [theme, setTheme] = React.useState('Default');
return (
<View>
<Text style={themedStyles.extraLargeStandardEmphasis}>Configure Theme</Text>
<Separator />
<View style={styles.pickerContainer}>
<RadioGroup label="Pick App Colors" onChange={onAppChange} defaultSelectedKey="Office">
<RadioButton buttonKey="Office" content="Office" />
{Object.keys(brandColors).map((app: string) => (
<RadioButton key={app} buttonKey={app} content={app} />
))}
</RadioGroup>
<Separator vertical />
<RadioGroup label="Pick Theme" onChange={setTheme} defaultSelectedKey="Default">
<RadioButton buttonKey="Default" content="Default (GrayB / TaskPane)" />
<RadioButton buttonKey="Caterpillar" content="Caterpillar (Custom JS Theme)" />
<RadioButton buttonKey="WhiteColors" content="WhiteColors (Platform Theme)" />
</RadioGroup>
</View>
<Text style={themedStyles.extraLargeStandardEmphasis}>{theme + ' Theme'}</Text>
<Separator />
<ThemeProvider theme={theme}>
<Panel />
</ThemeProvider>
<Text style={themedStyles.extraLargeStandardEmphasis}>Host-specific Theme Settings</Text>
<Separator />
<SwatchList />
</View>
);
};
export const ThemeTest: React.FunctionComponent = () => {
return (
<ThemeProvider theme="Default">
<ThemeTestInner />
</ThemeProvider>
);
};
import * as React from 'react';
import { FlatList, View, ViewStyle, TextStyle, StyleSheet } from 'react-native';
import { getHostSettingsWin32, ThemeProvider, useTheme, IThemeDefinition, ThemingModuleHelper } from '@uifabricshared/theming-react-native';
import { themedStyleSheet } from '@uifabricshared/themed-stylesheet';
import { commonTestStyles } from '../Common/styles';
import { Button, PrimaryButton, Separator, StealthButton, Text, RadioGroup, RadioButton } from '@fluentui/react-native';
import { ITheme, IPartialTheme } from '@uifabricshared/theming-ramp';
import { customRegistry } from './CustomThemes';
let brand = 'Office';
const brandColors = {
Word: ['#E3ECFA', '#A5B9D1', '#7DA3C6', '#4A78B0', '#3C65A4', '#2B579A', '#124078', '#002050'],
Excel: ['#E9F5EE', '#9FCDB3', '#6EB38A', '#4E9668', '#3F8159', '#217346', '#0E5C2F', '#004B1C'],
Powerpoint: ['#FCF0ED', '#FDC9B5', '#ED9583', '#E86E58', '#C75033', '#B7472A', '#A92B1A', '#740912'],
Outlook: ['#CCE3F5', '#B3D6F2', '#69AFE5', '#2488D8', '#0078D7', '#106EBE', '#1664A7', '#135995']
};
// This IProcessTheme takes the parent theme and shims in the brand colors selected in the RadioGroup
const fakeBrandTheme: IThemeDefinition = (theme: ITheme): IPartialTheme => {
if (brand === 'Office') {
return {};
}
const brandValues = theme.colors.brand.values;
const brandedTheme = { colors: {}, host: { palette: {} } };
Object.keys(theme.colors).forEach((value: string) => {
if (typeof theme.colors[value] === 'string') {
const index = brandValues.indexOf(theme.colors[value].toString());
if (index !== -1) brandedTheme.colors[value] = brandColors[brand][index];
}
});
const hostThemeSettings = getHostSettingsWin32(theme);
if (hostThemeSettings === undefined) return brandedTheme;
Object.keys(hostThemeSettings.palette).forEach((value: string) => {
const index = brandValues.indexOf(hostThemeSettings.palette[value].toString());
if (index !== -1) brandedTheme.host.palette[value] = brandColors[brand][index];
});
return brandedTheme;
};
// this applies the shim to the default theme
customRegistry.setTheme(fakeBrandTheme, 'Default');
// this registers platform white colors
customRegistry.setTheme(ThemingModuleHelper.getPlatformThemeDefinition('WhiteColors'), 'RealWhiteColors');
// this applies the shim to the white colors theme
customRegistry.setTheme(fakeBrandTheme, 'WhiteColors', 'RealWhiteColors');
const getThemedStyles = themedStyleSheet((theme: ITheme) => {
const hostSettings = getHostSettingsWin32(theme);
return {
swatch: {
width: 80,
height: 20,
marginRight: 5,
borderWidth: 2,
borderColor: theme.colors.bodyText
},
extraLargeStandardEmphasis: {
color: hostSettings ? hostSettings.palette.TextEmphasis : theme.colors.bodyText,
fontSize: theme.typography.sizes.header,
fontWeight: theme.typography.weights.regular,
fontFamily: theme.typography.families.primary
} as TextStyle,
largeStandard: {
color: theme.colors.bodyText,
fontSize: theme.typography.sizes.body,
fontWeight: theme.typography.weights.regular,
fontFamily: theme.typography.families.primary,
marginBottom: 5
} as TextStyle,
stackStyle: {
borderWidth: 2,
borderColor: theme.colors.focusBorder,
padding: 12,
margin: 8,
backgroundColor: theme.colors.background
}
};
});
const styles = StyleSheet.create({
swatchItem: {
flexDirection: 'row',
alignItems: 'center',
marginVertical: 5
},
pickerContainer: {
flexDirection: 'row',
justifyContent: 'space-evenly'
}
});
const Panel: React.FunctionComponent = () => {
const [disabled, setDisabled] = React.useState(false);
const onClick = React.useCallback(() => setDisabled(!disabled), [disabled, setDisabled]);
const themedStyles = getThemedStyles(useTheme());
return (
<View style={[commonTestStyles.view, themedStyles.stackStyle]}>
<PrimaryButton onClick={onClick} content="Primary Button" disabled={disabled} />
<Button onClick={onClick} content="Default Button" disabled={disabled} />
<StealthButton onClick={onClick} content="Stealth Button" disabled={disabled} />
<Text>This is a text element</Text>
<Button onClick={onClick} content="This button has longer text" disabled={disabled} />
</View>
);
};
const getSwatchColorStyle = (color: string): ViewStyle => {
styles[color] = styles[color] || { backgroundColor: color };
return styles[color];
};
type SemanticColorProps = { color: string; name: string };
const SemanticColor: React.FunctionComponent<SemanticColorProps> = (p: SemanticColorProps) => {
const themedStyles = getThemedStyles(useTheme());
return (
<View style={styles.swatchItem}>
<View style={[getSwatchColorStyle(p.color), themedStyles.swatch]} />
<Text>{p.name}</Text>
</View>
);
};
const SwatchList: React.FunctionComponent = () => {
const hostSettings = getHostSettingsWin32(useTheme());
const themedStyles = getThemedStyles(useTheme());
if (hostSettings === undefined) return <Text>Error</Text>;
const aggregator = React.useCallback(
(key: string) => {
return { name: key + ' (' + hostSettings.palette[key] + ')', color: hostSettings.palette[key] };
},
[hostSettings.palette]
);
const flattenArray = React.useCallback(() => {
return Object.keys(hostSettings.palette)
.sort()
.map(aggregator);
}, [hostSettings.palette, aggregator]);
const paletteAsArray = React.useMemo(flattenArray, [flattenArray]);
const renderSwatch = React.useCallback(({ item }) => {
const { color, name } = item;
return <SemanticColor key={name} color={color} name={name} />;
}, []);
return (
<View style={[commonTestStyles.view]}>
<Text style={themedStyles.largeStandard}>getHostSettingsWin32(theme: ITheme).palette</Text>
<View style={themedStyles.stackStyle}>
<FlatList data={paletteAsArray} renderItem={renderSwatch} />
</View>
</View>
);
};
const ThemeTestInner: React.FunctionComponent = () => {
const themedStyles = getThemedStyles(useTheme());
const onAppChange = React.useCallback((app: string) => {
brand = app;
// Invalidate the DAG children of the shimmed brand colors
customRegistry.setTheme(fakeBrandTheme, 'Default');
customRegistry.setTheme(fakeBrandTheme, 'WhiteColors', 'RealWhiteColors');
}, []);
const [theme, setTheme] = React.useState('Default');
return (
<View>
<Text style={themedStyles.extraLargeStandardEmphasis}>Configure Theme</Text>
<Separator />
<View style={styles.pickerContainer}>
<RadioGroup label="Pick App Colors" onChange={onAppChange} defaultSelectedKey="Office">
<RadioButton buttonKey="Office" content="Office" />
{Object.keys(brandColors).map((app: string) => (
<RadioButton key={app} buttonKey={app} content={app} />
))}
</RadioGroup>
<Separator vertical />
<RadioGroup label="Pick Theme" onChange={setTheme} defaultSelectedKey="Default">
<RadioButton buttonKey="Default" content="Default (GrayB / TaskPane)" />
<RadioButton buttonKey="Caterpillar" content="Caterpillar (Custom JS Theme)" />
<RadioButton buttonKey="WhiteColors" content="WhiteColors (Platform Theme)" />
</RadioGroup>
</View>
<Text style={themedStyles.extraLargeStandardEmphasis}>{theme + ' Theme'}</Text>
<Separator />
<ThemeProvider theme={theme}>
<Panel />
</ThemeProvider>
<Text style={themedStyles.extraLargeStandardEmphasis}>Host-specific Theme Settings</Text>
<Separator />
<SwatchList />
</View>
);
};
export const ThemeTest: React.FunctionComponent = () => {
return (
<ThemeProvider theme="Default">
<ThemeTestInner />
</ThemeProvider>
);
};

Просмотреть файл

@ -1,74 +1,74 @@
import * as React from 'react';
import { ButtonFocusTest } from './Button';
import { CalloutTest } from './Callout';
import { CheckboxTest } from './Checkbox';
import { FocusTrapTest } from './FocusTrapZone';
import { LinkTest } from './Link';
import { PersonaTest } from './Persona';
import { PersonaCoinTest } from './PersonaCoin';
import { PressableTest } from './Pressable';
import { RadioGroupTest } from './RadioGroup';
import { SeparatorTest } from './Separator';
import { SvgTest } from './Svg';
import { TextTest } from './Text';
import { ThemeTest } from './Theme';
export type TestDescription = {
name: string;
component: React.FunctionComponent<{}>;
};
export const allTestComponents: TestDescription[] = [
{
name: 'Button Test',
component: ButtonFocusTest
},
{
name: 'Callout Test',
component: CalloutTest
},
{
name: 'Focus Trap Zone Test',
component: FocusTrapTest
},
{
name: 'Pressable Test',
component: PressableTest
},
{
name: 'Link Test',
component: LinkTest
},
{
name: 'Separator Test',
component: SeparatorTest
},
{
name: 'Text Test',
component: TextTest
},
{
name: 'Theme Test',
component: ThemeTest
},
{
name: 'PersonaCoin Test',
component: PersonaCoinTest
},
{
name: 'RadioGroup Test',
component: RadioGroupTest
},
{
name: 'Persona Test',
component: PersonaTest
},
{
name: 'Checkbox Test',
component: CheckboxTest
},
{
name: 'Svg Test',
component: SvgTest
}
];
import * as React from 'react';
import { ButtonFocusTest } from './Button';
import { CalloutTest } from './Callout';
import { CheckboxTest } from './Checkbox';
import { FocusTrapTest } from './FocusTrapZone';
import { LinkTest } from './Link';
import { PersonaTest } from './Persona';
import { PersonaCoinTest } from './PersonaCoin';
import { PressableTest } from './Pressable';
import { RadioGroupTest } from './RadioGroup';
import { SeparatorTest } from './Separator';
import { SvgTest } from './Svg';
import { TextTest } from './Text';
import { ThemeTest } from './Theme';
export type TestDescription = {
name: string;
component: React.FunctionComponent<{}>;
};
export const allTestComponents: TestDescription[] = [
{
name: 'Button Test',
component: ButtonFocusTest
},
{
name: 'Callout Test',
component: CalloutTest
},
{
name: 'Focus Trap Zone Test',
component: FocusTrapTest
},
{
name: 'Pressable Test',
component: PressableTest
},
{
name: 'Link Test',
component: LinkTest
},
{
name: 'Separator Test',
component: SeparatorTest
},
{
name: 'Text Test',
component: TextTest
},
{
name: 'Theme Test',
component: ThemeTest
},
{
name: 'PersonaCoin Test',
component: PersonaCoinTest
},
{
name: 'RadioGroup Test',
component: RadioGroupTest
},
{
name: 'Persona Test',
component: PersonaTest
},
{
name: 'Checkbox Test',
component: CheckboxTest
},
{
name: 'Svg Test',
component: SvgTest
}
];

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@fluentui/react-native",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:23.897Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@fluentui-react-native/adapters",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:24.990Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@fluentui-react-native/build-tools",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:26.061Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@fluentui-react-native/button",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:04.618Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@fluentui-react-native/callout",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:06.521Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@fluentui-react-native/checkbox",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:07.762Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@fluentui-react-native/focus-trap-zone",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:08.906Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@fluentui-react-native/link",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:10.072Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@fluentui-react-native/persona",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:11.164Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@fluentui-react-native/persona-coin",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:12.343Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@fluentui-react-native/pressable",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:13.471Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@fluentui-react-native/radio-group",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:14.685Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@fluentui-react-native/separator",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:15.929Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@fluentui-react-native/text",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:17.203Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@fluentui-react-native/tokens",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:27.125Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@uifabricshared/foundation-compose",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:18.346Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@uifabricshared/themed-stylesheet",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:19.672Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@uifabricshared/theming-ramp",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:21.671Z"
}

Просмотреть файл

@ -0,0 +1,8 @@
{
"type": "patch",
"comment": "renormalize files",
"packageName": "@uifabricshared/theming-react-native",
"email": "jasonmo@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-04-24T07:22:22.676Z"
}

Просмотреть файл

@ -1,48 +1,48 @@
import { linkName, ILinkType } from './Link.types';
import { IComposeSettings } from '@uifabricshared/foundation-compose';
// import { IViewWin32Props } from '@office-iss/react-native-win32';
import { IViewProps } from '@fluentui-react-native/adapters';
export const settings: IComposeSettings<ILinkType> = [
{
tokens: {
variant: 'secondaryStandard',
color: 'link'
},
root: {
style: {
margin: 0,
textDecorationLine: 'underline'
} as IViewProps['style']
},
content: {
style: {
textDecorationLine: 'underline'
}
},
_precedence: ['visited', 'hovered', 'pressed', 'disabled'],
_overrides: {
disabled: {
tokens: {
color: 'link'
}
},
hovered: {
tokens: {
color: 'linkHovered'
}
},
pressed: {
tokens: {
color: 'linkPressed'
}
},
visited: {
tokens: {
color: 'link'
}
}
}
},
linkName
];
import { linkName, ILinkType } from './Link.types';
import { IComposeSettings } from '@uifabricshared/foundation-compose';
// import { IViewWin32Props } from '@office-iss/react-native-win32';
import { IViewProps } from '@fluentui-react-native/adapters';
export const settings: IComposeSettings<ILinkType> = [
{
tokens: {
variant: 'secondaryStandard',
color: 'link'
},
root: {
style: {
margin: 0,
textDecorationLine: 'underline'
} as IViewProps['style']
},
content: {
style: {
textDecorationLine: 'underline'
}
},
_precedence: ['visited', 'hovered', 'pressed', 'disabled'],
_overrides: {
disabled: {
tokens: {
color: 'link'
}
},
hovered: {
tokens: {
color: 'linkHovered'
}
},
pressed: {
tokens: {
color: 'linkPressed'
}
},
visited: {
tokens: {
color: 'link'
}
}
}
},
linkName
];

Просмотреть файл

@ -1,86 +1,86 @@
import { PersonaSize } from '@fluentui-react-native/persona-coin';
import { ITextTokens } from '@fluentui-react-native/tokens';
type IPersonaFontTable = {
[key in PersonaSize]: ITextTokens;
};
const textFontTable: IPersonaFontTable = {
size8: { fontSize: 'caption' },
size24: { fontSize: 'secondary' },
size32: { fontSize: 'secondary' },
size40: { fontSize: 'secondary' },
size48: { fontSize: 'secondary' },
size56: { fontSize: 'subheader' },
size72: { fontSize: 'subheader' },
size100: { fontSize: 'subheader' },
size120: { fontSize: 'subheader' }
};
const secondaryFontTable: IPersonaFontTable = {
size8: { fontSize: 0 },
size24: { fontSize: 0 },
size32: { fontSize: 0 },
size40: { fontSize: 'caption' },
size48: { fontSize: 'caption' },
size56: { fontSize: 'secondary' },
size72: { fontSize: 'secondary' },
size100: { fontSize: 'secondary' },
size120: { fontSize: 'secondary' }
};
const tertiaryFontTable: IPersonaFontTable = {
size8: { fontSize: 0 },
size24: { fontSize: 0 },
size32: { fontSize: 0 },
size40: { fontSize: 0 },
size48: { fontSize: 0 },
size56: { fontSize: 0 },
size72: { fontSize: 'secondary' },
size100: { fontSize: 'secondary' },
size120: { fontSize: 'secondary' }
};
const optionalFontTable: IPersonaFontTable = {
size8: { fontSize: 0 },
size24: { fontSize: 0 },
size32: { fontSize: 0 },
size40: { fontSize: 0 },
size48: { fontSize: 0 },
size56: { fontSize: 0 },
size72: { fontSize: 0 },
size100: { fontSize: 'secondary' },
size120: { fontSize: 'secondary' }
};
export function getTextFont(size: PersonaSize): ITextTokens {
return textFontTable[size];
}
export function getSecondaryFont(size: PersonaSize): ITextTokens {
return secondaryFontTable[size];
}
export function getTertiaryFont(size: PersonaSize): ITextTokens {
return tertiaryFontTable[size];
}
export function getOptionalFont(size: PersonaSize): ITextTokens {
return optionalFontTable[size];
}
const horizontalGapTable: { [P in PersonaSize]: number } = {
size8: 17,
size24: 8,
size32: 8,
size40: 12,
size48: 12,
size56: 16,
size72: 16,
size100: 16,
size120: 16
};
export function getHorizontalGap(size: PersonaSize | undefined): number {
return horizontalGapTable[size || 'size40'];
}
import { PersonaSize } from '@fluentui-react-native/persona-coin';
import { ITextTokens } from '@fluentui-react-native/tokens';
type IPersonaFontTable = {
[key in PersonaSize]: ITextTokens;
};
const textFontTable: IPersonaFontTable = {
size8: { fontSize: 'caption' },
size24: { fontSize: 'secondary' },
size32: { fontSize: 'secondary' },
size40: { fontSize: 'secondary' },
size48: { fontSize: 'secondary' },
size56: { fontSize: 'subheader' },
size72: { fontSize: 'subheader' },
size100: { fontSize: 'subheader' },
size120: { fontSize: 'subheader' }
};
const secondaryFontTable: IPersonaFontTable = {
size8: { fontSize: 0 },
size24: { fontSize: 0 },
size32: { fontSize: 0 },
size40: { fontSize: 'caption' },
size48: { fontSize: 'caption' },
size56: { fontSize: 'secondary' },
size72: { fontSize: 'secondary' },
size100: { fontSize: 'secondary' },
size120: { fontSize: 'secondary' }
};
const tertiaryFontTable: IPersonaFontTable = {
size8: { fontSize: 0 },
size24: { fontSize: 0 },
size32: { fontSize: 0 },
size40: { fontSize: 0 },
size48: { fontSize: 0 },
size56: { fontSize: 0 },
size72: { fontSize: 'secondary' },
size100: { fontSize: 'secondary' },
size120: { fontSize: 'secondary' }
};
const optionalFontTable: IPersonaFontTable = {
size8: { fontSize: 0 },
size24: { fontSize: 0 },
size32: { fontSize: 0 },
size40: { fontSize: 0 },
size48: { fontSize: 0 },
size56: { fontSize: 0 },
size72: { fontSize: 0 },
size100: { fontSize: 'secondary' },
size120: { fontSize: 'secondary' }
};
export function getTextFont(size: PersonaSize): ITextTokens {
return textFontTable[size];
}
export function getSecondaryFont(size: PersonaSize): ITextTokens {
return secondaryFontTable[size];
}
export function getTertiaryFont(size: PersonaSize): ITextTokens {
return tertiaryFontTable[size];
}
export function getOptionalFont(size: PersonaSize): ITextTokens {
return optionalFontTable[size];
}
const horizontalGapTable: { [P in PersonaSize]: number } = {
size8: 17,
size24: 8,
size32: 8,
size40: 12,
size48: 12,
size56: 16,
size72: 16,
size100: 16,
size120: 16
};
export function getHorizontalGap(size: PersonaSize | undefined): number {
return horizontalGapTable[size || 'size40'];
}

Просмотреть файл

@ -1,26 +1,26 @@
import { textName, ITextType } from './Text.types';
import { TextStyle } from 'react-native';
import { IComposeSettings } from '@uifabricshared/foundation-compose';
export const settings: IComposeSettings<ITextType> = [
{
tokens: {
variant: 'secondaryStandard',
color: 'bodyText'
},
root: {
style: {
margin: 0
} as TextStyle
},
_overrides: {
disabled: {
tokens: {
color: 'disabledText'
}
}
},
_precedence: ['disabled']
},
textName
];
import { textName, ITextType } from './Text.types';
import { TextStyle } from 'react-native';
import { IComposeSettings } from '@uifabricshared/foundation-compose';
export const settings: IComposeSettings<ITextType> = [
{
tokens: {
variant: 'secondaryStandard',
color: 'bodyText'
},
root: {
style: {
margin: 0
} as TextStyle
},
_overrides: {
disabled: {
tokens: {
color: 'disabledText'
}
}
},
_precedence: ['disabled']
},
textName
];

Просмотреть файл

@ -1,21 +1,21 @@
import { ITextTokens, ITextVariantTokens, IForegroundColorTokens, IColorTokens } from '@fluentui-react-native/tokens';
import { ITextProps as INativeTextProps } from '@fluentui-react-native/adapters';
export const textName = 'RNFText';
/**
* Properties for fabric native text field, these extend the default props for text
*/
export type ITextProps<TBase = INativeTextProps> = TBase &
ITextVariantTokens &
IForegroundColorTokens & {
disabled?: boolean;
};
export type ITextType<TBase = INativeTextProps> = {
props: ITextProps<TBase>;
tokens: ITextTokens & IColorTokens;
slotProps: {
root: TBase;
};
};
import { ITextTokens, ITextVariantTokens, IForegroundColorTokens, IColorTokens } from '@fluentui-react-native/tokens';
import { ITextProps as INativeTextProps } from '@fluentui-react-native/adapters';
export const textName = 'RNFText';
/**
* Properties for fabric native text field, these extend the default props for text
*/
export type ITextProps<TBase = INativeTextProps> = TBase &
ITextVariantTokens &
IForegroundColorTokens & {
disabled?: boolean;
};
export type ITextType<TBase = INativeTextProps> = {
props: ITextProps<TBase>;
tokens: ITextTokens & IColorTokens;
slotProps: {
root: TBase;
};
};

Просмотреть файл

@ -1,31 +1,31 @@
import * as React from 'react';
import { Text } from '..';
import * as renderer from 'react-test-renderer';
it('Text default', () => {
const tree = renderer.create(<Text>Text default</Text>).toJSON();
expect(tree).toMatchSnapshot();
});
it('Text all props', () => {
const tree = renderer
.create(
<Text disabled variant="bodyStandard">
All props
</Text>
)
.toJSON();
expect(tree).toMatchSnapshot();
});
it('Text all tokens', () => {
const BoldText = Text.customize({
tokens: {
fontFamily: 'Wingdings',
fontWeight: '900',
fontSize: 15
}
});
const tree = renderer.create(<BoldText>All tokens</BoldText>).toJSON();
expect(tree).toMatchSnapshot();
});
import * as React from 'react';
import { Text } from '..';
import * as renderer from 'react-test-renderer';
it('Text default', () => {
const tree = renderer.create(<Text>Text default</Text>).toJSON();
expect(tree).toMatchSnapshot();
});
it('Text all props', () => {
const tree = renderer
.create(
<Text disabled variant="bodyStandard">
All props
</Text>
)
.toJSON();
expect(tree).toMatchSnapshot();
});
it('Text all tokens', () => {
const BoldText = Text.customize({
tokens: {
fontFamily: 'Wingdings',
fontWeight: '900',
fontSize: 15
}
});
const tree = renderer.create(<BoldText>All tokens</BoldText>).toJSON();
expect(tree).toMatchSnapshot();
});

Просмотреть файл

@ -1,49 +1,49 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Text all props 1`] = `
<Text
style={
Object {
"color": "#a19f9d",
"fontFamily": "Segoe UI",
"fontSize": 11,
"fontWeight": "400",
"margin": 0,
}
}
>
All props
</Text>
`;
exports[`Text all tokens 1`] = `
<Text
style={
Object {
"color": "#323130",
"fontFamily": "Wingdings",
"fontSize": 15,
"fontWeight": "900",
"margin": 0,
}
}
>
All tokens
</Text>
`;
exports[`Text default 1`] = `
<Text
style={
Object {
"color": "#323130",
"fontFamily": "Segoe UI",
"fontSize": 9,
"fontWeight": "400",
"margin": 0,
}
}
>
Text default
</Text>
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Text all props 1`] = `
<Text
style={
Object {
"color": "#a19f9d",
"fontFamily": "Segoe UI",
"fontSize": 11,
"fontWeight": "400",
"margin": 0,
}
}
>
All props
</Text>
`;
exports[`Text all tokens 1`] = `
<Text
style={
Object {
"color": "#323130",
"fontFamily": "Wingdings",
"fontSize": 15,
"fontWeight": "900",
"margin": 0,
}
}
>
All tokens
</Text>
`;
exports[`Text default 1`] = `
<Text
style={
Object {
"color": "#323130",
"fontFamily": "Segoe UI",
"fontSize": 9,
"fontWeight": "400",
"margin": 0,
}
}
>
Text default
</Text>
`;

Просмотреть файл

@ -1,381 +1,381 @@
## API Report File for "@uifabricshared/theming-ramp"
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
import { IComponentSettings } from '@uifabricshared/foundation-settings';
import { IComponentSettingsCollection } from '@uifabricshared/foundation-settings';
// @public
export type Color = keyof IPalette | ColorValue;
// @public
export type ColorValue = string;
// @public
export type FontFamily = keyof IFontFamilies | FontFamilyValue;
// @public
export type FontFamilyValue = string;
// @public
export type FontSize = keyof IFontSizes | FontSizeValuePoints;
// @public
export type FontSizeValuePoints = number;
// @public
export type FontWeight = keyof IFontWeights | FontWeightValue;
// @public
export type FontWeightValue = '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
// @public (undocumented)
export function getSettings(theme: ITheme, name: string): IComponentSettings;
// @public (undocumented)
export function getStockWebPalette(): IThemeColorDefinition;
// @public (undocumented)
export interface ICastableToString {
// (undocumented)
toString: () => string;
}
// @public (undocumented)
export interface IColorRamp extends ICastableToString {
// (undocumented)
index: number;
// (undocumented)
values: string[];
}
// @public (undocumented)
export interface IFabricWebPalette {
// (undocumented)
accent: ColorValue;
// (undocumented)
black: ColorValue;
// (undocumented)
blackTranslucent40: ColorValue;
// (undocumented)
neutralDark: ColorValue;
// (undocumented)
neutralLight: ColorValue;
// (undocumented)
neutralLighter: ColorValue;
// (undocumented)
neutralLighterAlt: ColorValue;
// (undocumented)
neutralPrimary: ColorValue;
// (undocumented)
neutralPrimaryAlt: ColorValue;
// (undocumented)
neutralQuaternary: ColorValue;
// (undocumented)
neutralQuaternaryAlt: ColorValue;
// (undocumented)
neutralSecondary: ColorValue;
// (undocumented)
neutralSecondaryAlt: ColorValue;
// (undocumented)
neutralTertiary: ColorValue;
// (undocumented)
neutralTertiaryAlt: ColorValue;
// (undocumented)
red: ColorValue;
// (undocumented)
redDark: ColorValue;
// (undocumented)
themeDark: ColorValue;
// (undocumented)
themeDarkAlt: ColorValue;
// (undocumented)
themeDarker: ColorValue;
// (undocumented)
themeLight: ColorValue;
// (undocumented)
themeLighter: ColorValue;
// (undocumented)
themeLighterAlt: ColorValue;
// (undocumented)
themePrimary: ColorValue;
// (undocumented)
themeSecondary: ColorValue;
// (undocumented)
themeTertiary: ColorValue;
// (undocumented)
white: ColorValue;
}
// @public
export interface IFontFamilies {
// (undocumented)
cursive: FontFamilyValue;
// (undocumented)
monospace: FontFamilyValue;
// (undocumented)
primary: FontFamilyValue;
// (undocumented)
sansSerif: FontFamilyValue;
// (undocumented)
secondary: FontFamilyValue;
// (undocumented)
serif: FontFamilyValue;
}
// @public
export interface IFontSizes {
// (undocumented)
body: FontSizeValuePoints;
// (undocumented)
caption: FontSizeValuePoints;
// (undocumented)
header: FontSizeValuePoints;
// (undocumented)
hero: FontSizeValuePoints;
// (undocumented)
heroLarge: FontSizeValuePoints;
// (undocumented)
secondary: FontSizeValuePoints;
// (undocumented)
subheader: FontSizeValuePoints;
}
// @public
export interface IFontWeights {
// (undocumented)
regular: FontWeightValue;
// (undocumented)
semiBold: FontWeightValue;
}
// @public
export type IPalette = IPaletteTextColors & IPaletteBackgroundColors;
// @public
export interface IPaletteBackgroundColors {
accentButtonBackground: ColorValue;
background: ColorValue;
blockingBackground: ColorValue;
bodyDivider: ColorValue;
bodyFrameBackground: ColorValue;
bodyFrameDivider: ColorValue;
bodyStandoutBackground: ColorValue;
buttonBackground: ColorValue;
buttonBackgroundChecked: ColorValue;
buttonBackgroundCheckedHovered: ColorValue;
buttonBackgroundDisabled: ColorValue;
buttonBackgroundHovered: ColorValue;
buttonBackgroundPressed: ColorValue;
buttonBorder: ColorValue;
buttonBorderDisabled: ColorValue;
buttonBorderFocused: ColorValue;
defaultStateBackground: ColorValue;
disabledBackground: ColorValue;
errorBackground: ColorValue;
focusBorder: ColorValue;
inputBackground: ColorValue;
inputBackgroundChecked: ColorValue;
inputBackgroundCheckedHovered: ColorValue;
inputBorder: ColorValue;
inputBorderHovered: ColorValue;
inputFocusBorderAlt: ColorValue;
inputForegroundChecked: ColorValue;
listBackground: ColorValue;
listHeaderBackgroundHovered: ColorValue;
listHeaderBackgroundPressed: ColorValue;
listItemBackgroundChecked: ColorValue;
listItemBackgroundCheckedHovered: ColorValue;
listItemBackgroundHovered: ColorValue;
listText: ColorValue;
menuBackground: ColorValue;
menuDivider: ColorValue;
menuHeader: ColorValue;
menuIcon: ColorValue;
menuItemBackgroundHovered: ColorValue;
menuItemBackgroundPressed: ColorValue;
menuItemText: ColorValue;
menuItemTextHovered: ColorValue;
primaryButtonBackground: ColorValue;
primaryButtonBackgroundDisabled: ColorValue;
primaryButtonBackgroundHovered: ColorValue;
primaryButtonBackgroundPressed: ColorValue;
primaryButtonBorder: ColorValue;
primaryButtonBorderFocused: ColorValue;
smallInputBorder: ColorValue;
successBackground: ColorValue;
variantBorder: ColorValue;
variantBorderHovered: ColorValue;
warningBackground: ColorValue;
warningHighlight: ColorValue;
}
// @public
export interface IPaletteTextColors {
accentButtonText: ColorValue;
actionLink: ColorValue;
actionLinkHovered: ColorValue;
bodyText: ColorValue;
bodyTextChecked: ColorValue;
buttonText: ColorValue;
buttonTextChecked: ColorValue;
buttonTextCheckedHovered: ColorValue;
buttonTextDisabled: ColorValue;
buttonTextHovered: ColorValue;
buttonTextPressed: ColorValue;
disabledBodySubtext: ColorValue;
disabledBodyText: ColorValue;
disabledSubtext: ColorValue;
disabledText: ColorValue;
errorText: ColorValue;
inputPlaceholderText: ColorValue;
inputText: ColorValue;
inputTextHovered: ColorValue;
link: ColorValue;
linkHovered: ColorValue;
linkPressed: ColorValue;
listText: ColorValue;
primaryButtonText: ColorValue;
primaryButtonTextDisabled: ColorValue;
primaryButtonTextHovered: ColorValue;
primaryButtonTextPressed: ColorValue;
subText: ColorValue;
warningText: ColorValue;
}
// @public
export type IPartialPalette = Partial<IPalette>;
// @public
export interface IPartialTheme {
// (undocumented)
colors?: Partial<IThemeColorDefinition>;
// (undocumented)
components?: IComponentSettingsCollection;
// (undocumented)
host?: object;
// (undocumented)
name?: string;
// (undocumented)
spacing?: ISpacing;
// (undocumented)
typography?: IPartialTypography;
}
// @public
export type IPartialTypography = {
[P in keyof ITypography]?: Partial<ITypography[P]>;
};
// @public (undocumented)
export interface ISpacing {
// (undocumented)
l1: string;
// (undocumented)
l2: string;
// (undocumented)
m: string;
// (undocumented)
s1: string;
// (undocumented)
s2: string;
}
// @public
export interface ITextStyle {
// (undocumented)
families: IFontFamilies;
// (undocumented)
sizes: IFontSizes;
// (undocumented)
variants: IVariants;
// (undocumented)
weights: IFontWeights;
}
// @public
export interface ITheme {
// (undocumented)
colors: IThemeColorDefinition;
// (undocumented)
components: IComponentSettingsCollection;
// (undocumented)
host: object;
// (undocumented)
name?: string;
// (undocumented)
spacing: ISpacing;
// (undocumented)
typography: ITypography;
}
// @public (undocumented)
export type IThemeColorDefinition = IPalette & {
background: ColorValue;
bodyText: ColorValue;
subText: ColorValue;
disabledText: ColorValue;
brand: IColorRamp;
neutral: IColorRamp;
warning: IColorRamp;
[key: string]: IColorRamp | string;
};
// @public (undocumented)
export type ITypography = ITextStyle;
// @public
export interface IVariants {
// (undocumented)
bodySemibold: VariantValue;
// (undocumented)
bodyStandard: VariantValue;
// (undocumented)
captionStandard: VariantValue;
// (undocumented)
headerSemibold: VariantValue;
// (undocumented)
headerStandard: VariantValue;
// (undocumented)
heroLargeSemibold: VariantValue;
// (undocumented)
heroLargeStandard: VariantValue;
// (undocumented)
heroSemibold: VariantValue;
// (undocumented)
heroStandard: VariantValue;
// (undocumented)
secondarySemibold: VariantValue;
// (undocumented)
secondaryStandard: VariantValue;
// (undocumented)
subheaderSemibold: VariantValue;
// (undocumented)
subheaderStandard: VariantValue;
}
// @public
export function paletteFromFabricColors(p: IFabricWebPalette, isInverted?: boolean): IPalette;
// @public
export function resolvePartialTheme(theme: ITheme, partialTheme?: IPartialTheme): ITheme;
// @public
export function returnAsSlotProps(target: IComponentSettings): IComponentSettings;
// @public
export type Variant = keyof IVariants | VariantValue;
// @public
export type VariantValue = {
face: FontFamily;
size: FontSize;
weight: FontWeight;
};
// (No @packageDocumentation comment for this package)
```
## API Report File for "@uifabricshared/theming-ramp"
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
import { IComponentSettings } from '@uifabricshared/foundation-settings';
import { IComponentSettingsCollection } from '@uifabricshared/foundation-settings';
// @public
export type Color = keyof IPalette | ColorValue;
// @public
export type ColorValue = string;
// @public
export type FontFamily = keyof IFontFamilies | FontFamilyValue;
// @public
export type FontFamilyValue = string;
// @public
export type FontSize = keyof IFontSizes | FontSizeValuePoints;
// @public
export type FontSizeValuePoints = number;
// @public
export type FontWeight = keyof IFontWeights | FontWeightValue;
// @public
export type FontWeightValue = '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
// @public (undocumented)
export function getSettings(theme: ITheme, name: string): IComponentSettings;
// @public (undocumented)
export function getStockWebPalette(): IThemeColorDefinition;
// @public (undocumented)
export interface ICastableToString {
// (undocumented)
toString: () => string;
}
// @public (undocumented)
export interface IColorRamp extends ICastableToString {
// (undocumented)
index: number;
// (undocumented)
values: string[];
}
// @public (undocumented)
export interface IFabricWebPalette {
// (undocumented)
accent: ColorValue;
// (undocumented)
black: ColorValue;
// (undocumented)
blackTranslucent40: ColorValue;
// (undocumented)
neutralDark: ColorValue;
// (undocumented)
neutralLight: ColorValue;
// (undocumented)
neutralLighter: ColorValue;
// (undocumented)
neutralLighterAlt: ColorValue;
// (undocumented)
neutralPrimary: ColorValue;
// (undocumented)
neutralPrimaryAlt: ColorValue;
// (undocumented)
neutralQuaternary: ColorValue;
// (undocumented)
neutralQuaternaryAlt: ColorValue;
// (undocumented)
neutralSecondary: ColorValue;
// (undocumented)
neutralSecondaryAlt: ColorValue;
// (undocumented)
neutralTertiary: ColorValue;
// (undocumented)
neutralTertiaryAlt: ColorValue;
// (undocumented)
red: ColorValue;
// (undocumented)
redDark: ColorValue;
// (undocumented)
themeDark: ColorValue;
// (undocumented)
themeDarkAlt: ColorValue;
// (undocumented)
themeDarker: ColorValue;
// (undocumented)
themeLight: ColorValue;
// (undocumented)
themeLighter: ColorValue;
// (undocumented)
themeLighterAlt: ColorValue;
// (undocumented)
themePrimary: ColorValue;
// (undocumented)
themeSecondary: ColorValue;
// (undocumented)
themeTertiary: ColorValue;
// (undocumented)
white: ColorValue;
}
// @public
export interface IFontFamilies {
// (undocumented)
cursive: FontFamilyValue;
// (undocumented)
monospace: FontFamilyValue;
// (undocumented)
primary: FontFamilyValue;
// (undocumented)
sansSerif: FontFamilyValue;
// (undocumented)
secondary: FontFamilyValue;
// (undocumented)
serif: FontFamilyValue;
}
// @public
export interface IFontSizes {
// (undocumented)
body: FontSizeValuePoints;
// (undocumented)
caption: FontSizeValuePoints;
// (undocumented)
header: FontSizeValuePoints;
// (undocumented)
hero: FontSizeValuePoints;
// (undocumented)
heroLarge: FontSizeValuePoints;
// (undocumented)
secondary: FontSizeValuePoints;
// (undocumented)
subheader: FontSizeValuePoints;
}
// @public
export interface IFontWeights {
// (undocumented)
regular: FontWeightValue;
// (undocumented)
semiBold: FontWeightValue;
}
// @public
export type IPalette = IPaletteTextColors & IPaletteBackgroundColors;
// @public
export interface IPaletteBackgroundColors {
accentButtonBackground: ColorValue;
background: ColorValue;
blockingBackground: ColorValue;
bodyDivider: ColorValue;
bodyFrameBackground: ColorValue;
bodyFrameDivider: ColorValue;
bodyStandoutBackground: ColorValue;
buttonBackground: ColorValue;
buttonBackgroundChecked: ColorValue;
buttonBackgroundCheckedHovered: ColorValue;
buttonBackgroundDisabled: ColorValue;
buttonBackgroundHovered: ColorValue;
buttonBackgroundPressed: ColorValue;
buttonBorder: ColorValue;
buttonBorderDisabled: ColorValue;
buttonBorderFocused: ColorValue;
defaultStateBackground: ColorValue;
disabledBackground: ColorValue;
errorBackground: ColorValue;
focusBorder: ColorValue;
inputBackground: ColorValue;
inputBackgroundChecked: ColorValue;
inputBackgroundCheckedHovered: ColorValue;
inputBorder: ColorValue;
inputBorderHovered: ColorValue;
inputFocusBorderAlt: ColorValue;
inputForegroundChecked: ColorValue;
listBackground: ColorValue;
listHeaderBackgroundHovered: ColorValue;
listHeaderBackgroundPressed: ColorValue;
listItemBackgroundChecked: ColorValue;
listItemBackgroundCheckedHovered: ColorValue;
listItemBackgroundHovered: ColorValue;
listText: ColorValue;
menuBackground: ColorValue;
menuDivider: ColorValue;
menuHeader: ColorValue;
menuIcon: ColorValue;
menuItemBackgroundHovered: ColorValue;
menuItemBackgroundPressed: ColorValue;
menuItemText: ColorValue;
menuItemTextHovered: ColorValue;
primaryButtonBackground: ColorValue;
primaryButtonBackgroundDisabled: ColorValue;
primaryButtonBackgroundHovered: ColorValue;
primaryButtonBackgroundPressed: ColorValue;
primaryButtonBorder: ColorValue;
primaryButtonBorderFocused: ColorValue;
smallInputBorder: ColorValue;
successBackground: ColorValue;
variantBorder: ColorValue;
variantBorderHovered: ColorValue;
warningBackground: ColorValue;
warningHighlight: ColorValue;
}
// @public
export interface IPaletteTextColors {
accentButtonText: ColorValue;
actionLink: ColorValue;
actionLinkHovered: ColorValue;
bodyText: ColorValue;
bodyTextChecked: ColorValue;
buttonText: ColorValue;
buttonTextChecked: ColorValue;
buttonTextCheckedHovered: ColorValue;
buttonTextDisabled: ColorValue;
buttonTextHovered: ColorValue;
buttonTextPressed: ColorValue;
disabledBodySubtext: ColorValue;
disabledBodyText: ColorValue;
disabledSubtext: ColorValue;
disabledText: ColorValue;
errorText: ColorValue;
inputPlaceholderText: ColorValue;
inputText: ColorValue;
inputTextHovered: ColorValue;
link: ColorValue;
linkHovered: ColorValue;
linkPressed: ColorValue;
listText: ColorValue;
primaryButtonText: ColorValue;
primaryButtonTextDisabled: ColorValue;
primaryButtonTextHovered: ColorValue;
primaryButtonTextPressed: ColorValue;
subText: ColorValue;
warningText: ColorValue;
}
// @public
export type IPartialPalette = Partial<IPalette>;
// @public
export interface IPartialTheme {
// (undocumented)
colors?: Partial<IThemeColorDefinition>;
// (undocumented)
components?: IComponentSettingsCollection;
// (undocumented)
host?: object;
// (undocumented)
name?: string;
// (undocumented)
spacing?: ISpacing;
// (undocumented)
typography?: IPartialTypography;
}
// @public
export type IPartialTypography = {
[P in keyof ITypography]?: Partial<ITypography[P]>;
};
// @public (undocumented)
export interface ISpacing {
// (undocumented)
l1: string;
// (undocumented)
l2: string;
// (undocumented)
m: string;
// (undocumented)
s1: string;
// (undocumented)
s2: string;
}
// @public
export interface ITextStyle {
// (undocumented)
families: IFontFamilies;
// (undocumented)
sizes: IFontSizes;
// (undocumented)
variants: IVariants;
// (undocumented)
weights: IFontWeights;
}
// @public
export interface ITheme {
// (undocumented)
colors: IThemeColorDefinition;
// (undocumented)
components: IComponentSettingsCollection;
// (undocumented)
host: object;
// (undocumented)
name?: string;
// (undocumented)
spacing: ISpacing;
// (undocumented)
typography: ITypography;
}
// @public (undocumented)
export type IThemeColorDefinition = IPalette & {
background: ColorValue;
bodyText: ColorValue;
subText: ColorValue;
disabledText: ColorValue;
brand: IColorRamp;
neutral: IColorRamp;
warning: IColorRamp;
[key: string]: IColorRamp | string;
};
// @public (undocumented)
export type ITypography = ITextStyle;
// @public
export interface IVariants {
// (undocumented)
bodySemibold: VariantValue;
// (undocumented)
bodyStandard: VariantValue;
// (undocumented)
captionStandard: VariantValue;
// (undocumented)
headerSemibold: VariantValue;
// (undocumented)
headerStandard: VariantValue;
// (undocumented)
heroLargeSemibold: VariantValue;
// (undocumented)
heroLargeStandard: VariantValue;
// (undocumented)
heroSemibold: VariantValue;
// (undocumented)
heroStandard: VariantValue;
// (undocumented)
secondarySemibold: VariantValue;
// (undocumented)
secondaryStandard: VariantValue;
// (undocumented)
subheaderSemibold: VariantValue;
// (undocumented)
subheaderStandard: VariantValue;
}
// @public
export function paletteFromFabricColors(p: IFabricWebPalette, isInverted?: boolean): IPalette;
// @public
export function resolvePartialTheme(theme: ITheme, partialTheme?: IPartialTheme): ITheme;
// @public
export function returnAsSlotProps(target: IComponentSettings): IComponentSettings;
// @public
export type Variant = keyof IVariants | VariantValue;
// @public
export type VariantValue = {
face: FontFamily;
size: FontSize;
weight: FontWeight;
};
// (No @packageDocumentation comment for this package)
```

Просмотреть файл

@ -1,110 +1,110 @@
import { ITheme, IPartialTheme } from './Theme.types';
import { resolvePartialTheme } from './Theme';
import { IThemeColorDefinition } from './Color.types';
import { ITypography } from './Typography.types';
const theme: ITheme = {
colors: {
background: '#ff0000'
} as IThemeColorDefinition,
typography: {
families: {
primary: 'Arial'
},
sizes: {
secondary: 14
},
weights: {
regular: '400'
},
variants: {
secondaryStandard: {
face: 'Arial',
size: 14,
weight: '400'
}
}
} as ITypography,
spacing: { s2: '4px', s1: '8px', m: '16px', l1: '20px', l2: '32px' },
components: {
View: {
tokens: {
backgroundColor: 'bodyBackground',
fontFamily: 'primary'
}
}
},
host: {}
};
const partialTheme: IPartialTheme = {
colors: {
bodySubtext: 'rgb(100,100,100)'
},
components: {
Text: {
tokens: {
backgroundColor: 'cyan'
}
}
}
};
describe('Theme tests', () => {
test("resolvePartialTheme reuses the theme's colors object when the partial theme is empty", () => {
const resolved = resolvePartialTheme(theme, {});
expect(resolved.colors).toBe(theme.colors);
});
test("resolvePartialTheme reuses the theme's typography object when the partial theme is empty", () => {
const resolved = resolvePartialTheme(theme, {});
expect(resolved.typography).toBe(theme.typography);
});
test("resolvePartialTheme reuses the theme's layer collection object when the partial theme is empty", () => {
const resolved = resolvePartialTheme(theme, {});
expect(resolved.components).toBe(theme.components);
});
test('resolvePartialTheme returns a blend of the partial theme and the full theme', () => {
const resolved = resolvePartialTheme(theme, partialTheme);
expect(resolved).toEqual({
colors: ({
background: '#ff0000',
bodySubtext: 'rgb(100,100,100)'
} as unknown) as IThemeColorDefinition,
typography: {
families: {
primary: 'Arial'
},
sizes: {
secondary: 14
},
weights: {
regular: '400'
},
variants: {
secondaryStandard: {
face: 'Arial',
size: 14,
weight: '400'
}
}
} as ITypography,
spacing: { s2: '4px', s1: '8px', m: '16px', l1: '20px', l2: '32px' },
components: {
View: {
tokens: {
backgroundColor: 'bodyBackground',
fontFamily: 'primary'
}
},
Text: {
tokens: {
backgroundColor: 'cyan'
}
}
}
});
});
});
import { ITheme, IPartialTheme } from './Theme.types';
import { resolvePartialTheme } from './Theme';
import { IThemeColorDefinition } from './Color.types';
import { ITypography } from './Typography.types';
const theme: ITheme = {
colors: {
background: '#ff0000'
} as IThemeColorDefinition,
typography: {
families: {
primary: 'Arial'
},
sizes: {
secondary: 14
},
weights: {
regular: '400'
},
variants: {
secondaryStandard: {
face: 'Arial',
size: 14,
weight: '400'
}
}
} as ITypography,
spacing: { s2: '4px', s1: '8px', m: '16px', l1: '20px', l2: '32px' },
components: {
View: {
tokens: {
backgroundColor: 'bodyBackground',
fontFamily: 'primary'
}
}
},
host: {}
};
const partialTheme: IPartialTheme = {
colors: {
bodySubtext: 'rgb(100,100,100)'
},
components: {
Text: {
tokens: {
backgroundColor: 'cyan'
}
}
}
};
describe('Theme tests', () => {
test("resolvePartialTheme reuses the theme's colors object when the partial theme is empty", () => {
const resolved = resolvePartialTheme(theme, {});
expect(resolved.colors).toBe(theme.colors);
});
test("resolvePartialTheme reuses the theme's typography object when the partial theme is empty", () => {
const resolved = resolvePartialTheme(theme, {});
expect(resolved.typography).toBe(theme.typography);
});
test("resolvePartialTheme reuses the theme's layer collection object when the partial theme is empty", () => {
const resolved = resolvePartialTheme(theme, {});
expect(resolved.components).toBe(theme.components);
});
test('resolvePartialTheme returns a blend of the partial theme and the full theme', () => {
const resolved = resolvePartialTheme(theme, partialTheme);
expect(resolved).toEqual({
colors: ({
background: '#ff0000',
bodySubtext: 'rgb(100,100,100)'
} as unknown) as IThemeColorDefinition,
typography: {
families: {
primary: 'Arial'
},
sizes: {
secondary: 14
},
weights: {
regular: '400'
},
variants: {
secondaryStandard: {
face: 'Arial',
size: 14,
weight: '400'
}
}
} as ITypography,
spacing: { s2: '4px', s1: '8px', m: '16px', l1: '20px', l2: '32px' },
components: {
View: {
tokens: {
backgroundColor: 'bodyBackground',
fontFamily: 'primary'
}
},
Text: {
tokens: {
backgroundColor: 'cyan'
}
}
}
});
});
});

Просмотреть файл

@ -1,68 +1,68 @@
import { IFontFamilies, IFontSizes, IFontWeights, IVariants, ITypography } from './Typography.types';
import { resolveFontFamily, resolveFontSize, resolveFontWeight } from './Typography';
const families = {
primary: 'Verdana',
monospace: 'Courier New'
} as IFontFamilies;
const sizes = {
caption: 8,
subheader: 16
} as IFontSizes;
const weights = {
regular: '500',
semiBold: '700'
} as IFontWeights;
const variants = {
captionStandard: {
face: 'Verdana',
size: 8,
weight: '500'
},
subheaderStandard: {
face: 'Verdana',
size: 16,
weight: '500'
},
subheaderSemibold: {
face: 'Verdana',
size: 16,
weight: '700'
}
} as IVariants;
const typography: ITypography = {
families,
sizes,
weights,
variants
};
describe('Typography tests', () => {
test('resolveFontFamily "monospace" returns "Courier New"', () => {
expect(resolveFontFamily(typography, 'monospace')).toBe('Courier New');
});
test('resolveFontFamily "Arial" returns "Arial"', () => {
expect(resolveFontFamily(typography, 'Arial')).toBe('Arial');
});
test('resolveFontSize "caption" returns 8', () => {
expect(resolveFontSize(typography, 'caption')).toBe(8);
});
test('resolveFontSize 15 returns 15', () => {
expect(resolveFontSize(typography, 15)).toBe(15);
});
test('resolveFontSize "semiBold" returns 700', () => {
expect(resolveFontWeight(typography, 'semiBold')).toBe('700');
});
test('resolveFontSize 200 returns 200', () => {
expect(resolveFontWeight(typography, '200')).toBe('200');
});
});
import { IFontFamilies, IFontSizes, IFontWeights, IVariants, ITypography } from './Typography.types';
import { resolveFontFamily, resolveFontSize, resolveFontWeight } from './Typography';
const families = {
primary: 'Verdana',
monospace: 'Courier New'
} as IFontFamilies;
const sizes = {
caption: 8,
subheader: 16
} as IFontSizes;
const weights = {
regular: '500',
semiBold: '700'
} as IFontWeights;
const variants = {
captionStandard: {
face: 'Verdana',
size: 8,
weight: '500'
},
subheaderStandard: {
face: 'Verdana',
size: 16,
weight: '500'
},
subheaderSemibold: {
face: 'Verdana',
size: 16,
weight: '700'
}
} as IVariants;
const typography: ITypography = {
families,
sizes,
weights,
variants
};
describe('Typography tests', () => {
test('resolveFontFamily "monospace" returns "Courier New"', () => {
expect(resolveFontFamily(typography, 'monospace')).toBe('Courier New');
});
test('resolveFontFamily "Arial" returns "Arial"', () => {
expect(resolveFontFamily(typography, 'Arial')).toBe('Arial');
});
test('resolveFontSize "caption" returns 8', () => {
expect(resolveFontSize(typography, 'caption')).toBe(8);
});
test('resolveFontSize 15 returns 15', () => {
expect(resolveFontSize(typography, 15)).toBe(15);
});
test('resolveFontSize "semiBold" returns 700', () => {
expect(resolveFontWeight(typography, 'semiBold')).toBe('700');
});
test('resolveFontSize 200 returns 200', () => {
expect(resolveFontWeight(typography, '200')).toBe('200');
});
});

Просмотреть файл

@ -1,146 +1,146 @@
/**
* A font family designation, made up of one or more font names or groupings
* (comma-separated):
*
* - `Calibri Light`, `Calibri, Times`
* - `Menlo, Monaco`, `Courier New`, `Courier`
* - `Consolas`
*
* The font family expresses an ordered preference of fonts to use, working
* from the first entry to the last. This "fallback" mechanism is necessary
* because the availability of specific fonts varies between native platforms,
* as well as between operating system versions.
*/
export type FontFamilyValue = string;
/**
* A collection of named font families.
*
* The names express the fundamental character of the assigned font family. They
* should be used when defining a theme.
*
* **NOTE:** `primary` and `secondary` are both meant to be assigned a 'normal' family.
*/
export interface IFontFamilies {
primary: FontFamilyValue;
secondary: FontFamilyValue;
cursive: FontFamilyValue;
monospace: FontFamilyValue;
sansSerif: FontFamilyValue;
serif: FontFamilyValue;
}
/**
* A font family, used when defining a visual element in a theme.
*/
export type FontFamily = keyof IFontFamilies | FontFamilyValue;
/**
* A font size value, specified in points (pt).
*/
export type FontSizeValuePoints = number;
/**
* A collection of named font sizes.
*
* The names express a spectrum of relative sizes. Words are used instead
* of numbers to avoid implying anything about the size value, or its
* relationship to size values near it.
*
* These names should be used when defining a theme.
*/
export interface IFontSizes {
caption: FontSizeValuePoints;
secondary: FontSizeValuePoints;
body: FontSizeValuePoints;
subheader: FontSizeValuePoints;
header: FontSizeValuePoints;
hero: FontSizeValuePoints;
heroLarge: FontSizeValuePoints;
}
/**
* A font size, used when defining a visual element in a theme.
*/
export type FontSize = keyof IFontSizes | FontSizeValuePoints;
/**
* A font weight value.
*
* Smaller numbers yield a thinner, lighter font. Larger numbers yield a thicker, farker
* font.
*/
export type FontWeightValue = '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
/**
* A collection of named font weights.
*
* The names express a spectrum of relative weights. Words are used instead
* of numbers to avoid implying anything about the weight value, or its
* relationship to weight values near it.
*
* These names should be used when defining a theme.
*/
export interface IFontWeights {
regular: FontWeightValue;
semiBold: FontWeightValue;
}
/**
* A font weight, used when defining a visual element in a theme.
*/
export type FontWeight = keyof IFontWeights | FontWeightValue;
/**
* A font variant value.
*/
export type VariantValue = {
face: FontFamily;
size: FontSize;
weight: FontWeight;
};
/**
* A collection of named font variants.
*/
export interface IVariants {
captionStandard: VariantValue;
secondaryStandard: VariantValue;
secondarySemibold: VariantValue;
bodyStandard: VariantValue;
bodySemibold: VariantValue;
subheaderStandard: VariantValue;
subheaderSemibold: VariantValue;
headerStandard: VariantValue;
headerSemibold: VariantValue;
heroStandard: VariantValue;
heroSemibold: VariantValue;
heroLargeStandard: VariantValue;
heroLargeSemibold: VariantValue;
}
/**
* A font variant, used when defining a visual element in a theme.
*/
export type Variant = keyof IVariants | VariantValue;
/**
* A collection of typographic (font) information.
*
* When setting a font in a theme, choose a family, size and weight from
* this collection.
*/
export interface ITextStyle {
families: IFontFamilies;
sizes: IFontSizes;
weights: IFontWeights;
variants: IVariants;
}
export type ITypography = ITextStyle;
/**
* A partially specified typography.
*/
export type IPartialTypography = { [P in keyof ITypography]?: Partial<ITypography[P]> };
/**
* A font family designation, made up of one or more font names or groupings
* (comma-separated):
*
* - `Calibri Light`, `Calibri, Times`
* - `Menlo, Monaco`, `Courier New`, `Courier`
* - `Consolas`
*
* The font family expresses an ordered preference of fonts to use, working
* from the first entry to the last. This "fallback" mechanism is necessary
* because the availability of specific fonts varies between native platforms,
* as well as between operating system versions.
*/
export type FontFamilyValue = string;
/**
* A collection of named font families.
*
* The names express the fundamental character of the assigned font family. They
* should be used when defining a theme.
*
* **NOTE:** `primary` and `secondary` are both meant to be assigned a 'normal' family.
*/
export interface IFontFamilies {
primary: FontFamilyValue;
secondary: FontFamilyValue;
cursive: FontFamilyValue;
monospace: FontFamilyValue;
sansSerif: FontFamilyValue;
serif: FontFamilyValue;
}
/**
* A font family, used when defining a visual element in a theme.
*/
export type FontFamily = keyof IFontFamilies | FontFamilyValue;
/**
* A font size value, specified in points (pt).
*/
export type FontSizeValuePoints = number;
/**
* A collection of named font sizes.
*
* The names express a spectrum of relative sizes. Words are used instead
* of numbers to avoid implying anything about the size value, or its
* relationship to size values near it.
*
* These names should be used when defining a theme.
*/
export interface IFontSizes {
caption: FontSizeValuePoints;
secondary: FontSizeValuePoints;
body: FontSizeValuePoints;
subheader: FontSizeValuePoints;
header: FontSizeValuePoints;
hero: FontSizeValuePoints;
heroLarge: FontSizeValuePoints;
}
/**
* A font size, used when defining a visual element in a theme.
*/
export type FontSize = keyof IFontSizes | FontSizeValuePoints;
/**
* A font weight value.
*
* Smaller numbers yield a thinner, lighter font. Larger numbers yield a thicker, farker
* font.
*/
export type FontWeightValue = '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900';
/**
* A collection of named font weights.
*
* The names express a spectrum of relative weights. Words are used instead
* of numbers to avoid implying anything about the weight value, or its
* relationship to weight values near it.
*
* These names should be used when defining a theme.
*/
export interface IFontWeights {
regular: FontWeightValue;
semiBold: FontWeightValue;
}
/**
* A font weight, used when defining a visual element in a theme.
*/
export type FontWeight = keyof IFontWeights | FontWeightValue;
/**
* A font variant value.
*/
export type VariantValue = {
face: FontFamily;
size: FontSize;
weight: FontWeight;
};
/**
* A collection of named font variants.
*/
export interface IVariants {
captionStandard: VariantValue;
secondaryStandard: VariantValue;
secondarySemibold: VariantValue;
bodyStandard: VariantValue;
bodySemibold: VariantValue;
subheaderStandard: VariantValue;
subheaderSemibold: VariantValue;
headerStandard: VariantValue;
headerSemibold: VariantValue;
heroStandard: VariantValue;
heroSemibold: VariantValue;
heroLargeStandard: VariantValue;
heroLargeSemibold: VariantValue;
}
/**
* A font variant, used when defining a visual element in a theme.
*/
export type Variant = keyof IVariants | VariantValue;
/**
* A collection of typographic (font) information.
*
* When setting a font in a theme, choose a family, size and weight from
* this collection.
*/
export interface ITextStyle {
families: IFontFamilies;
sizes: IFontSizes;
weights: IFontWeights;
variants: IVariants;
}
export type ITypography = ITextStyle;
/**
* A partially specified typography.
*/
export type IPartialTypography = { [P in keyof ITypography]?: Partial<ITypography[P]> };

Просмотреть файл

@ -1,57 +1,57 @@
import { ITheme } from './Theme.types';
import { getStockWebPalette, ITypography, ISpacing } from '@uifabricshared/theming-ramp';
function _defaultTypography(): ITypography {
return {
sizes: {
caption: 8,
secondary: 9,
body: 11,
subheader: 12,
header: 15,
hero: 21,
heroLarge: 32
},
weights: {
regular: '400',
semiBold: '600'
},
families: {
primary: 'Segoe UI',
secondary: 'System',
cursive: 'System',
monospace: 'System',
sansSerif: 'System',
serif: 'System'
},
variants: {
captionStandard: { face: 'primary', size: 'caption', weight: 'regular' },
secondaryStandard: { face: 'primary', size: 'secondary', weight: 'regular' },
secondarySemibold: { face: 'primary', size: 'secondary', weight: 'semiBold' },
bodyStandard: { face: 'primary', size: 'body', weight: 'regular' },
bodySemibold: { face: 'primary', size: 'body', weight: 'semiBold' },
subheaderStandard: { face: 'primary', size: 'subheader', weight: 'regular' },
subheaderSemibold: { face: 'primary', size: 'subheader', weight: 'semiBold' },
headerStandard: { face: 'primary', size: 'header', weight: 'regular' },
headerSemibold: { face: 'primary', size: 'header', weight: 'semiBold' },
heroStandard: { face: 'primary', size: 'hero', weight: 'regular' },
heroSemibold: { face: 'primary', size: 'hero', weight: 'semiBold' },
heroLargeStandard: { face: 'primary', size: 'heroLarge', weight: 'regular' },
heroLargeSemibold: { face: 'primary', size: 'heroLarge', weight: 'semiBold' }
}
};
}
export function defaultSpacing(): ISpacing {
return { s2: '4px', s1: '8px', m: '16px', l1: '20px', l2: '32px' };
}
export function getBaselinePlatformTheme(): ITheme {
return {
colors: getStockWebPalette(),
typography: _defaultTypography(),
spacing: defaultSpacing(),
components: {},
host: {}
};
}
import { ITheme } from './Theme.types';
import { getStockWebPalette, ITypography, ISpacing } from '@uifabricshared/theming-ramp';
function _defaultTypography(): ITypography {
return {
sizes: {
caption: 8,
secondary: 9,
body: 11,
subheader: 12,
header: 15,
hero: 21,
heroLarge: 32
},
weights: {
regular: '400',
semiBold: '600'
},
families: {
primary: 'Segoe UI',
secondary: 'System',
cursive: 'System',
monospace: 'System',
sansSerif: 'System',
serif: 'System'
},
variants: {
captionStandard: { face: 'primary', size: 'caption', weight: 'regular' },
secondaryStandard: { face: 'primary', size: 'secondary', weight: 'regular' },
secondarySemibold: { face: 'primary', size: 'secondary', weight: 'semiBold' },
bodyStandard: { face: 'primary', size: 'body', weight: 'regular' },
bodySemibold: { face: 'primary', size: 'body', weight: 'semiBold' },
subheaderStandard: { face: 'primary', size: 'subheader', weight: 'regular' },
subheaderSemibold: { face: 'primary', size: 'subheader', weight: 'semiBold' },
headerStandard: { face: 'primary', size: 'header', weight: 'regular' },
headerSemibold: { face: 'primary', size: 'header', weight: 'semiBold' },
heroStandard: { face: 'primary', size: 'hero', weight: 'regular' },
heroSemibold: { face: 'primary', size: 'hero', weight: 'semiBold' },
heroLargeStandard: { face: 'primary', size: 'heroLarge', weight: 'regular' },
heroLargeSemibold: { face: 'primary', size: 'heroLarge', weight: 'semiBold' }
}
};
}
export function defaultSpacing(): ISpacing {
return { s2: '4px', s1: '8px', m: '16px', l1: '20px', l2: '32px' };
}
export function getBaselinePlatformTheme(): ITheme {
return {
colors: getStockWebPalette(),
typography: _defaultTypography(),
spacing: defaultSpacing(),
components: {},
host: {}
};
}

Просмотреть файл

@ -1,158 +1,158 @@
import { IOfficeThemingModule, IThemingModuleHelper, IEventEmitter } from './ThemingModule.types';
import { getBaselinePlatformTheme } from '../BaselinePlatformDefaults';
import { IOfficePalette } from './office';
import { createThemingModuleHelper } from './ThemingModuleHelpers';
const whiteColorsPalette: IOfficePalette = {
Bkg: 'antiquewhite',
BkgHover: '#E6E6E6',
BkgPressed: '#969696',
BkgSelected: '#D2D2D2',
BkgSelectionHighlight: '#737373',
Text: '#505050',
TextRest: '#505050',
TextHover: '#505050',
TextPressed: 'white',
TextSelected: '#505050',
TextDisabled: '#D2D2D2',
TextSelectionHighlight: 'white',
TextSecondary: '#737373',
TextSecondaryRest: '#737373',
TextSecondaryHover: '#505050',
TextSecondaryPressed: '#F3F3F3',
TextSecondarySelected: '#505050',
TextEmphasis: '#2B579A',
TextEmphasisRest: '#2B579A',
TextEmphasisHover: '#2B579A',
TextEmphasisPressed: '#2B579A',
TextEmphasisSelected: '#002050',
StrokeSelectedHover: '#969696',
StrokeKeyboard: '#505050',
StrokeOverlayRest: 'transparent',
StrokeOverlayHover: 'transparent',
StrokeOverlayPressed: 'transparent',
StrokeOverlaySelectedRest: 'transparent',
StrokeOverlaySelectedHover: '#969696',
StrokeOverlaySelectedPressed: 'transparent',
BkgCtl: '#D2D2D2',
BkgCtlHover: '#E6E6E6',
BkgCtlPressed: '#969696',
BkgCtlSelected: '#D2D2D2',
BkgCtlDisabled: '#D2D2D24D',
TextCtl: '#505050',
TextCtlHover: '#505050',
TextCtlPressed: '#505050',
TextCtlSelected: '#505050',
TextCtlDisabled: '#D2D2D24D',
StrokeCtl: 'transparent',
StrokeCtlHover: 'transparent',
StrokeCtlPressed: 'transparent',
StrokeCtlSelected: '#969696',
StrokeCtlDisabled: '#E6E6E6',
StrokeCtlKeyboard: '#737373',
BkgCtlEmphasis: 'pink',
BkgCtlEmphasisHover: 'pink',
BkgCtlEmphasisPressed: 'pink',
BkgCtlEmphasisDisabled: 'pink',
TextCtlEmphasis: 'white',
TextCtlEmphasisHover: 'white',
TextCtlEmphasisPressed: 'white',
TextCtlEmphasisDisabled: 'white',
StrokeCtlEmphasis: 'pink',
StrokeCtlEmphasisHover: 'pink',
StrokeCtlEmphasisPressed: 'pink',
StrokeCtlEmphasisDisabled: 'pink',
StrokeCtlEmphasisKeyboard: 'white',
BkgCtlSubtle: 'antiquewhite',
BkgCtlSubtleHover: 'white',
BkgCtlSubtlePressed: '#D2D2D24D',
BkgCtlSubtleDisabled: 'pink',
BkgCtlSubtleSelectionHighlight: 'pink',
TextCtlSubtle: 'pink',
TextCtlSubtlePlaceholder: 'pink',
TextCtlSubtleHover: 'pink',
TextCtlSubtlePressed: 'pink',
TextCtlSubtleDisabled: 'pink',
TextCtlSubtleSelectionHighlight: 'pink',
StrokeCtlSubtle: 'pink',
StrokeCtlSubtleHover: 'pink',
StrokeCtlSubtlePressed: 'pink',
StrokeCtlSubtleDisabled: 'pink',
StrokeCtlSubtleKeyboard: 'pink',
TextHyperlink: 'pink',
TextHyperlinkHover: 'pink',
TextHyperlinkPressed: 'pink',
TextActive: 'pink',
TextActiveHover: 'pink',
TextActivePressed: 'pink',
TextActiveSelected: 'pink',
TextError: 'pink',
TextErrorHover: 'pink',
TextErrorPressed: 'pink',
TextErrorSelected: 'pink',
AccentDark: 'pink',
AccentLight: 'pink',
AccentEmphasis: 'pink',
AccentOutline: 'pink',
BkgHeader: 'pink',
TextHeader: 'pink'
};
const taskPanePalette: IOfficePalette = {
...whiteColorsPalette,
Bkg: '#E6E6E6',
BkgCtlEmphasis: 'green',
TextCtlEmphasis: 'white'
};
const baseline = getBaselinePlatformTheme();
export const mockGetPaletteImpl = (pal?: string) => {
return (pal === 'TaskPane' && taskPanePalette) || whiteColorsPalette;
};
const mockModule: IOfficeThemingModule = {
ramps: {
App: ['#F8F8F8', '#EFF6FC', '#BBDAF3', '#55A4E2', '#359EDD', '#0078d7', '#283E4A', '#030C13'],
FluentGrays: ['#FAF9F8', '#797775', '#11100F'],
ClassicGrays: ['#FFFFFF', '#737373', '#000000'],
Sepias: ['#ECE6DE']
},
getPalette: mockGetPaletteImpl,
typography: baseline.typography,
fluentTypography: baseline.typography
};
export function createMockThemingModule(module?: Partial<IOfficeThemingModule>) {
return { ...mockModule, ...module };
}
export function createMockThemingModuleHelper(
module?: Partial<IOfficeThemingModule>,
emitter?: IEventEmitter,
behaviorOverrides?: Partial<IThemingModuleHelper>
): IThemingModuleHelper {
return {
...createThemingModuleHelper(createMockThemingModule(module), emitter),
...behaviorOverrides
};
}
import { IOfficeThemingModule, IThemingModuleHelper, IEventEmitter } from './ThemingModule.types';
import { getBaselinePlatformTheme } from '../BaselinePlatformDefaults';
import { IOfficePalette } from './office';
import { createThemingModuleHelper } from './ThemingModuleHelpers';
const whiteColorsPalette: IOfficePalette = {
Bkg: 'antiquewhite',
BkgHover: '#E6E6E6',
BkgPressed: '#969696',
BkgSelected: '#D2D2D2',
BkgSelectionHighlight: '#737373',
Text: '#505050',
TextRest: '#505050',
TextHover: '#505050',
TextPressed: 'white',
TextSelected: '#505050',
TextDisabled: '#D2D2D2',
TextSelectionHighlight: 'white',
TextSecondary: '#737373',
TextSecondaryRest: '#737373',
TextSecondaryHover: '#505050',
TextSecondaryPressed: '#F3F3F3',
TextSecondarySelected: '#505050',
TextEmphasis: '#2B579A',
TextEmphasisRest: '#2B579A',
TextEmphasisHover: '#2B579A',
TextEmphasisPressed: '#2B579A',
TextEmphasisSelected: '#002050',
StrokeSelectedHover: '#969696',
StrokeKeyboard: '#505050',
StrokeOverlayRest: 'transparent',
StrokeOverlayHover: 'transparent',
StrokeOverlayPressed: 'transparent',
StrokeOverlaySelectedRest: 'transparent',
StrokeOverlaySelectedHover: '#969696',
StrokeOverlaySelectedPressed: 'transparent',
BkgCtl: '#D2D2D2',
BkgCtlHover: '#E6E6E6',
BkgCtlPressed: '#969696',
BkgCtlSelected: '#D2D2D2',
BkgCtlDisabled: '#D2D2D24D',
TextCtl: '#505050',
TextCtlHover: '#505050',
TextCtlPressed: '#505050',
TextCtlSelected: '#505050',
TextCtlDisabled: '#D2D2D24D',
StrokeCtl: 'transparent',
StrokeCtlHover: 'transparent',
StrokeCtlPressed: 'transparent',
StrokeCtlSelected: '#969696',
StrokeCtlDisabled: '#E6E6E6',
StrokeCtlKeyboard: '#737373',
BkgCtlEmphasis: 'pink',
BkgCtlEmphasisHover: 'pink',
BkgCtlEmphasisPressed: 'pink',
BkgCtlEmphasisDisabled: 'pink',
TextCtlEmphasis: 'white',
TextCtlEmphasisHover: 'white',
TextCtlEmphasisPressed: 'white',
TextCtlEmphasisDisabled: 'white',
StrokeCtlEmphasis: 'pink',
StrokeCtlEmphasisHover: 'pink',
StrokeCtlEmphasisPressed: 'pink',
StrokeCtlEmphasisDisabled: 'pink',
StrokeCtlEmphasisKeyboard: 'white',
BkgCtlSubtle: 'antiquewhite',
BkgCtlSubtleHover: 'white',
BkgCtlSubtlePressed: '#D2D2D24D',
BkgCtlSubtleDisabled: 'pink',
BkgCtlSubtleSelectionHighlight: 'pink',
TextCtlSubtle: 'pink',
TextCtlSubtlePlaceholder: 'pink',
TextCtlSubtleHover: 'pink',
TextCtlSubtlePressed: 'pink',
TextCtlSubtleDisabled: 'pink',
TextCtlSubtleSelectionHighlight: 'pink',
StrokeCtlSubtle: 'pink',
StrokeCtlSubtleHover: 'pink',
StrokeCtlSubtlePressed: 'pink',
StrokeCtlSubtleDisabled: 'pink',
StrokeCtlSubtleKeyboard: 'pink',
TextHyperlink: 'pink',
TextHyperlinkHover: 'pink',
TextHyperlinkPressed: 'pink',
TextActive: 'pink',
TextActiveHover: 'pink',
TextActivePressed: 'pink',
TextActiveSelected: 'pink',
TextError: 'pink',
TextErrorHover: 'pink',
TextErrorPressed: 'pink',
TextErrorSelected: 'pink',
AccentDark: 'pink',
AccentLight: 'pink',
AccentEmphasis: 'pink',
AccentOutline: 'pink',
BkgHeader: 'pink',
TextHeader: 'pink'
};
const taskPanePalette: IOfficePalette = {
...whiteColorsPalette,
Bkg: '#E6E6E6',
BkgCtlEmphasis: 'green',
TextCtlEmphasis: 'white'
};
const baseline = getBaselinePlatformTheme();
export const mockGetPaletteImpl = (pal?: string) => {
return (pal === 'TaskPane' && taskPanePalette) || whiteColorsPalette;
};
const mockModule: IOfficeThemingModule = {
ramps: {
App: ['#F8F8F8', '#EFF6FC', '#BBDAF3', '#55A4E2', '#359EDD', '#0078d7', '#283E4A', '#030C13'],
FluentGrays: ['#FAF9F8', '#797775', '#11100F'],
ClassicGrays: ['#FFFFFF', '#737373', '#000000'],
Sepias: ['#ECE6DE']
},
getPalette: mockGetPaletteImpl,
typography: baseline.typography,
fluentTypography: baseline.typography
};
export function createMockThemingModule(module?: Partial<IOfficeThemingModule>) {
return { ...mockModule, ...module };
}
export function createMockThemingModuleHelper(
module?: Partial<IOfficeThemingModule>,
emitter?: IEventEmitter,
behaviorOverrides?: Partial<IThemingModuleHelper>
): IThemingModuleHelper {
return {
...createThemingModuleHelper(createMockThemingModule(module), emitter),
...behaviorOverrides
};
}

Просмотреть файл

@ -1,50 +1,50 @@
import { ITypography, ColorValue } from '@uifabricshared/theming-ramp';
import { ITheme, IPartialTheme } from '@uifabricshared/theming-ramp';
import { IOfficePalette } from './office';
import { IProcessTheme } from '@uifabricshared/theme-registry';
export type PlatformDefaultsChangedArgs = { hostThemeSetting: string };
export type PlatformDefaultsChangedCallback = (args?: PlatformDefaultsChangedArgs) => void;
export interface ICxxException {
message: string;
}
export interface INativeColorRamps {
FluentGrays: ColorValue[];
ClassicGrays: ColorValue[];
App: ColorValue[];
Sepias: ColorValue[];
[key: string]: ColorValue[];
}
export interface IOfficeThemingModule {
getPalette(palette?: string): IOfficePalette | ICxxException;
typography: object;
fluentTypography: ITypography;
ramps: INativeColorRamps;
initialHostThemeSetting?: string;
}
export interface IEventEmitter {
addListener: (event: string, PlatformDefaultsChangedCallback) => void;
}
export type IPlatformThemeDefinition = IPartialTheme | IProcessTheme<ITheme, IPartialTheme>;
export interface IThemingModuleHelper {
/**
* Gets a complete platform theme suitable for using with a Theme Registry
*/
getPlatformDefaults: (themeId?: string) => ITheme;
/**
* Gets a theme definition to register with a Theme Registry & use with the theme context to create a subtree with the
* look & feel of a platform theme.
*/
getPlatformThemeDefinition: (themeId?: string) => IPlatformThemeDefinition;
addListener: (listener: PlatformDefaultsChangedCallback) => void; // TODO: Should probably be able to remove
}
export type IHostSettingsWin32 = {
palette: IOfficePalette;
};
import { ITypography, ColorValue } from '@uifabricshared/theming-ramp';
import { ITheme, IPartialTheme } from '@uifabricshared/theming-ramp';
import { IOfficePalette } from './office';
import { IProcessTheme } from '@uifabricshared/theme-registry';
export type PlatformDefaultsChangedArgs = { hostThemeSetting: string };
export type PlatformDefaultsChangedCallback = (args?: PlatformDefaultsChangedArgs) => void;
export interface ICxxException {
message: string;
}
export interface INativeColorRamps {
FluentGrays: ColorValue[];
ClassicGrays: ColorValue[];
App: ColorValue[];
Sepias: ColorValue[];
[key: string]: ColorValue[];
}
export interface IOfficeThemingModule {
getPalette(palette?: string): IOfficePalette | ICxxException;
typography: object;
fluentTypography: ITypography;
ramps: INativeColorRamps;
initialHostThemeSetting?: string;
}
export interface IEventEmitter {
addListener: (event: string, PlatformDefaultsChangedCallback) => void;
}
export type IPlatformThemeDefinition = IPartialTheme | IProcessTheme<ITheme, IPartialTheme>;
export interface IThemingModuleHelper {
/**
* Gets a complete platform theme suitable for using with a Theme Registry
*/
getPlatformDefaults: (themeId?: string) => ITheme;
/**
* Gets a theme definition to register with a Theme Registry & use with the theme context to create a subtree with the
* look & feel of a platform theme.
*/
getPlatformThemeDefinition: (themeId?: string) => IPlatformThemeDefinition;
addListener: (listener: PlatformDefaultsChangedCallback) => void; // TODO: Should probably be able to remove
}
export type IHostSettingsWin32 = {
palette: IOfficePalette;
};

Просмотреть файл

@ -1,86 +1,86 @@
import { ITheme, IPartialPalette, IColorRamp, resolvePartialTheme } from '@uifabricshared/theming-ramp';
import {
IOfficeThemingModule,
ICxxException,
PlatformDefaultsChangedCallback,
IThemingModuleHelper,
IEventEmitter,
PlatformDefaultsChangedArgs
} from './ThemingModule.types';
import { getBaselinePlatformTheme } from '../BaselinePlatformDefaults';
import { IOfficePalette, paletteFromOfficeColors } from './office';
import { useFakePalette } from './useFakePalette';
const createColorRamp = ({ values, index = -1 }: Partial<IColorRamp>) => ({
values,
index,
toString() {
return this.values[Math.round(values.length / 2)];
}
});
type PaletteCache = { [key: string]: IOfficePalette };
function isException(palette: IOfficePalette | ICxxException): palette is ICxxException {
return (palette as ICxxException).message !== undefined;
}
function updatePaletteInCache(module: IOfficeThemingModule, cache: PaletteCache, palette: string) {
const paletteValue = module.getPalette(palette);
if (!isException(paletteValue)) {
cache[palette] = paletteValue;
}
}
function translatePalette(module: IOfficeThemingModule, paletteCache: PaletteCache, palette?: string): IPartialPalette {
const key = useFakePalette ? 'debug' : palette || 'WhiteColors';
if (!paletteCache[key]) {
updatePaletteInCache(module, paletteCache, key);
}
return paletteCache[key] ? paletteFromOfficeColors(paletteCache[key]) : {};
}
export function translateOfficeTheme(module: IOfficeThemingModule, cache: PaletteCache, id?: string) {
const palette = translatePalette(module, cache, id);
return {
colors: {
brand: createColorRamp({ values: module.ramps.App }),
neutrals: createColorRamp({ values: module.ramps.FluentGrays }),
warning: createColorRamp({ values: module.ramps.Sepias }),
neutrals2: createColorRamp({ values: module.ramps.ClassicGrays }),
...palette
},
typography: module.fluentTypography || {},
host: {
palette: cache[id]
}
};
}
export function createThemingModuleHelper(themingModule?: IOfficeThemingModule, emitter?: IEventEmitter): IThemingModuleHelper {
themingModule || console.error('No NativeModule for Theming found');
const paletteCache: PaletteCache = {};
let _hostTheme = themingModule.initialHostThemeSetting || '';
emitter &&
emitter.addListener('onPlatformDefaultsChanged', (args: PlatformDefaultsChangedArgs) => {
_hostTheme = (args && args.hostThemeSetting) || _hostTheme;
Object.keys(paletteCache).forEach((key: string) => delete paletteCache[key]);
});
return {
getPlatformDefaults: (themeId?: string) => {
return resolvePartialTheme(
getBaselinePlatformTheme(),
Object.assign(translateOfficeTheme(themingModule, paletteCache, themeId), { name: _hostTheme })
);
},
getPlatformThemeDefinition: (themeId?: string) => {
return (_parent: ITheme) => {
updatePaletteInCache(themingModule, paletteCache, themeId);
return translateOfficeTheme(themingModule, paletteCache, themeId);
};
},
addListener: (callback: PlatformDefaultsChangedCallback) => {
emitter && emitter.addListener('onPlatformDefaultsChanged', callback);
}
};
}
import { ITheme, IPartialPalette, IColorRamp, resolvePartialTheme } from '@uifabricshared/theming-ramp';
import {
IOfficeThemingModule,
ICxxException,
PlatformDefaultsChangedCallback,
IThemingModuleHelper,
IEventEmitter,
PlatformDefaultsChangedArgs
} from './ThemingModule.types';
import { getBaselinePlatformTheme } from '../BaselinePlatformDefaults';
import { IOfficePalette, paletteFromOfficeColors } from './office';
import { useFakePalette } from './useFakePalette';
const createColorRamp = ({ values, index = -1 }: Partial<IColorRamp>) => ({
values,
index,
toString() {
return this.values[Math.round(values.length / 2)];
}
});
type PaletteCache = { [key: string]: IOfficePalette };
function isException(palette: IOfficePalette | ICxxException): palette is ICxxException {
return (palette as ICxxException).message !== undefined;
}
function updatePaletteInCache(module: IOfficeThemingModule, cache: PaletteCache, palette: string) {
const paletteValue = module.getPalette(palette);
if (!isException(paletteValue)) {
cache[palette] = paletteValue;
}
}
function translatePalette(module: IOfficeThemingModule, paletteCache: PaletteCache, palette?: string): IPartialPalette {
const key = useFakePalette ? 'debug' : palette || 'WhiteColors';
if (!paletteCache[key]) {
updatePaletteInCache(module, paletteCache, key);
}
return paletteCache[key] ? paletteFromOfficeColors(paletteCache[key]) : {};
}
export function translateOfficeTheme(module: IOfficeThemingModule, cache: PaletteCache, id?: string) {
const palette = translatePalette(module, cache, id);
return {
colors: {
brand: createColorRamp({ values: module.ramps.App }),
neutrals: createColorRamp({ values: module.ramps.FluentGrays }),
warning: createColorRamp({ values: module.ramps.Sepias }),
neutrals2: createColorRamp({ values: module.ramps.ClassicGrays }),
...palette
},
typography: module.fluentTypography || {},
host: {
palette: cache[id]
}
};
}
export function createThemingModuleHelper(themingModule?: IOfficeThemingModule, emitter?: IEventEmitter): IThemingModuleHelper {
themingModule || console.error('No NativeModule for Theming found');
const paletteCache: PaletteCache = {};
let _hostTheme = themingModule.initialHostThemeSetting || '';
emitter &&
emitter.addListener('onPlatformDefaultsChanged', (args: PlatformDefaultsChangedArgs) => {
_hostTheme = (args && args.hostThemeSetting) || _hostTheme;
Object.keys(paletteCache).forEach((key: string) => delete paletteCache[key]);
});
return {
getPlatformDefaults: (themeId?: string) => {
return resolvePartialTheme(
getBaselinePlatformTheme(),
Object.assign(translateOfficeTheme(themingModule, paletteCache, themeId), { name: _hostTheme })
);
},
getPlatformThemeDefinition: (themeId?: string) => {
return (_parent: ITheme) => {
updatePaletteInCache(themingModule, paletteCache, themeId);
return translateOfficeTheme(themingModule, paletteCache, themeId);
};
},
addListener: (callback: PlatformDefaultsChangedCallback) => {
emitter && emitter.addListener('onPlatformDefaultsChanged', callback);
}
};
}

Просмотреть файл

@ -1,199 +1,199 @@
// @ts-check
import Metro from 'metro';
import path from 'path';
import fs from 'fs';
import { logger, TaskFunction } from 'just-task';
import { AllPlatforms } from './platforms';
import { addPlatformMetroConfig } from './configureMetro';
export interface BundleDetails {
/**
* entry file such as './src/index.ts'
*/
entry?: string;
outputPath?: string;
bundleName?: string;
noPlatformSuffix?: boolean;
noJSExtension?: boolean;
}
export type BundleDefinition = BundleDetails & {
name?: string;
targets?: AllPlatforms[];
platforms?: {
[K in AllPlatforms]: BundleDetails;
};
};
export type MetroBundles = BundleDefinition | BundleDefinition[];
function asArray<T>(opt: T | T[]): T[] {
return Array.isArray(opt) ? opt : [opt || ({} as T)];
}
/**
* Load a bundle definition from package.json. The bundle definition should be of type BundleDefinition and would
* typically look something like:
* "metroBundles": {
* "targets": ["win32", "windows"],
* "entryFile": "./src/index.ts",
* "outputPath": "./dist",
* "outputFile": "myBundleName"
* }
*
* Platform specific overrides can be specified by using a platforms which works as a selector. In this case
* add:
* "metroBundles": {
* ...stuff
* "platforms": {
* "ios": {
* "outputFile": "myIOSName"
* }
* }
* }
* @param bundleName - optional name of the bundle, use if there are multiple bundles defined in package JSON
*/
function loadBundleDefinition(bundleName?: string): BundleDefinition {
const packageConfigPath = path.resolve(process.cwd(), 'package.json');
const packageConfig = JSON.parse(fs.readFileSync(packageConfigPath, 'utf8'));
const metroBundles = asArray<BundleDefinition>(packageConfig.metroBundles);
if (bundleName) {
return metroBundles.find(bundle => bundle.name === bundleName) || {};
}
if (metroBundles.length > 1) {
logger.error('Multiple bundles are specified in the package, so bundle is ambiguous');
} else if (metroBundles.length === 0) {
logger.error('The package must contain a bundle definition');
}
return metroBundles[0];
}
/**
* Resolves the platform selector for each bundle target
* @param bundle - bundle definition, potentially including a platform selector
* @param platform - current platform target
*/
function getOptionsForPlatform(bundle: BundleDefinition, platform: AllPlatforms): BundleDefinition {
const platformValues = bundle.platforms && bundle.platforms[platform];
return platformValues ? { ...bundle, ...platformValues } : bundle;
}
/**
* options for the metro task
*/
export interface MetroTaskOptions {
/**
* name of the bundle to target, can be blank if the package.json only includes one bundle
*/
bundleName?: string;
/**
* platform to bundle for, if blank will bundle for all platforms in this folder
*/
platform?: AllPlatforms;
/**
* whether to bundle in development mode
*/
dev?: boolean;
/**
* run metro in server mode
*/
server?: boolean;
/**
* port override for server mode
*/
port?: number;
}
export function metroTask(options: MetroTaskOptions = {}): TaskFunction {
const { bundleName, platform, dev = false, server } = options;
const port = options.port || (platform === 'windows' ? 8081 : 8080);
return async function metroPack(done) {
logger.verbose(`Starting metropack task with platform ${bundleName}...`);
// get the bundle definition
const definition = loadBundleDefinition(bundleName);
const targets = (platform && [platform]) || definition.targets || [];
for (const targetPlatform of targets) {
// get the options specified for the platform
const platformDefinition = getOptionsForPlatform(definition, targetPlatform);
// set up file input and output
const { entry = './lib/index.js', outputPath = './dist', bundleName, noJSExtension, noPlatformSuffix } = platformDefinition;
let out = path.join(outputPath, bundleName);
if (!noPlatformSuffix) {
out = `${out}.${targetPlatform}`;
}
// get the config file, checking if there is a platform specific override
let configName = `metro.config.${targetPlatform}.js`;
configName = fs.existsSync(path.join(process.cwd(), configName)) ? configName : 'metro.config.js';
const configBase = await Metro.loadConfig({ config: configName });
// add platform specific details for bundling this config
const config = addPlatformMetroConfig(targetPlatform, configBase) as any;
if (server) {
config.server = config.server || {};
config.server.port = port;
}
// ensure the parent directory exists for the target output
const parentDirectory = path.dirname(path.resolve(process.cwd(), out));
if (!fs.existsSync(parentDirectory)) {
fs.mkdirSync(parentDirectory);
}
if (server) {
// for server start up the server, note that this is for only one platform, at least by configuration
logger.info(`Starting metro server for ${targetPlatform} platform on port ${port}.`);
await Metro.runServer(config, { port: port });
// break out of the loop, doesn't make sense to run servers for multiple platforms
break;
} else {
// log out what is about to happen
logger.info(`Starting metro bundling for ${targetPlatform}.`);
logger.info(`Entry file ${entry}.`);
logger.info(`Output file ${out}.`);
// now run the bundle task itself
await Metro.runBuild(config, {
platform: targetPlatform,
entry,
minify: !dev,
out,
optimize: !dev,
sourceMap: dev
});
// optionally rename the output to remove the JS extension if requested
if (noJSExtension && !out.endsWith('.js')) {
const metroBundlePath = out + '.js';
if (fs.existsSync(metroBundlePath)) {
if (fs.existsSync(out)) {
logger.verbose(`Deleting existing output file at ${out}...`);
fs.unlinkSync(out);
}
logger.verbose(`Renaming ${metroBundlePath} to ${out}...`);
fs.renameSync(metroBundlePath, out);
}
}
logger.info(`Finished bundling ${out} for ${targetPlatform}.`);
}
}
if (done) {
done();
}
};
}
// @ts-check
import Metro from 'metro';
import path from 'path';
import fs from 'fs';
import { logger, TaskFunction } from 'just-task';
import { AllPlatforms } from './platforms';
import { addPlatformMetroConfig } from './configureMetro';
export interface BundleDetails {
/**
* entry file such as './src/index.ts'
*/
entry?: string;
outputPath?: string;
bundleName?: string;
noPlatformSuffix?: boolean;
noJSExtension?: boolean;
}
export type BundleDefinition = BundleDetails & {
name?: string;
targets?: AllPlatforms[];
platforms?: {
[K in AllPlatforms]: BundleDetails;
};
};
export type MetroBundles = BundleDefinition | BundleDefinition[];
function asArray<T>(opt: T | T[]): T[] {
return Array.isArray(opt) ? opt : [opt || ({} as T)];
}
/**
* Load a bundle definition from package.json. The bundle definition should be of type BundleDefinition and would
* typically look something like:
* "metroBundles": {
* "targets": ["win32", "windows"],
* "entryFile": "./src/index.ts",
* "outputPath": "./dist",
* "outputFile": "myBundleName"
* }
*
* Platform specific overrides can be specified by using a platforms which works as a selector. In this case
* add:
* "metroBundles": {
* ...stuff
* "platforms": {
* "ios": {
* "outputFile": "myIOSName"
* }
* }
* }
* @param bundleName - optional name of the bundle, use if there are multiple bundles defined in package JSON
*/
function loadBundleDefinition(bundleName?: string): BundleDefinition {
const packageConfigPath = path.resolve(process.cwd(), 'package.json');
const packageConfig = JSON.parse(fs.readFileSync(packageConfigPath, 'utf8'));
const metroBundles = asArray<BundleDefinition>(packageConfig.metroBundles);
if (bundleName) {
return metroBundles.find(bundle => bundle.name === bundleName) || {};
}
if (metroBundles.length > 1) {
logger.error('Multiple bundles are specified in the package, so bundle is ambiguous');
} else if (metroBundles.length === 0) {
logger.error('The package must contain a bundle definition');
}
return metroBundles[0];
}
/**
* Resolves the platform selector for each bundle target
* @param bundle - bundle definition, potentially including a platform selector
* @param platform - current platform target
*/
function getOptionsForPlatform(bundle: BundleDefinition, platform: AllPlatforms): BundleDefinition {
const platformValues = bundle.platforms && bundle.platforms[platform];
return platformValues ? { ...bundle, ...platformValues } : bundle;
}
/**
* options for the metro task
*/
export interface MetroTaskOptions {
/**
* name of the bundle to target, can be blank if the package.json only includes one bundle
*/
bundleName?: string;
/**
* platform to bundle for, if blank will bundle for all platforms in this folder
*/
platform?: AllPlatforms;
/**
* whether to bundle in development mode
*/
dev?: boolean;
/**
* run metro in server mode
*/
server?: boolean;
/**
* port override for server mode
*/
port?: number;
}
export function metroTask(options: MetroTaskOptions = {}): TaskFunction {
const { bundleName, platform, dev = false, server } = options;
const port = options.port || (platform === 'windows' ? 8081 : 8080);
return async function metroPack(done) {
logger.verbose(`Starting metropack task with platform ${bundleName}...`);
// get the bundle definition
const definition = loadBundleDefinition(bundleName);
const targets = (platform && [platform]) || definition.targets || [];
for (const targetPlatform of targets) {
// get the options specified for the platform
const platformDefinition = getOptionsForPlatform(definition, targetPlatform);
// set up file input and output
const { entry = './lib/index.js', outputPath = './dist', bundleName, noJSExtension, noPlatformSuffix } = platformDefinition;
let out = path.join(outputPath, bundleName);
if (!noPlatformSuffix) {
out = `${out}.${targetPlatform}`;
}
// get the config file, checking if there is a platform specific override
let configName = `metro.config.${targetPlatform}.js`;
configName = fs.existsSync(path.join(process.cwd(), configName)) ? configName : 'metro.config.js';
const configBase = await Metro.loadConfig({ config: configName });
// add platform specific details for bundling this config
const config = addPlatformMetroConfig(targetPlatform, configBase) as any;
if (server) {
config.server = config.server || {};
config.server.port = port;
}
// ensure the parent directory exists for the target output
const parentDirectory = path.dirname(path.resolve(process.cwd(), out));
if (!fs.existsSync(parentDirectory)) {
fs.mkdirSync(parentDirectory);
}
if (server) {
// for server start up the server, note that this is for only one platform, at least by configuration
logger.info(`Starting metro server for ${targetPlatform} platform on port ${port}.`);
await Metro.runServer(config, { port: port });
// break out of the loop, doesn't make sense to run servers for multiple platforms
break;
} else {
// log out what is about to happen
logger.info(`Starting metro bundling for ${targetPlatform}.`);
logger.info(`Entry file ${entry}.`);
logger.info(`Output file ${out}.`);
// now run the bundle task itself
await Metro.runBuild(config, {
platform: targetPlatform,
entry,
minify: !dev,
out,
optimize: !dev,
sourceMap: dev
});
// optionally rename the output to remove the JS extension if requested
if (noJSExtension && !out.endsWith('.js')) {
const metroBundlePath = out + '.js';
if (fs.existsSync(metroBundlePath)) {
if (fs.existsSync(out)) {
logger.verbose(`Deleting existing output file at ${out}...`);
fs.unlinkSync(out);
}
logger.verbose(`Renaming ${metroBundlePath} to ${out}...`);
fs.renameSync(metroBundlePath, out);
}
}
logger.info(`Finished bundling ${out} for ${targetPlatform}.`);
}
}
if (done) {
done();
}
};
}

Просмотреть файл

@ -1,23 +1,23 @@
import { ITheme, IThemeColorDefinition } from '@uifabricshared/theming-ramp';
import { IOperationSet } from '@uifabricshared/foundation-tokens';
export interface IForegroundColorTokens {
color?: string;
}
export const getPaletteFromTheme = (theme: ITheme): IThemeColorDefinition => {
return theme.colors;
};
export const foregroundColorTokens: IOperationSet<IForegroundColorTokens, ITheme> = [{ source: 'color', lookup: getPaletteFromTheme }];
export interface IBackgroundColorTokens {
backgroundColor?: string;
}
export const backgroundColorTokens: IOperationSet<IBackgroundColorTokens, ITheme> = [
{ source: 'backgroundColor', lookup: getPaletteFromTheme }
];
export type IColorTokens = IForegroundColorTokens & IBackgroundColorTokens;
export const colorTokens = [...foregroundColorTokens, ...backgroundColorTokens];
import { ITheme, IThemeColorDefinition } from '@uifabricshared/theming-ramp';
import { IOperationSet } from '@uifabricshared/foundation-tokens';
export interface IForegroundColorTokens {
color?: string;
}
export const getPaletteFromTheme = (theme: ITheme): IThemeColorDefinition => {
return theme.colors;
};
export const foregroundColorTokens: IOperationSet<IForegroundColorTokens, ITheme> = [{ source: 'color', lookup: getPaletteFromTheme }];
export interface IBackgroundColorTokens {
backgroundColor?: string;
}
export const backgroundColorTokens: IOperationSet<IBackgroundColorTokens, ITheme> = [
{ source: 'backgroundColor', lookup: getPaletteFromTheme }
];
export type IColorTokens = IForegroundColorTokens & IBackgroundColorTokens;
export const colorTokens = [...foregroundColorTokens, ...backgroundColorTokens];

Просмотреть файл

@ -1,34 +1,34 @@
import { TextStyle, TextProps } from 'react-native';
import { ITheme, ITypography } from '@uifabricshared/theming-ramp';
import { styleFunction } from '@uifabricshared/foundation-tokens';
export interface ITextVariantTokens {
variant?: keyof ITypography['variants'];
}
export interface ITextStyleTokens {
fontFamily?: keyof ITypography['families'] | TextStyle['fontFamily'];
fontSize?: keyof ITypography['sizes'] | TextStyle['fontSize'];
fontWeight?: keyof ITypography['weights'] | TextStyle['fontWeight'];
}
export type ITextTokens = ITextStyleTokens & ITextVariantTokens;
export function _buildTextStyles({ fontFamily, fontSize, fontWeight, variant }: ITextTokens, { typography }: ITheme): TextProps {
const { families, sizes, weights, variants } = typography;
if (fontFamily || fontSize || fontWeight || variant) {
return {
style: {
fontFamily: families[fontFamily] || fontFamily || families[variants[variant].face] || variants[variant].face,
fontSize: sizes[fontSize] || fontSize || sizes[variants[variant].size] || variants[variant].size,
fontWeight: weights[fontWeight] || fontWeight || weights[variants[variant].weight] || variants[variant].weight
}
};
}
return {};
}
const _keyProps: (keyof ITextTokens)[] = ['fontFamily', 'fontSize', 'fontWeight', 'variant'];
export const textTokens = styleFunction<TextProps, ITextTokens, ITheme>(_buildTextStyles, _keyProps);
import { TextStyle, TextProps } from 'react-native';
import { ITheme, ITypography } from '@uifabricshared/theming-ramp';
import { styleFunction } from '@uifabricshared/foundation-tokens';
export interface ITextVariantTokens {
variant?: keyof ITypography['variants'];
}
export interface ITextStyleTokens {
fontFamily?: keyof ITypography['families'] | TextStyle['fontFamily'];
fontSize?: keyof ITypography['sizes'] | TextStyle['fontSize'];
fontWeight?: keyof ITypography['weights'] | TextStyle['fontWeight'];
}
export type ITextTokens = ITextStyleTokens & ITextVariantTokens;
export function _buildTextStyles({ fontFamily, fontSize, fontWeight, variant }: ITextTokens, { typography }: ITheme): TextProps {
const { families, sizes, weights, variants } = typography;
if (fontFamily || fontSize || fontWeight || variant) {
return {
style: {
fontFamily: families[fontFamily] || fontFamily || families[variants[variant].face] || variants[variant].face,
fontSize: sizes[fontSize] || fontSize || sizes[variants[variant].size] || variants[variant].size,
fontWeight: weights[fontWeight] || fontWeight || weights[variants[variant].weight] || variants[variant].weight
}
};
}
return {};
}
const _keyProps: (keyof ITextTokens)[] = ['fontFamily', 'fontSize', 'fontWeight', 'variant'];
export const textTokens = styleFunction<TextProps, ITextTokens, ITheme>(_buildTextStyles, _keyProps);

Просмотреть файл

@ -1,4 +1,4 @@
const { metroPackTask } = require('./tasks/metro-pack');
const bundleName = process.argv[2];
metroPackTask(bundleName)().then(() => console.log('Successful..'));
const { metroPackTask } = require('./tasks/metro-pack');
const bundleName = process.argv[2];
metroPackTask(bundleName)().then(() => console.log('Successful..'));