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 # Microsoft Open Source Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
Resources: Resources:
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns

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

@ -1,21 +1,21 @@
MIT License MIT License
Copyright (c) Microsoft Corporation. All rights reserved. Copyright (c) Microsoft Corporation. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions: furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 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 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE SOFTWARE

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

@ -1,84 +1,84 @@
# FluentUI React Native # 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. 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 ## 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). 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 ### Prerequisites
- [Standard React Native dependencies](http://facebook.github.io/react-native/docs/getting-started.html#node-python2-jdk) - [Standard React Native dependencies](http://facebook.github.io/react-native/docs/getting-started.html#node-python2-jdk)
- [Node.js](https://nodejs.org/en/download/) - [Node.js](https://nodejs.org/en/download/)
### Install FluentUI React Native into an existing project ### Install FluentUI React Native into an existing project
Navigate to the root folder of your project, and use npm to install the package: Navigate to the root folder of your project, and use npm to install the package:
``` ```
npm i @fluentui/react-native 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`: 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'; 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). 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 ## Documentation
### Components and Controls ### 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). 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 ### Theming framework
Our FluentUI framework documentation is found in this repository alongside the implementation. Our FluentUI framework documentation is found in this repository alongside the implementation.
- [Theming Overview](./packages/framework/theming-react-native/README.md) - [Theming Overview](./packages/framework/theming-react-native/README.md)
- [StyleSheets](./packages/framework/themed-stylesheet/README.md) - [StyleSheets](./packages/framework/themed-stylesheet/README.md)
- [Customizing Theme Settings](./packages/framework/themed-settings/README.md) - [Customizing Theme Settings](./packages/framework/themed-settings/README.md)
- [Theme Registry](./packages/framework/theme-registry/README.md) - [Theme Registry](./packages/framework/theme-registry/README.md)
- [Tokens](./packages/framework/foundation-tokens/README.md) - [Tokens](./packages/framework/foundation-tokens/README.md)
- [Settings and Slots](./packages/framework/foundation-settings/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) - [Compose](./packages/framework/foundation-compose/README.md) and [Composable](./packages/framework/foundation-composable/README.md)
## Developing in the repo ## Developing in the repo
### Yarn + Lerna ### 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/). 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 ### Setup your development environment
To start developing in the repository you can: To start developing in the repository you can:
1. `git clone https://github.com/microsoft/fluentui-react-native.git` 1. `git clone https://github.com/microsoft/fluentui-react-native.git`
1. `cd fluentui-react-native` 1. `cd fluentui-react-native`
1. `yarn` 1. `yarn`
1. `yarn build` 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). 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 ### 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: 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 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 2. Make sure to commit and push the newly generated change file
## Contributing ## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a 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 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. 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 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 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. 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/). 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 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. contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -1,14 +1,14 @@
import { StyleSheet } from 'react-native'; import { StyleSheet } from 'react-native';
export const styles = StyleSheet.create({ export const styles = StyleSheet.create({
oneCoin: { oneCoin: {
margin: 8 margin: 8
} }
}); });
export const satyaPhotoUrl = 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'; '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 steveBallmerPhotoUrl = 'http://www.rmndigital.com/wp-content/uploads/2012/11/stevems.jpg';
export const undefinedText = '(undefined)'; export const undefinedText = '(undefined)';

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -1,74 +1,74 @@
import * as React from 'react'; import * as React from 'react';
import { ButtonFocusTest } from './Button'; import { ButtonFocusTest } from './Button';
import { CalloutTest } from './Callout'; import { CalloutTest } from './Callout';
import { CheckboxTest } from './Checkbox'; import { CheckboxTest } from './Checkbox';
import { FocusTrapTest } from './FocusTrapZone'; import { FocusTrapTest } from './FocusTrapZone';
import { LinkTest } from './Link'; import { LinkTest } from './Link';
import { PersonaTest } from './Persona'; import { PersonaTest } from './Persona';
import { PersonaCoinTest } from './PersonaCoin'; import { PersonaCoinTest } from './PersonaCoin';
import { PressableTest } from './Pressable'; import { PressableTest } from './Pressable';
import { RadioGroupTest } from './RadioGroup'; import { RadioGroupTest } from './RadioGroup';
import { SeparatorTest } from './Separator'; import { SeparatorTest } from './Separator';
import { SvgTest } from './Svg'; import { SvgTest } from './Svg';
import { TextTest } from './Text'; import { TextTest } from './Text';
import { ThemeTest } from './Theme'; import { ThemeTest } from './Theme';
export type TestDescription = { export type TestDescription = {
name: string; name: string;
component: React.FunctionComponent<{}>; component: React.FunctionComponent<{}>;
}; };
export const allTestComponents: TestDescription[] = [ export const allTestComponents: TestDescription[] = [
{ {
name: 'Button Test', name: 'Button Test',
component: ButtonFocusTest component: ButtonFocusTest
}, },
{ {
name: 'Callout Test', name: 'Callout Test',
component: CalloutTest component: CalloutTest
}, },
{ {
name: 'Focus Trap Zone Test', name: 'Focus Trap Zone Test',
component: FocusTrapTest component: FocusTrapTest
}, },
{ {
name: 'Pressable Test', name: 'Pressable Test',
component: PressableTest component: PressableTest
}, },
{ {
name: 'Link Test', name: 'Link Test',
component: LinkTest component: LinkTest
}, },
{ {
name: 'Separator Test', name: 'Separator Test',
component: SeparatorTest component: SeparatorTest
}, },
{ {
name: 'Text Test', name: 'Text Test',
component: TextTest component: TextTest
}, },
{ {
name: 'Theme Test', name: 'Theme Test',
component: ThemeTest component: ThemeTest
}, },
{ {
name: 'PersonaCoin Test', name: 'PersonaCoin Test',
component: PersonaCoinTest component: PersonaCoinTest
}, },
{ {
name: 'RadioGroup Test', name: 'RadioGroup Test',
component: RadioGroupTest component: RadioGroupTest
}, },
{ {
name: 'Persona Test', name: 'Persona Test',
component: PersonaTest component: PersonaTest
}, },
{ {
name: 'Checkbox Test', name: 'Checkbox Test',
component: CheckboxTest component: CheckboxTest
}, },
{ {
name: 'Svg Test', name: 'Svg Test',
component: SvgTest 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 { linkName, ILinkType } from './Link.types';
import { IComposeSettings } from '@uifabricshared/foundation-compose'; import { IComposeSettings } from '@uifabricshared/foundation-compose';
// import { IViewWin32Props } from '@office-iss/react-native-win32'; // import { IViewWin32Props } from '@office-iss/react-native-win32';
import { IViewProps } from '@fluentui-react-native/adapters'; import { IViewProps } from '@fluentui-react-native/adapters';
export const settings: IComposeSettings<ILinkType> = [ export const settings: IComposeSettings<ILinkType> = [
{ {
tokens: { tokens: {
variant: 'secondaryStandard', variant: 'secondaryStandard',
color: 'link' color: 'link'
}, },
root: { root: {
style: { style: {
margin: 0, margin: 0,
textDecorationLine: 'underline' textDecorationLine: 'underline'
} as IViewProps['style'] } as IViewProps['style']
}, },
content: { content: {
style: { style: {
textDecorationLine: 'underline' textDecorationLine: 'underline'
} }
}, },
_precedence: ['visited', 'hovered', 'pressed', 'disabled'], _precedence: ['visited', 'hovered', 'pressed', 'disabled'],
_overrides: { _overrides: {
disabled: { disabled: {
tokens: { tokens: {
color: 'link' color: 'link'
} }
}, },
hovered: { hovered: {
tokens: { tokens: {
color: 'linkHovered' color: 'linkHovered'
} }
}, },
pressed: { pressed: {
tokens: { tokens: {
color: 'linkPressed' color: 'linkPressed'
} }
}, },
visited: { visited: {
tokens: { tokens: {
color: 'link' color: 'link'
} }
} }
} }
}, },
linkName linkName
]; ];

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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