console.log(e.target.value)}
17 | defaultValue="I got checked!"
18 | defaultChecked
19 | />
20 | );
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/examples/windows/components/label.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Label } from 'react-desktop/windows';
3 |
4 | export default class extends Component {
5 | render() {
6 | return (
7 |
8 | );
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/examples/windows/components/masterDetailsView.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import {
3 | MasterDetailsView,
4 | MasterDetailsViewItem,
5 | MasterDetailsViewItemMaster,
6 | MasterDetailsViewItemDetails,
7 | Text
8 | } from 'react-desktop/windows';
9 |
10 | export default class extends Component {
11 | static defaultProps = {
12 | color: '#cc7f29',
13 | theme: 'light'
14 | };
15 |
16 | render() {
17 | return (
18 |
19 | {this.renderItem('Item 1', 'Content 1')}
20 | {this.renderItem('Item 2', 'Content 2')}
21 | {this.renderItem('Item 3', 'Content 3')}
22 |
23 | );
24 | }
25 |
26 | renderItem(master, details) {
27 | return (
28 |
29 |
30 | {master}
31 |
32 |
33 | {details}
34 |
35 |
36 | );
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/examples/windows/components/progressCircle.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { ProgressCircle } from 'react-desktop/windows';
3 |
4 | export default class extends Component {
5 | static defaultProps = {
6 | color: '#cc7f29'
7 | };
8 |
9 | render() {
10 | return (
11 |
15 | );
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/windows/components/radio.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { View, Radio } from 'react-desktop/windows';
3 |
4 | export default class extends Component {
5 | static defaultProps = {
6 | color: '#cc7f29',
7 | theme: 'light'
8 | };
9 |
10 | render() {
11 | return (
12 |
13 | console.log(e.target.value)}
18 | defaultValue="I got checked!"
19 | defaultChecked
20 | />
21 | console.log(e.target.value)}
26 | defaultValue="I got checked!"
27 | />
28 |
29 | );
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/examples/windows/components/text.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Text } from 'react-desktop/windows';
3 |
4 | export default class extends Component {
5 | static defaultProps = {
6 | color: '#cc7f29',
7 | theme: 'light'
8 | };
9 |
10 | render() {
11 | return (
12 |
20 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam justo urna, posuere vitae est et, accumsan
21 | bibendum sapien. Suspendisse lobortis mollis finibus. Nunc tincidunt enim est, efficitur semper dolor luctus
22 | eget. Donec faucibus dolor id leo tincidunt, condimentum mattis augue finibus. Etiam hendrerit ipsum nisi,
23 | vel semper dolor malesuada a. Pellentesque a scelerisque sapien, quis interdum odio. Nulla posuere, velit sit
24 | amet lacinia pharetra, sapien arcu convallis dolor, id congue erat lectus nec sem. Praesent pretium a nisi et
25 | elementum. Cras lacinia sollicitudin suscipit. Phasellus accumsan felis odio. Pellentesque habitant morbi
26 | tristique senectus et netus et malesuada fames ac turpis egestas.
27 |
28 | );
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/examples/windows/components/textArea.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { TextArea } from 'react-desktop/windows';
3 |
4 | export default class extends Component {
5 | static defaultProps = {
6 | color: '#cc7f29',
7 | theme: 'light'
8 | };
9 |
10 | handleChange = e => console.log(e.target.value);
11 |
12 | render() {
13 | return (
14 |
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/examples/windows/components/textInput.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { TextInput } from 'react-desktop/windows';
3 |
4 | export default class extends Component {
5 | static defaultProps = {
6 | color: '#cc7f29',
7 | theme: 'light'
8 | };
9 |
10 | handleChange = e => console.log(e.target.value);
11 |
12 | render() {
13 | return (
14 |
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/examples/windows/components/titleBar.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { TitleBar } from 'react-desktop/windows';
3 |
4 | export default class extends Component {
5 | static defaultProps = {
6 | color: '#cc7f29',
7 | theme: 'light'
8 | };
9 |
10 | constructor(props) {
11 | super(props);
12 | this.state = { isMaximized: true };
13 | }
14 |
15 | close = () => console.log('close');
16 | minimize = () => console.log('minimize');
17 | toggleMaximize = () => this.setState({ isMaximized: !this.state.isMaximized });
18 |
19 | render() {
20 | return (
21 |
32 | );
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/examples/windows/components/view.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { View, Text } from 'react-desktop/windows';
3 |
4 | export default class extends Component {
5 | static defaultProps = {
6 | color: '#cc7f29',
7 | theme: 'light'
8 | };
9 |
10 | render() {
11 | return (
12 |
21 | Hello World
22 |
23 | );
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/examples/windows/components/window.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Window, TitleBar, Text } from 'react-desktop/windows';
3 |
4 | export default class extends Component {
5 | static defaultProps = {
6 | color: '#cc7f29',
7 | theme: 'light'
8 | };
9 |
10 | render() {
11 | return (
12 |
19 |
20 | Hello World
21 |
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import { default as whichOs, MACOS } from './src/os';
2 | import * as windows from './windows';
3 | import * as macOs from './macOs';
4 |
5 | const os = whichOs();
6 | const select = (macOs, windows) => os === MACOS ? macOs : windows;
7 |
8 | export { default as os } from './src/os';
9 |
10 | export const Box = macOs.Box;
11 | export const Button = select(macOs.Button, windows.Button);
12 | export const Checkbox = select(macOs.Checkbox, windows.Checkbox);
13 |
14 | export const Dialog = macOs.Dialog;
15 | export const Label = select(macOs.Label, windows.Label);
16 | export const Link = macOs.Link;
17 | export const ListView = macOs.ListView;
18 | export const ListViewFooter = macOs.ListViewFooter;
19 | export const ListViewHeader = macOs.ListViewHeader;
20 | export const ListViewRow = macOs.ListViewRow;
21 | export const ListViewSection = macOs.ListViewSection;
22 | export const ListViewSectionHeader = macOs.ListViewSectionHeader;
23 | export const ListViewSeparator = macOs.ListViewSeparator;
24 | export const MasterDetailsView = windows.MasterDetailsView;
25 | export const MasterDetailsViewItem = windows.MasterDetailsViewItem;
26 | export const MasterDetailsViewItemMaster = windows.MasterDetailsViewItemMaster;
27 | export const MasterDetailsViewItemDetails = windows.MasterDetailsViewItemDetails;
28 | export const NavPane = windows.NavPane;
29 | export const NavPaneItem = windows.NavPaneItem;
30 | export const Pin = macOs.Pin;
31 | export const ProgressCircle = select(macOs.ProgressCircle, windows.ProgressCircle);
32 | export const Radio = select(macOs.Radio, windows.Radio);
33 | export const SearchField = macOs.SearchField;
34 | export const SegmentedControl = macOs.SegmentedControl;
35 | export const SegmentedControlItem = macOs.SegmentedControlItem;
36 | export const Text = select(macOs.Text, windows.Text);
37 | export const TextInput = select(macOs.TextInput, windows.TextInput);
38 | export const TitleBar = select(macOs.TitleBar, windows.TitleBar);
39 | export const Toolbar = macOs.Toolbar;
40 | export const ToolbarNav = macOs.ToolbarNav;
41 | export const ToolbarNavItem = macOs.ToolbarNavItem;
42 | export const View = select(macOs.View, windows.View);
43 | export const Window = select(macOs.Window, windows.Window);
44 |
--------------------------------------------------------------------------------
/macOs.js:
--------------------------------------------------------------------------------
1 | export { default as Box } from './src/Box/macOs';
2 | export { default as Button } from './src/Button/macOs';
3 | export { default as Checkbox } from './src/Checkbox/macOs';
4 | export { default as Dialog } from './src/Dialog/macOs';
5 | export { default as Label } from './src/Label/macOs';
6 | export { default as Link } from './src/Link/macOs';
7 | export { default as ListView } from './src/ListView/macOs';
8 | export { default as ListViewFooter } from './src/ListView/macOs/Footer';
9 | export { default as ListViewHeader } from './src/ListView/macOs/Header';
10 | export { default as ListViewRow } from './src/ListView/macOs/Row';
11 | export { default as ListViewSection } from './src/ListView/macOs/Section';
12 | export { default as ListViewSectionHeader } from './src/ListView/macOs/Header';
13 | export { default as ListViewSeparator } from './src/ListView/macOs/Separator';
14 | export { default as Pin } from './src/Pin/macOs';
15 | export { default as ProgressCircle } from './src/ProgressCircle/macOs';
16 | export { default as Radio } from './src/Radio/macOs';
17 | export { default as SearchField } from './src/SearchField/macOs';
18 | export { default as SegmentedControl } from './src/SegmentedControl/macOs';
19 | export {
20 | default as SegmentedControlItem
21 | } from './src/SegmentedControl/macOs/Item';
22 | export { default as Text } from './src/Text/macOs';
23 | export { default as TextInput } from './src/TextInput/macOs';
24 | export { default as TextArea } from './src/TextArea/macOs';
25 | export { default as TitleBar } from './src/TitleBar/macOs';
26 | export { default as Toolbar } from './src/Toolbar/macOs';
27 | export { default as ToolbarNav } from './src/Toolbar/macOs/Nav';
28 | export { default as ToolbarNavItem } from './src/Toolbar/macOs/Nav/Item';
29 | export { default as View } from './src/View/macOs';
30 | export { default as Window } from './src/Window/macOs';
31 |
--------------------------------------------------------------------------------
/playground/assets/background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielbull/react-desktop/bba61374849dec896a9eea321cf4e3f02b3fd4c6/playground/assets/background.jpg
--------------------------------------------------------------------------------
/playground/assets/picture.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielbull/react-desktop/bba61374849dec896a9eea321cf4e3f02b3fd4c6/playground/assets/picture.jpg
--------------------------------------------------------------------------------
/playground/examplesLoader.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs');
2 | var path = require('path');
3 |
4 | function scanDir(dir) {
5 | var files = fs.readdirSync(dir);
6 | var filepath;
7 | var subFiles;
8 | var returnValue = [];
9 | for (var i = 0, len = files.length; i < len; ++i) {
10 | if (files[i].charAt(0) !== '.') {
11 | filepath = path.resolve(path.join(dir, files[i]));
12 | if (fs.lstatSync(filepath).isDirectory()) {
13 | subFiles = scanDir(path.join(dir, files[i]));
14 | returnValue.push.apply(returnValue, subFiles);
15 | } else {
16 | returnValue.push({
17 | file: path.join(dir, files[i]),
18 | filepath: filepath
19 | });
20 | }
21 | }
22 | }
23 | return returnValue;
24 | }
25 |
26 | module.exports = function(source) {
27 | var dirname = path.join(__dirname, '..');
28 | var files = scanDir(path.join(dirname, 'examples'));
29 | var file;
30 |
31 | source = 'let data = {};\n';
32 | for (var i = 0, len = files.length; i < len; ++i) {
33 | file = files[i];
34 | var filename = file.file.replace(dirname, '').replace(/\.js$/, '');
35 | var key = filename.replace(/[\/\-]/g, '_');
36 | source += 'import ' + key + ' from \'.' + filename + '\';\n';
37 | source += 'data[\'' + filename + '\'] = ' + key + ';\n';
38 | }
39 |
40 | source += 'export default data;';
41 |
42 | return source;
43 | };
44 |
--------------------------------------------------------------------------------
/playground/index.js:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { render } from 'react-dom';
3 | import Playground from './playground';
4 |
5 | document.title = 'React Desktop Playground';
6 | document.documentElement.style.width = '100%';
7 | document.documentElement.style.height = '100%';
8 | document.body.style.background = 'white';
9 | document.body.style.backgroundImage = 'url(assets/background.jpg)';
10 | document.body.style.backgroundSize = 'cover';
11 | document.body.style.margin = '0';
12 | document.body.style.padding = '0';
13 | document.body.style.width = '100%';
14 | document.body.style.height = '100%';
15 | document.body.style.overflow = 'hidden';
16 |
17 | document.body.innerHTML = `
18 |
19 | `;
20 |
21 | render(, document.getElementById('main'));
22 |
--------------------------------------------------------------------------------
/playground/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var HtmlWebpackPlugin = require('html-webpack-plugin');
3 |
4 | module.exports = {
5 | entry: path.join(__dirname, 'index.js'),
6 |
7 | output: {
8 | path: path.join(__dirname),
9 | filename: 'bundle.js',
10 | publicPath: '/'
11 | },
12 |
13 | devServer: {
14 | filename: 'index.js',
15 | contentBase: './playground'
16 | },
17 |
18 | devtool: 'source-map',
19 |
20 | resolveLoader: {
21 | alias: {
22 | 'examples-loader': path.join(__dirname, 'examplesLoader')
23 | }
24 | },
25 |
26 | resolve: {
27 | alias: {
28 | 'react-desktop': path.join(__dirname, '..'),
29 | 'examples': path.join(__dirname, '..', 'index.js'),
30 | }
31 | },
32 |
33 | module: {
34 | rules: [
35 | {
36 | test: /\.(js)$/,
37 | exclude: /node_modules/,
38 | use: 'babel-loader'
39 | }
40 | ]
41 | },
42 |
43 | plugins: [
44 | new HtmlWebpackPlugin()
45 | ]
46 | };
47 |
--------------------------------------------------------------------------------
/src/Box/macOs/styles/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | wrapper: {
3 | WebkitUserSelect: 'none',
4 | userSelect: 'none',
5 | cursor: 'default',
6 | flex: '1'
7 | },
8 |
9 | box: {
10 | backgroundColor: 'rgba(0, 0, 0, .04)',
11 | borderWidth: '1px',
12 | borderStyle: 'solid',
13 | borderTopColor: 'rgba(0, 0, 0, .07)',
14 | borderLeftColor: 'rgba(0, 0, 0, .037)',
15 | borderRightColor: 'rgba(0, 0, 0, .037)',
16 | borderBottomColor: 'rgba(0, 0, 0, .026)',
17 | borderRadius: '4px',
18 | position: 'relative',
19 | padding: '23px 18px 22px 18px'
20 | },
21 |
22 | segmentedControls: {
23 | marginTop: '10px',
24 | paddingTop: '33px'
25 | }
26 | };
27 |
--------------------------------------------------------------------------------
/src/Button/macOs/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import WindowFocus from '../../windowFocus';
4 | import Hidden, { hiddenPropTypes } from '../../style/hidden';
5 | import FontSize, { fontSizePropTypes } from '../../style/fontSize';
6 | import Padding, { paddingPropTypes, removeDuplicatePaddingProps } from '../../style/padding';
7 | import Margin, { marginPropTypes } from '../../style/margin';
8 | import styles from './styles/10.11';
9 | import Radium from 'radium';
10 |
11 | @WindowFocus()
12 | @Padding()
13 | @Margin()
14 | @Hidden()
15 | @FontSize()
16 | @Radium
17 | class Button extends Component {
18 | static propTypes = {
19 | ...hiddenPropTypes,
20 | ...fontSizePropTypes,
21 | ...paddingPropTypes,
22 | ...marginPropTypes,
23 | type: PropTypes.string,
24 | color: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
25 | onClick: PropTypes.func,
26 | onEnter: PropTypes.func,
27 | disabled: PropTypes.bool
28 | };
29 |
30 | componentDidMount() {
31 | if (window && this.props.onEnter) {
32 | window.addEventListener('keyup', this.handleKeyUp);
33 | }
34 | }
35 |
36 | componentWillUnmount() {
37 | if (window && this.props.onEnter) {
38 | window.removeEventListener('keyup', this.handleKeyUp);
39 | }
40 | }
41 |
42 | handleKeyUp = e => {
43 | if (e.keyCode === 13) {
44 | if (this.props.onEnter && !this.props.disabled) this.props.onEnter(e);
45 | }
46 | };
47 |
48 | render() {
49 | let { style, type, children, color, onClick, isWindowFocused, disabled, ...props } = this.props;
50 | delete props.onEnter;
51 |
52 | let componentStyle = { ...styles.button };
53 | if (!disabled && color === 'blue' && isWindowFocused) {
54 | componentStyle = { ...componentStyle, ...styles.blue };
55 | } else if (disabled) {
56 | componentStyle = { ...componentStyle, opacity: '.5' };
57 | }
58 |
59 | componentStyle = { ...componentStyle, ...style };
60 |
61 | return (
62 |
72 | );
73 | }
74 | }
75 |
76 | export default Button;
77 |
--------------------------------------------------------------------------------
/src/Button/macOs/styles/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | button: {
3 | WebkitUserSelect: 'none',
4 | userSelect: 'none',
5 | cursor: 'default',
6 | backgroundColor: '#ffffff',
7 | outline: 'none',
8 | borderWidth: '1px',
9 | borderStyle: 'solid',
10 | borderRadius: '5px',
11 | borderTopColor: '#c8c8c8',
12 | borderBottomColor: '#acacac',
13 | borderLeftColor: '#c2c2c2',
14 | borderRightColor: '#c2c2c2',
15 | boxShadow: '0 1px rgba(0, 0, 0, .039)',
16 | paddingTop: 0,
17 | paddingBottom: 0,
18 | paddingLeft: '13px',
19 | paddingRight: '13px',
20 | lineHeight: '19px',
21 | fontFamily: '-apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif',
22 | fontSize: '13px',
23 |
24 | ':active': {
25 | backgroundImage: '-webkit-linear-gradient(top, #4c98fe 0%, #0564e3 100%)',
26 | borderTopColor: '#247fff',
27 | borderBottomColor: '#003ddb',
28 | borderLeftColor: '#125eed',
29 | borderRightColor: '#125eed',
30 | color: 'rgba(255, 255, 255, .9 )'
31 | }
32 | },
33 |
34 | blue: {
35 | backgroundImage: '-webkit-linear-gradient(top, #6cb3fa 0%, #087eff 100%)',
36 | borderTopColor: '#4ca2f9',
37 | borderBottomColor: '#015cff',
38 | borderLeftColor: '#267ffc',
39 | borderRightColor: '#267ffc',
40 | color: 'rgba(255, 255, 255, .9)',
41 |
42 | ':active': {
43 | backgroundImage: '-webkit-linear-gradient(top, #4c98fe 0%, #0564e3 100%)',
44 | borderTopColor: '#247fff',
45 | borderBottomColor: '#003ddb',
46 | borderLeftColor: '#125eed',
47 | borderRightColor: '#125eed',
48 | color: 'rgba(255, 255, 255, .9 )'
49 | }
50 | }
51 | };
52 |
--------------------------------------------------------------------------------
/src/Button/windows/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { colorPropTypes, colorContextTypes } from '../../style/color/windows';
4 | import { ThemeContext, themePropTypes } from '../../style/theme/windows';
5 | import Hidden, { hiddenPropTypes } from '../../style/hidden';
6 | import Radium from 'radium';
7 | import { darkenColor } from '../../color';
8 | import styles from './styles/windows10';
9 |
10 | @Hidden()
11 | @ThemeContext()
12 | @Radium
13 | class Button extends Component {
14 | static propTypes = {
15 | ...hiddenPropTypes,
16 | ...colorPropTypes,
17 | ...themePropTypes,
18 | type: PropTypes.string,
19 | push: PropTypes.bool,
20 | onClick: PropTypes.func
21 | };
22 |
23 | static contextTypes = {
24 | ...colorContextTypes
25 | };
26 |
27 | render() {
28 | let { style, type, children, color, push, onClick, ...props } = this.props;
29 |
30 | let componentStyle = { ...styles.button, ...style };
31 |
32 | if (color) {
33 | color = color === true ? this.context.color : color;
34 | styles.colorButton = {
35 | ...styles.colorButton,
36 | borderColor: color,
37 | backgroundColor: color,
38 | ':hover': {
39 | ...styles.colorButton[':hover'],
40 | borderColor: darkenColor(color, .35)
41 | },
42 |
43 | ':active': {
44 | ...styles.colorButton[':active'],
45 | borderColor: darkenColor(color, .35),
46 | backgroundColor: darkenColor(color, .35)
47 | }
48 | };
49 | componentStyle = { ...componentStyle, ...styles.colorButton };
50 | }
51 |
52 | if (push) {
53 | componentStyle[':active'] = { ...componentStyle[':active'], ...styles.pushTransform };
54 | }
55 |
56 | return (
57 |
66 | );
67 | }
68 | }
69 |
70 | export default Button;
71 |
--------------------------------------------------------------------------------
/src/Button/windows/styles/windows10.js:
--------------------------------------------------------------------------------
1 | export default {
2 | button: {
3 | WebkitUserSelect: 'none',
4 | userSelect: 'none',
5 | cursor: 'default',
6 | backgroundColor: '#cccccc',
7 | outline: 'none',
8 | borderWidth: '2px',
9 | borderStyle: 'solid',
10 | borderColor: '#cccccc',
11 | paddingTop: 0,
12 | paddingBottom: 0,
13 | paddingLeft: '32px',
14 | paddingRight: '32px',
15 | lineHeight: '28px',
16 | fontFamily: '"Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif',
17 | fontSize: '15px',
18 | color: '#000000',
19 |
20 | ':hover': {
21 | color: '#000000',
22 | borderColor: '#7a7a7a'
23 | },
24 |
25 | ':active': {
26 | color: '#000000',
27 | borderColor: '#999999',
28 | backgroundColor: '#999999'
29 | }
30 | },
31 |
32 | colorButton: {
33 | color: '#ffffff',
34 | borderColor: '#0078d7',
35 | backgroundColor: '#0078d7',
36 |
37 | ':hover': {
38 | borderColor: '#004e8c'
39 | },
40 |
41 | ':active': {
42 | borderColor: '#004e8c',
43 | backgroundColor: '#004e8c'
44 | }
45 | },
46 |
47 | pushTransform: {
48 | transform: 'scale(0.97)',
49 | transition: 'transform .1s ease-in'
50 | }
51 | };
52 |
--------------------------------------------------------------------------------
/src/Checkbox/macOs/Checkmark.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Radium from 'radium';
4 | import styles from './styles/10.11';
5 |
6 | @Radium
7 | class Checkmark extends Component {
8 | static propTypes = {
9 | show: PropTypes.bool,
10 | color: PropTypes.string,
11 | shadowColor: PropTypes.string
12 | };
13 |
14 | static defaultProps = {
15 | color: '#FFFFFF'
16 | };
17 |
18 | render() {
19 | const { color, shadowColor } = this.props;
20 | let style = { ...styles.checkmark };
21 | style.opacity = '0';
22 | style.transform = 'scale(0)';
23 | style.transition = 'all 0.5s';
24 |
25 | if (this.props.show) {
26 | style.opacity = '1';
27 | style.transform = 'scale(1)';
28 | }
29 |
30 | return (
31 |
32 |
39 |
46 |
47 | );
48 | }
49 | }
50 |
51 | export default Checkmark;
52 |
--------------------------------------------------------------------------------
/src/Checkbox/macOs/styles/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | container: {
3 | display: 'flex'
4 | },
5 |
6 | label: {
7 | display: 'flex',
8 | height: '20px',
9 | position: 'relative',
10 |
11 | ':hover': {},
12 | ':active': {}
13 | },
14 |
15 | inputWrapper: {
16 | position: 'relative',
17 | marginRight: '3px',
18 | paddingTop: '1px'
19 | },
20 |
21 | checkbox: {
22 | WebkitUserSelect: 'none',
23 | userSelect: 'none',
24 | WebkitAppearance: 'none',
25 | appearance: 'none',
26 | borderWidth: '1px',
27 | borderStyle: 'solid',
28 | borderColor: '#b8b8b8',
29 | borderRadius: '3px',
30 | backgroundColor: '#ffffff',
31 | padding: '6px',
32 | margin: '0 1px',
33 | boxShadow: 'inset 0 1px 0 0 rgba(224, 224, 224, .4)',
34 | transition: 'all 0.4s',
35 |
36 | ':focus': {
37 | outline: 'none'
38 | }
39 | },
40 |
41 | 'checkbox:active': {
42 | borderColor: '#a4a4a4',
43 | backgroundColor: '#f0f0f0',
44 | boxShadow: 'inset 0 0 0 1px rgba(117, 117, 117, .35)',
45 | transition: 'all 0.4s'
46 | },
47 |
48 | 'checkbox:checked': {
49 | backgroundColor: '#3b99fc',
50 | boxShadow: 'none',
51 | borderColor: '#2c91fc',
52 | transition: 'all 0.4s'
53 | },
54 |
55 | 'checkbox:checked:unfocused': {
56 | backgroundColor: '#ffffff',
57 | boxShadow: 'none',
58 | borderColor: '#b8b8b8',
59 | transition: 'none'
60 | },
61 |
62 | 'checkbox:checked:active': {
63 | backgroundColor: '#0080f6',
64 | borderColor: '#006adc',
65 | boxShadow: 'inset 0 0 0 1px rgba(19, 68, 119, .22)',
66 | transition: 'all 0.4s'
67 | },
68 |
69 | checkmark: {
70 | position: 'absolute',
71 | top: '4px',
72 | left: '4px',
73 | width: '8px',
74 | height: '8px'
75 | },
76 |
77 | svg: {
78 | zIndex: '2',
79 | position: 'absolute',
80 | top: '0px',
81 | left: '0px',
82 | height: '8px'
83 | },
84 |
85 | svgShadow: {
86 | zIndex: '1',
87 | position: 'absolute',
88 | top: '1.5px',
89 | left: '0px',
90 | opacity: '.37',
91 | height: '8px',
92 | filter: 'blur(.5px)'
93 | }
94 | };
95 |
--------------------------------------------------------------------------------
/src/Checkbox/windows/styles/windows10.js:
--------------------------------------------------------------------------------
1 | export default {
2 | container: {
3 | display: 'flex',
4 | marginBottom: '22px'
5 | },
6 |
7 | label: {
8 | display: 'flex',
9 | alignItems: 'center',
10 | position: 'relative',
11 |
12 | ':hover': {},
13 | ':active': {}
14 | },
15 |
16 | text: {
17 | WebkitUserSelect: 'none',
18 | userSelect: 'none',
19 | fontFamily: '"Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif',
20 | fontSize: '15px',
21 | marginTop: '1px',
22 | color: '#000000'
23 | },
24 |
25 | textDark: {
26 | color: '#ffffff'
27 | },
28 |
29 | inputWrapper: {
30 | position: 'relative',
31 | marginRight: '3px',
32 | paddingTop: '1px'
33 | },
34 |
35 | checkbox: {
36 | WebkitUserSelect: 'none',
37 | userSelect: 'none',
38 | WebkitAppearance: 'none',
39 | appearance: 'none',
40 | outline: 'none',
41 | borderWidth: '2px',
42 | borderStyle: 'solid',
43 | borderColor: 'rgba(0, 0, 0, .8)',
44 | padding: '8px',
45 | color: '#fff',
46 | verticalAlign: 'bottom',
47 | marginRight: '6px',
48 |
49 | ':focus': {
50 | outline: 'none'
51 | }
52 | },
53 |
54 | checkboxDark: {
55 | borderColor: 'rgba(255, 255, 255, .82)',
56 | },
57 |
58 | 'checkbox:active': {
59 | borderColor: 'rgba(0, 0, 0, 0)',
60 | backgroundColor: 'rgba(0, 0, 0, .57)'
61 | },
62 |
63 | 'checkbox:hover': {
64 | borderColor: 'rgba(0, 0, 0, 1)'
65 | },
66 |
67 | 'checkbox:checked': {
68 | backgroundColor: '#007CD1',
69 | borderColor: '#007CD1'
70 | },
71 |
72 | 'checkboxDark:active': {
73 | borderColor: 'rgba(255, 255, 255, 0)',
74 | backgroundColor: 'rgba(255, 255, 255, .63)'
75 | },
76 |
77 | 'checkboxDark:hover': {
78 | borderColor: 'rgba(255, 255, 255, 1)'
79 | },
80 |
81 | 'checkboxDark:checked': {
82 | backgroundColor: '#007CD1',
83 | borderColor: '#007CD1'
84 | },
85 |
86 | svg: {
87 | position: 'absolute',
88 | top: '6px',
89 | left: '5px',
90 | color: '#fff',
91 | height: '16px'
92 | }
93 | };
94 |
--------------------------------------------------------------------------------
/src/Dialog/macOs/style/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | container: {
3 | MozUserSelect: 'none',
4 | WebkitUserSelect: 'none',
5 | MsUserSelect: 'none',
6 | userSelect: 'none',
7 | WebkitUserDrag: 'none',
8 | userDrag: 'none',
9 | WebkitTouchCallout: 'none',
10 | display: 'flex',
11 | position: 'relative'
12 | },
13 | icon: {
14 | width: '67px',
15 | marginRight: '20px',
16 | display: 'flex',
17 | justifyContent: 'center',
18 | },
19 | contentContainer: {
20 | flex: 1
21 | },
22 | title: {
23 | marginBottom: '5px'
24 | },
25 | message: {
26 | marginBottom: '16px'
27 | },
28 | content: {
29 | display: 'flex',
30 | flexDirection: 'column',
31 | marginBottom: '16px',
32 | position: 'relative'
33 | },
34 | buttons: {
35 | display: 'flex',
36 | justifyContent: 'flex-end'
37 | },
38 | buttonContainer: {
39 | marginLeft: '14px'
40 | }
41 | };
42 |
--------------------------------------------------------------------------------
/src/Label/macOs/index.js:
--------------------------------------------------------------------------------
1 | import Label from '../../Text/macOs';
2 |
3 | export default Label;
4 |
--------------------------------------------------------------------------------
/src/Label/windows/index.js:
--------------------------------------------------------------------------------
1 | import Label from '../../Text/windows';
2 |
3 | export default Label;
4 |
--------------------------------------------------------------------------------
/src/Link/macOs/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Margin, { marginPropTypes } from '../../style/margin';
4 | import Padding, { paddingPropTypes } from '../../style/padding';
5 | import FontSize, { fontSizePropTypes } from '../../style/fontSize';
6 | import Dimension, { dimensionPropTypes } from '../../style/dimension';
7 | import TextAlign, { textAlignPropTypes } from '../../style/textAlign';
8 | import Hidden, { hiddenPropTypes } from '../../style/hidden';
9 |
10 | const componentStyle = {
11 | display: 'inline-block',
12 | WebkitUserSelect: 'none',
13 | userSelect: 'none',
14 | cursor: 'default',
15 | fontFamily: '-apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif',
16 | fontSize: '11px',
17 | textDecoration: 'none'
18 | };
19 |
20 | @Margin()
21 | @Padding()
22 | @FontSize()
23 | @Dimension()
24 | @TextAlign()
25 | @Hidden()
26 | class Link extends Component {
27 | static propTypes = {
28 | ...marginPropTypes,
29 | ...paddingPropTypes,
30 | ...fontSizePropTypes,
31 | ...dimensionPropTypes,
32 | ...textAlignPropTypes,
33 | ...hiddenPropTypes,
34 | color: PropTypes.string
35 | };
36 |
37 | static defaultProps = {
38 | color: '#009df0'
39 | };
40 |
41 | render() {
42 | const { color, children, style, ...props } = this.props;
43 |
44 | return (
45 |
46 | {children}
47 |
48 | );
49 | }
50 | }
51 |
52 | export default Link;
53 |
--------------------------------------------------------------------------------
/src/ListView/macOs/Footer/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import Background, { backgroundPropTypes } from '../../../style/background/macOs';
3 | import Dimension, { dimensionPropTypes } from '../../../style/dimension';
4 | import Padding, { paddingPropTypes } from '../../../style/padding';
5 | import styles from './style/10.11';
6 |
7 | @Background({ background: '#f0f0f0' })
8 | @Dimension()
9 | @Padding({ paddingLeft: '10px', paddingRight: '10px', paddingTop: '2px', paddingBottom: '2px' })
10 | class Footer extends Component {
11 | static propTypes = {
12 | ...backgroundPropTypes,
13 | ...dimensionPropTypes,
14 | ...paddingPropTypes
15 | };
16 |
17 | render() {
18 | const { children, style, ...props } = this.props;
19 |
20 | return (
21 |
24 | );
25 | }
26 | }
27 |
28 | export default Footer;
29 |
--------------------------------------------------------------------------------
/src/ListView/macOs/Footer/style/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | header: {
3 | top: '0px',
4 | left: '0px',
5 | width: '100%',
6 | borderTopWidth: '1px',
7 | borderTopStyle: 'solid',
8 | borderTopColor: '#c9c9c9',
9 | boxSizing: 'border-box'
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/src/ListView/macOs/Header/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import Background, { backgroundPropTypes } from '../../../style/background/macOs';
3 | import Dimension, { dimensionPropTypes } from '../../../style/dimension';
4 | import Padding, { paddingPropTypes } from '../../../style/padding';
5 | import styles from './style/10.11';
6 |
7 | @Background({ background: '#f0f0f0' })
8 | @Dimension()
9 | @Padding({ paddingLeft: '10px', paddingRight: '10px', paddingTop: '2px', paddingBottom: '2px' })
10 | class Header extends Component {
11 | static propTypes = {
12 | ...backgroundPropTypes,
13 | ...dimensionPropTypes,
14 | ...paddingPropTypes
15 | };
16 |
17 | render() {
18 | const { children, style, ...props } = this.props;
19 |
20 | return (
21 |
24 | );
25 | }
26 | }
27 |
28 | export default Header;
29 |
--------------------------------------------------------------------------------
/src/ListView/macOs/Header/style/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | header: {
3 | top: '0px',
4 | left: '0px',
5 | width: '100%',
6 | borderBottomWidth: '1px',
7 | borderBottomStyle: 'solid',
8 | borderBottomColor: '#c9c9c9',
9 | boxSizing: 'border-box'
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/src/ListView/macOs/Row/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Background, { backgroundPropTypes } from '../../../style/background/macOs';
4 | import Alignment, { alignmentPropTypes } from '../../../style/alignment';
5 | import Dimension, { dimensionPropTypes } from '../../../style/dimension';
6 | import Hidden, { hiddenPropTypes } from '../../../style/hidden';
7 | import Margin, { marginPropTypes } from '../../../style/margin';
8 | import Padding, { paddingPropTypes } from '../../../style/padding';
9 | import styles from './style/10.11';
10 |
11 | @Background()
12 | @Alignment()
13 | @Dimension()
14 | @Hidden()
15 | @Margin({ marginTop: '4px', marginBottom: '4px' })
16 | @Padding({ paddingLeft: '18px', paddingRight: '18px', paddingTop: '5px', paddingBottom: '5px' })
17 | class Row extends Component {
18 | static propTypes = {
19 | ...backgroundPropTypes,
20 | ...alignmentPropTypes,
21 | ...dimensionPropTypes,
22 | ...hiddenPropTypes,
23 | ...marginPropTypes,
24 | ...paddingPropTypes,
25 | layout: PropTypes.string
26 | };
27 |
28 | static defaultProps = {
29 | layout: 'horizontal'
30 | };
31 |
32 | render() {
33 | const { horizontalAlignment, children, style, layout, ...props } = this.props;
34 |
35 | let componentStyle = { ...styles.row };
36 |
37 | if (layout === 'vertical') {
38 | componentStyle.flexDirection = 'column';
39 | if (horizontalAlignment) {
40 | switch(horizontalAlignment) {
41 | case 'center': componentStyle.alignItems = 'center'; break;
42 | case 'left': componentStyle.alignItems = 'flex-start'; break;
43 | case 'right': componentStyle.alignItems = 'flex-end'; break;
44 | }
45 | }
46 | } else {
47 | if (horizontalAlignment) {
48 | switch(horizontalAlignment) {
49 | case 'center': componentStyle.justifyContent = 'center'; break;
50 | case 'left': componentStyle.justifyContent = 'flex-start'; break;
51 | case 'right': componentStyle.justifyContent = 'flex-end'; break;
52 | }
53 | }
54 | }
55 |
56 | return (
57 |
58 | {children}
59 |
60 | );
61 | }
62 | }
63 |
64 | export default Row;
65 |
--------------------------------------------------------------------------------
/src/ListView/macOs/Row/style/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | row: {
3 | WebkitUserSelect: 'none',
4 | userSelect: 'none',
5 | cursor: 'default',
6 | display: 'flex',
7 | position: 'relative'
8 | }
9 | };
10 |
--------------------------------------------------------------------------------
/src/ListView/macOs/Section/Header/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import styles from './style/10.11';
4 | import Text from '../../../../Text/macOs';
5 | import Margin, {
6 | marginPropTypes,
7 | removeMarginProps
8 | } from '../../../../style/margin';
9 | import Padding, {
10 | paddingPropTypes,
11 | removePaddingProps
12 | } from '../../../../style/padding';
13 | import { fontSizePropTypes } from '../../../../style/fontSize';
14 | import mapStyles from '../../../../utils/mapStyles';
15 |
16 | class Header extends Component {
17 | static propTypes = {
18 | ...marginPropTypes,
19 | ...paddingPropTypes,
20 | ...fontSizePropTypes,
21 | color: PropTypes.string,
22 | bold: PropTypes.oneOfType([
23 | PropTypes.bool,
24 | PropTypes.number,
25 | PropTypes.string
26 | ])
27 | };
28 |
29 | static defaultProps = {
30 | color: '#5a5b5c',
31 | bold: true,
32 | size: '10'
33 | };
34 |
35 | static mapStyles = {
36 | text: ['color', 'fontSize', 'fontWeight', 'lineHeight', 'fontFamily']
37 | };
38 |
39 | render() {
40 | let { color, bold, size, children, style, ...props } = this.props;
41 |
42 | props = removePaddingProps(removeMarginProps(props));
43 |
44 | let [headerStyle, textStyle] = mapStyles(style, Header.mapStyles);
45 |
46 | return (
47 |
48 | {Padding(
49 | Margin(
50 |
51 |
52 | {children}
53 |
54 |
,
55 | this.props
56 | ),
57 | this.props
58 | )}
59 |
60 | );
61 | }
62 | }
63 |
64 | export default Header;
65 |
--------------------------------------------------------------------------------
/src/ListView/macOs/Section/Header/style/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | title: {
3 | margin: '9px 0px',
4 | padding: '0px 10px',
5 | fontWeight: 'normal'
6 | }
7 | };
8 |
--------------------------------------------------------------------------------
/src/ListView/macOs/Section/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Header from './Header';
4 | import styles from './style/10.11';
5 |
6 | class Section extends Component {
7 | static propTypes = {
8 | header: PropTypes.oneOfType([
9 | PropTypes.string,
10 | PropTypes.element,
11 | PropTypes.array
12 | ])
13 | };
14 |
15 | render() {
16 | let { children, header, ...props } = this.props;
17 |
18 | if (typeof header === 'string') {
19 | header = ;
20 | }
21 |
22 | return (
23 |
27 | );
28 | }
29 | }
30 |
31 | export default Section;
32 |
--------------------------------------------------------------------------------
/src/ListView/macOs/Section/style/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | list: {
3 | listStyle: 'none',
4 | padding: '0px',
5 | margin: '0px'
6 | }
7 | };
8 |
--------------------------------------------------------------------------------
/src/ListView/macOs/Separator/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Dimension, { dimensionPropTypes } from '../../../style/dimension';
4 | import Hidden, { hiddenPropTypes } from '../../../style/hidden';
5 | import Margin, { marginPropTypes } from '../../../style/margin';
6 | import Padding, { paddingPropTypes } from '../../../style/padding';
7 | import styles from './style/10.11';
8 |
9 | @Dimension()
10 | @Hidden()
11 | @Margin({ marginLeft: '10px', marginRight: '10px', marginTop: '4px', marginBottom: '4px' })
12 | @Padding()
13 | class Separator extends Component {
14 | static propTypes = {
15 | ...dimensionPropTypes,
16 | ...hiddenPropTypes,
17 | ...marginPropTypes,
18 | ...paddingPropTypes,
19 | color: PropTypes.string,
20 | };
21 |
22 | static defaultProps = {
23 | color: '#e5e5e5'
24 | };
25 |
26 | render() {
27 | const { style, ...props } = this.props;
28 |
29 | return (
30 |
31 | );
32 | }
33 | }
34 |
35 | export default Separator;
36 |
--------------------------------------------------------------------------------
/src/ListView/macOs/Separator/style/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | separator: {
3 | height: '1px',
4 | margin: '0px',
5 | padding: '0px',
6 | border: 'none'
7 | }
8 | };
9 |
--------------------------------------------------------------------------------
/src/ListView/macOs/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component, Children } from 'react';
2 | import styles from './style/10.11';
3 | import Background, { backgroundPropTypes } from '../../style/background/macOs';
4 | import Dimension, { dimensionPropTypes } from '../../style/dimension';
5 | import Hidden, { hiddenPropTypes } from '../../style/hidden';
6 | import Margin, { marginPropTypes } from '../../style/margin';
7 | import Padding, { paddingPropTypes } from '../../style/padding';
8 | import Header from './Header';
9 | import Footer from './Footer';
10 | import Row from './Row';
11 |
12 | @Background()
13 | @Dimension()
14 | @Hidden()
15 | @Margin()
16 | @Padding()
17 | class ListView extends Component {
18 | static propTypes = {
19 | ...backgroundPropTypes,
20 | ...dimensionPropTypes,
21 | ...hiddenPropTypes,
22 | ...marginPropTypes,
23 | ...paddingPropTypes
24 | };
25 |
26 | mapChildren(children) {
27 | let hasDirectRows = false;
28 | let header = null,
29 | items = null,
30 | footer = null;
31 | Children.map(children, child => {
32 | const HeaderEl = ;
33 | const FooterEl = ;
34 | const RowEl =
;
35 |
36 | if (child.type === HeaderEl.type) return (header = child);
37 | else if (child.type === FooterEl.type) return (footer = child);
38 | else if (child.type === RowEl.type) hasDirectRows = true;
39 |
40 | if (!items) items = [];
41 | items.push(child);
42 | });
43 |
44 | if (hasDirectRows) {
45 | items = ;
46 | }
47 |
48 | return { header, items, footer };
49 | }
50 |
51 | render() {
52 | const { children, style, ...props } = this.props;
53 |
54 | const { header, items, footer } = this.mapChildren(children);
55 |
56 | return (
57 |
58 | {header}
59 |
60 | {items}
61 |
62 | {footer}
63 |
64 | );
65 | }
66 | }
67 |
68 | export default ListView;
69 |
--------------------------------------------------------------------------------
/src/ListView/macOs/style/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | container: {
3 | position: 'relative',
4 | display: 'flex',
5 | flex: 1,
6 | height: '100%',
7 | flexDirection: 'column'
8 | },
9 |
10 | scrollable: {
11 | overflow: 'scroll',
12 | width: '100%',
13 | display: 'flex',
14 | flex: 1,
15 | flexDirection: 'column'
16 | },
17 |
18 | list: {
19 | listStyle: 'none',
20 | padding: '0px',
21 | margin: '0px',
22 | }
23 | };
24 |
--------------------------------------------------------------------------------
/src/MasterDetailsView/windows/Details/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { convertColor } from '../../../color';
4 | import { ColorContext, colorPropTypes, colorContextTypes } from '../../../style/color/windows';
5 | import { ThemeContext, themePropTypes } from '../../../style/theme/windows';
6 |
7 | const styles = {
8 | details: {
9 | display: 'flex',
10 | flexWrap: 'nowrap',
11 | position: 'relative',
12 | flex: '1'
13 | }
14 | };
15 |
16 | @ColorContext()
17 | @ThemeContext()
18 | class Details extends Component {
19 | static propTypes = {
20 | ...colorPropTypes,
21 | ...themePropTypes,
22 | background: PropTypes.oneOfType([PropTypes.string, PropTypes.bool])
23 | };
24 |
25 | static childContextTypes = {
26 | background: PropTypes.string
27 | };
28 |
29 | static contextTypes = {
30 | ...colorContextTypes
31 | };
32 |
33 | getChildContext() {
34 | return {
35 | background: typeof this.props.background === 'string' ? this.props.background : this.context.color
36 | };
37 | }
38 |
39 | render() {
40 | const { children, style, background, ...props } = this.props;
41 | delete props.index;
42 | let componentStyle = { ...styles.details, ...style };
43 |
44 | if (background === true) {
45 | componentStyle.backgroundColor = convertColor(this.context.color);
46 | } else if (typeof background === 'string') {
47 | componentStyle.backgroundColor = convertColor(background);
48 | }
49 |
50 | return (
51 |
55 | {children}
56 |
57 | );
58 | }
59 | }
60 |
61 | export default Details;
62 |
--------------------------------------------------------------------------------
/src/MasterDetailsView/windows/Item/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Master from '../Master';
4 | import Details from '../Details';
5 | import { ColorContext, colorPropTypes } from '../../../style/color/windows';
6 | import { ThemeContext, themePropTypes } from '../../../style/theme/windows';
7 |
8 | const styles = {
9 | display: 'flex',
10 | flexWrap: 'nowrap',
11 | position: 'relative',
12 | flex: '1'
13 | };
14 |
15 | let warnOnceMaster = false;
16 | let warnOnceDetails = false;
17 | function applyChildenClasses() {
18 | return function(ComposedComponent) {
19 | const nextMaster = Master;
20 | ComposedComponent.prototype.Master = ComposedComponent.Master = function(
21 | ...args
22 | ) {
23 | if (!warnOnceMaster) {
24 | warnOnceMaster = true;
25 | console.warn(
26 | 'React Desktop: Using MasterDetailsView.Item.Master is deprecated, import MasterDetailsViewItemMaster instead.'
27 | );
28 | }
29 | return new nextMaster(...args);
30 | };
31 | const nextDetails = Details;
32 | ComposedComponent.prototype.Details = ComposedComponent.Details = function(
33 | ...args
34 | ) {
35 | if (!warnOnceDetails) {
36 | warnOnceDetails = true;
37 | console.warn(
38 | 'React Desktop: Using MasterDetailsView.Item.Details is deprecated, import MasterDetailsViewItemDetails instead.'
39 | );
40 | }
41 | return new nextDetails(...args);
42 | };
43 | return ComposedComponent;
44 | };
45 | }
46 |
47 | @applyChildenClasses()
48 | @ColorContext()
49 | @ThemeContext()
50 | class Item extends Component {
51 | static propTypes = {
52 | ...colorPropTypes,
53 | ...themePropTypes,
54 | selected: PropTypes.bool
55 | };
56 |
57 | constructor(props, context, updater) {
58 | super(props, context, updater);
59 | this.state = {
60 | selected: props.selected ? props.selected : false
61 | };
62 | }
63 |
64 | render() {
65 | const { children, style, ...props } = this.props;
66 |
67 | return (
68 |
69 | {children}
70 |
71 | );
72 | }
73 | }
74 |
75 | export default Item;
76 |
--------------------------------------------------------------------------------
/src/MasterDetailsView/windows/Pane.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { parseDimension } from '../../styleHelper';
3 | import { ThemeContext, themeContextTypes } from '../../style/theme/windows';
4 |
5 | const styles = {
6 | pane: {
7 | display: 'flex',
8 | flexDirection: 'column',
9 | flexWrap: 'nowrap',
10 | position: 'relative',
11 | flex: '0 0 320px',
12 | width: '320px'
13 | },
14 |
15 | paneDark: {
16 | }
17 | };
18 |
19 | @ThemeContext()
20 | class Pane extends Component {
21 | static contextTypes = {
22 | ...themeContextTypes
23 | };
24 |
25 | render() {
26 | const { children, style, ...props } = this.props;
27 |
28 | let componentStyle = { ...styles.pane, ...style };
29 |
30 | if (this.props.width) {
31 | componentStyle.width = parseDimension(this.props.width);
32 | componentStyle.flex = '0 0 ' + parseDimension(this.props.width);
33 | }
34 |
35 | if (this.context.theme === 'dark') {
36 | componentStyle = { ...componentStyle, ...styles.paneDark };
37 | }
38 |
39 | return (
40 |
44 | {children}
45 |
46 | );
47 | }
48 | }
49 |
50 | export default Pane;
51 |
--------------------------------------------------------------------------------
/src/NavPane/windows/Item/Content/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Padding, { paddingPropTypes } from '../../../../style/padding';
4 | import Margin, { marginPropTypes } from '../../../../style/margin';
5 | import Background, { backgroundPropTypes } from '../../../../style/background/windows';
6 | import Alignment, { alignmentPropTypes } from '../../../../style/alignment';
7 | import styles from '../../style/windows10';
8 |
9 | @Padding()
10 | @Margin()
11 | @Background()
12 | @Alignment()
13 | class Content extends Component {
14 | static propTypes = {
15 | ...paddingPropTypes,
16 | ...marginPropTypes,
17 | ...backgroundPropTypes,
18 | ...alignmentPropTypes,
19 | content: PropTypes.oneOfType([PropTypes.string, PropTypes.element, PropTypes.array])
20 | };
21 |
22 | render() {
23 | const { content, style, ...props } = this.props;
24 |
25 | return (
26 |
30 | {content}
31 |
32 | );
33 | }
34 | }
35 |
36 | export default Content;
37 |
--------------------------------------------------------------------------------
/src/NavPane/windows/Item/Title/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Radium, { keyframes } from 'radium';
4 | import styles from '../../style/windows10';
5 |
6 | var appear = keyframes({
7 | '0%': {
8 | opacity: 0
9 | },
10 | '29%': {
11 | opacity: 0,
12 | transform: 'translateY(9px)'
13 | },
14 | '30%': {
15 | opacity: .35,
16 | transform: 'translateY(9px)'
17 | },
18 | '100%': {
19 | opacity: 1,
20 | transform: 'translateY(0)'
21 | }
22 | }, 'Title');
23 |
24 | var fadeOut = keyframes({
25 | '0%': {
26 | opacity: 1
27 | },
28 | '100%': {
29 | opacity: 0
30 | }
31 | }, 'span');
32 |
33 |
34 | styles.titleAnimation = {
35 | animation: 'x 300ms forwards',
36 | animationName: appear
37 | };
38 |
39 | styles.fadeSpanStyle = {
40 | position: 'absolute',
41 | top: '0px',
42 | left: '0px',
43 | animation: 'x 100ms forwards',
44 | animationName: fadeOut
45 | };
46 |
47 | @Radium
48 | class Title extends Component {
49 | static propTypes = {
50 | theme: PropTypes.string,
51 | title: PropTypes.oneOfType([PropTypes.string, PropTypes.element, PropTypes.array])
52 | };
53 |
54 | render() {
55 | const { title, prevTitle } = this.props;
56 |
57 | let componentStyle = { ...styles.title };
58 | let fadeSpanStyle = { ...styles.title };
59 | let titleStyle = {};
60 |
61 | if (this.props.theme === 'dark') {
62 | componentStyle = { ...componentStyle, ...styles.titleDark };
63 | fadeSpanStyle = { ...fadeSpanStyle, ...styles.titleDark };
64 | }
65 |
66 | if (prevTitle && prevTitle !== title) {
67 | fadeSpanStyle = { ...fadeSpanStyle, ...styles.fadeSpanStyle };
68 | titleStyle = { ...titleStyle, opacity: 0, ...styles.titleAnimation }
69 | }
70 |
71 | let fadeSpan;
72 | if (prevTitle) {
73 | fadeSpan = (
74 |
75 | {prevTitle}
76 |
77 | );
78 | }
79 |
80 | return (
81 |
84 | {fadeSpan}
85 |
86 | {title}
87 |
88 |
89 | );
90 | }
91 | }
92 |
93 | export default Title;
94 |
--------------------------------------------------------------------------------
/src/NavPane/windows/Pane/Button/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Radium, { getState } from 'radium';
4 | import { transparentize } from '../../../../color';
5 | import { ColorContext, colorContextTypes } from '../../../../style/color/windows';
6 | import { ThemeContext, themeContextTypes } from '../../../../style/theme/windows';
7 |
8 | const styles = {
9 | svg: {
10 | ':hover': {},
11 | ':active': {}
12 | }
13 | };
14 |
15 | @ColorContext()
16 | @ThemeContext()
17 | @Radium
18 | class Button extends Component {
19 | static propTypes = {
20 | onClick: PropTypes.func
21 | };
22 |
23 | static contextTypes = {
24 | ...colorContextTypes,
25 | ...themeContextTypes
26 | };
27 |
28 | render() {
29 | let fill = this.context.theme === 'dark' ? '#ffffff' : '#000000';
30 |
31 | if (getState(this.state, null, ':active')) {
32 | fill = transparentize(this.context.color, .1);
33 | } else if (getState(this.state, null, ':hover')) {
34 | fill = transparentize(this.context.color, .2);
35 | }
36 |
37 | return (
38 |
50 | );
51 | }
52 | }
53 |
54 | export default Button;
55 |
--------------------------------------------------------------------------------
/src/NavPane/windows/Pane/style/windows10.js:
--------------------------------------------------------------------------------
1 | export default {
2 | pane: {
3 | cursor: 'default',
4 | WebkitUserSelect: 'none',
5 | userSelect: 'none',
6 | display: 'flex',
7 | position: 'relative',
8 | flexGrow: '0',
9 | flexShrink: '0',
10 | flexDirection: 'column',
11 | overflow: 'hidden'
12 | },
13 |
14 | padding: {
15 | height: '48px'
16 | },
17 |
18 | buttonStyle: {
19 | position: 'absolute',
20 | padding: '8px 10px',
21 | top: '7px',
22 | left: '4px',
23 | width: '20px',
24 | height: '20px',
25 | boxSizing: 'content-box'
26 | },
27 |
28 | anchor: {
29 | display: 'flex',
30 | alignItems: 'center',
31 | height: '44px',
32 |
33 | ':hover': {
34 | backgroundColor: 'rgba(0, 0, 0, .1)',
35 | },
36 | ':active': {
37 | backgroundColor: 'rgba(0, 0, 0, .2)',
38 | }
39 | },
40 |
41 | anchorDark: {
42 | ':hover': {
43 | backgroundColor: 'rgba(255, 255, 255, .1)',
44 | },
45 | ':active': {
46 | backgroundColor: 'rgba(255, 255, 255, .2)',
47 | }
48 | },
49 |
50 | anchorTitle: {
51 |
52 | },
53 |
54 | anchorIcon: {
55 | marginRight: '8px',
56 | height: '44px',
57 | display: 'flex',
58 | alignItems: 'center'
59 | },
60 |
61 | span: {
62 | display: 'flex',
63 | alignItems: 'center',
64 | color: '#000000',
65 | fontFamily: '"Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif',
66 | fontSize: '15px',
67 | letterSpacing: '0.4pt',
68 | padding: '0 16px',
69 | transition: 'transform .1s ease-in',
70 | userSelect: 'none'
71 | },
72 |
73 | spanDark: {
74 | color: '#ffffff',
75 | },
76 |
77 | pushTransformHover: {
78 | transition: 'transform .1s ease-in'
79 | },
80 |
81 | pushTransformActive: {
82 | transform: 'scale(0.97)',
83 | transition: 'transform 0s ease-in'
84 | }
85 | };
86 |
--------------------------------------------------------------------------------
/src/NavPane/windows/style/windows10.js:
--------------------------------------------------------------------------------
1 | export default {
2 | navPane: {
3 | display: 'flex',
4 | flexWrap: 'nowrap',
5 | position: 'relative',
6 | flex: '1'
7 | },
8 |
9 | navPaneItem: {
10 | position: 'relative',
11 | flexGrow: '1',
12 | flexShrink: '0',
13 | display: 'flex'
14 | },
15 |
16 | contentWrapper: {
17 | display: 'flex',
18 | flex: '1',
19 | flexDirection: 'column'
20 | },
21 |
22 | content: {
23 | display: 'flex',
24 | flex: '1',
25 | flexDirection: 'column'
26 | },
27 |
28 | title: {
29 | position: 'relative',
30 | color: '#000000',
31 | height: '48px',
32 | display: 'flex',
33 | alignItems: 'center',
34 | fontFamily: '"Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif',
35 | fontSize: '15px',
36 | textTransform: 'uppercase',
37 | padding: '0 24px',
38 | overflow: 'hidden',
39 | cursor: 'default',
40 | userSelect: 'none'
41 | },
42 |
43 | titleDark: {
44 | color: '#ffffff'
45 | }
46 | };
47 |
--------------------------------------------------------------------------------
/src/Pin/macOs/style/10.11.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gabrielbull/react-desktop/bba61374849dec896a9eea321cf4e3f02b3fd4c6/src/Pin/macOs/style/10.11.js
--------------------------------------------------------------------------------
/src/ProgressCircle/macOs/progressCircleAnimation.js:
--------------------------------------------------------------------------------
1 | let ids = [];
2 | let animations = {};
3 |
4 | const framerate = 60;
5 | const duration = 1900;
6 |
7 | function animate(elements) {
8 | this.currentStep = 0;
9 | this.steps = duration / framerate;
10 | this.increment = 1 / this.steps;
11 | animateStep.apply(this, [elements]);
12 | animations[this.id] = setInterval(() => animateStep.apply(this, [elements]), 1000 / framerate);
13 | }
14 |
15 | function animateStep(elements) {
16 | this.currentStep++;
17 | if (this.currentStep > this.steps) {
18 | this.currentStep = 1;
19 | }
20 |
21 | for (let i = 0, len = 12; i < len; ++i) {
22 | elements[11-i].style.opacity = this.increment * findStep.apply(this, [i]);
23 | }
24 | }
25 |
26 | function findStep(index) {
27 | let step = this.currentStep + (this.steps / 12 * index);
28 | if (step > this.steps) {
29 | step = -this.steps + step;
30 | }
31 | return this.steps - step;
32 | }
33 |
34 | export function startAnimation(...elements) {
35 | let id = 0;
36 | if (ids.length) id = ids[ids.length - 1] + 1;
37 | ids.push(id);
38 | animate.apply({ id }, [elements]);
39 | return id;
40 | }
41 |
42 | export function stopAnimation(animation) {
43 | window.clearInterval(animations[animation]);
44 | }
45 |
--------------------------------------------------------------------------------
/src/ProgressCircle/macOs/styles/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | progress: {
3 | width: '16px',
4 | height: '16px'
5 | },
6 |
7 | container: {
8 | position: 'relative',
9 | height: '16px'
10 | },
11 |
12 | absolute: {
13 | position: 'absolute',
14 | top: 0,
15 | left: 0
16 | }
17 | };
18 |
--------------------------------------------------------------------------------
/src/ProgressCircle/windows/styles/windows10.js:
--------------------------------------------------------------------------------
1 | export default {
2 | progress: {
3 | width: '20px',
4 | height: '20px',
5 | position: 'relative'
6 | },
7 |
8 | container: {
9 | position: 'relative',
10 | height: '20px'
11 | },
12 |
13 | absolute: {
14 | position: 'absolute',
15 | top: 0,
16 | left: 0
17 | }
18 | };
19 |
--------------------------------------------------------------------------------
/src/Radio/macOs/Circle.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Radium from 'radium';
4 | import styles from './styles/10.11';
5 |
6 | @Radium
7 | class Circle extends Component {
8 | static propTypes = {
9 | show: PropTypes.bool,
10 | color: PropTypes.string,
11 | shadowColor: PropTypes.string
12 | };
13 |
14 | static defaultProps = {
15 | color: '#FFFFFF'
16 | };
17 |
18 | render() {
19 | const { color, shadowColor } = this.props;
20 | let style = { ...styles.checkmark };
21 | style.opacity = '0';
22 | style.transform = 'scale(2)';
23 | style.transition = 'opacity 0s, transform 0.2s';
24 |
25 | if (this.props.show) {
26 | style.opacity = '1';
27 | style.transform = 'scale(1)';
28 | }
29 |
30 | return (
31 |
32 |
35 |
38 |
39 | );
40 | }
41 | }
42 |
43 | export default Circle;
44 |
--------------------------------------------------------------------------------
/src/Radio/macOs/styles/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | container: {
3 | display: 'flex'
4 | },
5 |
6 | label: {
7 | display: 'flex',
8 | height: '20px',
9 | position: 'relative',
10 |
11 | ':hover': {},
12 | ':active': {}
13 | },
14 |
15 | inputWrapper: {
16 | position: 'relative',
17 | marginRight: '3px',
18 | paddingTop: '2px'
19 | },
20 |
21 | radio: {
22 | WebkitUserSelect: 'none',
23 | userSelect: 'none',
24 | WebkitAppearance: 'none',
25 | appearance: 'none',
26 | borderWidth: '1px',
27 | borderStyle: 'solid',
28 | borderColor: '#b8b8b8',
29 | borderRadius: '50%',
30 | backgroundColor: '#ffffff',
31 | padding: '7px',
32 | margin: '0px',
33 | boxShadow: 'inset 0 1px 0 0 rgba(224, 224, 224, .4)',
34 | transition: 'all 0.4s',
35 |
36 | ':focus': {
37 | outline: 'none'
38 | }
39 | },
40 |
41 | 'radio:active': {
42 | borderColor: '#a4a4a4',
43 | backgroundColor: '#f0f0f0',
44 | boxShadow: 'inset 0 0 0 1px rgba(117, 117, 117, .35)',
45 | transition: 'all 0.4s'
46 | },
47 |
48 | 'radio:checked': {
49 | backgroundColor: '#3b99fc',
50 | boxShadow: 'none',
51 | borderColor: '#2c91fc',
52 | transition: 'all 0s'
53 | },
54 |
55 | 'radio:checked:unfocused': {
56 | backgroundColor: '#FFFFFF',
57 | boxShadow: 'none',
58 | borderColor: '#b8b8b8',
59 | transition: 'none'
60 | },
61 |
62 | 'radio:checked:active': {
63 | backgroundColor: '#0080f6',
64 | borderColor: '#006adc',
65 | boxShadow: 'inset 0 0 0 1px rgba(19, 68, 119, .22)',
66 | transition: 'all 0.4s'
67 | },
68 |
69 | checkmark: {
70 | position: 'absolute',
71 | top: '7px',
72 | left: '5px',
73 | width: '6px',
74 | height: '6px'
75 | },
76 |
77 | svg: {
78 | zIndex: '2',
79 | position: 'absolute',
80 | top: '0px',
81 | left: '0px',
82 | height: '6px'
83 | },
84 |
85 | svgShadow: {
86 | zIndex: '1',
87 | position: 'absolute',
88 | top: '1.5px',
89 | left: '0px',
90 | opacity: '.37',
91 | height: '6px',
92 | filter: 'blur(.5px)'
93 | }
94 | };
95 |
--------------------------------------------------------------------------------
/src/Radio/windows/styles/windows.js:
--------------------------------------------------------------------------------
1 | export default {
2 | container: {
3 | display: 'flex',
4 | marginBottom: '21px'
5 | },
6 |
7 | label: {
8 | display: 'flex',
9 | position: 'relative',
10 | ':hover': {},
11 | ':active': {}
12 | },
13 |
14 | text: {
15 | fontFamily: '"Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif',
16 | fontSize: '15px',
17 | color: '#000000',
18 | display: 'inline'
19 | },
20 |
21 | textDark: {
22 | color: '#ffffff'
23 | },
24 |
25 | inputWrapper: {
26 | position: 'relative',
27 | marginRight: '7px',
28 | paddingTop: '2px'
29 | },
30 |
31 | radio: {
32 | WebkitUserSelect: 'none',
33 | userSelect: 'none',
34 | WebkitAppearance: 'none',
35 | appearance: 'none',
36 | borderWidth: '2px',
37 | borderStyle: 'solid',
38 | borderColor: '#333333',
39 | borderRadius: '50%',
40 | backgroundColor: 'transparent',
41 | padding: '8px',
42 | margin: '0px',
43 |
44 | ':focus': {
45 | outline: 'none'
46 | }
47 | },
48 |
49 | 'radio:hover': {
50 | borderColor: '#000000'
51 | },
52 |
53 | 'radio:active': {
54 | borderColor: '#666666'
55 | },
56 |
57 | 'radio:checked:active': {
58 | borderColor: '#666666'
59 | },
60 |
61 | radioDark: {
62 | borderColor: '#cccccc'
63 | },
64 |
65 | 'radioDark:hover': {
66 | borderColor: '#ffffff'
67 | },
68 |
69 | 'radioDark:active': {
70 | borderColor: '#999999'
71 | },
72 |
73 | 'radioDark:checked:active': {
74 | borderColor: '#999999'
75 | },
76 |
77 | circle: {
78 | position: 'absolute',
79 | top: '7px',
80 | left: '5px',
81 | width: '10px',
82 | height: '10px',
83 | borderRadius: '50%',
84 | background: '#333333'
85 | },
86 |
87 | 'circle:hover': {
88 | background: '#000000'
89 | },
90 |
91 | 'circle:active': {
92 | background: '#666666'
93 | },
94 |
95 | circleDark: {
96 | background: '#cccccc'
97 | },
98 |
99 | 'circleDark:hover': {
100 | background: '#ffffff'
101 | },
102 |
103 | 'circleDark:active': {
104 | background: '#999999'
105 | }
106 | };
107 |
--------------------------------------------------------------------------------
/src/SearchField/macOs/cancelAnimation.js:
--------------------------------------------------------------------------------
1 | let requestAnimationFrame;
2 | if (typeof window !== 'undefined') {
3 | requestAnimationFrame = window.requestAnimationFrame ||
4 | window.mozRequestAnimationFrame ||
5 | window.webkitRequestAnimationFrame ||
6 | window.msRequestAnimationFrame;
7 | }
8 |
9 | let startTimestamp;
10 | const duration = 150;
11 |
12 | function animateCancelIcon(timestamp, element) {
13 | if (!startTimestamp) startTimestamp = timestamp;
14 | let progress = (timestamp - startTimestamp) / duration;
15 | if (progress > 1) progress = 1;
16 |
17 | element.style.height = (14 * progress) + 'px';
18 | element.style.width = (14 * progress) + 'px';
19 | element.style.opacity = progress;
20 |
21 | if (progress !== 1) {
22 | requestAnimationFrame(timestamp => animateCancelIcon(timestamp, element));
23 | }
24 | }
25 |
26 | export default function(element) {
27 | if (requestAnimationFrame) {
28 | startTimestamp = null;
29 | const icon = element.getElementsByTagName('svg')[0];
30 | requestAnimationFrame(timestamp => animateCancelIcon(timestamp, icon));
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/SearchField/macOs/icons.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export const searchIcon1x = (
4 |
8 | );
9 |
10 | export const searchIcon2x = (
11 |
15 | );
16 |
17 | export const cancelIcon1x = (
18 |
23 | );
24 |
25 | export const cancelIcon2x = (
26 |
31 | );
32 |
--------------------------------------------------------------------------------
/src/SearchField/macOs/styles/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | container: {
3 | position: 'relative'
4 | },
5 |
6 | cancel: {
7 | position: 'absolute',
8 | zIndex: 4,
9 | top: '0px',
10 | right: '0px',
11 | width: '14px',
12 | height: '100%',
13 | display: 'flex',
14 | justifyContent: 'center',
15 | alignItems: 'center',
16 | marginRight: '4px',
17 | marginLeft: '4px'
18 | }
19 | };
20 |
--------------------------------------------------------------------------------
/src/SegmentedControl/macOs/Item/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | class Item extends Component {
5 | static propTypes = {
6 | title: PropTypes.string,
7 | selected: PropTypes.bool,
8 | onSelect: PropTypes.func
9 | };
10 |
11 | render() {
12 | let { children, ...props } = this.props;
13 |
14 | delete props.title;
15 | delete props.selected;
16 | delete props.onSelect;
17 |
18 | return (
19 |
22 | {children}
23 |
24 | );
25 | }
26 | }
27 |
28 | export default Item;
29 |
--------------------------------------------------------------------------------
/src/SegmentedControl/macOs/Tabs/Tab.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import styles from '../style/10.11';
4 | import WindowFocus from '../../../windowFocus';
5 | import Radium from 'radium';
6 |
7 | @WindowFocus()
8 | @Radium
9 | class Tab extends Component {
10 | static propTypes = {
11 | selected: PropTypes.bool,
12 | prevSelected: PropTypes.bool,
13 | afterSelected: PropTypes.bool,
14 | firstChild: PropTypes.bool,
15 | lastChild: PropTypes.bool,
16 | onSelect: PropTypes.func
17 | };
18 |
19 | render() {
20 | let { children, style, onSelect, afterSelected, prevSelected, lastChild, firstChild, isWindowFocused } = this.props;
21 |
22 | let componentStyle = { ...styles.tab, ...style };
23 |
24 | if (firstChild) componentStyle = { ...componentStyle, ...styles.firstChild };
25 | if (lastChild) componentStyle = { ...componentStyle, ...styles.lastChild };
26 |
27 | if (prevSelected) componentStyle = { ...componentStyle, ...styles.prevSelected };
28 | if (afterSelected) componentStyle = { ...componentStyle, ...styles.afterSelected };
29 |
30 | if (this.props.selected) {
31 | componentStyle = { ...componentStyle, ...styles.selected };
32 | if (!isWindowFocused) componentStyle = { ...componentStyle, ...styles.selectedUnfocused };
33 | if (firstChild) componentStyle = { ...componentStyle, ...styles.firstChildSelected };
34 | if (lastChild) componentStyle = { ...componentStyle, ...styles.lastChildSelected };
35 | }
36 |
37 | return (
38 |
42 | {children}
43 |
44 | );
45 | }
46 | }
47 |
48 | export default Tab;
49 |
--------------------------------------------------------------------------------
/src/Text/macOs/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Margin, { marginPropTypes } from '../../style/margin';
4 | import Padding, { paddingPropTypes } from '../../style/padding';
5 | import FontSize, { fontSizePropTypes } from '../../style/fontSize';
6 | import Dimension, { dimensionPropTypes } from '../../style/dimension';
7 | import TextAlign, { textAlignPropTypes } from '../../style/textAlign';
8 | import Hidden, { hiddenPropTypes } from '../../style/hidden';
9 | import Alignment, { alignmentPropTypes } from '../../style/alignment';
10 | import Background, { backgroundPropTypes } from '../../style/background/macOs';
11 | import styles from './styles/10.11';
12 |
13 | @Background()
14 | @Alignment()
15 | @Margin()
16 | @Padding()
17 | @FontSize()
18 | @Dimension()
19 | @TextAlign()
20 | @Hidden()
21 | class Text extends Component {
22 | static propTypes = {
23 | ...paddingPropTypes,
24 | ...alignmentPropTypes,
25 | ...backgroundPropTypes,
26 | ...hiddenPropTypes,
27 | ...textAlignPropTypes,
28 | ...marginPropTypes,
29 | ...fontSizePropTypes,
30 | ...dimensionPropTypes,
31 | color: PropTypes.string,
32 | bold: PropTypes.oneOfType([PropTypes.bool, PropTypes.number, PropTypes.string]),
33 | };
34 |
35 | static defaultProps = {
36 | color: '#000000'
37 | };
38 |
39 | render() {
40 | const { color, children, style, bold, ...props } = this.props;
41 |
42 | let componentStyle = { ...styles.text, color };
43 | if (bold && bold === true) {
44 | componentStyle = { ...componentStyle, fontWeight: 'bold' };
45 | } else if (bold) {
46 | componentStyle = { ...componentStyle, fontWeight: bold };
47 | }
48 |
49 | return (
50 |
51 | {children}
52 |
53 | );
54 |
55 | }
56 | }
57 |
58 | export default Text;
59 |
--------------------------------------------------------------------------------
/src/Text/macOs/styles/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | text: {
3 | display: 'block',
4 | WebkitUserSelect: 'none',
5 | userSelect: 'none',
6 | cursor: 'default',
7 | fontFamily: '-apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif',
8 | fontSize: '13px'
9 | }
10 | };
11 |
--------------------------------------------------------------------------------
/src/Text/windows/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Margin, { marginPropTypes } from '../../style/margin';
4 | import Padding, { paddingPropTypes } from '../../style/padding';
5 | import Alignment, { alignmentPropTypes } from '../../style/alignment';
6 | import Hidden, { hiddenPropTypes } from '../../style/hidden';
7 | import Background, { backgroundPropTypes } from '../../style/background/windows';
8 | import Dimension, { dimensionPropTypes } from '../../style/dimension';
9 | import { colorContextTypes } from '../../style/color/windows';
10 | import { ThemeContext, themePropTypes, themeContextTypes } from '../../style/theme/windows';
11 | import styles from './styles/windows10';
12 |
13 | @Margin()
14 | @Padding()
15 | @Alignment()
16 | @Hidden()
17 | @Background()
18 | @Dimension()
19 | @ThemeContext()
20 | class Text extends Component {
21 | static propTypes = {
22 | ...themePropTypes,
23 | ...marginPropTypes,
24 | ...paddingPropTypes,
25 | ...alignmentPropTypes,
26 | ...hiddenPropTypes,
27 | ...backgroundPropTypes,
28 | ...dimensionPropTypes,
29 | color: PropTypes.oneOfType([PropTypes.string, PropTypes.bool])
30 | };
31 |
32 | static contextTypes = {
33 | ...colorContextTypes,
34 | ...themeContextTypes
35 | };
36 |
37 | render() {
38 | let { children, style, color, ...props } = this.props;
39 | let componentStyle = { ...styles.text };
40 |
41 | color = color === true ? this.context.color : color ? color : '#000000';
42 | if (color) componentStyle = { ...componentStyle, color: color };
43 | else if (this.context.theme === 'dark') componentStyle = { ...componentStyle, color: '#ffffff' };
44 |
45 | if (props.horizontalAlignment) {
46 | componentStyle.textAlign = props.horizontalAlignment;
47 | }
48 |
49 | componentStyle = { ...componentStyle, ...style };
50 |
51 | return (
52 |
56 | {children}
57 |
58 | );
59 | }
60 | }
61 |
62 | export default Text;
63 |
--------------------------------------------------------------------------------
/src/Text/windows/styles/windows10.js:
--------------------------------------------------------------------------------
1 | export default {
2 | text: {
3 | WebkitUserSelect: 'none',
4 | userSelect: 'none',
5 | cursor: 'default',
6 | lineHeight: '25.96px',
7 | fontFamily: '"Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif',
8 | fontSize: '14px',
9 | display: 'flex'
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/src/TextArea/macOs/centerPlaceholderAnimation.js:
--------------------------------------------------------------------------------
1 | import BezierEasing from '../../animation/bezierEasing';
2 |
3 | let requestAnimationFrame;
4 | if (typeof window !== 'undefined') {
5 | requestAnimationFrame = window.requestAnimationFrame ||
6 | window.mozRequestAnimationFrame ||
7 | window.webkitRequestAnimationFrame ||
8 | window.msRequestAnimationFrame;
9 | }
10 |
11 | let startTimestamp;
12 | const duration = 350;
13 | const easing = BezierEasing(.3,.14,0,1);
14 |
15 | function moveLabel(timestamp, label, start, current, end, cb) {
16 | if (start === end) return null;
17 | if (!startTimestamp) startTimestamp = timestamp;
18 | let progress = 1 - (timestamp - startTimestamp) / duration;
19 | if (progress < 0) progress = 0;
20 | progress = 1 - (easing.get(1 - progress));
21 | if (start > end) {
22 | current = progress * start;
23 | } else {
24 | current = (1 - progress) * end + start;
25 | }
26 |
27 | label.style.left = current + 'px';
28 | if (start > end && current > end || start < end && current < end) {
29 | requestAnimationFrame(timestamp => moveLabel(timestamp, label, start, current, end));
30 | } else {
31 | label.style.left = end + 'px';
32 | if (cb) cb();
33 | }
34 | }
35 |
36 | function animateLabel(label, start, end) {
37 | return new Promise(resolve => {
38 | if (requestAnimationFrame) {
39 | requestAnimationFrame(timestamp => moveLabel(timestamp, label, start, start, end, resolve));
40 | }
41 | });
42 | }
43 |
44 | export function pullLeft(input, label) {
45 | startTimestamp = null;
46 | const start = label.offsetLeft;
47 | input.style.color = 'transparent';
48 | label.style.position = 'absolute';
49 | setTimeout(() => {
50 | animateLabel(label, start, 2);
51 | setTimeout(() => input.style.color = null, 300);
52 | }, 10);
53 | }
54 |
55 | export function pushCenter(input, label) {
56 | startTimestamp = null;
57 | label.style.position = 'relative';
58 | const end = label.offsetLeft;
59 | label.style.position = 'absolute';
60 |
61 | setTimeout(() => {
62 | animateLabel(label, 2, end)
63 | .then(() => label.style.position = 'relative');
64 | }, 10);
65 | }
66 |
--------------------------------------------------------------------------------
/src/TextArea/macOs/focusRingAnimation.js:
--------------------------------------------------------------------------------
1 | import { keyframes } from 'radium';
2 |
3 | export default function (borderRadius) {
4 | return keyframes(
5 | {
6 | '0%': {
7 | opacity: '0',
8 | borderWidth: '34px',
9 | top: '-34px',
10 | left: '-34px'
11 | },
12 | '32%': {
13 | opacity: '0',
14 | borderRadius: '10px',
15 | borderWidth: '30px',
16 | top: '-30px',
17 | left: '-30px'
18 | },
19 | '50%': {
20 | opacity: '.2',
21 | borderWidth: '15px',
22 | top: '-15px',
23 | left: '-15px'
24 | },
25 | '80%': {
26 | opacity: '.4',
27 | borderWidth: '9px',
28 | top: '-9px',
29 | left: '-9px'
30 | },
31 | '90%': {
32 | opacity: '.9',
33 | borderWidth: '6px',
34 | top: '-6px',
35 | left: '-6px'
36 | },
37 | '100%': {
38 | opacity: '1',
39 | ...(
40 | borderRadius ? {
41 | top: '-2px',
42 | left: '-2px',
43 | borderRadius: (parseInt(borderRadius) + 2) + 'px',
44 | borderWidth: '2px',
45 | boxShadow: '0 0 1px 0px rgba(125, 195, 242, .7)'
46 | } : {
47 | top: '-3px',
48 | left: '-3px',
49 | borderRadius: '4px',
50 | borderWidth: '3px'
51 | }
52 | )
53 | }
54 | },
55 | 'text-input-focus'
56 | );
57 | }
58 |
--------------------------------------------------------------------------------
/src/TextArea/windows/styles/windows10.js:
--------------------------------------------------------------------------------
1 | export default {
2 | textBox: {
3 | WebkitUserSelect: 'none',
4 | userSelect: 'none',
5 | borderWidth: '2px',
6 | borderStyle: 'solid',
7 | borderColor: 'rgba(148, 148, 148, 1)',
8 | padding: '2px 10px 3px 10px',
9 | lineHeight: '23px',
10 | fontFamily: '"Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif',
11 | fontSize: '15px',
12 | fontWeight: '100',
13 | color: '#000000',
14 | marginBottom: '-4px',
15 | background: 'rgba(255, 255, 255, .35)',
16 |
17 | ':hover': {
18 | borderColor: 'rgba(100, 100, 100, 1)',
19 | background: 'rgba(255, 255, 255, .5)'
20 | },
21 |
22 | ':focus': {
23 | outline: 'none',
24 | borderColor: 'rgba(0, 120, 215, 1)',
25 | background: 'rgba(255, 255, 255, 1)'
26 | }
27 | },
28 |
29 | textBoxDarkTheme: {
30 | borderColor: 'rgba(255, 255, 255, .41)',
31 | background: 'rgba(0, 0, 0, .4)',
32 | color: '#ffffff',
33 |
34 | ':hover': {
35 | borderColor: 'rgba(255, 255, 255, .94)',
36 | background: 'rgba(0, 0, 0, .6)'
37 | },
38 |
39 | ':focus': {
40 | outline: 'none',
41 | borderColor: 'rgba(0, 120, 215, 1)',
42 | background: 'rgba(255, 255, 255, 1)',
43 | color: '#000000'
44 | }
45 | },
46 |
47 | ':placeholder': {
48 | color: '#636363'
49 | },
50 |
51 | ':placeholderDarkTheme': {
52 | color: 'rgba(255, 255, 255, .64)',
53 |
54 | ':focus': {
55 | color: 'rgba(0, 0, 0, .41)'
56 | }
57 | },
58 |
59 | labalDarkTheme: {
60 |
61 | }
62 | };
63 |
--------------------------------------------------------------------------------
/src/TextInput/macOs/centerPlaceholderAnimation.js:
--------------------------------------------------------------------------------
1 | import BezierEasing from '../../animation/bezierEasing';
2 |
3 | let requestAnimationFrame;
4 | if (typeof window !== 'undefined') {
5 | requestAnimationFrame = window.requestAnimationFrame ||
6 | window.mozRequestAnimationFrame ||
7 | window.webkitRequestAnimationFrame ||
8 | window.msRequestAnimationFrame;
9 | }
10 |
11 | let startTimestamp;
12 | const duration = 350;
13 | const easing = BezierEasing(.3,.14,0,1);
14 |
15 | function moveLabel(timestamp, label, start, current, end, cb) {
16 | if (start === end) return null;
17 | if (!startTimestamp) startTimestamp = timestamp;
18 | let progress = 1 - (timestamp - startTimestamp) / duration;
19 | if (progress < 0) progress = 0;
20 | progress = 1 - (easing.get(1 - progress));
21 | if (start > end) {
22 | current = progress * start;
23 | } else {
24 | current = (1 - progress) * end + start;
25 | }
26 |
27 | label.style.left = current + 'px';
28 | if (start > end && current > end || start < end && current < end) {
29 | requestAnimationFrame(timestamp => moveLabel(timestamp, label, start, current, end));
30 | } else {
31 | label.style.left = end + 'px';
32 | if (cb) cb();
33 | }
34 | }
35 |
36 | function animateLabel(label, start, end) {
37 | return new Promise(resolve => {
38 | if (requestAnimationFrame) {
39 | requestAnimationFrame(timestamp => moveLabel(timestamp, label, start, start, end, resolve));
40 | }
41 | });
42 | }
43 |
44 | export function pullLeft(input, label) {
45 | startTimestamp = null;
46 | const start = label.offsetLeft;
47 | input.style.color = 'transparent';
48 | label.style.position = 'absolute';
49 | setTimeout(() => {
50 | animateLabel(label, start, 2);
51 | setTimeout(() => input.style.color = null, 300);
52 | }, 10);
53 | }
54 |
55 | export function pushCenter(input, label) {
56 | startTimestamp = null;
57 | label.style.position = 'relative';
58 | const end = label.offsetLeft;
59 | label.style.position = 'absolute';
60 |
61 | setTimeout(() => {
62 | animateLabel(label, 2, end)
63 | .then(() => label.style.position = 'relative');
64 | }, 10);
65 | }
66 |
--------------------------------------------------------------------------------
/src/TextInput/macOs/focusRingAnimation.js:
--------------------------------------------------------------------------------
1 | import { keyframes } from 'radium';
2 |
3 | export default function (borderRadius) {
4 | return keyframes(
5 | {
6 | '0%': {
7 | opacity: '0',
8 | borderWidth: '34px',
9 | top: '-34px',
10 | left: '-34px'
11 | },
12 | '32%': {
13 | opacity: '0',
14 | borderRadius: '10px',
15 | borderWidth: '30px',
16 | top: '-30px',
17 | left: '-30px'
18 | },
19 | '50%': {
20 | opacity: '.2',
21 | borderWidth: '15px',
22 | top: '-15px',
23 | left: '-15px'
24 | },
25 | '80%': {
26 | opacity: '.4',
27 | borderWidth: '9px',
28 | top: '-9px',
29 | left: '-9px'
30 | },
31 | '90%': {
32 | opacity: '.9',
33 | borderWidth: '6px',
34 | top: '-6px',
35 | left: '-6px'
36 | },
37 | '100%': {
38 | opacity: '1',
39 | ...(
40 | borderRadius ? {
41 | top: '-2px',
42 | left: '-2px',
43 | borderRadius: (parseInt(borderRadius) + 2) + 'px',
44 | borderWidth: '2px',
45 | boxShadow: '0 0 1px 0px rgba(125, 195, 242, .7)'
46 | } : {
47 | top: '-3px',
48 | left: '-3px',
49 | borderRadius: '4px',
50 | borderWidth: '3px'
51 | }
52 | )
53 | }
54 | },
55 | 'text-input-focus'
56 | );
57 | }
58 |
--------------------------------------------------------------------------------
/src/TextInput/windows/styles/windows10.js:
--------------------------------------------------------------------------------
1 | export default {
2 | textBox: {
3 | WebkitUserSelect: 'none',
4 | userSelect: 'none',
5 | borderWidth: '2px',
6 | borderStyle: 'solid',
7 | borderColor: 'rgba(148, 148, 148, 1)',
8 | padding: '2px 10px 3px 10px',
9 | lineHeight: '23px',
10 | fontFamily: '"Segoe UI", Frutiger, "Frutiger Linotype", "Dejavu Sans", "Helvetica Neue", Arial, sans-serif',
11 | fontSize: '15px',
12 | fontWeight: '100',
13 | color: '#000000',
14 | marginBottom: '18px',
15 | background: 'rgba(255, 255, 255, .35)',
16 |
17 | ':hover': {
18 | borderColor: 'rgba(100, 100, 100, 1)',
19 | background: 'rgba(255, 255, 255, .5)'
20 | },
21 |
22 | ':focus': {
23 | outline: 'none',
24 | borderColor: 'rgba(0, 120, 215, 1)',
25 | background: 'rgba(255, 255, 255, 1)'
26 | }
27 | },
28 |
29 | textBoxDarkTheme: {
30 | borderColor: 'rgba(255, 255, 255, .41)',
31 | background: 'rgba(0, 0, 0, .4)',
32 | color: '#ffffff',
33 |
34 | ':hover': {
35 | borderColor: 'rgba(255, 255, 255, .94)',
36 | background: 'rgba(0, 0, 0, .6)'
37 | },
38 |
39 | ':focus': {
40 | outline: 'none',
41 | borderColor: 'rgba(0, 120, 215, 1)',
42 | background: 'rgba(255, 255, 255, 1)',
43 | color: '#000000'
44 | }
45 | },
46 |
47 | ':placeholder': {
48 | color: '#636363'
49 | },
50 |
51 | ':placeholderDarkTheme': {
52 | color: 'rgba(255, 255, 255, .64)',
53 |
54 | ':focus': {
55 | color: 'rgba(0, 0, 0, .41)'
56 | }
57 | },
58 |
59 | labalDarkTheme: {
60 |
61 | }
62 | };
63 |
--------------------------------------------------------------------------------
/src/TitleBar/macOs/Controls/Minimize.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import WindowFocus from '../../../windowFocus';
4 | import styles from './styles/10.11';
5 | import Radium from 'radium';
6 |
7 | @WindowFocus()
8 | @Radium
9 | class Minimize extends Component {
10 | static propTypes = {
11 | style: PropTypes.object,
12 | showIcon: PropTypes.bool,
13 | disabled: PropTypes.bool
14 | };
15 |
16 | render() {
17 | const { style, isWindowFocused, showIcon, disabled, ...props } = this.props;
18 |
19 | delete props.isFullscreen;
20 |
21 | const iconStyle = {
22 | ...styles.minimize.icon,
23 | opacity: showIcon && !disabled ? 1 : 0
24 | };
25 |
26 | let componentStyle = { ...styles.minimize.button, ...style };
27 | if (!isWindowFocused && !showIcon) {
28 | componentStyle = { ...componentStyle, ...styles.minimize.unfocused };
29 | }
30 | if (disabled) {
31 | componentStyle = { ...componentStyle, ...styles.minimize.disabled };
32 | }
33 |
34 | return (
35 |
39 | {window && window.devicePixelRatio > 1.5 ? (
40 |
43 | ) : (
44 |
47 | )}
48 |
49 | );
50 | }
51 | }
52 |
53 | export default Minimize;
54 |
--------------------------------------------------------------------------------
/src/TitleBar/macOs/Controls/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Close from './Close';
4 | import Minimize from './Minimize';
5 | import Resize from './Resize';
6 |
7 | var styles = {
8 | controls: {
9 | WebkitUserSelect: 'none',
10 | userSelect: 'none',
11 | cursor: 'default',
12 | display: 'flex',
13 | width: '61px'
14 | },
15 |
16 | inset: {
17 | marginLeft: '5px'
18 | }
19 | };
20 |
21 | class Controls extends Component {
22 | static propTypes = {
23 | inset: PropTypes.bool,
24 | isFullscreen: PropTypes.bool,
25 | onCloseClick: PropTypes.func,
26 | onMinimizeClick: PropTypes.func,
27 | onMaximizeClick: PropTypes.func,
28 | onResizeClick: PropTypes.func,
29 | disableClose: PropTypes.bool,
30 | disableMinimize: PropTypes.bool,
31 | disableResize: PropTypes.bool,
32 | disableFullscreen: PropTypes.bool
33 | };
34 |
35 | constructor() {
36 | super();
37 | this.state = {
38 | isOver: false
39 | };
40 | }
41 |
42 | render() {
43 | return (
44 | this.setState({ isOver: true })}
47 | onMouseLeave={() => this.setState({ isOver: false })}
48 | >
49 |
55 |
61 |
70 |
71 | );
72 | }
73 | }
74 |
75 | export default Controls;
76 |
--------------------------------------------------------------------------------
/src/TitleBar/macOs/styles/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | titleBar: {
3 | WebkitUserSelect: 'none',
4 | userSelect: 'none',
5 | WebkitAppRegion: 'drag',
6 | cursor: 'default',
7 | width: '100%',
8 | boxSizing: 'border-box',
9 | display: 'flex',
10 | alignItems: 'center',
11 | minHeight: '22px',
12 | backgroundImage:
13 | '-webkit-linear-gradient(top, #ededed 0, #ededed 1px, #e7e7e7 2px, #d1d1d1 100%)',
14 | borderBottomWidth: '1px',
15 | borderBottomStyle: 'solid',
16 | borderBottomColor: '#afafaf',
17 | borderTopWidth: '1px',
18 | borderTopStyle: 'solid',
19 | borderTopColor: '#f6f6f6',
20 | borderTopLeftRadius: '5px',
21 | borderTopRightRadius: '5px',
22 | paddingLeft: '3px',
23 | paddingRight: '3px'
24 | },
25 |
26 | titleBarInset: {
27 | paddingTop: '11px',
28 | paddingBottom: '11px',
29 | paddingLeft: '8px',
30 | paddingRight: '8px'
31 | },
32 |
33 | unfocusedTitleBar: {
34 | backgroundImage:
35 | '-webkit-linear-gradient(top, #fafafa 0px, #f6f6f6 2px, #f6f6f6 100%)',
36 | borderBottomColor: '#d1d1d1'
37 | },
38 |
39 | title: {
40 | WebkitUserSelect: 'none',
41 | userSelect: 'none',
42 | cursor: 'default',
43 | fontFamily:
44 | '-apple-system, BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif',
45 | fontSize: '13px',
46 | letterSpacing: '0px',
47 | color: '#4d4d4d',
48 | flexGrow: '1',
49 | flexShrink: '1',
50 | textAlign: 'center',
51 | whiteSpace: 'nowrap',
52 | textOverflow: 'ellipsis'
53 | },
54 |
55 | unfocusedTitle: {
56 | color: '#d3d3d3'
57 | }
58 | };
59 |
--------------------------------------------------------------------------------
/src/TitleBar/windows/Controls/Minimize.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import WindowFocus from '../../../windowFocus';
3 | import { themeContextTypes } from '../../../style/theme/windows';
4 | import { backgroundContextTypes } from '../../../style/background/windows';
5 | import { isDarkColor } from '../../../color';
6 | import Radium from 'radium'
7 |
8 | var styles = {
9 | button: {
10 | WebkitUserSelect: 'none',
11 | userSelect: 'none',
12 | WebkitAppRegion: 'no-drag',
13 | appRegion: 'no-drag',
14 | cursor: 'default',
15 | width: '46px',
16 | height: '100%',
17 | lineHeight: 0,
18 | display: 'flex',
19 | justifyContent: 'center',
20 | alignItems: 'center',
21 | display: 'flex',
22 |
23 | ':hover': {
24 | transition: 'background-color 0.1s',
25 | backgroundColor: '#e5e5e5'
26 | },
27 |
28 | ':active': {
29 | backgroundColor: '#cccccc'
30 | }
31 | },
32 |
33 | buttonColorBackground: {
34 | ':hover': {
35 | transition: 'background-color 0.1s',
36 | backgroundColor: 'rgba(255, 255, 255, .13)'
37 | },
38 |
39 | ':active': {
40 | backgroundColor: 'rgba(255, 255, 255, .23)'
41 | }
42 | },
43 |
44 | icon: {
45 | width: '10px',
46 | height: '1px'
47 | }
48 | };
49 |
50 | @WindowFocus()
51 | @Radium
52 | class Minimize extends Component {
53 | static contextTypes = {
54 | ...themeContextTypes,
55 | ...backgroundContextTypes
56 | };
57 |
58 | render() {
59 | const { style, isWindowFocused, ...props } = this.props;
60 |
61 | let svgFill = '#000000';
62 | if (!isWindowFocused && this.context.theme !== 'dark') {
63 | svgFill = 'rgba(0, 0, 0, .4)';
64 | }
65 |
66 | let componentStyle = { ...styles.button, ...style };
67 | if (this.context.theme === 'dark' || this.context.background && isDarkColor(this.context.background)) {
68 | svgFill = '#ffffff';
69 | componentStyle = { ...componentStyle, ...styles.buttonColorBackground };
70 | }
71 |
72 | return (
73 |
78 |
81 |
82 | );
83 | }
84 | }
85 |
86 | export default Minimize;
87 |
--------------------------------------------------------------------------------
/src/TitleBar/windows/Controls/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Close from './Close';
4 | import Minimize from './Minimize';
5 | import Maximize from './Maximize';
6 |
7 | var styles = {
8 | controls: {
9 | WebkitUserSelect: 'none',
10 | userSelect: 'none',
11 | cursor: 'default',
12 | display: 'flex',
13 | height: '32px'
14 | }
15 | };
16 |
17 | class Controls extends Component {
18 | static propTypes = {
19 | onCloseClick: PropTypes.func,
20 | onMinimizeClick: PropTypes.func,
21 | onRestoreDownClick: PropTypes.func,
22 | onMaximizeClick: PropTypes.func
23 | };
24 |
25 | render() {
26 | return (
27 |
28 |
29 |
34 |
35 |
36 | );
37 | }
38 | }
39 |
40 | export default Controls;
41 |
--------------------------------------------------------------------------------
/src/TitleBar/windows/styles/windows10.js:
--------------------------------------------------------------------------------
1 | export default {
2 | titleBar: {
3 | WebkitUserSelect: 'none',
4 | userSelect: 'none',
5 | WebkitAppRegion: 'drag',
6 | appRegion: 'drag',
7 | cursor: 'default',
8 | display: 'flex',
9 | alignItems: 'center',
10 | width: '100%',
11 | height: '31px',
12 | backgroundColor: '#ffffff'
13 | },
14 |
15 | titleBarDark: {
16 | backgroundColor: '#171717'
17 | },
18 |
19 | title: {
20 | WebkitUserSelect: 'none',
21 | userSelect: 'none',
22 | cursor: 'default',
23 | paddingLeft: '12px',
24 | fontFamily: '"Segoe UI", "Arial"',
25 | fontSize: '12px',
26 | color: '#000000',
27 | flex: 1
28 | },
29 |
30 | titleDark: {
31 | color: '#ffffff'
32 | },
33 |
34 | unfocusedTitle: {
35 | color: '#a9a9a9'
36 | }
37 | };
38 |
--------------------------------------------------------------------------------
/src/Toolbar/macOs/Nav/Item/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Text from '../../../../Text/macOs';
4 |
5 | const styles = {
6 | container: {
7 | WebkitUserSelect: 'none',
8 | userSelect: 'none',
9 | WebkitAppRegion: 'no-drag',
10 | display: 'flex',
11 | flexDirection: 'column',
12 | alignItems: 'center',
13 | marginTop: '1px',
14 | marginLeft: '5px',
15 | marginRight: '5px',
16 | width: '64px'
17 | },
18 | iconContainer: {
19 | height: '25px',
20 | display: 'flex',
21 | justifyContent: 'center',
22 | alignItems: 'center',
23 | alignContent: 'center',
24 | marginBottom: '1px'
25 | }
26 | };
27 |
28 | class Item extends Component {
29 | static propTypes = {
30 | titel: PropTypes.string,
31 | icon: PropTypes.oneOfType([PropTypes.element, PropTypes.array]),
32 | selected: PropTypes.bool,
33 | onClick: PropTypes.func
34 | };
35 |
36 | render() {
37 | const { title, icon, style, selected, ...props } = this.props;
38 |
39 | return (
40 |
52 | );
53 | }
54 | }
55 |
56 | export default Item;
57 |
--------------------------------------------------------------------------------
/src/Toolbar/macOs/Nav/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Style } from 'radium';
3 | import Dimension, { dimensionPropTypes } from '../../../style/dimension';
4 | import WindowFocus from '../../../windowFocus';
5 |
6 | const styles = {
7 | nav: {
8 | display: 'flex',
9 | alignItems: 'center'
10 | }
11 | };
12 |
13 | @Dimension({ height: '54px' })
14 | @WindowFocus()
15 | class Nav extends Component {
16 | static propTypes = {
17 | ...dimensionPropTypes
18 | };
19 |
20 | render() {
21 | const { children, style, isWindowFocused, ...props } = this.props;
22 | let componentStyle = { ...styles.nav };
23 |
24 | let fillOpacity = '.8';
25 | if (!isWindowFocused) {
26 | componentStyle.opacity = '.5';
27 | fillOpacity = '.3';
28 | }
29 |
30 | return (
31 |
32 |
45 |
58 | {children}
59 |
60 | );
61 | }
62 | }
63 |
64 | export default Nav;
65 |
--------------------------------------------------------------------------------
/src/Toolbar/macOs/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import Dimension, { dimensionPropTypes } from '../../style/dimension';
4 | import Alignment, { alignmentPropTypes } from '../../style/alignment';
5 |
6 | var styles = {
7 | toolbar: {
8 | WebkitUserSelect: 'none',
9 | userSelect: 'none',
10 | cursor: 'default',
11 | display: 'flex',
12 | justifyContent: 'center',
13 | alignItems: 'center'
14 | }
15 | };
16 |
17 | @Alignment()
18 | @Dimension({ width: '100%' })
19 | class Toolbar extends Component {
20 | static propTypes = {
21 | ...alignmentPropTypes,
22 | ...dimensionPropTypes
23 | };
24 |
25 | static childContextTypes = {
26 | titlebarChild: PropTypes.bool
27 | };
28 |
29 | getChildContext() {
30 | return {
31 | titlebarChild: true
32 | };
33 | }
34 |
35 | render() {
36 | const { style, ...props } = this.props;
37 |
38 | return (
39 |
40 | {this.props.children}
41 |
42 | );
43 | }
44 | }
45 |
46 | export default Toolbar;
47 |
--------------------------------------------------------------------------------
/src/ValueRef.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { findDOMNode } from 'react-dom';
3 |
4 | function ValueRef(ComposedComponent) {
5 | return class extends Component {
6 | get value() {
7 | return findDOMNode(this).getElementsByTagName('input')[0].value;
8 | }
9 |
10 | set value(value) {
11 | findDOMNode(this).getElementsByTagName('input')[0].value = value;
12 | }
13 |
14 | render() {
15 | return ;
16 | }
17 | }
18 | }
19 |
20 | export default function(...options) {
21 | if (options.length === 1 && typeof options[0] === 'function') return ValueRef.apply(null, [options[0]]);
22 | return ValueRef.bind(options);
23 | }
24 |
--------------------------------------------------------------------------------
/src/Window/macOs/styles/10.11.js:
--------------------------------------------------------------------------------
1 | export default {
2 | window: {
3 | WebkitUserSelect: 'none',
4 | userSelect: 'none',
5 | cursor: 'default',
6 | backgroundColor: '#ececec',
7 | display: 'flex',
8 | flexDirection: 'column',
9 | boxSizing: 'border-box'
10 | },
11 |
12 | chrome: {
13 | borderTopLeftRadius: '4px',
14 | borderTopRightRadius: '4px',
15 | borderBottomLeftRadius: '4px',
16 | borderBottomRightRadius: '4px',
17 | boxShadow:
18 | '0 0 1px rgba(0, 0, 0, .26), ' + // Border
19 | '0 0 5px rgba(0, 0, 0, .16), ' + // Small Glow
20 | '0 8px 10px rgba(0, 0, 0, .06), ' + // Bottom Glow
21 | '0 25px 65px rgba(0, 0, 0, .48) ' // Big shadow
22 | },
23 |
24 | unfocused: {
25 | boxShadow:
26 | '0 0 1px rgba(0, 0, 0, .31), ' + // Border
27 | '0 0 5px rgba(0, 0, 0, .18), ' + // Small Glow
28 | '0 8px 50px rgba(0, 0, 0, .3) ' // Big shadow
29 | },
30 |
31 | content: {
32 | flex: 1,
33 | padding: '24px 20px 20px 20px'
34 | }
35 | };
36 |
--------------------------------------------------------------------------------
/src/Window/windows/styles/windows10.js:
--------------------------------------------------------------------------------
1 | export default {
2 | window: {
3 | WebkitUserSelect: 'none',
4 | userSelect: 'none',
5 | cursor: 'default',
6 | backgroundColor: '#ffffff',
7 | display: 'flex',
8 | flexDirection: 'column',
9 | padding: 'none',
10 | boxSizing: 'border-box'
11 | },
12 |
13 | windowDark: {
14 | backgroundColor: '#171717'
15 | },
16 |
17 | chrome: {
18 | borderWidth: '1px',
19 | borderStyle: 'solid',
20 | boxShadow: '0 2px 11px 3px rgba(0, 0, 0, .2)'
21 | },
22 |
23 | unfocused: {
24 | borderColor: '#aaaaaa'
25 | },
26 |
27 | content: {
28 | flexGrow: '1',
29 | display: 'flex'
30 | }
31 | };
32 |
--------------------------------------------------------------------------------
/src/monitor.js:
--------------------------------------------------------------------------------
1 | if (typeof window !== 'undefined') {
2 | window.addEventListener('focus', windowFocus);
3 | window.addEventListener('blur', windowBlur);
4 | }
5 |
6 | let isWindowFocused = true;
7 |
8 | if (typeof document === 'object' && typeof document.hasFocus === 'function') {
9 | isWindowFocused = document.hasFocus();
10 | }
11 |
12 | function windowFocus() {
13 | isWindowFocused = true;
14 | }
15 |
16 | function windowBlur() {
17 | isWindowFocused = false;
18 | }
19 |
20 | export function windowIsFocused() {
21 | return isWindowFocused;
22 | }
23 |
--------------------------------------------------------------------------------
/src/os.js:
--------------------------------------------------------------------------------
1 | export const MACOS = 'macOs';
2 | export const WINDOWS = 'windows';
3 |
4 | export default function os() {
5 | // explicitly set these to avoid issues
6 | const w = window || null;
7 | const n = navigator || null;
8 | const p = process || (w && w.process) || null;
9 |
10 | // via node
11 | if (p && p.platform) {
12 | if (p.platform === 'darwin') {
13 | return MACOS;
14 | }
15 | if (p.platform.includes('win')) {
16 | return WINDOWS;
17 | }
18 | }
19 |
20 | // via user agent
21 | if (n && n.userAgent) {
22 | if (n.userAgent.includes('Macintosh')) {
23 | return MACOS;
24 | }
25 | if (n.userAgent.includes('Windows')) {
26 | return WINDOWS;
27 | }
28 | }
29 |
30 | // default to macOs
31 | return MACOS;
32 | }
33 |
--------------------------------------------------------------------------------
/src/placeholderStyle.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Style } from 'radium';
3 |
4 | function generateUniqueId() {
5 | return Math.floor((Math.random() * 10000) + 1) + '-' + +Math.floor((Math.random() * 10000) + 1) + '-' + +Math.floor((Math.random() * 10000) + 1) + '-' + +Math.floor((Math.random() * 10000) + 1) + '-' + +Math.floor((Math.random() * 10000) + 1) + '-' + +Math.floor((Math.random() * 10000) + 1) + '-' + +Math.floor((Math.random() * 10000) + 1) + '-' +
6 | Math.floor((Math.random() * 100000000000000));
7 | }
8 |
9 | function mapRules(selector, style) {
10 | let styles = { 0: style };
11 | if (style[':hover']) {
12 | styles = { ...styles, ':hover': style[':hover'] };
13 | delete styles[0][':hover'];
14 | }
15 |
16 | if (style[':active']) {
17 | styles = { ...styles, ':active': style[':active'] };
18 | delete styles[0][':active'];
19 | }
20 |
21 | if (style[':focus']) {
22 | styles = { ...styles, ':focus': style[':focus'] };
23 | delete styles[0][':focus'];
24 | }
25 |
26 | let rules = {};
27 |
28 | for (var prop in styles) {
29 | if (styles.hasOwnProperty(prop)) {
30 | rules[`${selector} input${prop !== '0' ? prop : ''}::-webkit-input-placeholder`] = styles[prop];
31 | rules[`${selector} input${prop !== '0' ? prop : ''}::-moz-placeholder`] = styles[prop];
32 | rules[`${selector} input${prop !== '0' ? prop : ''}:-ms-input-placeholder`] = styles[prop];
33 | rules[`${selector} input${prop !== '0' ? prop : ''}:placeholder`] = styles[prop];
34 | }
35 | }
36 |
37 | return rules;
38 | }
39 |
40 | export default class extends Component {
41 | constructor() {
42 | super();
43 | this._id = generateUniqueId();
44 | }
45 |
46 | render() {
47 | const { children, placeholderStyle, ...props } = this.props;
48 |
49 | return (
50 |
51 | {children}
52 |
53 |
54 | );
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/style/alignment.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import styleHelper, { extractProps } from '../styleHelper';
3 |
4 | const allowedValues = ['left', 'right', 'center'];
5 |
6 | export const alignmentPropTypes = {
7 | horizontalAlignment: PropTypes.string,
8 | verticalAlignment: PropTypes.string
9 | };
10 |
11 | export function removeAlignmentProps(props) {
12 | return extractProps(props, alignmentPropTypes)[0];
13 | }
14 |
15 | function mapAlignmentStyle(key, value, props) {
16 | let finalKey, finalValue;
17 | if (allowedValues.indexOf(value) === -1) {
18 | console.error('Unknown value for ' + key + ': ' + value);
19 | } else {
20 | let layout = 'horizontal';
21 | if (props !== undefined && typeof props.layout !== 'undefined') {
22 | layout = props.layout;
23 | }
24 | if (key === 'horizontalAlignment' && layout === 'horizontal' || key === 'verticalAlignment' && layout === 'vertical') {
25 | finalKey = 'justifyContent';
26 | switch (value) {
27 | case 'center':
28 | finalValue = 'center';
29 | break;
30 | case 'left':
31 | finalValue = 'flex-start';
32 | break;
33 | case 'right':
34 | finalValue = 'flex-end';
35 | break;
36 | }
37 | } else if (key === 'verticalAlignment' && layout === 'horizontal' || key === 'horizontalAlignment' && layout === 'vertical') {
38 | finalKey = 'alignItems';
39 | switch (value) {
40 | case 'center':
41 | finalValue = 'center';
42 | break;
43 | case 'left':
44 | finalValue = 'flex-start';
45 | break;
46 | case 'right':
47 | finalValue = 'flex-end';
48 | break;
49 | }
50 | }
51 | }
52 | return [finalKey, finalValue];
53 | }
54 |
55 | export default function(...options) {
56 | return styleHelper(options, alignmentPropTypes, mapAlignmentStyle);
57 | }
58 |
--------------------------------------------------------------------------------
/src/style/background/macOs.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import styleHelper, { extractProps } from '../../styleHelper';
3 |
4 | export const backgroundPropTypes = {
5 | background: PropTypes.string
6 | };
7 |
8 | export function removeBackgroundProps(props) {
9 | return extractProps(props, backgroundPropTypes)[0];
10 | }
11 |
12 | export default function(...options) {
13 | return styleHelper(options, backgroundPropTypes);
14 | }
15 |
--------------------------------------------------------------------------------
/src/style/background/windows.js:
--------------------------------------------------------------------------------
1 | import React, { Component, isValidElement } from 'react';
2 | import PropTypes from 'prop-types';
3 | import styleHelper, { extractProps } from '../../styleHelper';
4 | import { ColorContext, colorContextTypes } from '../../style/color/windows';
5 | import Radium from 'radium';
6 |
7 | export const backgroundPropTypes = {
8 | background: PropTypes.oneOfType([PropTypes.string, PropTypes.bool])
9 | };
10 |
11 | export const backgroundContextTypes = {
12 | background: PropTypes.oneOfType([PropTypes.string, PropTypes.bool])
13 | };
14 |
15 | export function removeBackgroundProps(props) {
16 | return extractProps(props, backgroundPropTypes)[0];
17 | }
18 |
19 | export default function(...options) {
20 | if (options[0] && isValidElement(options[0])) {
21 | @ColorContext(true)
22 | @Radium
23 | class BackgroundElement extends Component {
24 | static contextTypes = { ...colorContextTypes };
25 |
26 | render () {
27 | const props = { ...options[1] };
28 | if (typeof props.background === 'boolean') {
29 | if (!props.background) delete props.background;
30 | else if (this.context.color) props.background = this.context.color;
31 | else delete props.background;
32 | }
33 |
34 | options[1] = { ...props };
35 | return styleHelper(options, backgroundPropTypes);
36 | }
37 | }
38 | return ;
39 | }
40 |
41 | return function (WrappedComponent) {
42 | const ComposedComponent = styleHelper(options, backgroundPropTypes, null, null, options[0])(WrappedComponent);
43 | @ColorContext(true)
44 | class BackgroundComponent extends Component {
45 | static contextTypes = { ...colorContextTypes };
46 |
47 | render() {
48 | const props = { ...this.props };
49 | if (typeof props.background === 'boolean') {
50 | if (!props.background) delete props.background;
51 | else {
52 | props.background = this.context.color;
53 | }
54 | }
55 | return ;
56 | }
57 | }
58 | return BackgroundComponent;
59 | };
60 | }
61 |
--------------------------------------------------------------------------------
/src/style/color/windows.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { applyDefaultProps } from '../../styleHelper';
4 |
5 | export const colorPropTypes = {
6 | color: PropTypes.oneOfType([PropTypes.string, PropTypes.bool])
7 | };
8 |
9 | export const colorContextTypes = {
10 | color: PropTypes.oneOfType([PropTypes.string, PropTypes.bool])
11 | };
12 |
13 | const applyColorProps = (props, context) => applyDefaultProps(props, context, { color: '#0063ae' });
14 |
15 | export function ColorContext(preserveProperty = false) {
16 | return function (ComposedComponent) {
17 | return class extends Component {
18 | static propTypes = { ...colorPropTypes };
19 | static contextTypes = { ...colorContextTypes };
20 | static childContextTypes = { ...colorContextTypes };
21 |
22 | getChildContext() {
23 | return {
24 | color: applyColorProps(this.props, this.context).color
25 | };
26 | }
27 |
28 | render() {
29 | const { ...props } = this.props;
30 | if (!preserveProperty) delete props.color;
31 | return (
32 |
33 | );
34 | }
35 | };
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/style/dimension.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import styleHelper, { extractProps, parseDimension } from '../styleHelper';
3 |
4 | export const dimensionPropTypes = {
5 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
6 | height: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
7 | };
8 |
9 | export function removeDimensionProps(props) {
10 | return extractProps(props, dimensionPropTypes)[0];
11 | }
12 |
13 | function mapDimensionStyle(key, value) {
14 | return [key, parseDimension(value)];
15 | }
16 |
17 | export default function(...options) {
18 | return styleHelper(options, dimensionPropTypes, mapDimensionStyle);
19 | }
20 |
--------------------------------------------------------------------------------
/src/style/fontSize.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import styleHelper, { extractProps, parseDimension } from '../styleHelper';
3 |
4 | export const fontSizePropTypes = {
5 | size: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
6 | };
7 |
8 | export function removeFontSizeProps(props) {
9 | return extractProps(props, fontSizePropTypes)[0];
10 | }
11 |
12 | function mapFontSizeStyle(key, value) {
13 | return ['fontSize', parseDimension(value)];
14 | }
15 |
16 | function mapFontSizeStyles(styles) {
17 | if (styles.fontSize && !styles.lineHeight) {
18 | styles.lineHeight = parseDimension(parseInt(styles.fontSize) * 1.2);
19 | }
20 | return styles;
21 | }
22 |
23 | export default function(...options) {
24 | return styleHelper(options, fontSizePropTypes, mapFontSizeStyle, mapFontSizeStyles);
25 | }
26 |
--------------------------------------------------------------------------------
/src/style/hidden.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import styleHelper, { extractProps } from '../styleHelper';
3 |
4 | export const hiddenPropTypes = {
5 | hidden: PropTypes.bool
6 | };
7 |
8 | export function removeHiddenProps(props) {
9 | return extractProps(props, hiddenPropTypes)[0];
10 | }
11 |
12 | function mapHiddenStyle(key, value) {
13 | return value ? ['display', 'none'] : null;
14 | }
15 |
16 | export default function(...options) {
17 | return styleHelper(options, hiddenPropTypes, mapHiddenStyle);
18 | }
19 |
--------------------------------------------------------------------------------
/src/style/margin.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import styleHelper, { extractProps, parseDimension } from '../styleHelper';
3 |
4 | export const marginPropTypes = {
5 | margin: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
6 | marginTop: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
7 | marginLeft: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
8 | marginRight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
9 | marginBottom: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
10 | };
11 |
12 | export function removeMarginProps(props) {
13 | return extractProps(props, marginPropTypes)[0];
14 | }
15 |
16 | function mapMarginStyle(key, value) {
17 | return [key, parseDimension(value)];
18 | }
19 |
20 | export default function(...options) {
21 | return styleHelper(options, marginPropTypes, mapMarginStyle);
22 | }
23 |
--------------------------------------------------------------------------------
/src/style/padding.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import styleHelper, { extractProps, parseDimension } from '../styleHelper';
3 |
4 | export const paddingPropTypes = {
5 | padding: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
6 | paddingTop: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
7 | paddingLeft: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
8 | paddingRight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
9 | paddingBottom: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
10 | };
11 |
12 | export function removePaddingProps(props) {
13 | return extractProps(props, paddingPropTypes)[0];
14 | }
15 |
16 | export function removeDuplicatePaddingProps(styles, props) {
17 | if (props !== undefined && typeof props.style !== 'undefined') {
18 | styles = { ...styles };
19 | if (props.style.padding) {
20 | delete styles.paddingBottom;
21 | delete styles.paddingLeft;
22 | delete styles.paddingRight;
23 | delete styles.paddingTop;
24 | return styles;
25 | } else if (props.style.paddingBottom || props.style.paddingLeft || props.style.paddingRight || props.style.paddingTop) {
26 | delete styles.padding;
27 | return styles;
28 | }
29 | }
30 | return styles;
31 | }
32 |
33 | function mapPaddingStyle(key, value) {
34 | return [key, parseDimension(value)];
35 | }
36 |
37 | export default function(...options) {
38 | return styleHelper(options, paddingPropTypes, mapPaddingStyle);
39 | }
40 |
--------------------------------------------------------------------------------
/src/style/textAlign.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import styleHelper, { extractProps } from '../styleHelper';
3 |
4 | const allowedValues = ['left', 'right', 'center'];
5 |
6 | export const textAlignPropTypes = {
7 | textAlign: PropTypes.string
8 | };
9 |
10 | export function removeTextAlignProps(props) {
11 | return extractProps(props, textAlignPropTypes)[0];
12 | }
13 |
14 | function mapTextAlignStyle(key, value) {
15 | let finalKey, finalValue;
16 | if (allowedValues.indexOf(value) === -1) {
17 | console.error('Unknown value for ' + key + ': ' + value);
18 | } else {
19 | finalKey = 'textAlign';
20 | finalValue = value;
21 | }
22 | return [finalKey, finalValue];
23 | }
24 |
25 | export default function(...options) {
26 | return styleHelper(options, textAlignPropTypes, mapTextAlignStyle);
27 | }
28 |
--------------------------------------------------------------------------------
/src/style/theme/windows.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { applyDefaultProps } from '../../styleHelper';
4 |
5 | export const themePropTypes = {
6 | theme: PropTypes.string
7 | };
8 |
9 | export const themeContextTypes = {
10 | theme: PropTypes.string
11 | };
12 |
13 | const applyThemeProps = (props, context) => applyDefaultProps(props, context, { theme: 'light' });
14 |
15 | export function ThemeContext() {
16 | return function (ComposedComponent) {
17 | return class extends Component {
18 | static propTypes = { ...themePropTypes };
19 | static contextTypes = { ...themeContextTypes };
20 | static childContextTypes = { ...themeContextTypes };
21 |
22 | getChildContext() {
23 | return {
24 | theme: applyThemeProps(this.props, this.context).theme
25 | };
26 | }
27 |
28 | render() {
29 | const { ...props } = this.props;
30 | delete props.theme;
31 | return (
32 |
33 | );
34 | }
35 | };
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/style/width.js:
--------------------------------------------------------------------------------
1 | import PropTypes from 'prop-types';
2 | import styleHelper, { extractProps, parseDimension } from '../styleHelper';
3 |
4 | export const widthPropTypes = {
5 | width: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
6 | };
7 |
8 | export function removeWidthProps(props) {
9 | return extractProps(props, widthPropTypes)[0];
10 | }
11 |
12 | function mapWidthStyle(key, value) {
13 | return [key, parseDimension(value)];
14 | }
15 |
16 | function mapWidthStyles(styles) {
17 | if (styles.width) {
18 | if (styles.flex) {
19 | delete styles.flex;
20 | } else if (styles.flexGrow) {
21 | delete styles.flexGrow;
22 | }
23 | }
24 | return styles;
25 | }
26 |
27 | export default function(...options) {
28 | return styleHelper(options, widthPropTypes, mapWidthStyle, mapWidthStyles);
29 | }
30 |
--------------------------------------------------------------------------------
/src/utils/mapStyles.js:
--------------------------------------------------------------------------------
1 | export default function mapStyles(styles, map) {
2 | let popped = [];
3 | let mappedStyles = {};
4 | for (let prop in map) {
5 | if (map.hasOwnProperty(prop)) {
6 | mappedStyles[prop] = {};
7 | map[prop].forEach(key => {
8 | if (styles !== undefined && typeof styles[key] !== 'undefined') {
9 | popped.push(key);
10 | mappedStyles[prop][key] = styles[key];
11 | }
12 | })
13 | }
14 | }
15 | let remaining = {};
16 | for (let prop in styles) {
17 | if (styles.hasOwnProperty(prop)) {
18 | if (popped.indexOf(prop) === -1) {
19 | remaining[prop] = styles[prop];
20 | }
21 | }
22 | }
23 |
24 | let finalStyles = [remaining];
25 | for (let prop in mappedStyles) {
26 | if (mappedStyles.hasOwnProperty(prop)) {
27 | finalStyles.push(mappedStyles[prop]);
28 | }
29 | }
30 |
31 | return finalStyles;
32 | }
33 |
--------------------------------------------------------------------------------
/src/windowFocus.js:
--------------------------------------------------------------------------------
1 | import { windowIsFocused } from './monitor';
2 | import React, { Component } from 'react';
3 |
4 | function WindowFocus(options, ComposedComponent) {
5 | return class extends Component {
6 | constructor() {
7 | super();
8 | this.state = {
9 | isWindowFocused: windowIsFocused()
10 | };
11 | }
12 |
13 | componentDidMount() {
14 | if (typeof window !== 'undefined') {
15 | window.addEventListener('focus', this.windowFocus);
16 | window.addEventListener('blur', this.windowBlur);
17 | }
18 | }
19 |
20 | componentWillUnmount() {
21 | if (typeof window !== 'undefined') {
22 | window.removeEventListener('focus', this.windowFocus);
23 | window.removeEventListener('blur', this.windowBlur);
24 | }
25 | }
26 |
27 | windowFocus = () => {
28 | this.setState({ isWindowFocused: true });
29 | };
30 |
31 | windowBlur = () => {
32 | this.setState({ isWindowFocused: false });
33 | };
34 |
35 | render() {
36 | return ;
37 | }
38 | }
39 | }
40 |
41 | export default function(...options) {
42 | if (options.length === 1 && typeof options[0] === 'function') return WindowFocus.apply(null, [[], options[0]]);
43 | return WindowFocus.bind(null, options);
44 | }
45 |
--------------------------------------------------------------------------------
/test/mocha.opts:
--------------------------------------------------------------------------------
1 | --compilers js:babel-core/register
2 | --recursive
3 | --require ./test/setup.js
4 |
--------------------------------------------------------------------------------
/test/setup.js:
--------------------------------------------------------------------------------
1 | import { JSDOM } from 'jsdom';
2 |
3 | const dom = new JSDOM('');
4 | global.window = dom.window;
5 | global.HTMLElement = dom.window.HTMLElement;
6 | global.document = dom.window.document;
7 | global.navigator = {
8 | ...global.window.navigator,
9 | userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.54 Safari/537.36'
10 | };
11 | global.__REACT_DEVTOOLS_GLOBAL_HOOK__ = {};
12 |
--------------------------------------------------------------------------------
/test/tests/box.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai';
2 | import React from 'react';
3 | import { renderToString } from 'react-dom/server';
4 | import Box from '../../src/Box/macOs';
5 |
6 | describe('Box', () => {
7 | it('create box component with label', () => {
8 | const string = renderToString();
9 | expect(string).to.match(/My Label/);
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/test/tests/button.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai';
2 | import React from 'react';
3 | import { renderToString } from 'react-dom/server';
4 | import Button from '../../src/Button/windows';
5 |
6 | describe('Button', () => {
7 | it('create button component with text', () => {
8 | const string = renderToString();
9 | expect(string).to.match(/Hello/);
10 | });
11 |
12 | it('create button component with one node', () => {
13 | const string = renderToString(
14 |
17 | );
18 | expect(string).to.match(/Hello/);
19 | });
20 |
21 | it('create button component with multiple nodes', () => {
22 | const string = renderToString(
23 |
27 | );
28 | expect(string).to.match(/Hello/);
29 | expect(string).to.match(/World/);
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/test/tests/checkbox.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai';
2 | import React from 'react';
3 | import { renderToString } from 'react-dom/server';
4 | import CheckboxOSX from '../../src/Checkbox/macOs';
5 | import CheckboxWindows from '../../src/Checkbox/windows';
6 |
7 | describe('Checkbox', () => {
8 | it('create osx checkbox', () => {
9 | const string = renderToString();
10 | expect(string).to.match(/my label/);
11 | });
12 |
13 | it('create windows checkbox', () => {
14 | const string = renderToString();
15 | expect(string).to.match(/my label/);
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/test/tests/color.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai';
2 | import * as Color from '../../src/color';
3 |
4 | describe('Color', () => {
5 | describe('#colorLuminance', () => {
6 |
7 | });
8 |
9 | describe('#hexToRgb', () => {
10 | it('works', () => {
11 | expect(Color.hexToRgb('#000000')).to.deep.equal({ r: 0, g: 0, b: 0 });
12 | expect(Color.hexToRgb('#1883d7')).to.deep.equal({ r: 24, g: 131, b: 215 });
13 | expect(Color.hexToRgb('#ffffff')).to.deep.equal({ r: 255, g: 255, b: 255 });
14 | expect(Color.hexToRgb('#000')).to.deep.equal({ r: 0, g: 0, b: 0 });
15 | expect(Color.hexToRgb('#fff')).to.deep.equal({ r: 255, g: 255, b: 255 });
16 | });
17 | });
18 |
19 | describe('#transparentize', () => {
20 | it('works', () => {
21 | expect(Color.transparentize('#000000', 0)).to.deep.equal('rgba(0, 0, 0, 1)');
22 | expect(Color.transparentize('#000000', 0.4)).to.deep.equal('rgba(0, 0, 0, 0.6)');
23 | expect(Color.transparentize('#000000', 0.7)).to.deep.equal('rgba(0, 0, 0, 0.3)');
24 | expect(Color.transparentize('#000000', 1)).to.deep.equal('rgba(0, 0, 0, 0)');
25 | });
26 | });
27 |
28 | describe('#darkenColor', () => {
29 |
30 | });
31 |
32 | describe('#ligthenColor', () => {
33 |
34 | });
35 |
36 | describe('#convertColor', () => {
37 | it('works', () => {
38 | expect(Color.convertColor('white')).to.equal('#ffffff');
39 | expect(Color.convertColor('blue')).to.equal('#0000ff');
40 | expect(Color.convertColor('black')).to.equal('#000000');
41 | });
42 | });
43 |
44 | describe('#isDarkColor', () => {
45 | it('works', () => {
46 | expect(Color.isDarkColor('#000000')).to.be.true;
47 | expect(Color.isDarkColor('#ffffff')).to.be.false;
48 | });
49 | });
50 | });
51 |
--------------------------------------------------------------------------------
/test/tests/dialog.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai';
2 | import React from 'react';
3 | import { renderToString } from 'react-dom/server';
4 | import Dialog from '../../src/Dialog/macOs';
5 |
6 | describe('Dialog', () => {
7 | it('create osx dialog', () => {
8 | const string = renderToString();
9 | expect(string).to.match(/div/);
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/test/tests/index.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai';
2 | import { MACOS, WINDOWS } from '../../src/os';
3 | import * as components from '../../index'
4 |
5 | describe('index', () => {
6 | it('detect os', () => {
7 | expect(components.os()).to.be.oneOf([MACOS, WINDOWS]);
8 | });
9 |
10 | it('should be exported', () => {
11 | expect(components.Box).to.exist;
12 | expect(components.Button).to.exist;
13 | expect(components.Checkbox).to.exist;
14 | expect(components.Dialog).to.exist;
15 | expect(components.Label).to.exist;
16 | expect(components.Link).to.exist;
17 | expect(components.ListView).to.exist;
18 | expect(components.ListViewFooter).to.exist;
19 | expect(components.ListViewHeader).to.exist;
20 | expect(components.ListViewRow).to.exist;
21 | expect(components.ListViewSection).to.exist;
22 | expect(components.ListViewSectionHeader).to.exist;
23 | expect(components.ListViewSeparator).to.exist;
24 | expect(components.MasterDetailsView).to.exist;
25 | expect(components.NavPane).to.exist;
26 | expect(components.Pin).to.exist;
27 | expect(components.ProgressCircle).to.exist;
28 | expect(components.Radio).to.exist;
29 | expect(components.SearchField).to.exist;
30 | expect(components.SegmentedControl).to.exist;
31 | expect(components.SegmentedControlItem).to.exist;
32 | expect(components.Text).to.exist;
33 | expect(components.TextInput).to.exist;
34 | expect(components.TitleBar).to.exist;
35 | expect(components.Toolbar).to.exist;
36 | expect(components.ToolbarNav).to.exist;
37 | expect(components.ToolbarNavItem).to.exist;
38 | expect(components.View).to.exist;
39 | expect(components.Window).to.exist;
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/test/tests/label.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai';
2 | import React from 'react';
3 | import { renderToString } from 'react-dom/server';
4 | import Label from '../../src/Label/windows';
5 |
6 | describe('Label', () => {
7 | it('create label component with text', () => {
8 | const string = renderToString();
9 | expect(string).to.match(/Hello/);
10 | });
11 |
12 | it('create label component with one node', () => {
13 | const string = renderToString(
14 |
17 | );
18 | expect(string).to.match(/Hello/);
19 | });
20 |
21 | it('create label component with multiple nodes', () => {
22 | const string = renderToString(
23 |
27 | );
28 | expect(string).to.match(/Hello/);
29 | expect(string).to.match(/World/);
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/test/tests/link.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai';
2 | import React from 'react';
3 | import { renderToString } from 'react-dom/server';
4 | import Link from '../../src/Link/macOs';
5 |
6 | describe('Link', () => {
7 | it('create osx link', () => {
8 | const string = renderToString(My Link);
9 | expect(string).to.match(/My Link/);
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/test/tests/listView.js:
--------------------------------------------------------------------------------
1 | import { expect } from 'chai';
2 | import React from 'react';
3 | import { renderToString } from 'react-dom/server';
4 | import ListView from '../../src/ListView/macOs';
5 | import ListViewFooter from '../../src/ListView/macOs/Footer';
6 | import ListViewHeader from '../../src/ListView/macOs/Header';
7 | import ListViewRow from '../../src/ListView/macOs/Row';
8 | import ListViewSection from '../../src/ListView/macOs/Section';
9 | import ListViewSectionHeader from '../../src/ListView/macOs/Section/Header';
10 | import ListViewSeparator from '../../src/ListView/macOs/Separator';
11 |
12 | describe('ListView', () => {
13 | it('create list view component', () => {
14 | const string = renderToString();
15 | expect(string).to.match(/ {
19 | const string = renderToString();
20 | expect(string).to.match(/