mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 00:20:04 +01:00
Initial public release
This commit is contained in:
commit
75897c2dcd
12
.editorconfig
Normal file
12
.editorconfig
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
21
.gitignore
vendored
Normal file
21
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
.DS_STORE
|
||||
node_modules
|
||||
*~
|
||||
*.pyc
|
||||
static
|
||||
.grunt
|
||||
_SpecRunner.html
|
||||
build/
|
||||
*.gem
|
||||
docs/code
|
||||
docs/_site
|
||||
docs/.sass-cache
|
||||
docs/css/react.css
|
||||
docs/js/JSXTransformer.js
|
||||
docs/js/react.min.js
|
||||
docs/js/docs.js
|
||||
docs/js/live_editor.js
|
||||
docs/js/examples
|
||||
docs/downloads
|
||||
examples/shared/*.js
|
||||
|
||||
20
.jshintrc
Normal file
20
.jshintrc
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"node": true,
|
||||
|
||||
"boss": true,
|
||||
"curly": true,
|
||||
"devel": true,
|
||||
"eqnull": true,
|
||||
"expr": true,
|
||||
"funcscope": true,
|
||||
"globalstrict": true,
|
||||
"loopfunc": true,
|
||||
"newcap": false,
|
||||
"noempty": true,
|
||||
"nonstandard": true,
|
||||
"onecase": true,
|
||||
"regexdash": true,
|
||||
"trailing": true,
|
||||
"undef": true,
|
||||
"unused": "vars"
|
||||
}
|
||||
63
CONTRIBUTING.md
Normal file
63
CONTRIBUTING.md
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# Contributing to React
|
||||
|
||||
React is one of Facebook's first open source projects that is both under very active development and is also being used to ship code to everybody on facebook.com. We're still working out the kinks to make contributing to this project as easy and transparent as possible, but we're not quite there yet. Hopefully this document makes the process for contributing clear and preempts some questions you may have.
|
||||
|
||||
## Our Development Process
|
||||
|
||||
Some of the core team will be working directly on GitHub. These changes will be public from the beginning. Other changesets will come via a bridge with Facebook's internal source control. This is a necessity as it allows engineers at Facebook outside of the core team to move fast and contribute from an environment they are comfortable in.
|
||||
|
||||
### `master` is unsafe
|
||||
|
||||
We will do our best to keep `master` in good shape, with tests passing at all times. But in order to move fast, we will make API changes that your application might not be compatible with. We will do our best to communicate these changes and always version appropriately so you can lock into a specific version if need be.
|
||||
|
||||
### Pull Requests
|
||||
|
||||
The core team will be monitoring for pull requests. When we get one, we will pull it in an apply it to Facebook's codebase and run our test suite to ensure nothing breaks. From here, we'll need to get another person to sign off on the changes. For API changes we may need to fix internal uses, which could cause some delay. We'll do our best to provide updates and feedback throughout the process.
|
||||
|
||||
*Before* submitting a pull request, please make sure the following is done…
|
||||
|
||||
1. Fork the repo and create your branch from `master`.
|
||||
2. If you've added code that should be tested, add tests!
|
||||
3. If you've changed APIs, update the documentation.
|
||||
4. Ensure the test suite passes (`grunt test`).
|
||||
5. Make sure your code lints (`grunt lint`) - we've done our best to make sure these rules match our internal linting guidelines.
|
||||
6. If you haven't already, complete the CLA.
|
||||
|
||||
### Contributor License Agreement ("CLA")
|
||||
|
||||
In order to accept your pull request, we need you to submit a CLA. You only need to do this once, so if you've done this for another Facebook open source project, you're good to go. If you are submitting a pull request for the first time, just let us know that you have completed the CLA and we can cross-check with your GitHub username.
|
||||
|
||||
Complete your CLA here: <https://developers.facebook.com/opensource/cla>
|
||||
|
||||
## Bugs
|
||||
|
||||
### Where to Find Known Issues
|
||||
|
||||
We will be using GitHub Issues for our public bugs. We will keep a close eye on this and try to make it clear when we have an internal fix in progress. Before filing a new task, try to make sure your problem doesn't already exist.
|
||||
|
||||
### Reporting New Issues
|
||||
|
||||
The best way to get your bug fixed is to provide a reduced test case. jsFiddle, jsBin, and other sites provide a way to give live examples. Those are especially helpful though may not work for `JSX`-based code.
|
||||
|
||||
### Security Bugs
|
||||
|
||||
Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe disclosure of security bugs. With that in mind, please do not file public issues and go through the process outlined on that page.
|
||||
|
||||
## How to Get in Touch
|
||||
|
||||
* IRC - [#reactjs on freenode](http://webchat.freenode.net/?channels=reactjs)
|
||||
* Mailing list - [reactjs on Google Groups](http://groups.google.com/group/reactjs)
|
||||
|
||||
## Coding Style
|
||||
|
||||
* Use semicolons;
|
||||
* Commas last,
|
||||
* 2 spaces for indentation (no tabs)
|
||||
* Prefer `'` over `"`
|
||||
* `"use strict";`
|
||||
* 80 character line length
|
||||
* "Attractive"
|
||||
|
||||
## License
|
||||
|
||||
By contributing to React, you agree that your contributions will be licensed under the [Apache License Version 2.0 (APLv2)](LICENSE).
|
||||
99
Gruntfile.js
Normal file
99
Gruntfile.js
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
'use strict';
|
||||
|
||||
var exec = require('child_process').exec;
|
||||
var jsxTask = require('./grunt/tasks/jsx');
|
||||
var browserifyTask = require('./grunt/tasks/browserify');
|
||||
var wrapupTask = require('./grunt/tasks/wrapup');
|
||||
var phantomTask = require('./grunt/tasks/phantom');
|
||||
var releaseTasks = require('./grunt/tasks/release');
|
||||
|
||||
module.exports = function(grunt) {
|
||||
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
copy: require('./grunt/config/copy'),
|
||||
jsx: require('./grunt/config/jsx/jsx'),
|
||||
browserify: require('./grunt/config/browserify'),
|
||||
wrapup: require('./grunt/config/wrapup'),
|
||||
phantom: require('./grunt/config/phantom'),
|
||||
clean: ['./build', './*.gem', './docs/_site', './examples/shared/*.js'],
|
||||
jshint: require('./grunt/config/jshint'),
|
||||
compare_size: require('./grunt/config/compare_size')
|
||||
});
|
||||
|
||||
grunt.config.set('compress', require('./grunt/config/compress'));
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
grunt.loadNpmTasks('grunt-compare-size');
|
||||
grunt.loadNpmTasks('grunt-contrib-compress');
|
||||
|
||||
// Alias 'jshint' to 'lint' to better match the workflow we know
|
||||
grunt.registerTask('lint', ['jshint']);
|
||||
|
||||
// Register jsx:debug and :release tasks.
|
||||
grunt.registerMultiTask('jsx', jsxTask);
|
||||
|
||||
// Our own browserify-based tasks to build a single JS file build
|
||||
grunt.registerMultiTask('browserify', browserifyTask);
|
||||
|
||||
// Similar to Browserify, use WrapUp to generate single JS file that
|
||||
// defines global variables instead of using require.
|
||||
grunt.registerMultiTask('wrapup', wrapupTask);
|
||||
|
||||
grunt.registerMultiTask('phantom', phantomTask);
|
||||
|
||||
grunt.registerTask('build:basic', ['jsx:debug', 'browserify:basic']);
|
||||
grunt.registerTask('build:transformer', ['jsx:debug', 'browserify:transformer']);
|
||||
grunt.registerTask('build:min', ['jsx:release', 'browserify:min']);
|
||||
grunt.registerTask('build:test', [
|
||||
'jsx:debug',
|
||||
'jsx:test',
|
||||
'browserify:test'
|
||||
]);
|
||||
|
||||
grunt.registerTask('test', ['build:test', 'phantom:run']);
|
||||
|
||||
// Optimized build task that does all of our builds. The subtasks will be run
|
||||
// in order so we can take advantage of that and only run jsx:debug once.
|
||||
grunt.registerTask('build', [
|
||||
'jsx:debug',
|
||||
'browserify:basic',
|
||||
'browserify:transformer',
|
||||
'jsx:release',
|
||||
'browserify:min',
|
||||
'copy:react_docs',
|
||||
'compare_size'
|
||||
]);
|
||||
|
||||
// Automate the release!
|
||||
grunt.registerTask('release:setup', releaseTasks.setup);
|
||||
grunt.registerTask('release:bower', releaseTasks.bower);
|
||||
grunt.registerTask('release:docs', releaseTasks.docs);
|
||||
grunt.registerTask('release:msg', releaseTasks.msg);
|
||||
grunt.registerTask('release:starter', releaseTasks.starter);
|
||||
|
||||
grunt.registerTask('release', [
|
||||
'release:setup',
|
||||
'clean',
|
||||
'build',
|
||||
'gem:only',
|
||||
'release:bower',
|
||||
'release:starter',
|
||||
'compress',
|
||||
'release:docs',
|
||||
'release:msg'
|
||||
]);
|
||||
|
||||
// `gem` task to build the react-source gem
|
||||
grunt.registerTask('gem', ['build', 'gem:only']);
|
||||
|
||||
grunt.registerTask('gem:only', function() {
|
||||
var done = this.async();
|
||||
exec('gem build react-source.gemspec', done);
|
||||
});
|
||||
|
||||
// The default task - build - to keep setup easy
|
||||
grunt.registerTask('default', ['build']);
|
||||
};
|
||||
201
LICENSE
Normal file
201
LICENSE
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
96
README.md
Normal file
96
README.md
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
# [React](http://facebook.github.io/react)
|
||||
|
||||
React is a JavaScript library for building user interfaces.
|
||||
|
||||
* **Declarative:** React uses a declarative paradigm that makes it easier to reason about your application.
|
||||
* **Efficient:** React minimizes interactions with the DOM by using a mock representation of the DOM.
|
||||
* **Flexible:** React works with the libraries and frameworks that you already know.
|
||||
|
||||
[Learn how to use React in your own project.](http://facebook.github.io/docs/getting-started.html)
|
||||
|
||||
## Examples
|
||||
|
||||
We have several examples [on the website](http://facebook.github.io/react). Here is the first one to get you started:
|
||||
|
||||
```js
|
||||
/** @jsx React.DOM */
|
||||
var HelloMessage = React.createClass({
|
||||
render: function() {
|
||||
return <div>{'Hello ' + this.props.name}</div>;
|
||||
}
|
||||
});
|
||||
|
||||
React.renderComponent(
|
||||
<HelloMessage name="John" />,
|
||||
document.getElementById('container')
|
||||
);
|
||||
```
|
||||
|
||||
This example will render "Hello John" into a container on the page.
|
||||
|
||||
You'll notice that we used an XML-like syntax; [we call it JSX](http://facebook.github.io/docs/syntax.html). JSX is not required to use React, but it makes code more readable, and writing it feels like writing HTML. A simple transform is included with React that allows converting JSX into native JavaScript for browsers to digest.
|
||||
|
||||
## Installation
|
||||
|
||||
The fastest way to get started is to serve JavaScript from the CDN:
|
||||
|
||||
```html
|
||||
<!-- The core React library -->
|
||||
<script src="http://fbcdn.com/javascript/react/0.6.0/react.min.js"></script>
|
||||
<!-- In-browser JSX transformer, remove when pre-compiling JSX. -->
|
||||
<script src="http://fbcdn.com/javascript/react/0.6.0/JSXTransformer.js"></script>
|
||||
```
|
||||
|
||||
We've also built a [starter kit](#) which might be useful if this is your first time using React. It includes a webpage with an example of using React with live code.
|
||||
|
||||
If you'd like to use [bower](http://bower.io), it's as easy as:
|
||||
|
||||
```sh
|
||||
bower install react
|
||||
```
|
||||
|
||||
## Contribute
|
||||
|
||||
The main purpose of this repository is to continue to evolve React core, making it faster and easier to use. If you're interested in helping with that, then keep reading. If you're not interested in helping right now that's ok too :) Any feedback you have about using React would be greatly appreciated.
|
||||
|
||||
### Building Your Copy of React
|
||||
|
||||
The process to build `react.js` is built entirely on top of node.js, using many libraries you may already be familiar with.
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
* You have `node` installed at v0.10.0+ (it might work at lower versions, we just haven't tested).
|
||||
* You are familiar with `npm` and know whether or not you need to use `sudo` when installing packages globally.
|
||||
* You are familiar with `git`.
|
||||
|
||||
#### Build
|
||||
|
||||
Once you have the repository cloned, building a copy of `react.js` is really easy.
|
||||
|
||||
```sh
|
||||
# grunt-cli is needed by grunt; you might have this installed already
|
||||
npm install -g grunt-cli
|
||||
npm install
|
||||
grunt build
|
||||
```
|
||||
|
||||
At this point, you should now have a `build/` directory populated with everything you need to use React. The examples should all work.
|
||||
|
||||
### Grunt
|
||||
|
||||
We use grunt to automate many tasks. Run `grunt -h` to see a mostly complete listing. The important ones to know:
|
||||
|
||||
```sh
|
||||
# Create test build & run tests with PhantomJS
|
||||
grunt test
|
||||
# Lint the core library code with JSHint
|
||||
grunt lint
|
||||
# Lint package code
|
||||
grunt lint:package
|
||||
# Wipe out build directory
|
||||
grunt clean
|
||||
```
|
||||
|
||||
### More…
|
||||
|
||||
There's only so much we can cram in here. To read more about the community and guidelines for submitting pull requests, please read the [Contributing document](CONTRIBUTING.md).
|
||||
42
bin/jsx
Executable file
42
bin/jsx
Executable file
|
|
@ -0,0 +1,42 @@
|
|||
#!/usr/bin/env node
|
||||
"use strict";
|
||||
|
||||
var visitors = require('../vendor/fbtransform/visitors').transformVisitors;
|
||||
var transform = require('../vendor/fbtransform/lib/transform').transform;
|
||||
var debranch = require("../vendor/woodchipper").debranch;
|
||||
|
||||
require("commoner").resolve(function(id) {
|
||||
var context = this;
|
||||
|
||||
// Note that the result of context.getProvidedP() is cached for the
|
||||
// duration of the build, so it is both consistent and cheap to
|
||||
// evaluate multiple times.
|
||||
return context.getProvidedP().then(function(idToPath) {
|
||||
// If a module declares its own identifier using @providesModule
|
||||
// then that identifier will be a key in the idToPath object.
|
||||
if (idToPath.hasOwnProperty(id)) {
|
||||
return context.readFileP(idToPath[id]);
|
||||
}
|
||||
|
||||
// Otherwise assume the identifier maps directly to a path in the
|
||||
// filesystem.
|
||||
return context.readModuleP(id);
|
||||
});
|
||||
|
||||
}).process(function(id, source) {
|
||||
var context = this;
|
||||
|
||||
// This is where JSX, ES6, etc. desugaring happens.
|
||||
source = transform(visitors.react, source).code;
|
||||
|
||||
return context.makePromise(function(callback) {
|
||||
var constants = context.config.constants || {};
|
||||
|
||||
// Debranching means removing any obviously dead code after
|
||||
// replacing constant conditional expressions with literal
|
||||
// (boolean) values.
|
||||
debranch(constants, source, function(source) {
|
||||
callback(null, source);
|
||||
});
|
||||
});
|
||||
});
|
||||
16
docs/Gemfile
Normal file
16
docs/Gemfile
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
# jekyll, which builds it all
|
||||
gem 'jekyll', '~>1.0'
|
||||
|
||||
# JSON
|
||||
gem 'json'
|
||||
|
||||
# SASS for CSS
|
||||
gem 'sass'
|
||||
|
||||
# For `rake watch`
|
||||
gem 'rb-fsevent'
|
||||
|
||||
# Redcarpet for Markdown
|
||||
gem 'redcarpet'
|
||||
46
docs/Gemfile.lock
Normal file
46
docs/Gemfile.lock
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
classifier (1.3.3)
|
||||
fast-stemmer (>= 1.0.0)
|
||||
colorator (0.1)
|
||||
commander (4.1.3)
|
||||
highline (~> 1.6.11)
|
||||
directory_watcher (1.4.1)
|
||||
fast-stemmer (1.0.2)
|
||||
highline (1.6.19)
|
||||
jekyll (1.0.2)
|
||||
classifier (~> 1.3)
|
||||
colorator (~> 0.1)
|
||||
commander (~> 4.1.3)
|
||||
directory_watcher (~> 1.4.1)
|
||||
kramdown (~> 1.0.2)
|
||||
liquid (~> 2.3)
|
||||
maruku (~> 0.5)
|
||||
pygments.rb (~> 0.5.0)
|
||||
safe_yaml (~> 0.7.0)
|
||||
json (1.8.0)
|
||||
kramdown (1.0.2)
|
||||
liquid (2.5.0)
|
||||
maruku (0.6.1)
|
||||
syntax (>= 1.0.0)
|
||||
posix-spawn (0.3.6)
|
||||
pygments.rb (0.5.0)
|
||||
posix-spawn (~> 0.3.6)
|
||||
yajl-ruby (~> 1.1.0)
|
||||
rb-fsevent (0.9.3)
|
||||
redcarpet (2.2.2)
|
||||
safe_yaml (0.7.1)
|
||||
sass (3.2.9)
|
||||
syntax (1.0.0)
|
||||
yajl-ruby (1.1.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
jekyll (~> 1.0)
|
||||
json
|
||||
rb-fsevent
|
||||
redcarpet
|
||||
sass
|
||||
61
docs/README.md
Normal file
61
docs/README.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# React Documentation & Website
|
||||
|
||||
We use [Jekyll](http://jekyllrb.com/) to build the site using ([mostly](http://zpao.com/posts/adding-line-highlights-to-markdown-code-fences/)) Markdown, and we host it by pushing HTML to [GitHub Pages](http://pages.github.com/).
|
||||
|
||||
## Installation
|
||||
|
||||
If you are working on the site, you will want to install and run a local copy of it.
|
||||
|
||||
### Dependencies
|
||||
|
||||
In order to use Jekyll, you will need to have Ruby installed.
|
||||
|
||||
- [Ruby](http://www.ruby-lang.org/) (version >= 1.8.7)
|
||||
- [RubyGems](http://rubygems.org/) (version >= 1.3.7)
|
||||
- [Bundler](http://gembundler.com/)
|
||||
|
||||
Mac OS X comes pre-installed with Ruby, but you may need to update RubyGems (via `gem update --system`).
|
||||
Otherwise, [RVM](https://rvm.io/) and [rbenv](https://github.com/sstephenson/rbenv) are popular ways to install Ruby.
|
||||
Once you have RubyGems and installed Bundler (via `gem install bundler`), use it to install the dependencies:
|
||||
|
||||
```sh
|
||||
$ cd react/docs
|
||||
$ bundle install # Might need sudo.
|
||||
```
|
||||
|
||||
### Instructions
|
||||
|
||||
The site requires React, so first make sure you've built the project (via `grunt`).
|
||||
|
||||
Use Jekyll to serve the website locally (by default, at `http://localhost:4000`):
|
||||
|
||||
```sh
|
||||
$ cd react/docs
|
||||
$ rake
|
||||
$ jekyll serve -w
|
||||
$ open http://localhost:4000/react/
|
||||
```
|
||||
|
||||
We use [SASS](http://sass-lang.com/) (with [Bourbon](http://bourbon.io/)) for our CSS, and we use JSX to transform some of our JS.
|
||||
If you only want to modify the HTML or Markdown, you do not have to do anything because we package pre-compiled copies of the CSS and JS.
|
||||
If you want to modify the CSS or JS, use [Rake](http://rake.rubyforge.org/) to compile them:
|
||||
|
||||
```sh
|
||||
$ cd react/docs
|
||||
$ rake watch # Automatically compiles as needed.
|
||||
# rake Manually compile CSS and JS.
|
||||
# rake css Manually compile CSS, only.
|
||||
# rake js Manually compile JS, only.
|
||||
```
|
||||
|
||||
## Afterthoughts
|
||||
|
||||
### Updating `facebook.github.io/react`
|
||||
|
||||
The easiest way to do this is to have a separate clone of this repository, checked out to the `gh-pages` branch. We have a build step that expects this to be in a directory named `react-gh-pages` at the same depth as `react`. Then it's just a matter of running `grunt docs`, which will compile the site and copy it out to this repository. From there you can check it in.
|
||||
|
||||
**Note:** This should only be done for new releases. You should create a tag corresponding to the relase tag in the main repository.
|
||||
|
||||
### Removing the Jekyll / Ruby Dependency
|
||||
|
||||
In an ideal world, we would not be adding a Ruby dependency on part of our project. We would like to move towards a point where we are using React to render the website.
|
||||
35
docs/Rakefile
Normal file
35
docs/Rakefile
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
require('rubygems')
|
||||
require('json')
|
||||
require('yaml')
|
||||
|
||||
desc "generate css from sass"
|
||||
task :css do
|
||||
system "sass --style=compressed _css/react.scss css/react.css"
|
||||
end
|
||||
|
||||
desc "generate js from jsx"
|
||||
task :js do
|
||||
system "../bin/jsx _js js"
|
||||
end
|
||||
|
||||
desc "watch css & js"
|
||||
task :watch => [:update_version] do
|
||||
Process.spawn "sass --style=compressed --watch _css/react.scss:css/react.css"
|
||||
Process.spawn "../bin/jsx --watch _js js"
|
||||
Process.waitall
|
||||
end
|
||||
|
||||
desc "update version to match ../package.json"
|
||||
task :update_version do
|
||||
react_version = JSON.parse(File.read('../package.json'))['version']
|
||||
site_config = YAML.load_file('_config.yml')
|
||||
site_config['react_version'] = react_version
|
||||
File.open('_config.yml', 'w+') { |f| f.write(site_config.to_yaml) }
|
||||
end
|
||||
|
||||
desc "build into ../../react-gh-pages"
|
||||
task :release => [:default] do
|
||||
system "jekyll build -d ../../react-gh-pages"
|
||||
end
|
||||
|
||||
task :default => [:update_version, :css, :js]
|
||||
14
docs/_config.yml
Normal file
14
docs/_config.yml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
markdown: redcarpet
|
||||
name: React
|
||||
react_version: 0.3.0
|
||||
redcarpet:
|
||||
extensions:
|
||||
- fenced_code_blocks
|
||||
pygments: true
|
||||
exclude:
|
||||
- Gemfile
|
||||
- Gemfile.lock
|
||||
- README.md
|
||||
- Rakefile
|
||||
baseurl: /react
|
||||
173
docs/_css/_solarized.scss
Normal file
173
docs/_css/_solarized.scss
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
html * {
|
||||
color-profile: sRGB;
|
||||
rendering-intent: auto;
|
||||
}
|
||||
.cm-s-solarized-light {
|
||||
background-color: #f8f5ec;
|
||||
color: #637c84;
|
||||
}
|
||||
.cm-s-solarized-light .emphasis {
|
||||
font-weight: bold;
|
||||
}
|
||||
.cm-s-solarized-light .dotted {
|
||||
border-bottom: 1px dotted #cb4b16;
|
||||
}
|
||||
.cm-s-solarized-light .CodeMirror-gutter {
|
||||
background-color: #eee8d5;
|
||||
border-right: 3px solid #eee8d5;
|
||||
}
|
||||
.cm-s-solarized-light .CodeMirror-gutter .CodeMirror-gutter-text {
|
||||
color: #93a1a1;
|
||||
}
|
||||
.cm-s-solarized-light .CodeMirror-cursor {
|
||||
border-left-color: #002b36 !important;
|
||||
}
|
||||
.cm-s-solarized-light .CodeMirror-matchingbracket {
|
||||
color: #002b36;
|
||||
background-color: #eee8d5;
|
||||
box-shadow: 0 0 10px #eee8d5;
|
||||
font-weight: bold;
|
||||
}
|
||||
.cm-s-solarized-light .CodeMirror-nonmatchingbracket {
|
||||
color: #002b36;
|
||||
background-color: #eee8d5;
|
||||
box-shadow: 0 0 10px #eee8d5;
|
||||
font-weight: bold;
|
||||
color: #dc322f;
|
||||
border-bottom: 1px dotted #cb4b16;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-keyword {
|
||||
color: #268bd2;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-atom {
|
||||
color: #2aa198;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-number {
|
||||
color: #586e75;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-def {
|
||||
color: #637c84;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-variable {
|
||||
color: #637c84;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-variable-2 {
|
||||
color: #b58900;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-variable-3 {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-comment {
|
||||
color: #93a1a1;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-property {
|
||||
color: #637c84;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-operator {
|
||||
color: #657b83;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-string {
|
||||
color: #36958e;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-error {
|
||||
font-weight: bold;
|
||||
border-bottom: 1px dotted #cb4b16;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-bracket {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-tag {
|
||||
color: #657b83;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-attribute {
|
||||
color: #586e75;
|
||||
font-weight: bold;
|
||||
}
|
||||
.cm-s-solarized-light span.cm-meta {
|
||||
color: #268bd2;
|
||||
}
|
||||
.cm-s-solarized-dark {
|
||||
background-color: #002b36;
|
||||
color: #839496;
|
||||
}
|
||||
.cm-s-solarized-dark .emphasis {
|
||||
font-weight: bold;
|
||||
}
|
||||
.cm-s-solarized-dark .dotted {
|
||||
border-bottom: 1px dotted #cb4b16;
|
||||
}
|
||||
.cm-s-solarized-dark .CodeMirror-gutter {
|
||||
background-color: #073642;
|
||||
border-right: 3px solid #073642;
|
||||
}
|
||||
.cm-s-solarized-dark .CodeMirror-gutter .CodeMirror-gutter-text {
|
||||
color: #586e75;
|
||||
}
|
||||
.cm-s-solarized-dark .CodeMirror-cursor {
|
||||
border-left-color: #fdf6e3 !important;
|
||||
}
|
||||
.cm-s-solarized-dark .CodeMirror-matchingbracket {
|
||||
color: #fdf6e3;
|
||||
background-color: #073642;
|
||||
box-shadow: 0 0 10px #073642;
|
||||
font-weight: bold;
|
||||
}
|
||||
.cm-s-solarized-dark .CodeMirror-nonmatchingbracket {
|
||||
color: #fdf6e3;
|
||||
background-color: #073642;
|
||||
box-shadow: 0 0 10px #073642;
|
||||
font-weight: bold;
|
||||
color: #dc322f;
|
||||
border-bottom: 1px dotted #cb4b16;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-keyword {
|
||||
color: #839496;
|
||||
font-weight: bold;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-atom {
|
||||
color: #2aa198;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-number {
|
||||
color: #93a1a1;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-def {
|
||||
color: #268bd2;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-variable {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-variable-2 {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-variable-3 {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-comment {
|
||||
color: #586e75;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-property {
|
||||
color: #b58900;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-operator {
|
||||
color: #839496;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-string {
|
||||
color: #6c71c4;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-error {
|
||||
font-weight: bold;
|
||||
border-bottom: 1px dotted #cb4b16;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-bracket {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-tag {
|
||||
color: #839496;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-attribute {
|
||||
color: #93a1a1;
|
||||
font-weight: bold;
|
||||
}
|
||||
.cm-s-solarized-dark span.cm-meta {
|
||||
color: #268bd2;
|
||||
}
|
||||
136
docs/_css/_typography.scss
Normal file
136
docs/_css/_typography.scss
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
@import 'variables.scss';
|
||||
|
||||
$textColor: $mediumColor;
|
||||
$textColorLight: lighten($textColor, 20%);
|
||||
|
||||
html {
|
||||
font-family: $helvetica;
|
||||
font-family: proxima-nova, $helvetica;
|
||||
font-weight: 300;
|
||||
color: $textColor;
|
||||
line-height: 1.28;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
|
||||
.subHeader {
|
||||
font-size: 21px;
|
||||
font-weight: 200;
|
||||
line-height: 30px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
margin: 10px 0;
|
||||
font-family: inherit;
|
||||
font-weight: bold;
|
||||
line-height: 20px;
|
||||
color: inherit;
|
||||
text-rendering: optimizelegibility;
|
||||
}
|
||||
|
||||
h1 small,
|
||||
h2 small,
|
||||
h3 small,
|
||||
h4 small,
|
||||
h5 small,
|
||||
h6 small {
|
||||
font-weight: normal;
|
||||
color: $textColorLight
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3 {
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 39px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 31px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 23px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
h1 small {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
h2 small {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
h3 small {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
h4 small {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
ul,
|
||||
ol {
|
||||
margin: 0 0 10px 25px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul ul,
|
||||
ul ol,
|
||||
ol ol,
|
||||
ol ul {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
a {
|
||||
color: $linkColor;
|
||||
text-decoration: none;
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: $linkInteract;
|
||||
text-decoration: underline;
|
||||
}
|
||||
&:focus {
|
||||
outline: thin dotted #333;
|
||||
outline: 5px auto -webkit-focus-ring-color;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
}
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
22
docs/_css/_variables.scss
Normal file
22
docs/_css/_variables.scss
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
$primary: #cc7a6f;
|
||||
$linkColor: darken($primary, 9%);
|
||||
$linkInteract: darken($linkColor, 9%);
|
||||
$pageBg: #f9f9f9;
|
||||
|
||||
$lightColor: #e9e9e9;
|
||||
$mediumestColor: #666;
|
||||
$mediumColor: #484848;
|
||||
$darkColor: #2d2d2d;
|
||||
$darkestColor: #222222;
|
||||
$blueColor: #61dafb;
|
||||
$orangeColor: complement($blueColor);
|
||||
|
||||
$lightTextColor: #fafafa;
|
||||
$mediumTextColor: #aaa;
|
||||
$darkTextColor: $mediumColor;
|
||||
|
||||
$buttonBlueTop: #77a3d2;
|
||||
$buttonBlueBottom: #4783c2;
|
||||
$buttonGreyTop: #9a9a9a;
|
||||
$buttonGreyBottom: #646464;
|
||||
|
||||
13
docs/_css/bourbon/_bourbon-deprecated-upcoming.scss
vendored
Normal file
13
docs/_css/bourbon/_bourbon-deprecated-upcoming.scss
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
//************************************************************************//
|
||||
// These mixins/functions are deprecated
|
||||
// They will be removed in the next MAJOR version release
|
||||
//************************************************************************//
|
||||
@mixin box-shadow ($shadows...) {
|
||||
@include prefixer(box-shadow, $shadows, spec);
|
||||
@warn "box-shadow is deprecated and will be removed in the next major version release";
|
||||
}
|
||||
|
||||
@mixin background-size ($lengths...) {
|
||||
@include prefixer(background-size, $lengths, spec);
|
||||
@warn "background-size is deprecated and will be removed in the next major version release";
|
||||
}
|
||||
59
docs/_css/bourbon/_bourbon.scss
vendored
Normal file
59
docs/_css/bourbon/_bourbon.scss
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
// Custom Helpers
|
||||
@import "helpers/deprecated-webkit-gradient";
|
||||
@import "helpers/gradient-positions-parser";
|
||||
@import "helpers/linear-positions-parser";
|
||||
@import "helpers/radial-arg-parser";
|
||||
@import "helpers/radial-positions-parser";
|
||||
@import "helpers/render-gradients";
|
||||
@import "helpers/shape-size-stripper";
|
||||
|
||||
// Custom Functions
|
||||
@import "functions/compact";
|
||||
@import "functions/flex-grid";
|
||||
@import "functions/grid-width";
|
||||
@import "functions/linear-gradient";
|
||||
@import "functions/modular-scale";
|
||||
@import "functions/px-to-em";
|
||||
@import "functions/radial-gradient";
|
||||
@import "functions/tint-shade";
|
||||
@import "functions/transition-property-name";
|
||||
|
||||
// CSS3 Mixins
|
||||
@import "css3/animation";
|
||||
@import "css3/appearance";
|
||||
@import "css3/backface-visibility";
|
||||
@import "css3/background";
|
||||
@import "css3/background-image";
|
||||
@import "css3/border-image";
|
||||
@import "css3/border-radius";
|
||||
@import "css3/box-sizing";
|
||||
@import "css3/columns";
|
||||
@import "css3/flex-box";
|
||||
@import "css3/font-face";
|
||||
@import "css3/hidpi-media-query";
|
||||
@import "css3/image-rendering";
|
||||
@import "css3/inline-block";
|
||||
@import "css3/keyframes";
|
||||
@import "css3/linear-gradient";
|
||||
@import "css3/perspective";
|
||||
@import "css3/radial-gradient";
|
||||
@import "css3/transform";
|
||||
@import "css3/transition";
|
||||
@import "css3/user-select";
|
||||
@import "css3/placeholder";
|
||||
|
||||
// Addons & other mixins
|
||||
@import "addons/button";
|
||||
@import "addons/clearfix";
|
||||
@import "addons/font-family";
|
||||
@import "addons/hide-text";
|
||||
@import "addons/html5-input-types";
|
||||
@import "addons/position";
|
||||
@import "addons/prefixer";
|
||||
@import "addons/retina-image";
|
||||
@import "addons/size";
|
||||
@import "addons/timing-functions";
|
||||
@import "addons/triangle";
|
||||
|
||||
// Soon to be deprecated Mixins
|
||||
@import "bourbon-deprecated-upcoming";
|
||||
273
docs/_css/bourbon/addons/_button.scss
vendored
Normal file
273
docs/_css/bourbon/addons/_button.scss
vendored
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
@mixin button ($style: simple, $base-color: #4294f0) {
|
||||
|
||||
@if type-of($style) == color {
|
||||
$base-color: $style;
|
||||
$style: simple;
|
||||
}
|
||||
|
||||
// Grayscale button
|
||||
@if $base-color == grayscale($base-color) {
|
||||
@if $style == simple {
|
||||
@include simple($base-color, $grayscale: true);
|
||||
}
|
||||
|
||||
@else if $style == shiny {
|
||||
@include shiny($base-color, $grayscale: true);
|
||||
}
|
||||
|
||||
@else if $style == pill {
|
||||
@include pill($base-color, $grayscale: true);
|
||||
}
|
||||
}
|
||||
|
||||
// Colored button
|
||||
@else {
|
||||
@if $style == simple {
|
||||
@include simple($base-color);
|
||||
}
|
||||
|
||||
@else if $style == shiny {
|
||||
@include shiny($base-color);
|
||||
}
|
||||
|
||||
@else if $style == pill {
|
||||
@include pill($base-color);
|
||||
}
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Simple Button
|
||||
//************************************************************************//
|
||||
@mixin simple($base-color, $grayscale: false) {
|
||||
$color: hsl(0, 0, 100%);
|
||||
$border: adjust-color($base-color, $saturation: 9%, $lightness: -14%);
|
||||
$inset-shadow: adjust-color($base-color, $saturation: -8%, $lightness: 15%);
|
||||
$stop-gradient: adjust-color($base-color, $saturation: 9%, $lightness: -11%);
|
||||
$text-shadow: adjust-color($base-color, $saturation: 15%, $lightness: -18%);
|
||||
|
||||
@if lightness($base-color) > 70% {
|
||||
$color: hsl(0, 0, 20%);
|
||||
$text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%);
|
||||
}
|
||||
|
||||
@if $grayscale == true {
|
||||
$border: grayscale($border);
|
||||
$inset-shadow: grayscale($inset-shadow);
|
||||
$stop-gradient: grayscale($stop-gradient);
|
||||
$text-shadow: grayscale($text-shadow);
|
||||
}
|
||||
|
||||
border: 1px solid $border;
|
||||
border-radius: 3px;
|
||||
box-shadow: inset 0 1px 0 0 $inset-shadow;
|
||||
color: $color;
|
||||
display: inline-block;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
@include linear-gradient ($base-color, $stop-gradient);
|
||||
padding: 7px 18px;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 1px 0 $text-shadow;
|
||||
background-clip: padding-box;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
$base-color-hover: adjust-color($base-color, $saturation: -4%, $lightness: -5%);
|
||||
$inset-shadow-hover: adjust-color($base-color, $saturation: -7%, $lightness: 5%);
|
||||
$stop-gradient-hover: adjust-color($base-color, $saturation: 8%, $lightness: -14%);
|
||||
|
||||
@if $grayscale == true {
|
||||
$base-color-hover: grayscale($base-color-hover);
|
||||
$inset-shadow-hover: grayscale($inset-shadow-hover);
|
||||
$stop-gradient-hover: grayscale($stop-gradient-hover);
|
||||
}
|
||||
|
||||
box-shadow: inset 0 1px 0 0 $inset-shadow-hover;
|
||||
cursor: pointer;
|
||||
@include linear-gradient ($base-color-hover, $stop-gradient-hover);
|
||||
}
|
||||
|
||||
&:active:not(:disabled) {
|
||||
$border-active: adjust-color($base-color, $saturation: 9%, $lightness: -14%);
|
||||
$inset-shadow-active: adjust-color($base-color, $saturation: 7%, $lightness: -17%);
|
||||
|
||||
@if $grayscale == true {
|
||||
$border-active: grayscale($border-active);
|
||||
$inset-shadow-active: grayscale($inset-shadow-active);
|
||||
}
|
||||
|
||||
border: 1px solid $border-active;
|
||||
box-shadow: inset 0 0 8px 4px $inset-shadow-active, inset 0 0 8px 4px $inset-shadow-active, 0 1px 1px 0 #eee;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Shiny Button
|
||||
//************************************************************************//
|
||||
@mixin shiny($base-color, $grayscale: false) {
|
||||
$color: hsl(0, 0, 100%);
|
||||
$border: adjust-color($base-color, $red: -117, $green: -111, $blue: -81);
|
||||
$border-bottom: adjust-color($base-color, $red: -126, $green: -127, $blue: -122);
|
||||
$fourth-stop: adjust-color($base-color, $red: -79, $green: -70, $blue: -46);
|
||||
$inset-shadow: adjust-color($base-color, $red: 37, $green: 29, $blue: 12);
|
||||
$second-stop: adjust-color($base-color, $red: -56, $green: -50, $blue: -33);
|
||||
$text-shadow: adjust-color($base-color, $red: -140, $green: -141, $blue: -114);
|
||||
$third-stop: adjust-color($base-color, $red: -86, $green: -75, $blue: -48);
|
||||
|
||||
@if lightness($base-color) > 70% {
|
||||
$color: hsl(0, 0, 20%);
|
||||
$text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%);
|
||||
}
|
||||
|
||||
@if $grayscale == true {
|
||||
$border: grayscale($border);
|
||||
$border-bottom: grayscale($border-bottom);
|
||||
$fourth-stop: grayscale($fourth-stop);
|
||||
$inset-shadow: grayscale($inset-shadow);
|
||||
$second-stop: grayscale($second-stop);
|
||||
$text-shadow: grayscale($text-shadow);
|
||||
$third-stop: grayscale($third-stop);
|
||||
}
|
||||
|
||||
border: 1px solid $border;
|
||||
border-bottom: 1px solid $border-bottom;
|
||||
border-radius: 5px;
|
||||
box-shadow: inset 0 1px 0 0 $inset-shadow;
|
||||
color: $color;
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
@include linear-gradient(top, $base-color 0%, $second-stop 50%, $third-stop 50%, $fourth-stop 100%);
|
||||
padding: 8px 20px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 -1px 1px $text-shadow;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
$first-stop-hover: adjust-color($base-color, $red: -13, $green: -15, $blue: -18);
|
||||
$second-stop-hover: adjust-color($base-color, $red: -66, $green: -62, $blue: -51);
|
||||
$third-stop-hover: adjust-color($base-color, $red: -93, $green: -85, $blue: -66);
|
||||
$fourth-stop-hover: adjust-color($base-color, $red: -86, $green: -80, $blue: -63);
|
||||
|
||||
@if $grayscale == true {
|
||||
$first-stop-hover: grayscale($first-stop-hover);
|
||||
$second-stop-hover: grayscale($second-stop-hover);
|
||||
$third-stop-hover: grayscale($third-stop-hover);
|
||||
$fourth-stop-hover: grayscale($fourth-stop-hover);
|
||||
}
|
||||
|
||||
cursor: pointer;
|
||||
@include linear-gradient(top, $first-stop-hover 0%,
|
||||
$second-stop-hover 50%,
|
||||
$third-stop-hover 50%,
|
||||
$fourth-stop-hover 100%);
|
||||
}
|
||||
|
||||
&:active:not(:disabled) {
|
||||
$inset-shadow-active: adjust-color($base-color, $red: -111, $green: -116, $blue: -122);
|
||||
|
||||
@if $grayscale == true {
|
||||
$inset-shadow-active: grayscale($inset-shadow-active);
|
||||
}
|
||||
|
||||
box-shadow: inset 0 0 20px 0 $inset-shadow-active, 0 1px 0 #fff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Pill Button
|
||||
//************************************************************************//
|
||||
@mixin pill($base-color, $grayscale: false) {
|
||||
$color: hsl(0, 0, 100%);
|
||||
$border-bottom: adjust-color($base-color, $hue: 8, $saturation: -11%, $lightness: -26%);
|
||||
$border-sides: adjust-color($base-color, $hue: 4, $saturation: -21%, $lightness: -21%);
|
||||
$border-top: adjust-color($base-color, $hue: -1, $saturation: -30%, $lightness: -15%);
|
||||
$inset-shadow: adjust-color($base-color, $hue: -1, $saturation: -1%, $lightness: 7%);
|
||||
$stop-gradient: adjust-color($base-color, $hue: 8, $saturation: 14%, $lightness: -10%);
|
||||
$text-shadow: adjust-color($base-color, $hue: 5, $saturation: -19%, $lightness: -15%);
|
||||
|
||||
@if lightness($base-color) > 70% {
|
||||
$color: hsl(0, 0, 20%);
|
||||
$text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%);
|
||||
}
|
||||
|
||||
@if $grayscale == true {
|
||||
$border-bottom: grayscale($border-bottom);
|
||||
$border-sides: grayscale($border-sides);
|
||||
$border-top: grayscale($border-top);
|
||||
$inset-shadow: grayscale($inset-shadow);
|
||||
$stop-gradient: grayscale($stop-gradient);
|
||||
$text-shadow: grayscale($text-shadow);
|
||||
}
|
||||
|
||||
border: 1px solid $border-top;
|
||||
border-color: $border-top $border-sides $border-bottom;
|
||||
border-radius: 16px;
|
||||
box-shadow: inset 0 1px 0 0 $inset-shadow, 0 1px 2px 0 #b3b3b3;
|
||||
color: $color;
|
||||
display: inline-block;
|
||||
font-size: 11px;
|
||||
font-weight: normal;
|
||||
line-height: 1;
|
||||
@include linear-gradient ($base-color, $stop-gradient);
|
||||
padding: 5px 16px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 -1px 1px $text-shadow;
|
||||
background-clip: padding-box;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
$base-color-hover: adjust-color($base-color, $lightness: -4.5%);
|
||||
$border-bottom: adjust-color($base-color, $hue: 8, $saturation: 13.5%, $lightness: -32%);
|
||||
$border-sides: adjust-color($base-color, $hue: 4, $saturation: -2%, $lightness: -27%);
|
||||
$border-top: adjust-color($base-color, $hue: -1, $saturation: -17%, $lightness: -21%);
|
||||
$inset-shadow-hover: adjust-color($base-color, $saturation: -1%, $lightness: 3%);
|
||||
$stop-gradient-hover: adjust-color($base-color, $hue: 8, $saturation: -4%, $lightness: -15.5%);
|
||||
$text-shadow-hover: adjust-color($base-color, $hue: 5, $saturation: -5%, $lightness: -22%);
|
||||
|
||||
@if $grayscale == true {
|
||||
$base-color-hover: grayscale($base-color-hover);
|
||||
$border-bottom: grayscale($border-bottom);
|
||||
$border-sides: grayscale($border-sides);
|
||||
$border-top: grayscale($border-top);
|
||||
$inset-shadow-hover: grayscale($inset-shadow-hover);
|
||||
$stop-gradient-hover: grayscale($stop-gradient-hover);
|
||||
$text-shadow-hover: grayscale($text-shadow-hover);
|
||||
}
|
||||
|
||||
border: 1px solid $border-top;
|
||||
border-color: $border-top $border-sides $border-bottom;
|
||||
box-shadow: inset 0 1px 0 0 $inset-shadow-hover;
|
||||
cursor: pointer;
|
||||
@include linear-gradient ($base-color-hover, $stop-gradient-hover);
|
||||
text-shadow: 0 -1px 1px $text-shadow-hover;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
&:active:not(:disabled) {
|
||||
$active-color: adjust-color($base-color, $hue: 4, $saturation: -12%, $lightness: -10%);
|
||||
$border-active: adjust-color($base-color, $hue: 6, $saturation: -2.5%, $lightness: -30%);
|
||||
$border-bottom-active: adjust-color($base-color, $hue: 11, $saturation: 6%, $lightness: -31%);
|
||||
$inset-shadow-active: adjust-color($base-color, $hue: 9, $saturation: 2%, $lightness: -21.5%);
|
||||
$text-shadow-active: adjust-color($base-color, $hue: 5, $saturation: -12%, $lightness: -21.5%);
|
||||
|
||||
@if $grayscale == true {
|
||||
$active-color: grayscale($active-color);
|
||||
$border-active: grayscale($border-active);
|
||||
$border-bottom-active: grayscale($border-bottom-active);
|
||||
$inset-shadow-active: grayscale($inset-shadow-active);
|
||||
$text-shadow-active: grayscale($text-shadow-active);
|
||||
}
|
||||
|
||||
background: $active-color;
|
||||
border: 1px solid $border-active;
|
||||
border-bottom: 1px solid $border-bottom-active;
|
||||
box-shadow: inset 0 0 6px 3px $inset-shadow-active, 0 1px 0 0 #fff;
|
||||
text-shadow: 0 -1px 1px $text-shadow-active;
|
||||
}
|
||||
}
|
||||
29
docs/_css/bourbon/addons/_clearfix.scss
vendored
Normal file
29
docs/_css/bourbon/addons/_clearfix.scss
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// Micro clearfix provides an easy way to contain floats without adding additional markup
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// // Contain all floats within .wrapper
|
||||
// .wrapper {
|
||||
// @include clearfix;
|
||||
// .content,
|
||||
// .sidebar {
|
||||
// float : left;
|
||||
// }
|
||||
// }
|
||||
|
||||
@mixin clearfix {
|
||||
*zoom: 1;
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: " ";
|
||||
display: table;
|
||||
}
|
||||
|
||||
&:after {
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
// Acknowledgements
|
||||
// Micro clearfix: [Nicolas Gallagher](http://nicolasgallagher.com/micro-clearfix-hack/)
|
||||
5
docs/_css/bourbon/addons/_font-family.scss
vendored
Normal file
5
docs/_css/bourbon/addons/_font-family.scss
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
$georgia: Georgia, Cambria, "Times New Roman", Times, serif;
|
||||
$helvetica: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
$lucida-grande: "Lucida Grande", Tahoma, Verdana, Arial, sans-serif;
|
||||
$monospace: "Bitstream Vera Sans Mono", Consolas, Courier, monospace;
|
||||
$verdana: Verdana, Geneva, sans-serif;
|
||||
5
docs/_css/bourbon/addons/_hide-text.scss
vendored
Normal file
5
docs/_css/bourbon/addons/_hide-text.scss
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
@mixin hide-text {
|
||||
color: transparent;
|
||||
font: 0/0 a;
|
||||
text-shadow: none;
|
||||
}
|
||||
56
docs/_css/bourbon/addons/_html5-input-types.scss
vendored
Normal file
56
docs/_css/bourbon/addons/_html5-input-types.scss
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
//************************************************************************//
|
||||
// Generate a variable ($all-text-inputs) with a list of all html5
|
||||
// input types that have a text-based input, excluding textarea.
|
||||
// http://diveintohtml5.org/forms.html
|
||||
//************************************************************************//
|
||||
$inputs-list: 'input[type="email"]',
|
||||
'input[type="number"]',
|
||||
'input[type="password"]',
|
||||
'input[type="search"]',
|
||||
'input[type="tel"]',
|
||||
'input[type="text"]',
|
||||
'input[type="url"]',
|
||||
|
||||
// Webkit & Gecko may change the display of these in the future
|
||||
'input[type="color"]',
|
||||
'input[type="date"]',
|
||||
'input[type="datetime"]',
|
||||
'input[type="datetime-local"]',
|
||||
'input[type="month"]',
|
||||
'input[type="time"]',
|
||||
'input[type="week"]';
|
||||
|
||||
$unquoted-inputs-list: ();
|
||||
@each $input-type in $inputs-list {
|
||||
$unquoted-inputs-list: append($unquoted-inputs-list, unquote($input-type), comma);
|
||||
}
|
||||
|
||||
$all-text-inputs: $unquoted-inputs-list;
|
||||
|
||||
|
||||
// Hover Pseudo-class
|
||||
//************************************************************************//
|
||||
$all-text-inputs-hover: ();
|
||||
@each $input-type in $unquoted-inputs-list {
|
||||
$input-type-hover: $input-type + ":hover";
|
||||
$all-text-inputs-hover: append($all-text-inputs-hover, $input-type-hover, comma);
|
||||
}
|
||||
|
||||
// Focus Pseudo-class
|
||||
//************************************************************************//
|
||||
$all-text-inputs-focus: ();
|
||||
@each $input-type in $unquoted-inputs-list {
|
||||
$input-type-focus: $input-type + ":focus";
|
||||
$all-text-inputs-focus: append($all-text-inputs-focus, $input-type-focus, comma);
|
||||
}
|
||||
|
||||
// You must use interpolation on the variable:
|
||||
// #{$all-text-inputs}
|
||||
// #{$all-text-inputs-hover}
|
||||
// #{$all-text-inputs-focus}
|
||||
|
||||
// Example
|
||||
//************************************************************************//
|
||||
// #{$all-text-inputs}, textarea {
|
||||
// border: 1px solid red;
|
||||
// }
|
||||
42
docs/_css/bourbon/addons/_position.scss
vendored
Normal file
42
docs/_css/bourbon/addons/_position.scss
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
@mixin position ($position: relative, $coordinates: 0 0 0 0) {
|
||||
|
||||
@if type-of($position) == list {
|
||||
$coordinates: $position;
|
||||
$position: relative;
|
||||
}
|
||||
|
||||
$top: nth($coordinates, 1);
|
||||
$right: nth($coordinates, 2);
|
||||
$bottom: nth($coordinates, 3);
|
||||
$left: nth($coordinates, 4);
|
||||
|
||||
position: $position;
|
||||
|
||||
@if $top == auto {
|
||||
top: $top;
|
||||
}
|
||||
@else if not(unitless($top)) {
|
||||
top: $top;
|
||||
}
|
||||
|
||||
@if $right == auto {
|
||||
right: $right;
|
||||
}
|
||||
@else if not(unitless($right)) {
|
||||
right: $right;
|
||||
}
|
||||
|
||||
@if $bottom == auto {
|
||||
bottom: $bottom;
|
||||
}
|
||||
@else if not(unitless($bottom)) {
|
||||
bottom: $bottom;
|
||||
}
|
||||
|
||||
@if $left == auto {
|
||||
left: $left;
|
||||
}
|
||||
@else if not(unitless($left)) {
|
||||
left: $left;
|
||||
}
|
||||
}
|
||||
49
docs/_css/bourbon/addons/_prefixer.scss
vendored
Normal file
49
docs/_css/bourbon/addons/_prefixer.scss
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
//************************************************************************//
|
||||
// Example: @include prefixer(border-radius, $radii, webkit ms spec);
|
||||
//************************************************************************//
|
||||
$prefix-for-webkit: true !default;
|
||||
$prefix-for-mozilla: true !default;
|
||||
$prefix-for-microsoft: true !default;
|
||||
$prefix-for-opera: true !default;
|
||||
$prefix-for-spec: true !default; // required for keyframe mixin
|
||||
|
||||
@mixin prefixer ($property, $value, $prefixes) {
|
||||
@each $prefix in $prefixes {
|
||||
@if $prefix == webkit {
|
||||
@if $prefix-for-webkit {
|
||||
-webkit-#{$property}: $value;
|
||||
}
|
||||
}
|
||||
@else if $prefix == moz {
|
||||
@if $prefix-for-mozilla {
|
||||
-moz-#{$property}: $value;
|
||||
}
|
||||
}
|
||||
@else if $prefix == ms {
|
||||
@if $prefix-for-microsoft {
|
||||
-ms-#{$property}: $value;
|
||||
}
|
||||
}
|
||||
@else if $prefix == o {
|
||||
@if $prefix-for-opera {
|
||||
-o-#{$property}: $value;
|
||||
}
|
||||
}
|
||||
@else if $prefix == spec {
|
||||
@if $prefix-for-spec {
|
||||
#{$property}: $value;
|
||||
}
|
||||
}
|
||||
@else {
|
||||
@warn "Unrecognized prefix: #{$prefix}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin disable-prefix-for-all() {
|
||||
$prefix-for-webkit: false;
|
||||
$prefix-for-mozilla: false;
|
||||
$prefix-for-microsoft: false;
|
||||
$prefix-for-opera: false;
|
||||
$prefix-for-spec: false;
|
||||
}
|
||||
32
docs/_css/bourbon/addons/_retina-image.scss
vendored
Normal file
32
docs/_css/bourbon/addons/_retina-image.scss
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
@mixin retina-image($filename, $background-size, $extension: png, $retina-filename: null, $asset-pipeline: false) {
|
||||
@if $asset-pipeline {
|
||||
background-image: image_url($filename + "." + $extension);
|
||||
}
|
||||
@else {
|
||||
background-image: url($filename + "." + $extension);
|
||||
}
|
||||
|
||||
@include hidpi {
|
||||
|
||||
@if $asset-pipeline {
|
||||
@if $retina-filename {
|
||||
background-image: image_url($retina-filename + "." + $extension);
|
||||
}
|
||||
@else {
|
||||
background-image: image_url($filename + "@2x" + "." + $extension);
|
||||
}
|
||||
}
|
||||
|
||||
@else {
|
||||
@if $retina-filename {
|
||||
background-image: url($retina-filename + "." + $extension);
|
||||
}
|
||||
@else {
|
||||
background-image: url($filename + "@2x" + "." + $extension);
|
||||
}
|
||||
}
|
||||
|
||||
background-size: $background-size;
|
||||
|
||||
}
|
||||
}
|
||||
44
docs/_css/bourbon/addons/_size.scss
vendored
Normal file
44
docs/_css/bourbon/addons/_size.scss
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
@mixin size($size) {
|
||||
@if length($size) == 1 {
|
||||
@if $size == auto {
|
||||
width: $size;
|
||||
height: $size;
|
||||
}
|
||||
|
||||
@else if unitless($size) {
|
||||
width: $size + px;
|
||||
height: $size + px;
|
||||
}
|
||||
|
||||
@else if not(unitless($size)) {
|
||||
width: $size;
|
||||
height: $size;
|
||||
}
|
||||
}
|
||||
|
||||
// Width x Height
|
||||
@if length($size) == 2 {
|
||||
$width: nth($size, 1);
|
||||
$height: nth($size, 2);
|
||||
|
||||
@if $width == auto {
|
||||
width: $width;
|
||||
}
|
||||
@else if not(unitless($width)) {
|
||||
width: $width;
|
||||
}
|
||||
@else if unitless($width) {
|
||||
width: $width + px;
|
||||
}
|
||||
|
||||
@if $height == auto {
|
||||
height: $height;
|
||||
}
|
||||
@else if not(unitless($height)) {
|
||||
height: $height;
|
||||
}
|
||||
@else if unitless($height) {
|
||||
height: $height + px;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
docs/_css/bourbon/addons/_timing-functions.scss
vendored
Normal file
32
docs/_css/bourbon/addons/_timing-functions.scss
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
// CSS cubic-bezier timing functions. Timing functions courtesy of jquery.easie (github.com/jaukia/easie)
|
||||
// Timing functions are the same as demo'ed here: http://jqueryui.com/demos/effect/easing.html
|
||||
|
||||
// EASE IN
|
||||
$ease-in-quad: cubic-bezier(0.550, 0.085, 0.680, 0.530);
|
||||
$ease-in-cubic: cubic-bezier(0.550, 0.055, 0.675, 0.190);
|
||||
$ease-in-quart: cubic-bezier(0.895, 0.030, 0.685, 0.220);
|
||||
$ease-in-quint: cubic-bezier(0.755, 0.050, 0.855, 0.060);
|
||||
$ease-in-sine: cubic-bezier(0.470, 0.000, 0.745, 0.715);
|
||||
$ease-in-expo: cubic-bezier(0.950, 0.050, 0.795, 0.035);
|
||||
$ease-in-circ: cubic-bezier(0.600, 0.040, 0.980, 0.335);
|
||||
$ease-in-back: cubic-bezier(0.600, -0.280, 0.735, 0.045);
|
||||
|
||||
// EASE OUT
|
||||
$ease-out-quad: cubic-bezier(0.250, 0.460, 0.450, 0.940);
|
||||
$ease-out-cubic: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
$ease-out-quart: cubic-bezier(0.165, 0.840, 0.440, 1.000);
|
||||
$ease-out-quint: cubic-bezier(0.230, 1.000, 0.320, 1.000);
|
||||
$ease-out-sine: cubic-bezier(0.390, 0.575, 0.565, 1.000);
|
||||
$ease-out-expo: cubic-bezier(0.190, 1.000, 0.220, 1.000);
|
||||
$ease-out-circ: cubic-bezier(0.075, 0.820, 0.165, 1.000);
|
||||
$ease-out-back: cubic-bezier(0.175, 0.885, 0.320, 1.275);
|
||||
|
||||
// EASE IN OUT
|
||||
$ease-in-out-quad: cubic-bezier(0.455, 0.030, 0.515, 0.955);
|
||||
$ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
$ease-in-out-quart: cubic-bezier(0.770, 0.000, 0.175, 1.000);
|
||||
$ease-in-out-quint: cubic-bezier(0.860, 0.000, 0.070, 1.000);
|
||||
$ease-in-out-sine: cubic-bezier(0.445, 0.050, 0.550, 0.950);
|
||||
$ease-in-out-expo: cubic-bezier(1.000, 0.000, 0.000, 1.000);
|
||||
$ease-in-out-circ: cubic-bezier(0.785, 0.135, 0.150, 0.860);
|
||||
$ease-in-out-back: cubic-bezier(0.680, -0.550, 0.265, 1.550);
|
||||
45
docs/_css/bourbon/addons/_triangle.scss
vendored
Normal file
45
docs/_css/bourbon/addons/_triangle.scss
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
@mixin triangle ($size, $color, $direction) {
|
||||
height: 0;
|
||||
width: 0;
|
||||
|
||||
@if ($direction == up) or ($direction == down) or ($direction == right) or ($direction == left) {
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
border-width: $size / 2;
|
||||
|
||||
@if $direction == up {
|
||||
border-bottom-color: $color;
|
||||
|
||||
} @else if $direction == right {
|
||||
border-left-color: $color;
|
||||
|
||||
} @else if $direction == down {
|
||||
border-top-color: $color;
|
||||
|
||||
} @else if $direction == left {
|
||||
border-right-color: $color;
|
||||
}
|
||||
}
|
||||
|
||||
@else if ($direction == up-right) or ($direction == up-left) {
|
||||
border-top: $size solid $color;
|
||||
|
||||
@if $direction == up-right {
|
||||
border-left: $size solid transparent;
|
||||
|
||||
} @else if $direction == up-left {
|
||||
border-right: $size solid transparent;
|
||||
}
|
||||
}
|
||||
|
||||
@else if ($direction == down-right) or ($direction == down-left) {
|
||||
border-bottom: $size solid $color;
|
||||
|
||||
@if $direction == down-right {
|
||||
border-left: $size solid transparent;
|
||||
|
||||
} @else if $direction == down-left {
|
||||
border-right: $size solid transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
52
docs/_css/bourbon/css3/_animation.scss
vendored
Normal file
52
docs/_css/bourbon/css3/_animation.scss
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// http://www.w3.org/TR/css3-animations/#the-animation-name-property-
|
||||
// Each of these mixins support comma separated lists of values, which allows different transitions for individual properties to be described in a single style rule. Each value in the list corresponds to the value at that same position in the other properties.
|
||||
|
||||
// Official animation shorthand property.
|
||||
@mixin animation ($animations...) {
|
||||
@include prefixer(animation, $animations, webkit moz spec);
|
||||
}
|
||||
|
||||
// Individual Animation Properties
|
||||
@mixin animation-name ($names...) {
|
||||
@include prefixer(animation-name, $names, webkit moz spec);
|
||||
}
|
||||
|
||||
|
||||
@mixin animation-duration ($times...) {
|
||||
@include prefixer(animation-duration, $times, webkit moz spec);
|
||||
}
|
||||
|
||||
|
||||
@mixin animation-timing-function ($motions...) {
|
||||
// ease | linear | ease-in | ease-out | ease-in-out
|
||||
@include prefixer(animation-timing-function, $motions, webkit moz spec);
|
||||
}
|
||||
|
||||
|
||||
@mixin animation-iteration-count ($values...) {
|
||||
// infinite | <number>
|
||||
@include prefixer(animation-iteration-count, $values, webkit moz spec);
|
||||
}
|
||||
|
||||
|
||||
@mixin animation-direction ($directions...) {
|
||||
// normal | alternate
|
||||
@include prefixer(animation-direction, $directions, webkit moz spec);
|
||||
}
|
||||
|
||||
|
||||
@mixin animation-play-state ($states...) {
|
||||
// running | paused
|
||||
@include prefixer(animation-play-state, $states, webkit moz spec);
|
||||
}
|
||||
|
||||
|
||||
@mixin animation-delay ($times...) {
|
||||
@include prefixer(animation-delay, $times, webkit moz spec);
|
||||
}
|
||||
|
||||
|
||||
@mixin animation-fill-mode ($modes...) {
|
||||
// none | forwards | backwards | both
|
||||
@include prefixer(animation-fill-mode, $modes, webkit moz spec);
|
||||
}
|
||||
3
docs/_css/bourbon/css3/_appearance.scss
vendored
Normal file
3
docs/_css/bourbon/css3/_appearance.scss
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
@mixin appearance ($value) {
|
||||
@include prefixer(appearance, $value, webkit moz ms o spec);
|
||||
}
|
||||
6
docs/_css/bourbon/css3/_backface-visibility.scss
vendored
Normal file
6
docs/_css/bourbon/css3/_backface-visibility.scss
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
//************************************************************************//
|
||||
// Backface-visibility mixin
|
||||
//************************************************************************//
|
||||
@mixin backface-visibility($visibility) {
|
||||
@include prefixer(backface-visibility, $visibility, webkit spec);
|
||||
}
|
||||
48
docs/_css/bourbon/css3/_background-image.scss
vendored
Normal file
48
docs/_css/bourbon/css3/_background-image.scss
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
//************************************************************************//
|
||||
// Background-image property for adding multiple background images with
|
||||
// gradients, or for stringing multiple gradients together.
|
||||
//************************************************************************//
|
||||
|
||||
@mixin background-image($images...) {
|
||||
background-image: _add-prefix($images, webkit);
|
||||
background-image: _add-prefix($images);
|
||||
}
|
||||
|
||||
@function _add-prefix($images, $vendor: false) {
|
||||
$images-prefixed: ();
|
||||
$gradient-positions: false;
|
||||
@for $i from 1 through length($images) {
|
||||
$type: type-of(nth($images, $i)); // Get type of variable - List or String
|
||||
|
||||
// If variable is a list - Gradient
|
||||
@if $type == list {
|
||||
$gradient-type: nth(nth($images, $i), 1); // linear or radial
|
||||
$gradient-pos: null;
|
||||
$gradient-args: null;
|
||||
|
||||
@if ($gradient-type == linear) or ($gradient-type == radial) {
|
||||
$gradient-pos: nth(nth($images, $i), 2); // Get gradient position
|
||||
$gradient-args: nth(nth($images, $i), 3); // Get actual gradient (red, blue)
|
||||
}
|
||||
@else {
|
||||
$gradient-args: nth(nth($images, $i), 2); // Get actual gradient (red, blue)
|
||||
}
|
||||
|
||||
$gradient-positions: _gradient-positions-parser($gradient-type, $gradient-pos);
|
||||
$gradient: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor);
|
||||
$images-prefixed: append($images-prefixed, $gradient, comma);
|
||||
}
|
||||
// If variable is a string - Image
|
||||
@else if $type == string {
|
||||
$images-prefixed: join($images-prefixed, nth($images, $i), comma);
|
||||
}
|
||||
}
|
||||
@return $images-prefixed;
|
||||
}
|
||||
|
||||
//Examples:
|
||||
//@include background-image(linear-gradient(top, orange, red));
|
||||
//@include background-image(radial-gradient(50% 50%, cover circle, orange, red));
|
||||
//@include background-image(url("/images/a.png"), linear-gradient(orange, red));
|
||||
//@include background-image(url("image.png"), linear-gradient(orange, red), url("image.png"));
|
||||
//@include background-image(linear-gradient(hsla(0, 100%, 100%, 0.25) 0%, hsla(0, 100%, 100%, 0.08) 50%, transparent 50%), linear-gradient(orange, red));
|
||||
103
docs/_css/bourbon/css3/_background.scss
vendored
Normal file
103
docs/_css/bourbon/css3/_background.scss
vendored
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
//************************************************************************//
|
||||
// Background property for adding multiple backgrounds using shorthand
|
||||
// notation.
|
||||
//************************************************************************//
|
||||
|
||||
@mixin background(
|
||||
$background-1 , $background-2: false,
|
||||
$background-3: false, $background-4: false,
|
||||
$background-5: false, $background-6: false,
|
||||
$background-7: false, $background-8: false,
|
||||
$background-9: false, $background-10: false,
|
||||
$fallback: false
|
||||
) {
|
||||
$backgrounds: compact($background-1, $background-2,
|
||||
$background-3, $background-4,
|
||||
$background-5, $background-6,
|
||||
$background-7, $background-8,
|
||||
$background-9, $background-10);
|
||||
|
||||
$fallback-color: false;
|
||||
@if (type-of($fallback) == color) or ($fallback == "transparent") {
|
||||
$fallback-color: $fallback;
|
||||
}
|
||||
@else {
|
||||
$fallback-color: _extract-background-color($backgrounds);
|
||||
}
|
||||
|
||||
@if $fallback-color {
|
||||
background-color: $fallback-color;
|
||||
}
|
||||
background: _background-add-prefix($backgrounds, webkit);
|
||||
background: _background-add-prefix($backgrounds);
|
||||
}
|
||||
|
||||
@function _extract-background-color($backgrounds) {
|
||||
$final-bg-layer: nth($backgrounds, length($backgrounds));
|
||||
@if type-of($final-bg-layer) == list {
|
||||
@for $i from 1 through length($final-bg-layer) {
|
||||
$value: nth($final-bg-layer, $i);
|
||||
@if type-of($value) == color {
|
||||
@return $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@return false;
|
||||
}
|
||||
|
||||
@function _background-add-prefix($backgrounds, $vendor: false) {
|
||||
$backgrounds-prefixed: ();
|
||||
|
||||
@for $i from 1 through length($backgrounds) {
|
||||
$shorthand: nth($backgrounds, $i); // Get member for current index
|
||||
$type: type-of($shorthand); // Get type of variable - List (gradient) or String (image)
|
||||
|
||||
// If shorthand is a list (gradient)
|
||||
@if $type == list {
|
||||
$first-member: nth($shorthand, 1); // Get first member of shorthand
|
||||
|
||||
// Linear Gradient
|
||||
@if index(linear radial, nth($first-member, 1)) {
|
||||
$gradient-type: nth($first-member, 1); // linear || radial
|
||||
$gradient-args: false;
|
||||
$gradient-positions: false;
|
||||
$shorthand-start: false;
|
||||
@if type-of($first-member) == list { // Linear gradient plus additional shorthand values - lg(red,orange)repeat,...
|
||||
$gradient-positions: nth($first-member, 2);
|
||||
$gradient-args: nth($first-member, 3);
|
||||
$shorthand-start: 2;
|
||||
}
|
||||
@else { // Linear gradient only - lg(red,orange),...
|
||||
$gradient-positions: nth($shorthand, 2);
|
||||
$gradient-args: nth($shorthand, 3); // Get gradient (red, blue)
|
||||
}
|
||||
|
||||
$gradient-positions: _gradient-positions-parser($gradient-type, $gradient-positions);
|
||||
$gradient: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor);
|
||||
|
||||
// Append any additional shorthand args to gradient
|
||||
@if $shorthand-start {
|
||||
@for $j from $shorthand-start through length($shorthand) {
|
||||
$gradient: join($gradient, nth($shorthand, $j), space);
|
||||
}
|
||||
}
|
||||
$backgrounds-prefixed: append($backgrounds-prefixed, $gradient, comma);
|
||||
}
|
||||
// Image with additional properties
|
||||
@else {
|
||||
$backgrounds-prefixed: append($backgrounds-prefixed, $shorthand, comma);
|
||||
}
|
||||
}
|
||||
// If shorthand is a simple string (color or image)
|
||||
@else if $type == string {
|
||||
$backgrounds-prefixed: join($backgrounds-prefixed, $shorthand, comma);
|
||||
}
|
||||
}
|
||||
@return $backgrounds-prefixed;
|
||||
}
|
||||
|
||||
//Examples:
|
||||
//@include background(linear-gradient(top, orange, red));
|
||||
//@include background(radial-gradient(circle at 40% 40%, orange, red));
|
||||
//@include background(url("/images/a.png") no-repeat, linear-gradient(orange, red));
|
||||
//@include background(url("image.png") center center, linear-gradient(orange, red), url("image.png"));
|
||||
55
docs/_css/bourbon/css3/_border-image.scss
vendored
Normal file
55
docs/_css/bourbon/css3/_border-image.scss
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
@mixin border-image($images) {
|
||||
-webkit-border-image: _border-add-prefix($images, webkit);
|
||||
-moz-border-image: _border-add-prefix($images, moz);
|
||||
-o-border-image: _border-add-prefix($images, o);
|
||||
border-image: _border-add-prefix($images);
|
||||
}
|
||||
|
||||
@function _border-add-prefix($images, $vendor: false) {
|
||||
$border-image: null;
|
||||
$images-type: type-of(nth($images, 1));
|
||||
$first-var: nth(nth($images, 1), 1); // Get type of Gradient (Linear || radial)
|
||||
|
||||
// If input is a gradient
|
||||
@if $images-type == string {
|
||||
@if ($first-var == "linear") or ($first-var == "radial") {
|
||||
$gradient-type: nth($images, 1); // Get type of gradient (linear || radial)
|
||||
$gradient-pos: nth($images, 2); // Get gradient position
|
||||
$gradient-args: nth($images, 3); // Get actual gradient (red, blue)
|
||||
$gradient-positions: _gradient-positions-parser($gradient-type, $gradient-pos);
|
||||
$border-image: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor);
|
||||
}
|
||||
// If input is a URL
|
||||
@else {
|
||||
$border-image: $images;
|
||||
}
|
||||
}
|
||||
// If input is gradient or url + additional args
|
||||
@else if $images-type == list {
|
||||
$type: type-of(nth($images, 1)); // Get type of variable - List or String
|
||||
|
||||
// If variable is a list - Gradient
|
||||
@if $type == list {
|
||||
$gradient: nth($images, 1);
|
||||
$gradient-type: nth($gradient, 1); // Get type of gradient (linear || radial)
|
||||
$gradient-pos: nth($gradient, 2); // Get gradient position
|
||||
$gradient-args: nth($gradient, 3); // Get actual gradient (red, blue)
|
||||
$gradient-positions: _gradient-positions-parser($gradient-type, $gradient-pos);
|
||||
$border-image: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor);
|
||||
|
||||
@for $i from 2 through length($images) {
|
||||
$border-image: append($border-image, nth($images, $i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@return $border-image;
|
||||
}
|
||||
|
||||
//Examples:
|
||||
// @include border-image(url("image.png"));
|
||||
// @include border-image(url("image.png") 20 stretch);
|
||||
// @include border-image(linear-gradient(45deg, orange, yellow));
|
||||
// @include border-image(linear-gradient(45deg, orange, yellow) stretch);
|
||||
// @include border-image(linear-gradient(45deg, orange, yellow) 20 30 40 50 stretch round);
|
||||
// @include border-image(radial-gradient(top, cover, orange, yellow, orange));
|
||||
|
||||
22
docs/_css/bourbon/css3/_border-radius.scss
vendored
Normal file
22
docs/_css/bourbon/css3/_border-radius.scss
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
//************************************************************************//
|
||||
// Shorthand Border-radius mixins
|
||||
//************************************************************************//
|
||||
@mixin border-top-radius($radii) {
|
||||
@include prefixer(border-top-left-radius, $radii, spec);
|
||||
@include prefixer(border-top-right-radius, $radii, spec);
|
||||
}
|
||||
|
||||
@mixin border-bottom-radius($radii) {
|
||||
@include prefixer(border-bottom-left-radius, $radii, spec);
|
||||
@include prefixer(border-bottom-right-radius, $radii, spec);
|
||||
}
|
||||
|
||||
@mixin border-left-radius($radii) {
|
||||
@include prefixer(border-top-left-radius, $radii, spec);
|
||||
@include prefixer(border-bottom-left-radius, $radii, spec);
|
||||
}
|
||||
|
||||
@mixin border-right-radius($radii) {
|
||||
@include prefixer(border-top-right-radius, $radii, spec);
|
||||
@include prefixer(border-bottom-right-radius, $radii, spec);
|
||||
}
|
||||
4
docs/_css/bourbon/css3/_box-sizing.scss
vendored
Normal file
4
docs/_css/bourbon/css3/_box-sizing.scss
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
@mixin box-sizing ($box) {
|
||||
// content-box | border-box | inherit
|
||||
@include prefixer(box-sizing, $box, webkit moz spec);
|
||||
}
|
||||
47
docs/_css/bourbon/css3/_columns.scss
vendored
Normal file
47
docs/_css/bourbon/css3/_columns.scss
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
@mixin columns($arg: auto) {
|
||||
// <column-count> || <column-width>
|
||||
@include prefixer(columns, $arg, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-count($int: auto) {
|
||||
// auto || integer
|
||||
@include prefixer(column-count, $int, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-gap($length: normal) {
|
||||
// normal || length
|
||||
@include prefixer(column-gap, $length, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-fill($arg: auto) {
|
||||
// auto || length
|
||||
@include prefixer(columns-fill, $arg, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-rule($arg) {
|
||||
// <border-width> || <border-style> || <color>
|
||||
@include prefixer(column-rule, $arg, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-rule-color($color) {
|
||||
@include prefixer(column-rule-color, $color, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-rule-style($style: none) {
|
||||
// none | hidden | dashed | dotted | double | groove | inset | inset | outset | ridge | solid
|
||||
@include prefixer(column-rule-style, $style, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-rule-width ($width: none) {
|
||||
@include prefixer(column-rule-width, $width, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-span($arg: none) {
|
||||
// none || all
|
||||
@include prefixer(column-span, $arg, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin column-width($length: auto) {
|
||||
// auto || length
|
||||
@include prefixer(column-width, $length, webkit moz spec);
|
||||
}
|
||||
52
docs/_css/bourbon/css3/_flex-box.scss
vendored
Normal file
52
docs/_css/bourbon/css3/_flex-box.scss
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// CSS3 Flexible Box Model and property defaults
|
||||
|
||||
// Custom shorthand notation for flexbox
|
||||
@mixin box($orient: inline-axis, $pack: start, $align: stretch) {
|
||||
@include display-box;
|
||||
@include box-orient($orient);
|
||||
@include box-pack($pack);
|
||||
@include box-align($align);
|
||||
}
|
||||
|
||||
@mixin display-box {
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: box;
|
||||
}
|
||||
|
||||
@mixin box-orient($orient: inline-axis) {
|
||||
// horizontal|vertical|inline-axis|block-axis|inherit
|
||||
@include prefixer(box-orient, $orient, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin box-pack($pack: start) {
|
||||
// start|end|center|justify
|
||||
@include prefixer(box-pack, $pack, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin box-align($align: stretch) {
|
||||
// start|end|center|baseline|stretch
|
||||
@include prefixer(box-align, $align, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin box-direction($direction: normal) {
|
||||
// normal|reverse|inherit
|
||||
@include prefixer(box-direction, $direction, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin box-lines($lines: single) {
|
||||
// single|multiple
|
||||
@include prefixer(box-lines, $lines, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin box-ordinal-group($int: 1) {
|
||||
@include prefixer(box-ordinal-group, $int, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin box-flex($value: 0.0) {
|
||||
@include prefixer(box-flex, $value, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin box-flex-group($int: 1) {
|
||||
@include prefixer(box-flex-group, $int, webkit moz spec);
|
||||
}
|
||||
23
docs/_css/bourbon/css3/_font-face.scss
vendored
Normal file
23
docs/_css/bourbon/css3/_font-face.scss
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Order of the includes matters, and it is: normal, bold, italic, bold+italic.
|
||||
|
||||
@mixin font-face($font-family, $file-path, $weight: normal, $style: normal, $asset-pipeline: false ) {
|
||||
@font-face {
|
||||
font-family: $font-family;
|
||||
font-weight: $weight;
|
||||
font-style: $style;
|
||||
|
||||
@if $asset-pipeline == true {
|
||||
src: font-url('#{$file-path}.eot');
|
||||
src: font-url('#{$file-path}.eot?#iefix') format('embedded-opentype'),
|
||||
font-url('#{$file-path}.woff') format('woff'),
|
||||
font-url('#{$file-path}.ttf') format('truetype'),
|
||||
font-url('#{$file-path}.svg##{$font-family}') format('svg');
|
||||
} @else {
|
||||
src: url('#{$file-path}.eot');
|
||||
src: url('#{$file-path}.eot?#iefix') format('embedded-opentype'),
|
||||
url('#{$file-path}.woff') format('woff'),
|
||||
url('#{$file-path}.ttf') format('truetype'),
|
||||
url('#{$file-path}.svg##{$font-family}') format('svg');
|
||||
}
|
||||
}
|
||||
}
|
||||
10
docs/_css/bourbon/css3/_hidpi-media-query.scss
vendored
Normal file
10
docs/_css/bourbon/css3/_hidpi-media-query.scss
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
// HiDPI mixin. Default value set to 1.3 to target Google Nexus 7 (http://bjango.com/articles/min-device-pixel-ratio/)
|
||||
@mixin hidpi($ratio: 1.3) {
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: $ratio),
|
||||
only screen and (min--moz-device-pixel-ratio: $ratio),
|
||||
only screen and (-o-min-device-pixel-ratio: #{$ratio}/1),
|
||||
only screen and (min-resolution: #{round($ratio*96)}dpi),
|
||||
only screen and (min-resolution: #{$ratio}dppx) {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
13
docs/_css/bourbon/css3/_image-rendering.scss
vendored
Normal file
13
docs/_css/bourbon/css3/_image-rendering.scss
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
@mixin image-rendering ($mode:optimizeQuality) {
|
||||
|
||||
@if ($mode == optimize-contrast) {
|
||||
image-rendering: -moz-crisp-edges;
|
||||
image-rendering: -o-crisp-edges;
|
||||
image-rendering: -webkit-optimize-contrast;
|
||||
image-rendering: optimize-contrast;
|
||||
}
|
||||
|
||||
@else {
|
||||
image-rendering: $mode;
|
||||
}
|
||||
}
|
||||
8
docs/_css/bourbon/css3/_inline-block.scss
vendored
Normal file
8
docs/_css/bourbon/css3/_inline-block.scss
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// Legacy support for inline-block in IE7 (maybe IE6)
|
||||
@mixin inline-block {
|
||||
display: inline-block;
|
||||
vertical-align: baseline;
|
||||
zoom: 1;
|
||||
*display: inline;
|
||||
*vertical-align: auto;
|
||||
}
|
||||
43
docs/_css/bourbon/css3/_keyframes.scss
vendored
Normal file
43
docs/_css/bourbon/css3/_keyframes.scss
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// Adds keyframes blocks for supported prefixes, removing redundant prefixes in the block's content
|
||||
@mixin keyframes($name) {
|
||||
$original-prefix-for-webkit: $prefix-for-webkit;
|
||||
$original-prefix-for-mozilla: $prefix-for-mozilla;
|
||||
$original-prefix-for-microsoft: $prefix-for-microsoft;
|
||||
$original-prefix-for-opera: $prefix-for-opera;
|
||||
$original-prefix-for-spec: $prefix-for-spec;
|
||||
|
||||
@if $original-prefix-for-webkit {
|
||||
@include disable-prefix-for-all();
|
||||
$prefix-for-webkit: true;
|
||||
@-webkit-keyframes #{$name} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
@if $original-prefix-for-mozilla {
|
||||
@include disable-prefix-for-all();
|
||||
$prefix-for-mozilla: true;
|
||||
@-moz-keyframes #{$name} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
@if $original-prefix-for-opera {
|
||||
@include disable-prefix-for-all();
|
||||
$prefix-for-opera: true;
|
||||
@-o-keyframes #{$name} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
@if $original-prefix-for-spec {
|
||||
@include disable-prefix-for-all();
|
||||
$prefix-for-spec: true;
|
||||
@keyframes #{$name} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
$prefix-for-webkit: $original-prefix-for-webkit;
|
||||
$prefix-for-mozilla: $original-prefix-for-mozilla;
|
||||
$prefix-for-microsoft: $original-prefix-for-microsoft;
|
||||
$prefix-for-opera: $original-prefix-for-opera;
|
||||
$prefix-for-spec: $original-prefix-for-spec;
|
||||
}
|
||||
41
docs/_css/bourbon/css3/_linear-gradient.scss
vendored
Normal file
41
docs/_css/bourbon/css3/_linear-gradient.scss
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
@mixin linear-gradient($pos, $G1, $G2: false,
|
||||
$G3: false, $G4: false,
|
||||
$G5: false, $G6: false,
|
||||
$G7: false, $G8: false,
|
||||
$G9: false, $G10: false,
|
||||
$deprecated-pos1: left top,
|
||||
$deprecated-pos2: left bottom,
|
||||
$fallback: false) {
|
||||
// Detect what type of value exists in $pos
|
||||
$pos-type: type-of(nth($pos, 1));
|
||||
$pos-spec: null;
|
||||
$pos-degree: null;
|
||||
|
||||
// If $pos is missing from mixin, reassign vars and add default position
|
||||
@if ($pos-type == color) or (nth($pos, 1) == "transparent") {
|
||||
$G10: $G9; $G9: $G8; $G8: $G7; $G7: $G6; $G6: $G5;
|
||||
$G5: $G4; $G4: $G3; $G3: $G2; $G2: $G1; $G1: $pos;
|
||||
$pos: null;
|
||||
}
|
||||
|
||||
@if $pos {
|
||||
$positions: _linear-positions-parser($pos);
|
||||
$pos-degree: nth($positions, 1);
|
||||
$pos-spec: nth($positions, 2);
|
||||
}
|
||||
|
||||
$full: compact($G1, $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10);
|
||||
|
||||
// Set $G1 as the default fallback color
|
||||
$fallback-color: nth($G1, 1);
|
||||
|
||||
// If $fallback is a color use that color as the fallback color
|
||||
@if (type-of($fallback) == color) or ($fallback == "transparent") {
|
||||
$fallback-color: $fallback;
|
||||
}
|
||||
|
||||
background-color: $fallback-color;
|
||||
background-image: _deprecated-webkit-gradient(linear, $deprecated-pos1, $deprecated-pos2, $full); // Safari <= 5.0
|
||||
background-image: -webkit-linear-gradient($pos-degree $full); // Safari 5.1+, Chrome
|
||||
background-image: unquote("linear-gradient(#{$pos-spec}#{$full})");
|
||||
}
|
||||
8
docs/_css/bourbon/css3/_perspective.scss
vendored
Normal file
8
docs/_css/bourbon/css3/_perspective.scss
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
@mixin perspective($depth: none) {
|
||||
// none | <length>
|
||||
@include prefixer(perspective, $depth, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin perspective-origin($value: 50% 50%) {
|
||||
@include prefixer(perspective-origin, $value, webkit moz spec);
|
||||
}
|
||||
29
docs/_css/bourbon/css3/_placeholder.scss
vendored
Normal file
29
docs/_css/bourbon/css3/_placeholder.scss
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
$placeholders: '-webkit-input-placeholder',
|
||||
'-moz-placeholder',
|
||||
'-ms-input-placeholder';
|
||||
|
||||
@mixin placeholder {
|
||||
@each $placeholder in $placeholders {
|
||||
@if $placeholder == "-webkit-input-placeholder" {
|
||||
&::#{$placeholder} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
@else if $placeholder == "-moz-placeholder" {
|
||||
// FF 18-
|
||||
&:#{$placeholder} {
|
||||
@content;
|
||||
}
|
||||
|
||||
// FF 19+
|
||||
&::#{$placeholder} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
@else {
|
||||
&:#{$placeholder} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
docs/_css/bourbon/css3/_radial-gradient.scss
vendored
Normal file
44
docs/_css/bourbon/css3/_radial-gradient.scss
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// Requires Sass 3.1+
|
||||
@mixin radial-gradient($G1, $G2,
|
||||
$G3: false, $G4: false,
|
||||
$G5: false, $G6: false,
|
||||
$G7: false, $G8: false,
|
||||
$G9: false, $G10: false,
|
||||
$pos: null,
|
||||
$shape-size: null,
|
||||
$deprecated-pos1: center center,
|
||||
$deprecated-pos2: center center,
|
||||
$deprecated-radius1: 0,
|
||||
$deprecated-radius2: 460,
|
||||
$fallback: false) {
|
||||
|
||||
$data: _radial-arg-parser($G1, $G2, $pos, $shape-size);
|
||||
$G1: nth($data, 1);
|
||||
$G2: nth($data, 2);
|
||||
$pos: nth($data, 3);
|
||||
$shape-size: nth($data, 4);
|
||||
|
||||
$full: compact($G1, $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10);
|
||||
|
||||
// Strip deprecated cover/contain for spec
|
||||
$shape-size-spec: _shape-size-stripper($shape-size);
|
||||
|
||||
// Set $G1 as the default fallback color
|
||||
$first-color: nth($full, 1);
|
||||
$fallback-color: nth($first-color, 1);
|
||||
|
||||
@if (type-of($fallback) == color) or ($fallback == "transparent") {
|
||||
$fallback-color: $fallback;
|
||||
}
|
||||
|
||||
// Add Commas and spaces
|
||||
$shape-size: if($shape-size, '#{$shape-size}, ', null);
|
||||
$pos: if($pos, '#{$pos}, ', null);
|
||||
$pos-spec: if($pos, 'at #{$pos}', null);
|
||||
$shape-size-spec: if(($shape-size-spec != ' ') and ($pos == null), '#{$shape-size-spec}, ', '#{$shape-size-spec} ');
|
||||
|
||||
background-color: $fallback-color;
|
||||
background-image: _deprecated-webkit-gradient(radial, $deprecated-pos1, $deprecated-pos2, $full, $deprecated-radius1, $deprecated-radius2); // Safari <= 5.0 && IOS 4
|
||||
background-image: -webkit-radial-gradient(unquote(#{$pos}#{$shape-size}#{$full}));
|
||||
background-image: unquote("radial-gradient(#{$shape-size-spec}#{$pos-spec}#{$full})");
|
||||
}
|
||||
15
docs/_css/bourbon/css3/_transform.scss
vendored
Normal file
15
docs/_css/bourbon/css3/_transform.scss
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
@mixin transform($property: none) {
|
||||
// none | <transform-function>
|
||||
@include prefixer(transform, $property, webkit moz ms o spec);
|
||||
}
|
||||
|
||||
@mixin transform-origin($axes: 50%) {
|
||||
// x-axis - left | center | right | length | %
|
||||
// y-axis - top | center | bottom | length | %
|
||||
// z-axis - length
|
||||
@include prefixer(transform-origin, $axes, webkit moz ms o spec);
|
||||
}
|
||||
|
||||
@mixin transform-style ($style: flat) {
|
||||
@include prefixer(transform-style, $style, webkit moz ms o spec);
|
||||
}
|
||||
34
docs/_css/bourbon/css3/_transition.scss
vendored
Normal file
34
docs/_css/bourbon/css3/_transition.scss
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// Shorthand mixin. Supports multiple parentheses-deliminated values for each variable.
|
||||
// Example: @include transition (all, 2.0s, ease-in-out);
|
||||
// @include transition ((opacity, width), (1.0s, 2.0s), ease-in, (0, 2s));
|
||||
// @include transition ($property:(opacity, width), $delay: (1.5s, 2.5s));
|
||||
|
||||
@mixin transition ($properties...) {
|
||||
@if length($properties) >= 1 {
|
||||
@include prefixer(transition, $properties, webkit moz spec);
|
||||
}
|
||||
|
||||
@else {
|
||||
$properties: all 0.15s ease-out 0;
|
||||
@include prefixer(transition, $properties, webkit moz spec);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin transition-property ($properties...) {
|
||||
-webkit-transition-property: transition-property-names($properties, 'webkit');
|
||||
-moz-transition-property: transition-property-names($properties, 'moz');
|
||||
transition-property: transition-property-names($properties, false);
|
||||
}
|
||||
|
||||
@mixin transition-duration ($times...) {
|
||||
@include prefixer(transition-duration, $times, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin transition-timing-function ($motions...) {
|
||||
// ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier()
|
||||
@include prefixer(transition-timing-function, $motions, webkit moz spec);
|
||||
}
|
||||
|
||||
@mixin transition-delay ($times...) {
|
||||
@include prefixer(transition-delay, $times, webkit moz spec);
|
||||
}
|
||||
3
docs/_css/bourbon/css3/_user-select.scss
vendored
Normal file
3
docs/_css/bourbon/css3/_user-select.scss
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
@mixin user-select($arg: none) {
|
||||
@include prefixer(user-select, $arg, webkit moz ms spec);
|
||||
}
|
||||
11
docs/_css/bourbon/functions/_compact.scss
vendored
Normal file
11
docs/_css/bourbon/functions/_compact.scss
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// Remove `false` values from a list
|
||||
|
||||
@function compact($vars...) {
|
||||
$list: ();
|
||||
@each $var in $vars {
|
||||
@if $var {
|
||||
$list: append($list, $var, comma);
|
||||
}
|
||||
}
|
||||
@return $list;
|
||||
}
|
||||
39
docs/_css/bourbon/functions/_flex-grid.scss
vendored
Normal file
39
docs/_css/bourbon/functions/_flex-grid.scss
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// Flexible grid
|
||||
@function flex-grid($columns, $container-columns: $fg-max-columns) {
|
||||
$width: $columns * $fg-column + ($columns - 1) * $fg-gutter;
|
||||
$container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter;
|
||||
@return percentage($width / $container-width);
|
||||
}
|
||||
|
||||
// Flexible gutter
|
||||
@function flex-gutter($container-columns: $fg-max-columns, $gutter: $fg-gutter) {
|
||||
$container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter;
|
||||
@return percentage($gutter / $container-width);
|
||||
}
|
||||
|
||||
// The $fg-column, $fg-gutter and $fg-max-columns variables must be defined in your base stylesheet to properly use the flex-grid function.
|
||||
// This function takes the fluid grid equation (target / context = result) and uses columns to help define each.
|
||||
//
|
||||
// The calculation presumes that your column structure will be missing the last gutter:
|
||||
//
|
||||
// -- column -- gutter -- column -- gutter -- column
|
||||
//
|
||||
// $fg-column: 60px; // Column Width
|
||||
// $fg-gutter: 25px; // Gutter Width
|
||||
// $fg-max-columns: 12; // Total Columns For Main Container
|
||||
//
|
||||
// div {
|
||||
// width: flex-grid(4); // returns (315px / 995px) = 31.65829%;
|
||||
// margin-left: flex-gutter(); // returns (25px / 995px) = 2.51256%;
|
||||
//
|
||||
// p {
|
||||
// width: flex-grid(2, 4); // returns (145px / 315px) = 46.031746%;
|
||||
// float: left;
|
||||
// margin: flex-gutter(4); // returns (25px / 315px) = 7.936508%;
|
||||
// }
|
||||
//
|
||||
// blockquote {
|
||||
// float: left;
|
||||
// width: flex-grid(2, 4); // returns (145px / 315px) = 46.031746%;
|
||||
// }
|
||||
// }
|
||||
13
docs/_css/bourbon/functions/_grid-width.scss
vendored
Normal file
13
docs/_css/bourbon/functions/_grid-width.scss
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
@function grid-width($n) {
|
||||
@return $n * $gw-column + ($n - 1) * $gw-gutter;
|
||||
}
|
||||
|
||||
// The $gw-column and $gw-gutter variables must be defined in your base stylesheet to properly use the grid-width function.
|
||||
//
|
||||
// $gw-column: 100px; // Column Width
|
||||
// $gw-gutter: 40px; // Gutter Width
|
||||
//
|
||||
// div {
|
||||
// width: grid-width(4); // returns 520px;
|
||||
// margin-left: $gw-gutter; // returns 40px;
|
||||
// }
|
||||
13
docs/_css/bourbon/functions/_linear-gradient.scss
vendored
Normal file
13
docs/_css/bourbon/functions/_linear-gradient.scss
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
@function linear-gradient($pos, $gradients...) {
|
||||
$type: linear;
|
||||
$pos-type: type-of(nth($pos, 1));
|
||||
|
||||
// if $pos doesn't exist, fix $gradient
|
||||
@if ($pos-type == color) or (nth($pos, 1) == "transparent") {
|
||||
$gradients: zip($pos $gradients);
|
||||
$pos: false;
|
||||
}
|
||||
|
||||
$type-gradient: $type, $pos, $gradients;
|
||||
@return $type-gradient;
|
||||
}
|
||||
40
docs/_css/bourbon/functions/_modular-scale.scss
vendored
Normal file
40
docs/_css/bourbon/functions/_modular-scale.scss
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
@function modular-scale($value, $increment, $ratio) {
|
||||
@if $increment > 0 {
|
||||
@for $i from 1 through $increment {
|
||||
$value: ($value * $ratio);
|
||||
}
|
||||
}
|
||||
|
||||
@if $increment < 0 {
|
||||
$increment: abs($increment);
|
||||
@for $i from 1 through $increment {
|
||||
$value: ($value / $ratio);
|
||||
}
|
||||
}
|
||||
|
||||
@return $value;
|
||||
}
|
||||
|
||||
// div {
|
||||
// Increment Up GR with positive value
|
||||
// font-size: modular-scale(14px, 1, 1.618); // returns: 22.652px
|
||||
//
|
||||
// Increment Down GR with negative value
|
||||
// font-size: modular-scale(14px, -1, 1.618); // returns: 8.653px
|
||||
//
|
||||
// Can be used with ceil(round up) or floor(round down)
|
||||
// font-size: floor( modular-scale(14px, 1, 1.618) ); // returns: 22px
|
||||
// font-size: ceil( modular-scale(14px, 1, 1.618) ); // returns: 23px
|
||||
// }
|
||||
//
|
||||
// modularscale.com
|
||||
|
||||
@function golden-ratio($value, $increment) {
|
||||
@return modular-scale($value, $increment, 1.618)
|
||||
}
|
||||
|
||||
// div {
|
||||
// font-size: golden-ratio(14px, 1); // returns: 22.652px
|
||||
// }
|
||||
//
|
||||
// goldenratiocalculator.com
|
||||
8
docs/_css/bourbon/functions/_px-to-em.scss
vendored
Normal file
8
docs/_css/bourbon/functions/_px-to-em.scss
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
// Convert pixels to ems
|
||||
// eg. for a relational value of 12px write em(12) when the parent is 16px
|
||||
// if the parent is another value say 24px write em(12, 24)
|
||||
|
||||
@function em($pxval, $base: 16) {
|
||||
@return ($pxval / $base) * 1em;
|
||||
}
|
||||
|
||||
23
docs/_css/bourbon/functions/_radial-gradient.scss
vendored
Normal file
23
docs/_css/bourbon/functions/_radial-gradient.scss
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// This function is required and used by the background-image mixin.
|
||||
@function radial-gradient($G1, $G2,
|
||||
$G3: false, $G4: false,
|
||||
$G5: false, $G6: false,
|
||||
$G7: false, $G8: false,
|
||||
$G9: false, $G10: false,
|
||||
$pos: null,
|
||||
$shape-size: null) {
|
||||
|
||||
$data: _radial-arg-parser($G1, $G2, $pos, $shape-size);
|
||||
$G1: nth($data, 1);
|
||||
$G2: nth($data, 2);
|
||||
$pos: nth($data, 3);
|
||||
$shape-size: nth($data, 4);
|
||||
|
||||
$type: radial;
|
||||
$gradient: compact($G1, $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10);
|
||||
|
||||
$type-gradient: $type, $shape-size $pos, $gradient;
|
||||
@return $type-gradient;
|
||||
}
|
||||
|
||||
|
||||
9
docs/_css/bourbon/functions/_tint-shade.scss
vendored
Normal file
9
docs/_css/bourbon/functions/_tint-shade.scss
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// Add percentage of white to a color
|
||||
@function tint($color, $percent){
|
||||
@return mix(white, $color, $percent);
|
||||
}
|
||||
|
||||
// Add percentage of black to a color
|
||||
@function shade($color, $percent){
|
||||
@return mix(black, $color, $percent);
|
||||
}
|
||||
22
docs/_css/bourbon/functions/_transition-property-name.scss
vendored
Normal file
22
docs/_css/bourbon/functions/_transition-property-name.scss
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// Return vendor-prefixed property names if appropriate
|
||||
// Example: transition-property-names((transform, color, background), moz) -> -moz-transform, color, background
|
||||
//************************************************************************//
|
||||
@function transition-property-names($props, $vendor: false) {
|
||||
$new-props: ();
|
||||
|
||||
@each $prop in $props {
|
||||
$new-props: append($new-props, transition-property-name($prop, $vendor), comma);
|
||||
}
|
||||
|
||||
@return $new-props;
|
||||
}
|
||||
|
||||
@function transition-property-name($prop, $vendor: false) {
|
||||
// put other properties that need to be prefixed here aswell
|
||||
@if $vendor and $prop == transform {
|
||||
@return unquote('-'+$vendor+'-'+$prop);
|
||||
}
|
||||
@else {
|
||||
@return $prop;
|
||||
}
|
||||
}
|
||||
39
docs/_css/bourbon/helpers/_deprecated-webkit-gradient.scss
vendored
Normal file
39
docs/_css/bourbon/helpers/_deprecated-webkit-gradient.scss
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
// Render Deprecated Webkit Gradient - Linear || Radial
|
||||
//************************************************************************//
|
||||
@function _deprecated-webkit-gradient($type,
|
||||
$deprecated-pos1, $deprecated-pos2,
|
||||
$full,
|
||||
$deprecated-radius1: false, $deprecated-radius2: false) {
|
||||
$gradient-list: ();
|
||||
$gradient: false;
|
||||
$full-length: length($full);
|
||||
$percentage: false;
|
||||
$gradient-type: $type;
|
||||
|
||||
@for $i from 1 through $full-length {
|
||||
$gradient: nth($full, $i);
|
||||
|
||||
@if length($gradient) == 2 {
|
||||
$color-stop: color-stop(nth($gradient, 2), nth($gradient, 1));
|
||||
$gradient-list: join($gradient-list, $color-stop, comma);
|
||||
}
|
||||
@else if $gradient != null {
|
||||
@if $i == $full-length {
|
||||
$percentage: 100%;
|
||||
}
|
||||
@else {
|
||||
$percentage: ($i - 1) * (100 / ($full-length - 1)) + "%";
|
||||
}
|
||||
$color-stop: color-stop(unquote($percentage), $gradient);
|
||||
$gradient-list: join($gradient-list, $color-stop, comma);
|
||||
}
|
||||
}
|
||||
|
||||
@if $type == radial {
|
||||
$gradient: -webkit-gradient(radial, $deprecated-pos1, $deprecated-radius1, $deprecated-pos2, $deprecated-radius2, $gradient-list);
|
||||
}
|
||||
@else if $type == linear {
|
||||
$gradient: -webkit-gradient(linear, $deprecated-pos1, $deprecated-pos2, $gradient-list);
|
||||
}
|
||||
@return $gradient;
|
||||
}
|
||||
13
docs/_css/bourbon/helpers/_gradient-positions-parser.scss
vendored
Normal file
13
docs/_css/bourbon/helpers/_gradient-positions-parser.scss
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
@function _gradient-positions-parser($gradient-type, $gradient-positions) {
|
||||
@if $gradient-positions
|
||||
and ($gradient-type == linear)
|
||||
and (type-of($gradient-positions) != color) {
|
||||
$gradient-positions: _linear-positions-parser($gradient-positions);
|
||||
}
|
||||
@else if $gradient-positions
|
||||
and ($gradient-type == radial)
|
||||
and (type-of($gradient-positions) != color) {
|
||||
$gradient-positions: _radial-positions-parser($gradient-positions);
|
||||
}
|
||||
@return $gradient-positions;
|
||||
}
|
||||
61
docs/_css/bourbon/helpers/_linear-positions-parser.scss
vendored
Normal file
61
docs/_css/bourbon/helpers/_linear-positions-parser.scss
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
@function _linear-positions-parser($pos) {
|
||||
$type: type-of(nth($pos, 1));
|
||||
$spec: null;
|
||||
$degree: null;
|
||||
$side: null;
|
||||
$corner: null;
|
||||
$length: length($pos);
|
||||
// Parse Side and corner positions
|
||||
@if ($length > 1) {
|
||||
@if nth($pos, 1) == "to" { // Newer syntax
|
||||
$side: nth($pos, 2);
|
||||
|
||||
@if $length == 2 { // eg. to top
|
||||
// Swap for backwards compatability
|
||||
$degree: _position-flipper(nth($pos, 2));
|
||||
}
|
||||
@else if $length == 3 { // eg. to top left
|
||||
$corner: nth($pos, 3);
|
||||
}
|
||||
}
|
||||
@else if $length == 2 { // Older syntax ("top left")
|
||||
$side: _position-flipper(nth($pos, 1));
|
||||
$corner: _position-flipper(nth($pos, 2));
|
||||
}
|
||||
|
||||
@if ("#{$side} #{$corner}" == "left top") or ("#{$side} #{$corner}" == "top left") {
|
||||
$degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
|
||||
}
|
||||
@else if ("#{$side} #{$corner}" == "right top") or ("#{$side} #{$corner}" == "top right") {
|
||||
$degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
|
||||
}
|
||||
@else if ("#{$side} #{$corner}" == "right bottom") or ("#{$side} #{$corner}" == "bottom right") {
|
||||
$degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
|
||||
}
|
||||
@else if ("#{$side} #{$corner}" == "left bottom") or ("#{$side} #{$corner}" == "bottom left") {
|
||||
$degree: _position-flipper(#{$side}) _position-flipper(#{$corner});
|
||||
}
|
||||
$spec: to $side $corner;
|
||||
}
|
||||
@else if $length == 1 {
|
||||
// Swap for backwards compatability
|
||||
@if $type == string {
|
||||
$degree: $pos;
|
||||
$spec: to _position-flipper($pos);
|
||||
}
|
||||
@else {
|
||||
$degree: -270 - $pos; //rotate the gradient opposite from spec
|
||||
$spec: $pos;
|
||||
}
|
||||
}
|
||||
$degree: unquote($degree + ",");
|
||||
$spec: unquote($spec + ",");
|
||||
@return $degree $spec;
|
||||
}
|
||||
|
||||
@function _position-flipper($pos) {
|
||||
@return if($pos == left, right, null)
|
||||
if($pos == right, left, null)
|
||||
if($pos == top, bottom, null)
|
||||
if($pos == bottom, top, null);
|
||||
}
|
||||
69
docs/_css/bourbon/helpers/_radial-arg-parser.scss
vendored
Normal file
69
docs/_css/bourbon/helpers/_radial-arg-parser.scss
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
@function _radial-arg-parser($G1, $G2, $pos, $shape-size) {
|
||||
@each $value in $G1, $G2 {
|
||||
$first-val: nth($value, 1);
|
||||
$pos-type: type-of($first-val);
|
||||
$spec-at-index: null;
|
||||
|
||||
// Determine if spec was passed to mixin
|
||||
@if type-of($value) == list {
|
||||
$spec-at-index: if(index($value, at), index($value, at), false);
|
||||
}
|
||||
@if $spec-at-index {
|
||||
@if $spec-at-index > 1 {
|
||||
@for $i from 1 through ($spec-at-index - 1) {
|
||||
$shape-size: $shape-size nth($value, $i);
|
||||
}
|
||||
@for $i from ($spec-at-index + 1) through length($value) {
|
||||
$pos: $pos nth($value, $i);
|
||||
}
|
||||
}
|
||||
@else if $spec-at-index == 1 {
|
||||
@for $i from ($spec-at-index + 1) through length($value) {
|
||||
$pos: $pos nth($value, $i);
|
||||
}
|
||||
}
|
||||
$G1: false;
|
||||
}
|
||||
|
||||
// If not spec calculate correct values
|
||||
@else {
|
||||
@if ($pos-type != color) or ($first-val != "transparent") {
|
||||
@if ($pos-type == number)
|
||||
or ($first-val == "center")
|
||||
or ($first-val == "top")
|
||||
or ($first-val == "right")
|
||||
or ($first-val == "bottom")
|
||||
or ($first-val == "left") {
|
||||
|
||||
$pos: $value;
|
||||
|
||||
@if $pos == $G1 {
|
||||
$G1: false;
|
||||
}
|
||||
}
|
||||
|
||||
@else if
|
||||
($first-val == "ellipse")
|
||||
or ($first-val == "circle")
|
||||
or ($first-val == "closest-side")
|
||||
or ($first-val == "closest-corner")
|
||||
or ($first-val == "farthest-side")
|
||||
or ($first-val == "farthest-corner")
|
||||
or ($first-val == "contain")
|
||||
or ($first-val == "cover") {
|
||||
|
||||
$shape-size: $value;
|
||||
|
||||
@if $value == $G1 {
|
||||
$G1: false;
|
||||
}
|
||||
|
||||
@else if $value == $G2 {
|
||||
$G2: false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@return $G1, $G2, $pos, $shape-size;
|
||||
}
|
||||
18
docs/_css/bourbon/helpers/_radial-positions-parser.scss
vendored
Normal file
18
docs/_css/bourbon/helpers/_radial-positions-parser.scss
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
@function _radial-positions-parser($gradient-pos) {
|
||||
$shape-size: nth($gradient-pos, 1);
|
||||
$pos: nth($gradient-pos, 2);
|
||||
$shape-size-spec: _shape-size-stripper($shape-size);
|
||||
|
||||
$pre-spec: unquote(if($pos, "#{$pos}, ", null))
|
||||
unquote(if($shape-size, "#{$shape-size},", null));
|
||||
$pos-spec: if($pos, "at #{$pos}", null);
|
||||
|
||||
$spec: "#{$shape-size-spec} #{$pos-spec}";
|
||||
|
||||
// Add comma
|
||||
@if ($spec != ' ') {
|
||||
$spec: "#{$spec},"
|
||||
}
|
||||
|
||||
@return $pre-spec $spec;
|
||||
}
|
||||
26
docs/_css/bourbon/helpers/_render-gradients.scss
vendored
Normal file
26
docs/_css/bourbon/helpers/_render-gradients.scss
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// User for linear and radial gradients within background-image or border-image properties
|
||||
|
||||
@function _render-gradients($gradient-positions, $gradients, $gradient-type, $vendor: false) {
|
||||
$pre-spec: null;
|
||||
$spec: null;
|
||||
$vendor-gradients: null;
|
||||
@if $gradient-type == linear {
|
||||
@if $gradient-positions {
|
||||
$pre-spec: nth($gradient-positions, 1);
|
||||
$spec: nth($gradient-positions, 2);
|
||||
}
|
||||
}
|
||||
@else if $gradient-type == radial {
|
||||
$pre-spec: nth($gradient-positions, 1);
|
||||
$spec: nth($gradient-positions, 2);
|
||||
}
|
||||
|
||||
@if $vendor {
|
||||
$vendor-gradients: -#{$vendor}-#{$gradient-type}-gradient(#{$pre-spec} $gradients);
|
||||
}
|
||||
@else if $vendor == false {
|
||||
$vendor-gradients: "#{$gradient-type}-gradient(#{$spec} #{$gradients})";
|
||||
$vendor-gradients: unquote($vendor-gradients);
|
||||
}
|
||||
@return $vendor-gradients;
|
||||
}
|
||||
10
docs/_css/bourbon/helpers/_shape-size-stripper.scss
vendored
Normal file
10
docs/_css/bourbon/helpers/_shape-size-stripper.scss
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
@function _shape-size-stripper($shape-size) {
|
||||
$shape-size-spec: null;
|
||||
@each $value in $shape-size {
|
||||
@if ($value == "cover") or ($value == "contain") {
|
||||
$value: null;
|
||||
}
|
||||
$shape-size-spec: "#{$shape-size-spec} #{$value}";
|
||||
}
|
||||
@return $shape-size-spec;
|
||||
}
|
||||
630
docs/_css/react.scss
Normal file
630
docs/_css/react.scss
Normal file
|
|
@ -0,0 +1,630 @@
|
|||
@import 'bourbon/bourbon';
|
||||
@import '_variables';
|
||||
@import '_typography';
|
||||
@import '_solarized';
|
||||
|
||||
$skinnyContentWidth: 650px;
|
||||
$contentWidth: 920px;
|
||||
$contentPadding: 20px;
|
||||
$columnWidth: 280px;
|
||||
$columnGutter: 40px;
|
||||
$twoColumnWidth: 2 * $columnWidth + $columnGutter;
|
||||
|
||||
|
||||
|
||||
// basic reset
|
||||
* {
|
||||
@include box-sizing(border-box);
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
background: $pageBg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
.container {
|
||||
padding-top: 50px;
|
||||
min-width: $contentWidth + (2 * $contentPadding);
|
||||
}
|
||||
|
||||
.wrap {
|
||||
width: $contentWidth + (2 * $contentPadding);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.skinnyWrap {
|
||||
width: $skinnyContentWidth + (2 * $contentPadding);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 0;
|
||||
border-top: 1px solid #ccc;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
ul,
|
||||
li {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
// Main Nav
|
||||
|
||||
.nav-main {
|
||||
@include clearfix;
|
||||
background: $darkestColor;
|
||||
color: $lightTextColor;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
height: 50px;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, .5);
|
||||
width: 100%;
|
||||
z-index: 100;
|
||||
|
||||
a {
|
||||
color: $lightColor;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nav-site {
|
||||
float: right;
|
||||
margin: 0;
|
||||
|
||||
li {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
padding: 0 8px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
line-height: 50px;
|
||||
display: inline-block;
|
||||
height: 50px;
|
||||
color: $mediumTextColor;
|
||||
|
||||
&:hover {
|
||||
color: $lightTextColor;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: $lightTextColor;
|
||||
border-bottom: 3px solid $primary;
|
||||
background: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-home {
|
||||
color: #00d8ff;
|
||||
font-size: 24px;
|
||||
line-height: 50px;
|
||||
}
|
||||
|
||||
.nav-logo {
|
||||
@include retina-image('../img/logo_small', 38px 38px);
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
ul {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
li {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
// Hero!
|
||||
|
||||
.hero {
|
||||
height: 300px;
|
||||
// background: $darkColor url(../img/header.png) no-repeat center;
|
||||
background: $darkColor;
|
||||
padding-top: 50px;
|
||||
color: $lightColor;
|
||||
font-weight: 300;
|
||||
|
||||
.text {
|
||||
font-size: 64px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.minitext {
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
strong {
|
||||
color: $blueColor;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.buttons-unit {
|
||||
margin-top: 60px;
|
||||
text-align: center;
|
||||
|
||||
a {
|
||||
color: $blueColor;
|
||||
}
|
||||
|
||||
.button {
|
||||
font-size: 24px;
|
||||
background: $primary;
|
||||
color: $lightTextColor;
|
||||
|
||||
&:active {
|
||||
background: darken($primary, 5%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Downloads
|
||||
|
||||
.buttons-unit.downloads {
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
// Docs Nav
|
||||
|
||||
.nav-docs {
|
||||
color: $darkColor;
|
||||
font-size: 14px;
|
||||
// position: fixed;
|
||||
float: left;
|
||||
top: 100px;
|
||||
width: 180px;
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
}
|
||||
li {
|
||||
margin: 0;
|
||||
}
|
||||
h3 {
|
||||
text-transform: uppercase;
|
||||
font-size: 14px;
|
||||
}
|
||||
a {
|
||||
color: $mediumestColor;
|
||||
display: block;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
color: $primary;
|
||||
}
|
||||
|
||||
&.active {
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-docs-section {
|
||||
border-bottom: 1px solid #ccc;
|
||||
border-top: 1px solid #eee;
|
||||
padding: 12px 0;
|
||||
|
||||
&:first-child {
|
||||
padding-top: 0;
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-bottom: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Home Page specifics
|
||||
|
||||
.home-section {
|
||||
margin: 50px 0;
|
||||
}
|
||||
|
||||
.home-divider {
|
||||
border-top-color: #bbb;
|
||||
margin: 0 auto;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.marketing-row {
|
||||
@include clearfix;
|
||||
margin: 50px 0;
|
||||
}
|
||||
|
||||
.marketing-col {
|
||||
float: left;
|
||||
margin-right: 40px;
|
||||
width: $columnWidth;
|
||||
|
||||
h3 {
|
||||
color: $darkColor;
|
||||
font-size: 24px;
|
||||
font-weight: normal;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
p {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.marketing-col:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
#examples {
|
||||
h3 {
|
||||
color: $darkColor;
|
||||
font-size: 24px;
|
||||
font-weight: normal;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 0 25px 0;
|
||||
max-width: $twoColumnWidth;
|
||||
}
|
||||
|
||||
.example {
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
#todoExample {
|
||||
font-size: 14px;
|
||||
ul {
|
||||
list-style-type: square;
|
||||
margin: 0 0 10px 0;
|
||||
}
|
||||
input {
|
||||
border: 1px solid #ccc;
|
||||
font: 14px proxima-nova, $helvetica;
|
||||
padding: 3px;
|
||||
width: 150px;
|
||||
}
|
||||
button {
|
||||
font: 14px proxima-nova, $helvetica;
|
||||
margin-left: 5px;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
#markdownExample {
|
||||
textarea {
|
||||
border: 1px solid #ccc;
|
||||
font: 14px proxima-nova, $helvetica;
|
||||
margin-bottom: 10px;
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.home-bottom-section {
|
||||
margin-bottom: 100px;
|
||||
}
|
||||
|
||||
.docs-nextprev {
|
||||
@include clearfix;
|
||||
}
|
||||
|
||||
.docs-prev {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.docs-next {
|
||||
float: right;
|
||||
}
|
||||
|
||||
footer {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
margin-top: 36px;
|
||||
margin-bottom: 18px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
section.black content {
|
||||
padding-bottom: 18px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Docs
|
||||
*/
|
||||
|
||||
.documentationContent {
|
||||
@include clearfix;
|
||||
|
||||
.subHeader {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
// H2s form documentation topic dividers. Extra space helps.
|
||||
h2 {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
padding-top: 20px;
|
||||
|
||||
// Make a notice box out of blockquotes in the documetation:
|
||||
blockquote {
|
||||
padding: 15px 30px 15px 15px;
|
||||
margin: 20px 0;
|
||||
background-color: rgba(204, 122, 111, 0.09999999999999998);
|
||||
border-left: 5px solid rgba(191, 87, 73, 0.19999999999999996);
|
||||
h4 {
|
||||
margin-top: 0;
|
||||
}
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
// Treat first child as the title - promote to H4.
|
||||
p:first-child {
|
||||
font-weight: bold;
|
||||
font-size: 17.5px;
|
||||
line-height: 20px;
|
||||
margin-top: 0;
|
||||
text-rendering: optimizelegibility;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.docs-prevnext {
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
|
||||
/* Button */
|
||||
|
||||
.button {
|
||||
@include background(linear-gradient($buttonGreyTop, $buttonGreyBottom));
|
||||
// border: 1px solid $darkestColor;
|
||||
border-radius: 4px;
|
||||
padding: 8px 16px;
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
margin: 0 12px;
|
||||
// word-spacing: -2px;
|
||||
// letter-spacing: 1px;
|
||||
display: inline-block;
|
||||
color: $lightTextColor;
|
||||
text-decoration: none;
|
||||
text-shadow: 0 1px 3px rgba(0, 0, 0, .3);
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, .2);
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&:active {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.hero {
|
||||
.button {
|
||||
box-shadow: 1px 3px 3px rgba(0, 0, 0, .3);
|
||||
}
|
||||
}
|
||||
|
||||
.button.blue {
|
||||
@include background(linear-gradient($buttonBlueTop, $buttonBlueBottom));
|
||||
}
|
||||
|
||||
|
||||
/* Row */
|
||||
|
||||
.row {
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.row .span4 {
|
||||
width: 33.33%;
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.row .span8 {
|
||||
width: 66.66%;
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.row .span6 {
|
||||
width: 50%;
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
|
||||
/* Content */
|
||||
|
||||
p {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
padding: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.inner-content {
|
||||
float: right;
|
||||
width: $skinnyContentWidth;
|
||||
}
|
||||
|
||||
.nosidebar .inner-content {
|
||||
float: none;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Code Mirror */
|
||||
|
||||
div.CodeMirror pre, div.CodeMirror-linenumber, code {
|
||||
font-family: 'source-code-pro', Menlo, 'Courier New', Consolas, monospace;
|
||||
font-size: 13px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
div.CodeMirror-linenumber:after {
|
||||
content: '.';
|
||||
}
|
||||
|
||||
.CodeMirror, div.CodeMirror-gutters, div.highlight {
|
||||
border: none;
|
||||
}
|
||||
|
||||
small code,
|
||||
li code,
|
||||
p code {
|
||||
color: #555;
|
||||
background-color: rgba(0, 0, 0, .04);
|
||||
padding: 1px 3px;
|
||||
}
|
||||
|
||||
.cm-s-default span.cm-string-2 {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.playground {
|
||||
@include clearfix;
|
||||
}
|
||||
|
||||
.playground::before {
|
||||
border-bottom: none !important;
|
||||
border-radius: 3px 3px 0 0;
|
||||
padding: 3px 7px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: #c2c0bc;
|
||||
background-color: #f1ede4;
|
||||
content: 'Live editor';
|
||||
}
|
||||
|
||||
.playground::before,
|
||||
.playgroundCode,
|
||||
.playgroundPreview {
|
||||
border: 1px solid rgba(16,16,16,0.1);
|
||||
}
|
||||
|
||||
.playgroundCode {
|
||||
border-radius: 0 3px 3px 3px;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
width: $twoColumnWidth;
|
||||
}
|
||||
|
||||
.playgroundPreview {
|
||||
background-color: white;
|
||||
border-radius: 3px;
|
||||
float: right;
|
||||
padding: 15px 20px;
|
||||
width: $columnWidth;
|
||||
}
|
||||
|
||||
.MarkdownEditor textarea {
|
||||
width: 100%;
|
||||
height: 100px
|
||||
}
|
||||
|
||||
.hll {
|
||||
background-color: #f7ebc6;
|
||||
border-left: 5px solid #f7d87c;
|
||||
display: block;
|
||||
margin-left: -14px;
|
||||
margin-right: -14px;
|
||||
padding-left: 9px;
|
||||
}
|
||||
|
||||
/* Codemirror doesn't support <jsx> syntax. Instead of highlighting it
|
||||
as error, just ignore it */
|
||||
.highlight .javascript .err {
|
||||
background-color: transparent;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
position: relative;
|
||||
margin-bottom: 14px;
|
||||
padding: 30px 14px 14px;
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
|
||||
.highlight pre {
|
||||
padding: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.highlight pre code {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.highlight pre .lineno {
|
||||
display: inline-block;
|
||||
width: 22px;
|
||||
padding-right: 5px;
|
||||
margin-right: 10px;
|
||||
color: #bebec5;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Echo out a label for the example */
|
||||
|
||||
.highlight:after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
padding: 3px 7px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: #c2c0bc;
|
||||
background-color: #f1ede4;
|
||||
content: "Code";
|
||||
}
|
||||
|
||||
.downloadCenter {
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.downloadSection:hover {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 960px) {
|
||||
.nav-main {
|
||||
position: static;
|
||||
}
|
||||
.container {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
23
docs/_includes/nav_docs.html
Normal file
23
docs/_includes/nav_docs.html
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
<div class="nav-docs">
|
||||
<div class="nav-docs-section">
|
||||
<h3>Getting started</h3>
|
||||
<ul>
|
||||
<li><a href="/react/docs/getting-started.html"{% if page.id == 'docs-getting-started' %} class="active"{% endif %}>Getting Started</a></li>
|
||||
<li><a href="/react/docs/tutorial.html"{% if page.id == 'docs-tutorial' %} class="active"{% endif %}>Tutorial</a></li>
|
||||
<li><a href="/react/docs/common-questions.html"{% if page.id == 'docs-common-questions' %} class="active"{% endif %}>Common Questions</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="nav-docs-section">
|
||||
<h3>Reference</h3>
|
||||
<ul>
|
||||
<li><a href="/react/docs/syntax.html"{% if page.id == 'docs-syntax' %} class="active"{% endif %}>JSX Syntax</a></li>
|
||||
<li><a href="/react/docs/component-basics.html"{% if page.id == 'docs-component-basics' %} class="active"{% endif %}>Component Basics</a></li>
|
||||
<li><a href="/react/docs/component-data.html"{% if page.id == 'docs-component-data' %} class="active"{% endif %}>Component Data</a></li>
|
||||
<li><a href="/react/docs/component-lifecycle.html"{% if page.id == 'docs-component-lifecycle' %} class="active"{% endif %}>Component Lifecycle</a></li>
|
||||
<li><a href="/react/docs/event-handling.html"{% if page.id == 'docs-event-handling' %} class="active"{% endif %}>Event Handling</a></li>
|
||||
<li><a href="/react/docs/advanced-components.html"{% if page.id == 'docs-advanced-components' %} class="active"{% endif %}>Advanced Components</a></li>
|
||||
<li><a href="/react/docs/api.html"{% if page.id == 'docs-api' %} class="active"{% endif %}>API</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
19
docs/_js/examples/hello.js
Normal file
19
docs/_js/examples/hello.js
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* @jsx React.DOM
|
||||
*/
|
||||
|
||||
var HELLO_COMPONENT = "\
|
||||
/** @jsx React.DOM */\n\
|
||||
var HelloMessage = React.createClass({\n\
|
||||
render: function() {\n\
|
||||
return <div>{'Hello ' + this.props.name}</div>;\n\
|
||||
}\n\
|
||||
});\n\
|
||||
\n\
|
||||
React.renderComponent(<HelloMessage name=\"John\" />, mountNode);\
|
||||
";
|
||||
|
||||
React.renderComponent(
|
||||
<ReactPlayground codeText={HELLO_COMPONENT} />,
|
||||
document.getElementById('helloExample')
|
||||
);
|
||||
42
docs/_js/examples/markdown.js
Normal file
42
docs/_js/examples/markdown.js
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* @jsx React.DOM
|
||||
*/
|
||||
|
||||
var MARKDOWN_COMPONENT = "\
|
||||
/** @jsx React.DOM */\n\
|
||||
\n\
|
||||
var converter = new Showdown.converter();\n\
|
||||
\n\
|
||||
var MarkdownEditor = React.createClass({\n\
|
||||
getInitialState: function() {\n\
|
||||
return {value: 'Type some *markdown* here!'};\n\
|
||||
},\n\
|
||||
handleKeyUp: React.autoBind(function() {\n\
|
||||
this.setState({value: this.refs.textarea.getDOMNode().value});\n\
|
||||
}),\n\
|
||||
render: function() {\n\
|
||||
return (\n\
|
||||
<div className=\"MarkdownEditor\">\n\
|
||||
<h3>Input</h3>\n\
|
||||
<textarea onKeyUp={this.handleKeyUp} ref=\"textarea\">\n\
|
||||
{this.state.value}\n\
|
||||
</textarea>\n\
|
||||
<h3>Output</h3>\n\
|
||||
<div\n\
|
||||
className=\"content\"\n\
|
||||
dangerouslySetInnerHTML={{\n\
|
||||
__html: converter.makeHtml(this.state.value)\n\
|
||||
}}\n\
|
||||
/>\n\
|
||||
</div>\n\
|
||||
);\n\
|
||||
}\n\
|
||||
});\n\
|
||||
\n\
|
||||
React.renderComponent(<MarkdownEditor />, mountNode);\
|
||||
";
|
||||
|
||||
React.renderComponent(
|
||||
<ReactPlayground codeText={MARKDOWN_COMPONENT} />,
|
||||
document.getElementById('markdownExample')
|
||||
);
|
||||
32
docs/_js/examples/timer.js
Normal file
32
docs/_js/examples/timer.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* @jsx React.DOM
|
||||
*/
|
||||
|
||||
var TIMER_COMPONENT = "\
|
||||
/** @jsx React.DOM */\n\
|
||||
var Timer = React.createClass({\n\
|
||||
getInitialState: function() {\n\
|
||||
return {secondsElapsed: 0};\n\
|
||||
},\n\
|
||||
tick: React.autoBind(function() {\n\
|
||||
this.setState({secondsElapsed: this.state.secondsElapsed + 1});\n\
|
||||
}),\n\
|
||||
componentDidMount: function() {\n\
|
||||
setInterval(this.tick, 1000);\n\
|
||||
},\n\
|
||||
render: function() {\n\
|
||||
return (\n\
|
||||
<div>\n\
|
||||
{'Seconds Ellapsed: ' + this.state.secondsElapsed}\n\
|
||||
</div>\n\
|
||||
);\n\
|
||||
}\n\
|
||||
});\n\
|
||||
\n\
|
||||
React.renderComponent(<Timer />, mountNode);\
|
||||
";
|
||||
|
||||
React.renderComponent(
|
||||
<ReactPlayground codeText={TIMER_COMPONENT} />,
|
||||
document.getElementById('timerExample')
|
||||
);
|
||||
57
docs/_js/examples/todo.js
Normal file
57
docs/_js/examples/todo.js
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* @jsx React.DOM
|
||||
*/
|
||||
|
||||
var TODO_COMPONENT = "\
|
||||
/** @jsx React.DOM */\n\
|
||||
var TodoList = React.createClass({\n\
|
||||
render: function() {\n\
|
||||
var items = this.props.items.map(function(item) {\n\
|
||||
return <li>{item}</li>;\n\
|
||||
});\n\
|
||||
return <ul>{items}</ul>;\n\
|
||||
}\n\
|
||||
});\n\
|
||||
\n\
|
||||
var TodoCreate = React.createClass({\n\
|
||||
handleSubmit: function() {\n\
|
||||
var textInput = this.refs.textInput.getDOMNode();\n\
|
||||
this.props.onCreate(textInput.value);\n\
|
||||
textInput.value = '';\n\
|
||||
return false;\n\
|
||||
},\n\
|
||||
render: function() {\n\
|
||||
return (\n\
|
||||
<form onSubmit={this.handleSubmit.bind(this)}>\n\
|
||||
<input type=\"text\" ref=\"textInput\" />\n\
|
||||
<button>Add</button>\n\
|
||||
</form>\n\
|
||||
);\n\
|
||||
}\n\
|
||||
});\n\
|
||||
\n\
|
||||
var TodoApp = React.createClass({\n\
|
||||
getInitialState: function() {\n\
|
||||
return {items: []};\n\
|
||||
},\n\
|
||||
onItemCreate: function(value) {\n\
|
||||
this.setState({items: this.state.items.concat([value])});\n\
|
||||
},\n\
|
||||
render: function() {\n\
|
||||
return (\n\
|
||||
<div>\n\
|
||||
<h3>TODO</h3>\n\
|
||||
<TodoList items={this.state.items} />\n\
|
||||
<TodoCreate onCreate={this.onItemCreate.bind(this)} />\n\
|
||||
</div>\n\
|
||||
);\n\
|
||||
}\n\
|
||||
});\n\
|
||||
\n\
|
||||
React.renderComponent(<TodoApp />, mountNode);\
|
||||
";
|
||||
|
||||
React.renderComponent(
|
||||
<ReactPlayground codeText={TODO_COMPONENT} />,
|
||||
document.getElementById('todoExample')
|
||||
);
|
||||
98
docs/_js/live_editor.js
Normal file
98
docs/_js/live_editor.js
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* @jsx React.DOM
|
||||
*/
|
||||
|
||||
var CodeMirrorEditor = React.createClass({
|
||||
componentDidMount: function(root) {
|
||||
this.editor = CodeMirror.fromTextArea(this.refs.editor.getDOMNode(), {
|
||||
mode: 'javascript',
|
||||
lineNumbers: false,
|
||||
matchBrackets: true,
|
||||
theme: 'solarized-light'
|
||||
});
|
||||
this.editor.on('change', this.onChange.bind(this));
|
||||
this.onChange();
|
||||
},
|
||||
onChange: function() {
|
||||
if (this.props.onChange) {
|
||||
var content = this.editor.getValue();
|
||||
this.props.onChange(content);
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
// wrap in a div to fully contain CodeMirror
|
||||
return (
|
||||
<div class={this.props.className}>
|
||||
<textarea ref="editor">{this.props.codeText}</textarea>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var ReactPlayground = React.createClass({
|
||||
MODES: {XJS: 'XJS', JS: 'JS'}, //keyMirror({XJS: true, JS: true}),
|
||||
|
||||
getInitialState: function() {
|
||||
return {mode: this.MODES.XJS, code: this.props.codeText};
|
||||
},
|
||||
|
||||
bindState: function(name) {
|
||||
return function(value) {
|
||||
var newState = {};
|
||||
newState[name] = value;
|
||||
this.setState(newState);
|
||||
}.bind(this);
|
||||
},
|
||||
|
||||
getDesugaredCode: function() {
|
||||
return JSXTransformer.transform(this.state.code).code;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var content;
|
||||
if (this.state.mode === this.MODES.XJS) {
|
||||
content =
|
||||
<CodeMirrorEditor
|
||||
onChange={this.bindState('code')}
|
||||
class="playgroundStage"
|
||||
codeText={this.state.code}
|
||||
/>;
|
||||
} else if (this.state.mode === this.MODES.JS) {
|
||||
content =
|
||||
<div class={{playgroundJS: true, playgroundStage: true}}>
|
||||
{this.getDesugaredCode()}
|
||||
</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="playground">
|
||||
<div class="playgroundCode">
|
||||
{content}
|
||||
</div>
|
||||
<div class="playgroundPreview">
|
||||
<div ref="mount" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this.executeCode();
|
||||
},
|
||||
componentDidUpdate: function() {
|
||||
this.executeCode();
|
||||
},
|
||||
executeCode: function() {
|
||||
var mountNode = this.refs.mount.getDOMNode();
|
||||
|
||||
try {
|
||||
React.unmountAndReleaseReactRootNode(mountNode);
|
||||
} catch (e) { }
|
||||
|
||||
try {
|
||||
eval(this.getDesugaredCode());
|
||||
} catch (e) {
|
||||
React.renderComponent(<div content={e.toString()} class={{playgroundError: true}} />, mountNode);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
75
docs/_layouts/default.html
Normal file
75
docs/_layouts/default.html
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>React | {{ page.title }}</title>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta property="og:title" content="React | {{ page.title }}" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="http://facebook.github.io/react{{ page.url }}" />
|
||||
<meta property="og:image" content="http://facebook.github.io/react/img/logo_og.png" />
|
||||
<meta property="og:description" content="A JavaScript library for building user interfaces" />
|
||||
|
||||
<link rel="shortcut icon" href="/react/favicon.ico">
|
||||
|
||||
<link rel="stylesheet" href="/react/css/react.css">
|
||||
<link rel="stylesheet" href="/react/css/syntax.css">
|
||||
<link rel="stylesheet" href="/react/css/codemirror.css">
|
||||
|
||||
<script type="text/javascript" src="//use.typekit.net/vqa1hcx.js"></script>
|
||||
<script type="text/javascript">try{Typekit.load();}catch(e){}</script>
|
||||
|
||||
<script type="text/javascript" src="/react/js/codemirror.js"></script>
|
||||
<script type="text/javascript" src="/react/js/javascript.js"></script>
|
||||
<script type="text/javascript" src="/react/js/react.min.js"></script>
|
||||
<script type="text/javascript" src="/react/js/JSXTransformer.js"></script>
|
||||
<script type="text/javascript" src="/react/js/live_editor.js"></script>
|
||||
<script type="text/javascript" src="/react/js/showdown.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<div class="nav-main">
|
||||
<div class="wrap">
|
||||
<a class="nav-home" href="/react/index.html">
|
||||
<img class="nav-logo" alt="" src="/react/img/logo_small.png">
|
||||
React
|
||||
</a>
|
||||
<ul class="nav-site">
|
||||
<li><a href="/react/docs/getting-started.html"{% if page.sectionid == 'docs' %} class="active"{% endif %}>docs</a></li>
|
||||
<li><a href="/react/support.html"{% if page.id == 'support' %} class="active"{% endif %}>support</a></li>
|
||||
<li><a href="/react/downloads.html"{% if page.id == 'downloads' %} class="active"{% endif %}>download</a></li>
|
||||
<li><a href="http://github.com/facebook/react">github</a>
|
||||
</ul>
|
||||
<!-- <iframe src="http://ghbtns.com/github-btn.html?user=facebook&repo=react.js&type=fork"allowtransparency="true" frameborder="0" scrolling="0" width="62" height="20"></iframe> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if page.id == 'home' %}
|
||||
<div class="hero">
|
||||
<div class="wrap">
|
||||
<div class="text"><strong>React</strong></div>
|
||||
<div class="minitext">
|
||||
A JavaScript library for building user interfaces
|
||||
</div>
|
||||
|
||||
<div class="buttons-unit">
|
||||
<a href="/react/docs/getting-started.html" class="button">Get Started</a>
|
||||
<a href="/react/downloads.html" class="button">Download React v{{site.react_version}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{ content }}
|
||||
|
||||
<footer class="wrap">
|
||||
<div class="left">A Facebook & Instagram collaboration.</div>
|
||||
<div class="right">© 2013 Facebook Inc.</div>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
23
docs/_layouts/docs.html
Normal file
23
docs/_layouts/docs.html
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
layout: default
|
||||
sectionid: docs
|
||||
---
|
||||
|
||||
<section class="content wrap documentationContent">
|
||||
{% include nav_docs.html %}
|
||||
|
||||
<div class="inner-content">
|
||||
<h1>{{ page.title }}</h1>
|
||||
<div class="subHeader">{{ page.description }}</div>
|
||||
{{ content }}
|
||||
|
||||
<div class="docs-prevnext">
|
||||
{% if page.prev %}
|
||||
<a class="docs-prev" href="/react/docs/{{ page.prev }}">← Prev</a>
|
||||
{% endif %}
|
||||
{% if page.next %}
|
||||
<a class="docs-next" href="/react/docs/{{ page.next }}">Next →</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
7
docs/_layouts/page.html
Normal file
7
docs/_layouts/page.html
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
<section class="content wrap">
|
||||
{{ content }}
|
||||
</section>
|
||||
12
docs/_layouts/post.html
Normal file
12
docs/_layouts/post.html
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
<section class="content wrap">
|
||||
<h2>{{ page.title }}</h2>
|
||||
<p class="meta">{{ page.date | date_to_string }}</p>
|
||||
|
||||
<div id="post">
|
||||
{{ content }}
|
||||
</div>
|
||||
</section>
|
||||
20
docs/_layouts/single.html
Normal file
20
docs/_layouts/single.html
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
<section class="content wrap documentationContent nosidebar">
|
||||
<div class="inner-content">
|
||||
<h1>{{ page.title }}</h1>
|
||||
<div class="subHeader">{{ page.description }}</div>
|
||||
{{ content }}
|
||||
|
||||
<div class="docs-prevnext">
|
||||
{% if page.prev %}
|
||||
<a class="docs-prev" href="/react/docs/{{ page.prev }}">← Prev</a>
|
||||
{% endif %}
|
||||
{% if page.next %}
|
||||
<a class="docs-next" href="/react/docs/{{ page.next }}">Next →</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
39
docs/_plugins/highlight_lines.rb
Normal file
39
docs/_plugins/highlight_lines.rb
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# Replace Jekyll's handling of the Redcarpet code_block (which already adds
|
||||
# support for highlighting, but needs support for the very non-standard
|
||||
# "code fences with line highlights" extension).
|
||||
# Since this is currently depending on Redcarpet to cooperate, we are going to
|
||||
# be naive, and only allow line highlighting when a language is specified. If
|
||||
# you don't want any syntax highlighting but want to highlight lines, then you
|
||||
# need to specify text as your language, like:
|
||||
# ```text{4}
|
||||
|
||||
|
||||
module Jekyll
|
||||
module Converters
|
||||
class Markdown
|
||||
class RedcarpetParser
|
||||
module WithPygments
|
||||
def block_code(code, lang)
|
||||
require 'pygments'
|
||||
lang_parts = lang && lang.split('{')
|
||||
lang = lang_parts && !lang_parts[0].empty? && lang_parts[0] || 'text'
|
||||
hl_lines = ''
|
||||
if lang_parts && lang_parts.size >= 2
|
||||
hl_lines = lang_parts[1].gsub(/[{}]/, '').split(',').map do |ln|
|
||||
if matches = /(\d+)-(\d+)/.match(ln)
|
||||
ln = Range.new(matches[1], matches[2]).to_a.join(' ')
|
||||
end
|
||||
ln
|
||||
end.join(' ')
|
||||
end
|
||||
output = add_code_tags(
|
||||
Pygments.highlight(code, :lexer => lang,
|
||||
:options => { :encoding => 'utf-8', :hl_lines => hl_lines }),
|
||||
lang
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
239
docs/css/codemirror.css
Normal file
239
docs/css/codemirror.css
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
/* BASICS */
|
||||
|
||||
.CodeMirror {
|
||||
/* Set height, width, borders, and global font properties here */
|
||||
font-family: monospace;
|
||||
}
|
||||
.CodeMirror-scroll {
|
||||
/* Set scrolling behaviour here */
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* PADDING */
|
||||
|
||||
.CodeMirror-lines {
|
||||
padding: 14px 0; /* Vertical padding around content */
|
||||
}
|
||||
.CodeMirror pre {
|
||||
padding: 0 14px; /* Horizontal padding of content */
|
||||
}
|
||||
|
||||
.CodeMirror-scrollbar-filler {
|
||||
background-color: white; /* The little square between H and V scrollbars */
|
||||
}
|
||||
|
||||
/* GUTTER */
|
||||
|
||||
.CodeMirror-gutters {
|
||||
border-right: 1px solid #ddd;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
.CodeMirror-linenumbers {}
|
||||
.CodeMirror-linenumber {
|
||||
padding: 0 3px 0 5px;
|
||||
min-width: 20px;
|
||||
text-align: right;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* CURSOR */
|
||||
|
||||
.CodeMirror div.CodeMirror-cursor {
|
||||
border-left: 1px solid black;
|
||||
}
|
||||
/* Shown when moving in bi-directional text */
|
||||
.CodeMirror div.CodeMirror-secondarycursor {
|
||||
border-left: 1px solid silver;
|
||||
}
|
||||
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
|
||||
width: auto;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
background: rgba(0, 200, 0, .4);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);
|
||||
}
|
||||
/* Kludge to turn off filter in ie9+, which also accepts rgba */
|
||||
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor:not(#nonsense_id) {
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
||||
}
|
||||
/* Can style cursor different in overwrite (non-insert) mode */
|
||||
.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
|
||||
|
||||
/* DEFAULT THEME */
|
||||
|
||||
.cm-s-default .cm-keyword {color: #708;}
|
||||
.cm-s-default .cm-atom {color: #219;}
|
||||
.cm-s-default .cm-number {color: #164;}
|
||||
.cm-s-default .cm-def {color: #00f;}
|
||||
.cm-s-default .cm-variable {color: black;}
|
||||
.cm-s-default .cm-variable-2 {color: #05a;}
|
||||
.cm-s-default .cm-variable-3 {color: #085;}
|
||||
.cm-s-default .cm-property {color: black;}
|
||||
.cm-s-default .cm-operator {color: black;}
|
||||
.cm-s-default .cm-comment {color: #a50;}
|
||||
.cm-s-default .cm-string {color: #a11;}
|
||||
.cm-s-default .cm-string-2 {color: #f50;}
|
||||
.cm-s-default .cm-meta {color: #555;}
|
||||
.cm-s-default .cm-error {color: #f00;}
|
||||
.cm-s-default .cm-qualifier {color: #555;}
|
||||
.cm-s-default .cm-builtin {color: #30a;}
|
||||
.cm-s-default .cm-bracket {color: #997;}
|
||||
.cm-s-default .cm-tag {color: #170;}
|
||||
.cm-s-default .cm-attribute {color: #00c;}
|
||||
.cm-s-default .cm-header {color: blue;}
|
||||
.cm-s-default .cm-quote {color: #090;}
|
||||
.cm-s-default .cm-hr {color: #999;}
|
||||
.cm-s-default .cm-link {color: #00c;}
|
||||
|
||||
.cm-negative {color: #d44;}
|
||||
.cm-positive {color: #292;}
|
||||
.cm-header, .cm-strong {font-weight: bold;}
|
||||
.cm-em {font-style: italic;}
|
||||
.cm-emstrong {font-style: italic; font-weight: bold;}
|
||||
.cm-link {text-decoration: underline;}
|
||||
|
||||
.cm-invalidchar {color: #f00;}
|
||||
|
||||
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
|
||||
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
|
||||
|
||||
/* STOP */
|
||||
|
||||
/* The rest of this file contains styles related to the mechanics of
|
||||
the editor. You probably shouldn't touch them. */
|
||||
|
||||
.CodeMirror {
|
||||
line-height: 1;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.CodeMirror-scroll {
|
||||
/* 30px is the magic margin used to hide the element's real scrollbars */
|
||||
/* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */
|
||||
margin-bottom: -30px; margin-right: -30px;
|
||||
padding-bottom: 30px; padding-right: 30px;
|
||||
height: 100%;
|
||||
outline: none; /* Prevent dragging from highlighting the element */
|
||||
position: relative;
|
||||
}
|
||||
.CodeMirror-sizer {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
||||
before actuall scrolling happens, thus preventing shaking and
|
||||
flickering artifacts. */
|
||||
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler {
|
||||
position: absolute;
|
||||
z-index: 6;
|
||||
display: none;
|
||||
}
|
||||
.CodeMirror-vscrollbar {
|
||||
right: 0; top: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.CodeMirror-hscrollbar {
|
||||
bottom: 0; left: 0;
|
||||
overflow-y: hidden;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
.CodeMirror-scrollbar-filler {
|
||||
right: 0; bottom: 0;
|
||||
z-index: 6;
|
||||
}
|
||||
|
||||
.CodeMirror-gutters {
|
||||
position: absolute; left: 0; top: 0;
|
||||
height: 100%;
|
||||
z-index: 3;
|
||||
}
|
||||
.CodeMirror-gutter {
|
||||
height: 100%;
|
||||
display: inline-block;
|
||||
/* Hack to make IE7 behave */
|
||||
*zoom:1;
|
||||
*display:inline;
|
||||
}
|
||||
.CodeMirror-gutter-elt {
|
||||
position: absolute;
|
||||
cursor: default;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
.CodeMirror-lines {
|
||||
cursor: text;
|
||||
}
|
||||
.CodeMirror pre {
|
||||
/* Reset some styles that the rest of the page might have set */
|
||||
-moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; border-radius: 0;
|
||||
border-width: 0;
|
||||
background: transparent;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
margin: 0;
|
||||
white-space: pre;
|
||||
word-wrap: normal;
|
||||
line-height: inherit;
|
||||
color: inherit;
|
||||
z-index: 2;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
}
|
||||
.CodeMirror-wrap pre {
|
||||
word-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
word-break: normal;
|
||||
}
|
||||
.CodeMirror-linebackground {
|
||||
position: absolute;
|
||||
left: 0; right: 0; top: 0; bottom: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.CodeMirror-linewidget {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.CodeMirror-wrap .CodeMirror-scroll {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.CodeMirror-measure {
|
||||
position: absolute;
|
||||
width: 100%; height: 0px;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
}
|
||||
.CodeMirror-measure pre { position: static; }
|
||||
|
||||
.CodeMirror div.CodeMirror-cursor {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
border-right: none;
|
||||
width: 0;
|
||||
}
|
||||
.CodeMirror-focused div.CodeMirror-cursor {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.CodeMirror-selected { background: #d9d9d9; }
|
||||
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
|
||||
|
||||
.cm-searching {
|
||||
background: #ffa;
|
||||
background: rgba(255, 255, 0, .4);
|
||||
}
|
||||
|
||||
/* IE7 hack to prevent it from returning funny offsetTops on the spans */
|
||||
.CodeMirror span { *vertical-align: text-bottom; }
|
||||
|
||||
@media print {
|
||||
/* Hide the cursor when printing */
|
||||
.CodeMirror div.CodeMirror-cursor {
|
||||
visibility: hidden;
|
||||
}
|
||||
}
|
||||
165
docs/css/main.css
Executable file
165
docs/css/main.css
Executable file
|
|
@ -0,0 +1,165 @@
|
|||
/*****************************************************************************/
|
||||
/*
|
||||
/* Common
|
||||
/*
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Global Reset */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html, body { height: 100%; }
|
||||
|
||||
body {
|
||||
background-color: #FFF;
|
||||
font: 13.34px Helvetica, Arial, sans-serif;
|
||||
font-size: small;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-size: 100%; }
|
||||
|
||||
h1 { margin-bottom: 1em; }
|
||||
p { margin: 1em 0; }
|
||||
|
||||
a { color: #00a; }
|
||||
a:hover { color: #000; }
|
||||
a:visited { color: #a0a; }
|
||||
|
||||
table {
|
||||
font-size: inherit;
|
||||
font: 100%;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
/* Home
|
||||
/*
|
||||
/*****************************************************************************/
|
||||
ul.posts {
|
||||
list-style-type: none;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
ul.posts li {
|
||||
line-height: 1.75em;
|
||||
}
|
||||
|
||||
ul.posts span {
|
||||
color: #aaa;
|
||||
font-family: Monaco, "Courier New", monospace;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
/* Site
|
||||
/*
|
||||
/*****************************************************************************/
|
||||
|
||||
.site {
|
||||
font-size: 115%;
|
||||
text-align: justify;
|
||||
width: 42em;
|
||||
margin: 3em auto 2em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.site .header a {
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.site .header h1.title {
|
||||
display: inline-block;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
.site .header h1.title a {
|
||||
color: #a00;
|
||||
}
|
||||
|
||||
.site .header h1.title a:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.site .header a.extra {
|
||||
color: #aaa;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.site .header a.extra:hover {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.site .meta {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.site .footer {
|
||||
font-size: 80%;
|
||||
color: #666;
|
||||
border-top: 4px solid #eee;
|
||||
margin-top: 2em;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.site .footer .contact {
|
||||
float: left;
|
||||
margin-right: 3em;
|
||||
}
|
||||
|
||||
.site .footer .contact a {
|
||||
color: #8085C1;
|
||||
}
|
||||
|
||||
.site .footer .rss {
|
||||
margin-top: 1.1em;
|
||||
margin-right: -.2em;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.site .footer .rss img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
/* Posts
|
||||
/*
|
||||
/*****************************************************************************/
|
||||
|
||||
/* standard */
|
||||
#post pre {
|
||||
border: 1px solid #ddd;
|
||||
background-color: #eef;
|
||||
padding: 0 .4em;
|
||||
}
|
||||
|
||||
#post ul, #post ol {
|
||||
margin-left: 1.35em;
|
||||
}
|
||||
|
||||
#post code {
|
||||
border: 1px solid #ddd;
|
||||
background-color: #eef;
|
||||
padding: 0 .2em;
|
||||
}
|
||||
|
||||
#post pre code {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* terminal */
|
||||
#post pre.terminal {
|
||||
border: 1px solid #000;
|
||||
background-color: #333;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
#post pre.terminal code {
|
||||
background-color: #333;
|
||||
}
|
||||
409
docs/css/syntax.css
Normal file
409
docs/css/syntax.css
Normal file
|
|
@ -0,0 +1,409 @@
|
|||
.highlight pre code {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
color: #333333;
|
||||
background: #f8f5ec;
|
||||
}
|
||||
|
||||
.highlight .c {
|
||||
color: #93a1a1;
|
||||
}
|
||||
|
||||
|
||||
.highlight .g {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Generic */
|
||||
|
||||
.highlight .k {
|
||||
color: #859900;
|
||||
}
|
||||
|
||||
/* Keyword */
|
||||
|
||||
.highlight .l {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Literal */
|
||||
|
||||
.highlight .n {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Name */
|
||||
|
||||
.highlight .o {
|
||||
color: #859900;
|
||||
}
|
||||
|
||||
/* Operator */
|
||||
|
||||
.highlight .x {
|
||||
color: #cc7a6f;
|
||||
}
|
||||
|
||||
/* Other */
|
||||
|
||||
.highlight .p {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Punctuation */
|
||||
|
||||
.highlight .cm {
|
||||
color: #93a1a1;
|
||||
}
|
||||
|
||||
/* Comment.Multiline */
|
||||
|
||||
.highlight .cp {
|
||||
color: #859900;
|
||||
}
|
||||
|
||||
/* Comment.Preproc */
|
||||
|
||||
.highlight .c1 {
|
||||
color: #93a1a1;
|
||||
}
|
||||
|
||||
/* Comment.Single */
|
||||
|
||||
.highlight .cs {
|
||||
color: #859900;
|
||||
}
|
||||
|
||||
/* Comment.Special */
|
||||
|
||||
.highlight .gd {
|
||||
color: #36958e;
|
||||
}
|
||||
|
||||
/* Generic.Deleted */
|
||||
|
||||
.highlight .ge {
|
||||
font-style: italic;
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Generic.Emph */
|
||||
|
||||
.highlight .gr {
|
||||
color: #dc322f;
|
||||
}
|
||||
|
||||
/* Generic.Error */
|
||||
|
||||
.highlight .gh {
|
||||
color: #cc7a6f;
|
||||
}
|
||||
|
||||
/* Generic.Heading */
|
||||
|
||||
.highlight .gi {
|
||||
color: #859900;
|
||||
}
|
||||
|
||||
/* Generic.Inserted */
|
||||
|
||||
.highlight .go {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Generic.Output */
|
||||
|
||||
.highlight .gp {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Generic.Prompt */
|
||||
|
||||
.highlight .gs {
|
||||
font-weight: bold;
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Generic.Strong */
|
||||
|
||||
.highlight .gu {
|
||||
color: #cc7a6f;
|
||||
}
|
||||
|
||||
/* Generic.Subheading */
|
||||
|
||||
.highlight .gt {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Generic.Traceback */
|
||||
|
||||
.highlight .kc {
|
||||
color: #cc7a6f;
|
||||
}
|
||||
|
||||
/* Keyword.Constant */
|
||||
|
||||
.highlight .kd {
|
||||
color: #268bd2;
|
||||
}
|
||||
|
||||
/* Keyword.Declaration */
|
||||
|
||||
.highlight .kn {
|
||||
color: #859900;
|
||||
}
|
||||
|
||||
/* Keyword.Namespace */
|
||||
|
||||
.highlight .kp {
|
||||
color: #859900;
|
||||
}
|
||||
|
||||
/* Keyword.Pseudo */
|
||||
|
||||
.highlight .kr {
|
||||
color: #268bd2;
|
||||
}
|
||||
|
||||
/* Keyword.Reserved */
|
||||
|
||||
.highlight .kt {
|
||||
color: #dc322f;
|
||||
}
|
||||
|
||||
/* Keyword.Type */
|
||||
|
||||
.highlight .ld {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Literal.Date */
|
||||
|
||||
.highlight .m {
|
||||
color: #36958e;
|
||||
}
|
||||
|
||||
/* Literal.Number */
|
||||
|
||||
.highlight .s {
|
||||
color: #36958e;
|
||||
}
|
||||
|
||||
/* Literal.String */
|
||||
|
||||
.highlight .na {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Name.Attribute */
|
||||
|
||||
.highlight .nb {
|
||||
color: #b58900;
|
||||
}
|
||||
|
||||
/* Name.Builtin */
|
||||
|
||||
.highlight .nc {
|
||||
color: #268bd2;
|
||||
}
|
||||
|
||||
/* Name.Class */
|
||||
|
||||
.highlight .no {
|
||||
color: #cc7a6f;
|
||||
}
|
||||
|
||||
/* Name.Constant */
|
||||
|
||||
.highlight .nd {
|
||||
color: #268bd2;
|
||||
}
|
||||
|
||||
/* Name.Decorator */
|
||||
|
||||
.highlight .ni {
|
||||
color: #cc7a6f;
|
||||
}
|
||||
|
||||
/* Name.Entity */
|
||||
|
||||
.highlight .ne {
|
||||
color: #cc7a6f;
|
||||
}
|
||||
|
||||
/* Name.Exception */
|
||||
|
||||
.highlight .nf {
|
||||
color: #268bd2;
|
||||
}
|
||||
|
||||
/* Name.Function */
|
||||
|
||||
.highlight .nl {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Name.Label */
|
||||
|
||||
.highlight .nn {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Name.Namespace */
|
||||
|
||||
.highlight .nx {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Name.Other */
|
||||
|
||||
.highlight .py {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Name.Property */
|
||||
|
||||
.highlight .nt {
|
||||
color: #268bd2;
|
||||
}
|
||||
|
||||
/* Name.Tag */
|
||||
|
||||
.highlight .nv {
|
||||
color: #268bd2;
|
||||
}
|
||||
|
||||
/* Name.Variable */
|
||||
|
||||
.highlight .ow {
|
||||
color: #859900;
|
||||
}
|
||||
|
||||
/* Operator.Word */
|
||||
|
||||
.highlight .w {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Text.Whitespace */
|
||||
|
||||
.highlight .mf {
|
||||
color: #36958e;
|
||||
}
|
||||
|
||||
/* Literal.Number.Float */
|
||||
|
||||
.highlight .mh {
|
||||
color: #36958e;
|
||||
}
|
||||
|
||||
/* Literal.Number.Hex */
|
||||
|
||||
.highlight .mi {
|
||||
color: #36958e;
|
||||
}
|
||||
|
||||
/* Literal.Number.Integer */
|
||||
|
||||
.highlight .mo {
|
||||
color: #36958e;
|
||||
}
|
||||
|
||||
/* Literal.Number.Oct */
|
||||
|
||||
.highlight .sb {
|
||||
color: #93a1a1;
|
||||
}
|
||||
|
||||
/* Literal.String.Backtick */
|
||||
|
||||
.highlight .sc {
|
||||
color: #36958e;
|
||||
}
|
||||
|
||||
/* Literal.String.Char */
|
||||
|
||||
.highlight .sd {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Literal.String.Doc */
|
||||
|
||||
.highlight .s2 {
|
||||
color: #36958e;
|
||||
}
|
||||
|
||||
/* Literal.String.Double */
|
||||
|
||||
.highlight .se {
|
||||
color: #cc7a6f;
|
||||
}
|
||||
|
||||
/* Literal.String.Escape */
|
||||
|
||||
.highlight .sh {
|
||||
color: #637c84;
|
||||
}
|
||||
|
||||
/* Literal.String.Heredoc */
|
||||
|
||||
.highlight .si {
|
||||
color: #36958e;
|
||||
}
|
||||
|
||||
/* Literal.String.Interpol */
|
||||
|
||||
.highlight .sx {
|
||||
color: #36958e;
|
||||
}
|
||||
|
||||
/* Literal.String.Other */
|
||||
|
||||
.highlight .sr {
|
||||
color: #dc322f;
|
||||
}
|
||||
|
||||
/* Literal.String.Regex */
|
||||
|
||||
.highlight .s1 {
|
||||
color: #36958e;
|
||||
}
|
||||
|
||||
/* Literal.String.Single */
|
||||
|
||||
.highlight .ss {
|
||||
color: #36958e;
|
||||
}
|
||||
|
||||
/* Literal.String.Symbol */
|
||||
|
||||
.highlight .bp {
|
||||
color: #268bd2;
|
||||
}
|
||||
|
||||
/* Name.Builtin.Pseudo */
|
||||
|
||||
.highlight .vc {
|
||||
color: #268bd2;
|
||||
}
|
||||
|
||||
/* Name.Variable.Class */
|
||||
|
||||
.highlight .vg {
|
||||
color: #268bd2;
|
||||
}
|
||||
|
||||
/* Name.Variable.Global */
|
||||
|
||||
.highlight .vi {
|
||||
color: #268bd2;
|
||||
}
|
||||
|
||||
/* Name.Variable.Instance */
|
||||
|
||||
.highlight .il {
|
||||
color: #36958e;
|
||||
}
|
||||
119
docs/docs/advanced-components.md
Normal file
119
docs/docs/advanced-components.md
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
---
|
||||
id: docs-advanced-components
|
||||
title: Advanced Components
|
||||
description: How to build advanced composite components.
|
||||
layout: docs
|
||||
prev: event-handling.html
|
||||
next: api.html
|
||||
---
|
||||
|
||||
Composite components extend a `ReactCompositeComponent` base class that provides
|
||||
a very powerful API that makes React flexible and able to easily work with other
|
||||
libraries and frameworks.
|
||||
|
||||
## Lifecycle Methods
|
||||
|
||||
Composite components can optionally implement lifecycle methods that are invoked
|
||||
at various stages in the [component lifecycle](component-lifecycle.html) that
|
||||
each have unique guarantees.
|
||||
|
||||
### Mounting
|
||||
|
||||
- `getInitialState(): object` is invoked before a component is mounted.
|
||||
Stateful components should implement this and return the initial state data.
|
||||
- `componentWillMount()` is invoked immediately before mounting occurs.
|
||||
- `componentDidMount(DOMElement rootNode)` is invoked immediately after
|
||||
mounting occurs. Initialization that requires DOM nodes should go here.
|
||||
|
||||
### Updating
|
||||
|
||||
- `componentWillReceiveProps(object nextProps)` is invoked when a mounted
|
||||
component receives new props. This method should be used to compare
|
||||
`this.props` and `nextProps` to perform state transitions using
|
||||
`this.setState()`.
|
||||
- `shouldComponentUpdate(object nextProps, object nextState): boolean` is
|
||||
invoked when a component decides whether any changes warrant an update to the
|
||||
DOM. Implement this as an optimization to compare `this.props` with
|
||||
`nextProps` and `this.state` with `nextState` and return false if React
|
||||
should skip updating.
|
||||
- `componentWillUpdate(object nextProps, object nextState)` is invoked
|
||||
immediately before updating occurs. You cannot call `this.setState()` here.
|
||||
- `componentDidUpdate(object prevProps, object prevState, DOMElement rootNode)`
|
||||
is invoked immediately after updating occurs.
|
||||
|
||||
### Unmounting
|
||||
|
||||
- `componentWillUnmount()` is invoked immediately before a component is
|
||||
unmounted and destroyed. Cleanup should go here.
|
||||
|
||||
## Mounted Methods
|
||||
|
||||
_Mounted_ composite components also support the following methods:
|
||||
|
||||
- `getDOMNode(): DOMElement` can be invoked on any mounted component in order
|
||||
to obtain a reference to its rendered DOM node.
|
||||
- `forceUpdate()` can be invoked on any mounted component when you know that
|
||||
some deeper aspect of the component's state has changed without using
|
||||
`this.setState()`.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> The `DOMElement rootNode` argument of `componentDidMount()` and
|
||||
> `componentDidUpdate()` is a convenience. The same node can be obtained by
|
||||
> calling `this.getDOMNode()`.
|
||||
|
||||
## Component Refs
|
||||
|
||||
A common use case of event callbacks or the lifecycle methods is to operate on a
|
||||
component returned by `render()`. For example, consider a search component that
|
||||
should auto-focus the input once mounted:
|
||||
|
||||
```javascript
|
||||
var SearchForm = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<form action={this.props.action}>
|
||||
<input type="search" placeholder="Search..." />
|
||||
</form>
|
||||
);
|
||||
},
|
||||
componentDidMount: function(rootNode) {
|
||||
var searchInput = rootNode.firstChild;
|
||||
searchInput.focus();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Although this implementation works, it is fragile because `componentDidMount()`
|
||||
now relies on `render()` returning a particular DOM structure.
|
||||
|
||||
React provides a better way for composite components to reference components
|
||||
that it constructs in its `render()` method through the use of refs. A component
|
||||
can assign a `ref` to any component it constructs. This will create a reference
|
||||
to those components on `this.refs`. For example:
|
||||
|
||||
```javascript{5,10}
|
||||
var SearchForm = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<form action={this.props.action}>
|
||||
<input type="search" placeholder="Search..." ref="searchInput" />
|
||||
</form>
|
||||
);
|
||||
},
|
||||
componentDidMount: function(rootNode) {
|
||||
var searchInput = this.refs.searchInput.getDOMNode();
|
||||
searchInput.focus();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
In this example, `this.refs.searchInput` will reference the `<input>` component
|
||||
and is available in most lifecycle methods and event callbacks. We obtain a
|
||||
reference to the `<input>`'s DOM node using `getDOMNode()`.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> If you want to preserve compatibility with Google Closure Compiler's
|
||||
> property crushing in `ADVANCED_OPTIMIZATIONS` mode, make sure to use string
|
||||
> literals with `this.refs`.
|
||||
104
docs/docs/api.md
Normal file
104
docs/docs/api.md
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
---
|
||||
id: docs-api
|
||||
title: React API
|
||||
layout: docs
|
||||
prev: advanced-components.html
|
||||
---
|
||||
|
||||
## React
|
||||
|
||||
`React` is the entry point to the React framework. If you're using one of the prebuilt packages it's available as a global; if you're using CommonJS modules you can `require()` it.
|
||||
|
||||
### DOM
|
||||
|
||||
`React.DOM` provides all of the standard HTML tags needed to build a React app. You generally don't use it directly; instead, just include it as part of the `/** @jsx React.DOM */` docblock.
|
||||
|
||||
### initializeTouchEvents(boolean shouldUseTouch)
|
||||
|
||||
Configure React's event system to handle touch events on mobile devices.
|
||||
|
||||
### function autoBind(function method)
|
||||
|
||||
Marks the provided function to be automatically bound to each React component instance created. This allows React components to define automatically bound methods and ensure that when called they will always reference their current instance.
|
||||
|
||||
Example:
|
||||
|
||||
```javascript
|
||||
React.createClass({
|
||||
click: React.autoBind(function(evt) {
|
||||
this.setState({jumping: true});
|
||||
}),
|
||||
render: function() {
|
||||
// Look: no bind!
|
||||
return <a onClick={this.click}>Jump</a>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### function createClass(object specification)
|
||||
|
||||
Creates a component given a specification. A component implements a `render` method which returns a single child. That child may have an arbitrarily deep child structure. One thing that makes components different than a standard prototypal classes is that you don't need to call new on them. They are convenience wrappers that construct backing instances (via new) for you.
|
||||
|
||||
### ReactComponent renderComponent(ReactComponent container, DOMElement mountPoint)
|
||||
|
||||
Renders a React component into the DOM in the supplied `container`.
|
||||
|
||||
If the React component was previously rendered into `container`, this will perform an update on it and only mutate the DOM as necessary to reflect the latest React component.
|
||||
|
||||
## AbstractEvent
|
||||
|
||||
Your event handlers will be passed instances of `AbstractEvent`, a cross-browser wrapper around the browser's native event. It has the same interface as the browser's native event (such as `stopPropagation()` and `preventDefault()`) except they work exactly the same across all browsers.
|
||||
|
||||
If you find that you need the underlying browser event for some reason, simply use the `nativeEvent` attribute to get it.
|
||||
|
||||
## ReactComponent
|
||||
|
||||
Component classses created by `createClass()` return instances of `ReactComponent` when called. Most of the time when you're using React you're either creating or consuming `ReactComponent`s.
|
||||
|
||||
### DOMElement getDOMNode()
|
||||
|
||||
If this component has been mounted into the DOM, this returns the corresponding native browser DOM element. This method is useful for reading values out of the DOM, such as form field values and performing DOM measurements.
|
||||
|
||||
### setProps(object nextProps)
|
||||
|
||||
When you're integrating with an external JavaScript application you may want to signal a change to a React component rendered with `renderComponent()`. Simply call `setProps()` to change its properties and trigger a re-render.
|
||||
|
||||
**Note:** This method can only be called on a root-level component. That is, it's only available on the component passed directly to `renderComponent()` and none of its children. If you're inclined to use `setProps()` on a child component, instead take advantage of reactive updates and pass the new prop to the child component when it's created in `render()`.
|
||||
|
||||
### replaceProps(object nextProps)
|
||||
|
||||
Like `setProps()` but deletes any pre-existing props that are not in nextProps.
|
||||
|
||||
### ReactComponent transferPropsTo(ReactComponent targetComponent)
|
||||
|
||||
Transfer properties from this component to a target component that have not already been set on the target component. This is usually used to pass down properties to the returned root component. `targetComponent`, now updated with some new props is returned as a convenience.
|
||||
|
||||
### setState(object nextState)
|
||||
|
||||
Merges nextState with the current state. This is the primary method you use to trigger UI updates from event handlers and server request callbacks.
|
||||
|
||||
**Note:** *NEVER* mutate `this.state` directly. As calling `setState()` afterwards may replace the mutation you made. Treat `this.state` as if it were immutable.
|
||||
|
||||
**Note:** `setState()` does not immediately mutate `this.state` but creates a pending state transition. Accessing `this.state` after calling this method can potentially return the existing value.
|
||||
|
||||
### replaceState(object nextState)
|
||||
|
||||
Like `setState()` but deletes any pre-existing state keys that are not in nextState.
|
||||
|
||||
### forceUpdate()
|
||||
|
||||
If your `render()` method reads from something other than `this.props` or `this.state` you'll need to tell React when it needs to re-run `render()`. Use `forceUpdate()` to cause React to automatically re-render. This will cause `render()` to be called on the component and all of its children but React will only update the DOM if the markup changes.
|
||||
|
||||
Normally you should try to avoid all uses of `forceUpdate()` and only read from `this.props` and `this.state` in `render()`. This makes your application much simpler and more efficient.
|
||||
|
||||
### object getInitialState()
|
||||
### componentWillMount()
|
||||
### componentDidMount(DOMElement domNode)
|
||||
### componentWillReceiveProps(object nextProps)
|
||||
### boolean shouldComponentUpdate(object nextProps, object nextState)
|
||||
### componentWillUpdate(object nextProps, object nextState)
|
||||
### ReactComponent render()
|
||||
### componentDidUpdate(object prevProps, object prevState, DOMElement domNode)
|
||||
### componentWillUnmount()
|
||||
|
||||
These are overridable lifecycle methods; see the [lifecycle methods](lifecycle.html) documentation for more information.
|
||||
22
docs/docs/common-questions.md
Normal file
22
docs/docs/common-questions.md
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
id: docs-common-questions
|
||||
title: Common Questions
|
||||
layout: docs
|
||||
prev: tutorial.html
|
||||
next: syntax.html
|
||||
---
|
||||
### What browsers does React support?
|
||||
|
||||
React supports the latest two Chrome, Firefox, Safari, and Internet Explorer versions. React can work with Internet Explorer 8 with polyfills.
|
||||
|
||||
### How do I get React to support Internet Explorer 8?
|
||||
|
||||
React requires ES5 JavaScript shims to run in Internet Explorer 8. Include the [ES5 Shims](https://github.com/kriskowal/es5-shim) to implement these shims.
|
||||
|
||||
### Who uses React?
|
||||
|
||||
The [Instagram](http://instagram.com/) website is built entirely in React. The [Facebook](https://www.facebook.com/) website is also increasingly using React, including the common commenting plugin across the site.
|
||||
|
||||
### Can I integrate with other JavaScript libraries?
|
||||
|
||||
Absolutely! In fact, we encourage it! See [our GitHub repo](http://github.com/facebook/react/) for a [TodoMVC example using Backbone](https://github.com/facebook/react/tree/master/examples/todomvc-backbone) and a [jQuery + Bootstrap modal demo](https://github.com/facebook/react/tree/master/examples/jquery-bootstrap).
|
||||
73
docs/docs/component-basics.md
Normal file
73
docs/docs/component-basics.md
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
---
|
||||
id: docs-component-basics
|
||||
title: Component Basics
|
||||
description: What are components?
|
||||
layout: docs
|
||||
next: component-data.html
|
||||
prev: syntax.html
|
||||
---
|
||||
|
||||
_Components_ are the basic units of composition in React. Components encapsulate
|
||||
the logic necessary to take input parameters and render markup. Components can
|
||||
be rendered into an existing DOM element on the page by using
|
||||
`React.renderComponent`:
|
||||
|
||||
```javascript
|
||||
// Replaces everything in `document.body` with <div>Hello, world!</div>;
|
||||
React.renderComponent(<div>Hello, world!</div>, document.body);
|
||||
```
|
||||
|
||||
Keep in mind that `<div>` is **not** a DOM element! Keep reading...
|
||||
|
||||
## Types of Components
|
||||
|
||||
There are two types of components:
|
||||
|
||||
- **Composite Components**
|
||||
- **DOM Components**
|
||||
|
||||
### Composite Components <small>such as `TodoApp` and `Typeahead`.</small>
|
||||
|
||||
The majority of your React code will be implementing composite components.
|
||||
|
||||
Composite components are higher-level components with custom rendering logic
|
||||
that may compose other composite components or DOM components.
|
||||
|
||||
```javascript
|
||||
/** @jsx React.DOM */
|
||||
var LinkButton = React.createClass({
|
||||
render: function() {
|
||||
return <a className="btn" />;
|
||||
}
|
||||
});
|
||||
|
||||
var myButton = <LinkButton />;
|
||||
```
|
||||
|
||||
This example defines a `LinkButton` component class using `React.createClass()`,
|
||||
and its `render()` method composes the `<a>` DOM component.
|
||||
|
||||
### DOM Components <small>such as `div` and `span`.</small>
|
||||
|
||||
DOM components are the set of classes that correspond to browser DOM elements.
|
||||
They are defined in `React.DOM` and can be brought "into scope" by setting
|
||||
`@jsx React.DOM` in the docblock. See [JSX Syntax](syntax.html) for more
|
||||
details.
|
||||
|
||||
Although `React.DOM` components look like browser DOM elements, they differ in a
|
||||
few ways:
|
||||
|
||||
- All property names, including event handlers, are camelCased.
|
||||
- JavaScript identifiers should be used, namely `className` and `htmlFor`.
|
||||
- The `style` prop expects an object instead of a string. The object should map
|
||||
camelCased style properties to values, e.g. `{backgroundColor: '#fff'}`.
|
||||
|
||||
Here is an example of a React link styled as a button with a click handler:
|
||||
|
||||
```javascript
|
||||
/** @jsx React.DOM */
|
||||
var handleClick = function() {alert('Clicked!');};
|
||||
var inlineStyle = {textDecoration: 'none'};
|
||||
|
||||
var myLink = <a className="btn" onClick={handleClick} style={inlineStyle} />;
|
||||
```
|
||||
145
docs/docs/component-data.md
Normal file
145
docs/docs/component-data.md
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
---
|
||||
id: docs-component-data
|
||||
title: Component Data
|
||||
description: How is data passed into a component?
|
||||
layout: docs
|
||||
prev: component-basics.html
|
||||
next: component-lifecycle.html
|
||||
---
|
||||
|
||||
## Props
|
||||
|
||||
Components use data to determine what should be rendered. For example:
|
||||
|
||||
```javascript
|
||||
var LikeLink = React.createClass({
|
||||
render: function() {
|
||||
var text = this.props.liked ? 'Liked' : 'Like';
|
||||
return <a>{text}</a>;
|
||||
}
|
||||
});
|
||||
var myLikeLink = <LikeLink liked={false} />;
|
||||
```
|
||||
|
||||
In this example, `LikeLink` takes `liked` as boolean data. This type of data
|
||||
that is passed in is called a "prop". Examples of props on DOM components
|
||||
include `className` and `onClick`.
|
||||
|
||||
Whenever a component's props change, its `render()` function will be
|
||||
re-evaluated and the DOM will be updated. React will ensure that the DOM is
|
||||
always kept up-to-date.
|
||||
|
||||
## State
|
||||
|
||||
Let's build a small `LikeApp` application that makes use of the `<LikeLink>`
|
||||
component from above. It should start off unliked and we should be able to like
|
||||
it by clicking the link:
|
||||
|
||||
```javascript
|
||||
var LikeApp = React.createClass({
|
||||
render: function() {
|
||||
var isClicked = false;
|
||||
return <LikeLink liked={isClicked} onClick={this.handleClick.bind(this)} />;
|
||||
},
|
||||
handleClick: function() {
|
||||
// Somehow update `isClicked`.
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
This renders a `<LikeLink>` with a click listener. However, it is not clear how
|
||||
`handleClick` should update `isClicked` to true. `LikeApp` needs a way to store
|
||||
**state** about whether or not it has been clicked.
|
||||
|
||||
### State vs. Props
|
||||
|
||||
State is data that is managed _internally_ by a composite component. Like props,
|
||||
the `render()` function will be re-evaluated whenever state changes. Props and
|
||||
state differ in that:
|
||||
|
||||
- Props are passed in from the creator.
|
||||
- State is private to and managed by the component.
|
||||
|
||||
### Managing State
|
||||
|
||||
Let's update our `LikeApp` component using state:
|
||||
|
||||
```javascript{2-4,6,10}
|
||||
var LikeApp = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {isClicked: false};
|
||||
},
|
||||
render: function() {
|
||||
var isClicked = this.state.isClicked;
|
||||
return <LikeLink liked={isClicked} onClick={this.handleClick.bind(this)} />;
|
||||
},
|
||||
handleClick: function() {
|
||||
this.setState({isClicked: true});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
There's a lot going on here, so let's work our way from top to bottom:
|
||||
|
||||
- `getInitialState()` describes what state data looks like when the component
|
||||
is created.
|
||||
- In `render()`, state data can be accessed via `this.state`.
|
||||
- When the link is clicked, we update state using `setState()`.
|
||||
|
||||
Now when we click the link, the `<LikeLink>` will get updated, right? Wrong.
|
||||
|
||||
## Transferring Props
|
||||
|
||||
If you have been following carefully, you may have noticed that although we pass
|
||||
a click handler into `<LikeLink>` as a prop, `LikeLink` does not do anything
|
||||
with `this.props.onClick`! Let's fix that.
|
||||
|
||||
```javascript{4}
|
||||
var LikeLink = React.createClass({
|
||||
render: function() {
|
||||
var text = this.props.liked ? 'Liked' : 'Like';
|
||||
return <a onClick={this.props.onClick}>{text}</a>;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Although this works, realize that this would quickly become tedious if we wanted
|
||||
to also transfer `href`, `title`, `target`, and other events from `this` to the
|
||||
rendered `<a>`. React provides a convenience method, `transferPropsTo()`, for
|
||||
transferring props:
|
||||
|
||||
```javascript{4}
|
||||
var LikeLink = React.createClass({
|
||||
render: function() {
|
||||
var text = this.props.liked ? 'Liked' : 'Like';
|
||||
return this.transferPropsTo(<a>{text}</a>);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
This will transfer all props from `this` to the specified component (including
|
||||
`onClick`).
|
||||
|
||||
## Summary
|
||||
|
||||
Now we are done. `LikeApp` renders an unliked link which, when clicked, will:
|
||||
|
||||
1. Update the internal state of `LikeApp`.
|
||||
2. Change the props passed into `LikeLink`.
|
||||
3. Change the return value of `render()`.
|
||||
4. Trigger an update to the DOM.
|
||||
|
||||
It's worth noting that React will handle new return values of `render()` by
|
||||
making the mininal set of mutations necessary to bring the DOM up-to-date. In
|
||||
this case, only the `textContent` of the rendered link will be mutated.
|
||||
|
||||
In summary:
|
||||
|
||||
- Props are passed in whereas state is managed internally by a component.
|
||||
- Never mutate `this.props` or `this.state`. You should pass props into other
|
||||
components and mutate state using `setState()`.
|
||||
- State is private. Never read `state` or call `setState()` on
|
||||
anything but `this`.
|
||||
- Whenever props or state changes, `render()` will be re-evaluated and the DOM
|
||||
updated. Also, `render()` should not depend on anything besides `this.props`
|
||||
and `this.state`.
|
||||
85
docs/docs/component-lifecycle.md
Normal file
85
docs/docs/component-lifecycle.md
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
---
|
||||
id: docs-component-lifecycle
|
||||
title: Component Lifecycle
|
||||
description: What happens when I render a React component?
|
||||
layout: docs
|
||||
prev: component-data.html
|
||||
next: event-handling.html
|
||||
---
|
||||
|
||||
## Mounting
|
||||
|
||||
[We have previously seen](component-basics.html) how to render components into
|
||||
existing DOM elements on the page:
|
||||
|
||||
```javascript
|
||||
React.renderComponent(<div>Hello, world!</div>, document.body);
|
||||
```
|
||||
|
||||
In this one simple line, we have accomplished the following:
|
||||
|
||||
- A `<div>` (defined by `React.DOM.div`) component is instantiated.
|
||||
- The component is **mounted** into `document.body`.
|
||||
|
||||
**Mounting** is the process of initializing a React component by creating its
|
||||
DOM nodes and inserting the them into a supplied container node.
|
||||
|
||||
At this point, the entire page consists of a single `<div>` with "Hello,
|
||||
world!".
|
||||
|
||||
## Updating
|
||||
|
||||
Let's add a second call to `React.renderComponent()` after three
|
||||
seconds:
|
||||
|
||||
```javascript{2-4}
|
||||
React.renderComponent(<div>Hello, world!</div>, document.body);
|
||||
setTimeout(function() {
|
||||
React.renderComponent(<div>Goodbye, world.</div>, document.body);
|
||||
}, 3000);
|
||||
```
|
||||
|
||||
The second call to `React.renderComponent()` will trigger the following:
|
||||
|
||||
- The `<div>` component will check the new props to see if anything changed.
|
||||
- The set of changes are used to **update** the DOM node as necessary.
|
||||
|
||||
**Updating** is the process of mutating the rendered DOM nodes and occurs
|
||||
whenever either props or state has changed. This ensures that the rendered DOM
|
||||
is consistent with the data.
|
||||
|
||||
## Unmounting
|
||||
|
||||
Let's add one final call to `React.renderComponent()` after another three
|
||||
seconds:
|
||||
|
||||
```javascript{5-7}
|
||||
React.renderComponent(<div>Hello, world!</div>, document.body);
|
||||
setTimeout(function() {
|
||||
React.renderComponent(<div>Goodbye, world.</div>, document.body);
|
||||
}, 3000);
|
||||
setTimeout(function() {
|
||||
React.renderComponent(<img src="/images/fin.png" />, document.body);
|
||||
}, 6000);
|
||||
```
|
||||
|
||||
The third call to `React.renderComponent()` will trigger the following:
|
||||
|
||||
- An `<img>` (defined by `React.DOM.img`) component is instantiated.
|
||||
- React will compare the `<div>` component with the `<img>` component.
|
||||
- Since the component class is different, the `<div>` component will be
|
||||
**unmounted**.
|
||||
- The `<img>` component will then be mounted into `document.body`.
|
||||
|
||||
**Unmounting** is the process of releasing resources that have been allocated by
|
||||
a component. This allows user interfaces built with React to live long without
|
||||
memory leaks.
|
||||
|
||||
Components can also be unmounted using
|
||||
`React.unmountAndReleaseReactRootNode()`:
|
||||
|
||||
```javascript
|
||||
React.unmountAndReleaseReactRootNode(document.body);
|
||||
```
|
||||
|
||||
This will unmount any components mounted immediately within `document.body`.
|
||||
124
docs/docs/event-handling.md
Normal file
124
docs/docs/event-handling.md
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
---
|
||||
id: docs-event-handling
|
||||
title: Event Handling
|
||||
description: How do events work with React components?
|
||||
layout: docs
|
||||
prev: component-lifecycle.html
|
||||
next: advanced-components.html
|
||||
---
|
||||
|
||||
Events in React work the way they do with HTML, except the event names are
|
||||
camelCased.
|
||||
|
||||
```javascript
|
||||
var Clicker = React.createClass({
|
||||
render: function() {
|
||||
return <span onClick={this.handleClick}>Click me!</span>;
|
||||
},
|
||||
handleClick: function(event) {
|
||||
alert('You clicked me!');
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
When `<Clicker>` is clicked, the `handleClick()` function will get fired. Under
|
||||
the hood, React uses top-level event delegation to achieve high performance.
|
||||
|
||||
## Automatically Binding Callbacks
|
||||
|
||||
Just like any callback in JavaScript, if you want to refer to the component as
|
||||
`this` from the callback, you need to bind the callback to the component:
|
||||
|
||||
```javascript{3}
|
||||
var Clicker = React.createClass({
|
||||
render: function() {
|
||||
var handleClick = this.handleClick.bind(this);
|
||||
return <span onClick={handleClick}>Click me!</span>;
|
||||
},
|
||||
handleClick: function(event) {
|
||||
alert(this.ALERT_MESSAGE);
|
||||
},
|
||||
ALERT_MESSAGE: 'You clicked me!'
|
||||
});
|
||||
```
|
||||
|
||||
React provides a convenient and _efficient_ way to bind methods using
|
||||
`React.autoBind()`:
|
||||
|
||||
```javascript{3,5-7}
|
||||
var Clicker = React.createClass({
|
||||
render: function() {
|
||||
return <span onClick={this.handleClick}>Click me!</span>;
|
||||
},
|
||||
handleClick: React.autoBind(function(event) {
|
||||
alert(this.ALERT_MESSAGE);
|
||||
}),
|
||||
ALERT_MESSAGE: 'You clicked me!'
|
||||
});
|
||||
```
|
||||
|
||||
> Note:
|
||||
>
|
||||
> Binding a function allocates memory to create a new bound function. Since
|
||||
> `render()` may be invoked many times, it is a bad place to bind functions.
|
||||
> `React.autoBind()` sidesteps this issue by only binding once at instantiation
|
||||
> time.
|
||||
|
||||
## DOM Events
|
||||
|
||||
React uses [top-level event delegation](http://davidwalsh.name/event-delegate)
|
||||
to achieve high performance when implementing DOM events. For each type of DOM
|
||||
event, React adds a single top-level listener and determines which event
|
||||
handlers to execute by simulating event capturing and bubbling.
|
||||
|
||||
DOM event handlers are called with a normalized `AbstractEvent` object that has
|
||||
cross-browser compatible implementations of `stopPropagation` and
|
||||
`preventDefault()`. If you need access to the raw browser event, you can use the
|
||||
`nativeEvent` property.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> The `AbstractEvent` object is JSON serializable so that React applications can
|
||||
> be executed inside web workers.
|
||||
|
||||
### Touch Events
|
||||
|
||||
If you want to use touch events, you must configure React's event system to
|
||||
initialize them:
|
||||
|
||||
```javascript
|
||||
// Invoke before calling `React.renderComponent()`.
|
||||
React.initializeTouchEvents(true);
|
||||
```
|
||||
|
||||
## Custom Events
|
||||
|
||||
Notice that event listeners are attached by simply passing them into components
|
||||
as props. For DOM components, events are handled using top-level event
|
||||
delegation. For composite components, event handling is up to the component's
|
||||
implementation.
|
||||
|
||||
Here is an example of a toggle link that fires a custom `onToggle` event:
|
||||
|
||||
```javascript
|
||||
var ToggleLink = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {isEnabled: false};
|
||||
},
|
||||
render: function() {
|
||||
return <a onClick={this.handleClick}>Toggle</a>;
|
||||
},
|
||||
handleClick: React.autoBind(function() {
|
||||
var willEnable = !this.state.isEnabled;
|
||||
if (this.props.onToggle) {
|
||||
this.props.onToggle(willEnable)
|
||||
}
|
||||
this.setState({isEnabled: willEnable});
|
||||
})
|
||||
});
|
||||
|
||||
var handleToggle = function(enabled) {
|
||||
alert(enabled ? 'Enabled.' : 'Disabled.');
|
||||
};
|
||||
var myToggleLink = <ToggleLink onToggle={handleToggle} />;
|
||||
```
|
||||
106
docs/docs/getting-started.md
Normal file
106
docs/docs/getting-started.md
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
---
|
||||
id: docs-getting-started
|
||||
title: Getting Started
|
||||
layout: docs
|
||||
next: tutorial.html
|
||||
---
|
||||
Download the starter kit to get started.
|
||||
|
||||
<div class="buttons-unit downloads">
|
||||
<a href="/react/downloads/react-{{site.react_version}}.zip" class="button">
|
||||
Download Starter Kit {{site.react_version}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## Hello, world!
|
||||
|
||||
In the root directory of the starter kit, create a `helloworld.html` with the following contents.
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src="build/react.min.js"></script>
|
||||
<script src="build/JSXTransformer.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
<script type="text/jsx">
|
||||
/** @jsx React.DOM */
|
||||
React.renderComponent(
|
||||
<h1>Hello, world!</h1>,
|
||||
document.getElementById('example')
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
The XML syntax inside of JavaScript is called JSX; check out the [JSX syntax](syntax.html) to learn more about it. In order to translate it to vanilla JavaScript we use `<script type="text/jsx">` and include `JSXTransformer.js` to actually perform the transformation in the browser.
|
||||
|
||||
### Separate File
|
||||
|
||||
Your React JSX file can live in a separate file. Create the following `src/helloworld.js`.
|
||||
|
||||
```javascript
|
||||
/** @jsx React.DOM */
|
||||
React.renderComponent(
|
||||
<h1>Hello, world!</h1>,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
Then reference it from `helloworld.html`:
|
||||
|
||||
```html{10}
|
||||
<script type="text/jsx" src="src/helloworld.js"></script>
|
||||
```
|
||||
|
||||
### Offline Transform
|
||||
|
||||
First install the command-line tools (requires [npm](http://npmjs.org/)):
|
||||
|
||||
```
|
||||
npm install -g react-tools
|
||||
```
|
||||
|
||||
Then, translate your `src/helloworld.js` file to plain JavaScript:
|
||||
|
||||
```
|
||||
jsx --watch src/ build/
|
||||
|
||||
```
|
||||
|
||||
The file `build/helloworld.js` is autogenerated whenever you make a change.
|
||||
|
||||
```javascript{3}
|
||||
/** @jsx React.DOM */
|
||||
React.renderComponent(
|
||||
React.DOM.h1(null, 'Hello, world!'),
|
||||
document.getElementyById('example')
|
||||
);
|
||||
```
|
||||
|
||||
Update your HTML file as below:
|
||||
|
||||
```html{6,10}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Hello React!</title>
|
||||
<script src="build/react.min.js"></script>
|
||||
<!-- No need for JSXTransformer! -->
|
||||
</head>
|
||||
<body>
|
||||
<div id="example"></div>
|
||||
<script src="build/helloworld.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Want CommonJS?
|
||||
|
||||
If you want to use React within a module system, [fork our repo](http://github.com/facebook/react), `npm install` and run `grunt`. A nice set of CommonJS modules will be generated. Our `jsx` build tool can be integrated into most packaging systems (not just CommonJS) quite easily.
|
||||
|
||||
## Next Steps
|
||||
|
||||
Check out [the tutorial](tutorial.html) and the other examples in the `/examples` directory to learn more. Good luck, and welcome!
|
||||
151
docs/docs/syntax.md
Normal file
151
docs/docs/syntax.md
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
---
|
||||
id: docs-syntax
|
||||
title: JSX Syntax
|
||||
description: Writing JavaScript with XML syntax.
|
||||
layout: docs
|
||||
prev: common-questions.html
|
||||
next: component-basics.html
|
||||
---
|
||||
|
||||
JSX is a JavaScript XML syntax extension recommended (but not required) for use
|
||||
with React.
|
||||
|
||||
JSX makes code that deeply nested React components more readable, and writing it
|
||||
feels like writing HTML. React documentation examples make use of JSX.
|
||||
|
||||
## The Transform
|
||||
|
||||
JSX transforms XML-like syntax into native JavaScript. It turns XML elements and
|
||||
attributes into function calls and objects, respectively.
|
||||
|
||||
```javascript
|
||||
var Nav;
|
||||
// Input (JSX):
|
||||
var app = <Nav color="blue" />;
|
||||
// Output (JS):
|
||||
var app = Nav({color:'blue'});
|
||||
```
|
||||
|
||||
Notice that in order to use `<Nav />`, the `Nav` variable must be in scope.
|
||||
|
||||
JSX also allows specifying children using XML syntax:
|
||||
|
||||
```javascript
|
||||
var Nav, Profile;
|
||||
// Input (JSX):
|
||||
var app = <Nav color="blue"><Profile>click</Profile></Nav>;
|
||||
// Output (JS):
|
||||
var app = Nav({color:'blue'}, Profile({}, 'click'));
|
||||
```
|
||||
|
||||
The [Getting Started](getting-started.html) guide shows how to setup JSX
|
||||
compilation.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> Details about the code transform are given here to increase understanding, but
|
||||
> your code should not rely on these implementation details.
|
||||
|
||||
## React and JSX
|
||||
|
||||
React and JSX are independent technologies, but JSX was primarily built with
|
||||
React in mind. The two valid uses of JSX are:
|
||||
|
||||
- To construct instances of React DOM components (`React.DOM.*`).
|
||||
- To construct instances of composite components created with
|
||||
`React.createClass()`.
|
||||
|
||||
**React DOM Components**
|
||||
|
||||
To construct a `<div>` is to create a variable that refers to `React.DOM.div`.
|
||||
|
||||
```javascript
|
||||
var div = React.DOM.div;
|
||||
var app = <div className="appClass">Hello, React!</div>;
|
||||
```
|
||||
|
||||
**React Component Components**
|
||||
|
||||
To construct an instance of a composite component, create a variable that
|
||||
references the class.
|
||||
|
||||
```javascript
|
||||
var MyComponent = React.createClass({/*...*/});
|
||||
var app = <MyComponent someProperty={true} />;
|
||||
```
|
||||
|
||||
See [Component Basics](component-basics.html) to learn more about components.
|
||||
|
||||
> Note:
|
||||
>
|
||||
> Since JSX is JavaScript, identifiers such as `class` and `for` are discouraged
|
||||
> as XML attribute names. Instead, React DOM components expect attributes like
|
||||
> `className` and `htmlFor`, respectively.
|
||||
|
||||
## DOM Convenience
|
||||
|
||||
Having to define variables for every type of DOM element can get tedious
|
||||
(e.g. `var div, span, h1, h2, ...`). JSX provides a convenience to address this
|
||||
problem by allowing you to specify a variable in an `@jsx` docblock field. JSX
|
||||
will use that field to find DOM components.
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* @jsx React.DOM
|
||||
*/
|
||||
var Nav;
|
||||
// Input (JSX):
|
||||
var tree = <Nav><span /></Nav>;
|
||||
// Output (JS):
|
||||
var tree = Nav({}, React.DOM.span({}));
|
||||
```
|
||||
|
||||
> Remember:
|
||||
>
|
||||
> JSX simply transforms elements into function calls and has no notion of the
|
||||
> DOM. The docblock parameter is only a convenience to resolve the most commonly
|
||||
> used elements. In general, JSX has no notion of the DOM.
|
||||
|
||||
## JavaScript Expressions
|
||||
|
||||
#### Attribute Expressions
|
||||
|
||||
To use a JavaScript expression as an attribute value, wrap the expression in a
|
||||
pair of curly braces (`{}`) instead of quotes (`""`).
|
||||
|
||||
```javascript
|
||||
// Input (JSX):
|
||||
var person = <Person name={window.isLoggedIn ? window.name : ''} />;
|
||||
// Output (JS):
|
||||
var person = Person({name: window.isLoggedIn ? window.name : ''});
|
||||
```
|
||||
|
||||
#### Child Expressions
|
||||
|
||||
Likewise, JavaScript expressions may be used to express children:
|
||||
|
||||
```javascript
|
||||
// Input (JSX):
|
||||
var content = <Container>{window.isLoggedIn ? <Nav /> : <Login />}</Container>;
|
||||
// Output (JS):
|
||||
var content = Container({}, window.isLoggedIn ? <Nav /> : <Login />);
|
||||
```
|
||||
|
||||
## Tooling
|
||||
|
||||
Beyond the compilation step, JSX does not require any special tools.
|
||||
|
||||
- Many editors already include reasonable support for JSX (Vim, Emacs js2-mode).
|
||||
- Linting provides accurate line numbers after compiling without sourcemaps.
|
||||
- Elements use standard scoping so linters can find usage of out-of-scope
|
||||
components.
|
||||
|
||||
## Prior Work
|
||||
|
||||
JSX is similar to several other JavaScript embedded XML language
|
||||
proposals/projects. Some of the features of JSX that distinguish it from similar
|
||||
efforts include:
|
||||
|
||||
- JSX is a simple syntactic transform.
|
||||
- JSX neither provides nor requires a runtime library.
|
||||
- JSX does not alter or add to the semantics of JavaScript.
|
||||
674
docs/docs/tutorial.md
Normal file
674
docs/docs/tutorial.md
Normal file
|
|
@ -0,0 +1,674 @@
|
|||
---
|
||||
id: docs-tutorial
|
||||
title: Tutorial
|
||||
layout: docs
|
||||
prev: getting-started.html
|
||||
next: common-questions.html
|
||||
---
|
||||
|
||||
We'll be building a simple, but realistic comments box that you can drop into a blog, similar to Disqus, LiveFyre or Facebook comments.
|
||||
|
||||
We'll provide:
|
||||
|
||||
* A view of all of the comments
|
||||
* A form to submit a comment
|
||||
* Hooks for you to provide a custom backend
|
||||
|
||||
It'll also have a few neat features:
|
||||
|
||||
* **Optimistic commenting:** comments appear in the list before they're saved on the server so it feels fast.
|
||||
* **Live updates:** as other users comment we'll pop them into the comment view in real time
|
||||
* **Markdown formatting:** users can use Markdown to format their text
|
||||
|
||||
## Getting started
|
||||
|
||||
For this tutorial we'll use prebuilt JavaScript files on a CDN. Open up your favorite editor and create a new HTML document:
|
||||
|
||||
```html
|
||||
<!-- template.html -->
|
||||
<html>
|
||||
<head>
|
||||
<title>Hello React</title>
|
||||
<script src="http://fb.me/react-{{site.react_version}}.js"></script>
|
||||
<script src="http://fb.me/JSXTransformer-{{site.react_version}}.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content"></div>
|
||||
<script type="text/jsx">
|
||||
/**
|
||||
* @jsx React.DOM
|
||||
*/
|
||||
// Your code here
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
For the remainder of this tutorial, we'll be writing our JavaScript code in this script tag.
|
||||
|
||||
## Your first component
|
||||
|
||||
React is all about modular, composable components. For our comment box example, we'll have the following component structure:
|
||||
|
||||
```
|
||||
- CommentBox
|
||||
- CommentList
|
||||
- Comment
|
||||
- CommentForm
|
||||
```
|
||||
|
||||
Let's build the `CommentBox` component, which is just a simple `<div>`:
|
||||
|
||||
```javascript
|
||||
// tutorial1.js
|
||||
var CommentBox = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div class="commentBox">
|
||||
Hello, world! I am a CommentBox.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
React.renderComponent(
|
||||
<CommentBox />,
|
||||
document.getElementById('content')
|
||||
);
|
||||
```
|
||||
|
||||
### JSX Syntax
|
||||
|
||||
The first thing you'll notice is the XML-ish syntax in your JavaScript. We have a simple precompiler that translates the syntactic sugar to this plain JavaScript:
|
||||
|
||||
```javascript
|
||||
// tutorial1-raw.js
|
||||
var CommentBox = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
ReactDOM.div({
|
||||
className: 'commentBox',
|
||||
children: 'Hello, world! I am a CommentBox.'
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
React.renderComponent(
|
||||
CommentBox({}),
|
||||
document.getElementById('content')
|
||||
);
|
||||
```
|
||||
|
||||
Its use is optional but we've found JSX syntax easier to use than plain JavaScript. Read more on the [JSX Syntax article](syntax.html).
|
||||
|
||||
### What's going on
|
||||
|
||||
We pass some methods in a JavaScript object to `React.createClass()` to create a new React component. The most important of these methods is called `render` which returns a tree of React components that will eventually render to HTML.
|
||||
|
||||
The `<div>` tags are not actual DOM nodes; they are instantiations of React `div` components. You can think of these as markers or pieces of data that React knows how to handle. React is **safe**. We are not generating HTML strings so XSS protection is the default.
|
||||
|
||||
You do not have to return basic HTML. You can return a tree of components that you (or someone else built). This is what makes React **composable**: a key tenet of maintainable frontends.
|
||||
|
||||
`React.renderComponent()` instantiates the root component, starts the framework, and injects the markup into a raw DOM element, provided as the second argument.
|
||||
|
||||
# Composing components
|
||||
|
||||
Let's build skeletons for `CommentList` and `CommentForm` which will, again, be simple `<div>`s:
|
||||
|
||||
```javascript
|
||||
// tutorial2.js
|
||||
var CommentList = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div class="commentList">
|
||||
Hello, world! I am a CommentList.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var CommentForm = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div class="commentForm">
|
||||
Hello, world! I am a CommentForm.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Next, update the `CommentBox` component to use its new friends:
|
||||
|
||||
```javascript{6-8}
|
||||
// tutorial3.js
|
||||
var CommentBox = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div class="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList />
|
||||
<CommentForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Notice how we're mixing HTML tags and components we've built. HTML components are regular React components, just like the ones you define, with one difference. The JSX compiler will automatically rewrite HTML tags to "ReactDOM.tagName" expressions and leave everything else alone. This is to prevent the pollution of the global namespace.
|
||||
|
||||
## Component Properties
|
||||
|
||||
Let's create our third component, `Comment`. We will want to pass it the author name and comment text so we can reuse the same code for each unique comment. First let's add some comments to the `CommentList`:
|
||||
|
||||
```javascript{6-7}
|
||||
// tutorial4.js
|
||||
var CommentList = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div class="commentList">
|
||||
<Comment author="Pete Hunt">This is one comment</Comment>
|
||||
<Comment author="Jordan Walke">This is *another* comment</Comment>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Note that we have passed some data from the parent `CommentList` component to the child `Comment` component as both XML-like children and attributes. Data passed from parent to child is called **props**, short for properties.
|
||||
|
||||
## Using props
|
||||
|
||||
Let's create the Comment component. It will read the data passed to it from the CommentList and render some markup:
|
||||
|
||||
```javascript
|
||||
// tutorial5.js
|
||||
var Comment = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div class="comment">
|
||||
<h2 class="commentAuthor">
|
||||
{this.props.author}
|
||||
</h2>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
By surrounding a JavaScript expression in braces inside JSX (as either an attribute or child), you can drop text or React components into the tree. We access named attributes passed to the component as keys on `this.props` and any nested elements as `this.props.children`.
|
||||
|
||||
## Adding Markdown
|
||||
|
||||
Markdown is a simple way to format your text inline. For example, surrounding text with asterisks will make it emphasized.
|
||||
|
||||
First, add the third-party **Showdown** library to your application. This is a JavaScript library which takes Markdown text and converts it to raw HTML. This requires a script tag in your head (which we have already included in the React playground).
|
||||
|
||||
Next, let's convert the comment text to Markdown and output it:
|
||||
|
||||
```javascript{2,10}
|
||||
// tutorial6.js
|
||||
var converter = new Showdown.converter();
|
||||
var Comment = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div class="comment">
|
||||
<h2 class="commentAuthor">
|
||||
{this.props.author}
|
||||
</h2>
|
||||
{converter.makeHtml(this.props.children.toString())}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
All we're doing here is calling the Showdown library. We need to convert `this.props.children` from React's wrapped text to a raw string that Showdown will understand so we explicitly call `toString()`.
|
||||
|
||||
But there's a problem! Our rendered comments look like this in the browser: "`<p>`This is `<em>`another`</em>` comment`</p>`". We want those tags to actually render as HTML.
|
||||
|
||||
That's React protecting you from an XSS attack. There's a way to get around it but the framework warns you not to use it:
|
||||
|
||||
```javascript{5,11}
|
||||
// tutorial7.js
|
||||
var converter = new Showdown.converter();
|
||||
var Comment = React.createClass({
|
||||
render: function() {
|
||||
var rawMarkup = converter.makeHtml(this.props.children.toString());
|
||||
return (
|
||||
<div class="comment">
|
||||
<h2 class="commentAuthor">
|
||||
{this.props.author}
|
||||
</h2>
|
||||
<span dangerouslySetInnerHTML={{"{{"}}__html: rawMarkup}} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
This is a special API that intentionally makes it difficult to insert raw HTML, but for Showdown we'll take advantage of this backdoor.
|
||||
|
||||
**Remember:** by using this feature you're relying on Showdown to be secure.
|
||||
|
||||
## Hook up the data model
|
||||
|
||||
So far we've been inserting the comments directly in the source code. Instead, let's render a blob of JSON data into the comment list. Eventually this will come from the server, but for now, write it in your source:
|
||||
|
||||
```javascript
|
||||
// tutorial8.js
|
||||
var data = [
|
||||
{author: 'Pete Hunt', text: 'This is one comment'},
|
||||
{author: 'Jordan Walke', text: 'This is *another* comment'}
|
||||
];
|
||||
```
|
||||
|
||||
We need to get this data into `CommentList` in a modular way. Modify `CommentBox` and the `renderComponent()` call to pass this data into the `CommentList` via props:
|
||||
|
||||
```javascript{7,15}
|
||||
// tutorial9.js
|
||||
var CommentBox = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<div class="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.props.data} />
|
||||
<CommentForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
React.renderComponent(
|
||||
<CommentBox data={data} />,
|
||||
document.getElementById('content')
|
||||
);
|
||||
```
|
||||
|
||||
Now that the data is available in the `CommentList`, let's render the comments dynamically:
|
||||
|
||||
```javascript{4-6}
|
||||
// tutorial10.js
|
||||
var CommentList = React.createClass({
|
||||
render: function() {
|
||||
var commentNodes = this.props.data.map(function (comment) {
|
||||
return <Comment author={comment.author}>{comment.text}</Comment>;
|
||||
});
|
||||
return (
|
||||
<div class="commentList">
|
||||
{commentNodes}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
That's it!
|
||||
|
||||
## Fetching from the server
|
||||
|
||||
Let's replace the hard-coded data with some dynamic data from the server. We will remove the data prop and replace it with a URL to fetch:
|
||||
|
||||
```javascript{2}
|
||||
// tutorial11.js
|
||||
React.renderComponent(
|
||||
<CommentBox url="comments.json" />,
|
||||
document.getElementById('example')
|
||||
);
|
||||
```
|
||||
|
||||
This component is different from the prior components because it will have to re-render itself. The component won't have any data until the request from the server comes back, at which point the component may need to render some new comments.
|
||||
|
||||
## Reactive state
|
||||
|
||||
So far, each component has rendered itself once based on its props. `props` are immutable: they are passed from the parent and are "owned" by the parent. To implement interactions, we introduce mutable **state** to the component. `this.state` is private to the component and can be changed by calling `this.setState()`. When the state is updated, the component re-renders itself.
|
||||
|
||||
`render()` methods are written declaratively as functions of `this.props` and `this.state`. The framework guarantees the UI is always consistent with the inputs.
|
||||
|
||||
When the server fetches data, we will be changing the comment data we have. Let's add an array of comment data to the `CommentBox` component as its state:
|
||||
|
||||
```javascript{3-5}
|
||||
// tutorial12.js
|
||||
var CommentBox = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {data: []};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div class="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.state.data} />
|
||||
<CommentForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
`getInitialState()` executes exactly once during the lifecycle of the component and sets up the initial state of the component.
|
||||
|
||||
### Updating state
|
||||
When the component is first created, we want to GET some JSON from the server and update the state to reflect the latest data. In a real application this would be a dynamic endpoint, but for this example, we will use a static JSON file to keep things simple:
|
||||
|
||||
```javascript
|
||||
// tutorial13.json
|
||||
[
|
||||
{'author': 'Pete Hunt', 'text': 'This is one comment'},
|
||||
{'author': 'Jordan Walke', 'text': 'This is *another* comment'}
|
||||
]
|
||||
```
|
||||
|
||||
We will use jQuery 1.5 to help make an asynchronous request to the server.
|
||||
|
||||
Note: because this is becoming an AJAX application you'll need to develop your app using a web server rather than as a file sitting on your file system. The easiest way to do this is to run `python -m SimpleHTTPServer` in your application's directory.
|
||||
|
||||
```javascript{4-11}
|
||||
// tutorial13.js
|
||||
var CommentBox = React.createClass({
|
||||
getInitialState: function() {
|
||||
$.ajax({
|
||||
url: 'comments.json',
|
||||
dataType: 'json',
|
||||
mimeType: 'textPlain',
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this)
|
||||
});
|
||||
return {data: []};
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div class="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.state.data} />
|
||||
<CommentForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
The key is the call to `this.setState()`. We replace the old array of comments with the new one from the server and the UI automatically updates itself. Because of this reactivity, it is trivial to add live updates. We will use simple polling here but you could easily use WebSockets or other technologies.
|
||||
|
||||
```javascript{3,17-21,35}
|
||||
// tutorial14.js
|
||||
var CommentBox = React.createClass({
|
||||
loadCommentsFromServer: function() {
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
dataType: 'json',
|
||||
mimeType: 'textPlain',
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
getInitialState: function() {
|
||||
return {data: []};
|
||||
},
|
||||
componentWillMount: function() {
|
||||
this.loadCommentsFromServer();
|
||||
setInterval(
|
||||
this.loadCommentsFromServer.bind(this),
|
||||
this.props.pollInterval
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div class="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.state.data} />
|
||||
<CommentForm />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
React.renderComponent(
|
||||
<CommentBox url="comments.json" pollInterval={5000} />,
|
||||
document.getElementById('content')
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
All we have done here is move the AJAX call to a separate method and call it when the component is first loaded and every 60 seconds after that. Try running this in your browser and changing the `comments.json` file; within 5 seconds, the changes will show!
|
||||
|
||||
## Adding new comments
|
||||
|
||||
Now it's time to build the form. Our `CommentForm` component should ask the user for their name and comment text and send a request to the server to save the comment.
|
||||
|
||||
```javascript{5-8}
|
||||
// tutorial15.js
|
||||
var CommentForm = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<form class="commentForm">
|
||||
<input type="text" placeholder="Your name" />
|
||||
<input type="text" placeholder="Say something..." />
|
||||
</form>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Let's make the form interactive. When the user presses enter, we should clear the form, submit a request to the server, and refresh the list of comments. To start, let's listen for this event and just clear the form.
|
||||
|
||||
```javascript{3-12,15,20}
|
||||
// tutorial16.js
|
||||
var CommentForm = React.createClass({
|
||||
handleSubmit: React.autoBind(function() {
|
||||
var author = this.refs.author.getDOMNode().value.trim();
|
||||
var text = this.refs.text.getDOMNode().value.trim();
|
||||
if (!text || !author) {
|
||||
return;
|
||||
}
|
||||
// TODO: send request to the server
|
||||
this.refs.author.getDOMNode().value = '';
|
||||
this.refs.text.getDOMNode().value = '';
|
||||
}),
|
||||
render: function() {
|
||||
return (
|
||||
<form class="commentForm" onSubmit={this.handleSubmit}>
|
||||
<input type="text" placeholder="Your name" ref="author" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Say something..."
|
||||
ref="text"
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### Events
|
||||
|
||||
React attaches event handlers to components using a camelCase naming convention. We attach an onKeyUp handler to the text field, check if the user has entered text and pressed the enter key and then clear the form fields.
|
||||
|
||||
`React.autoBind()` is a simple way to ensure that a method is always bound to its component. Inside the method, `this` will be bound to the component instance.
|
||||
|
||||
#### Refs
|
||||
|
||||
We use the `ref` attribute to assign a name to a child component and `this.refs` to reference the component. We can call `getDOMNode()` on a component to get the native browser DOM element.
|
||||
|
||||
#### Callbacks as props
|
||||
|
||||
When a user submits a comment, we will need to refresh the list of comments to include the new one. It makes sense to do all of this logic in `CommentBox` since `CommentBox` owns the state that represents the list of comments.
|
||||
|
||||
We need to pass data from the child component to its parent. We do this by passing a `callback` in props from parent to child:
|
||||
|
||||
```javascript{13-15,30}
|
||||
// tutorial17.js
|
||||
var CommentBox = React.createClass({
|
||||
loadCommentsFromServer: function() {
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
dataType: 'json',
|
||||
mimeType: 'textPlain',
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
handleCommentSubmit: React.autoBind(function(comment) {
|
||||
// TODO: submit to the server and refresh the list
|
||||
}),
|
||||
getInitialState: function() {
|
||||
return {data: []};
|
||||
},
|
||||
componentWillMount: function() {
|
||||
this.loadCommentsFromServer();
|
||||
setInterval(
|
||||
this.loadCommentsFromServer.bind(this),
|
||||
this.props.pollInterval
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div class="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.state.data} />
|
||||
<CommentForm
|
||||
onCommentSubmit={this.handleCommentSubmit}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Let's call the callback from the `CommentForm` when the user presses enter:
|
||||
|
||||
```javascript{6}
|
||||
// tutorial18.js
|
||||
var CommentForm = React.createClass({
|
||||
handleSubmit: React.autoBind(function() {
|
||||
var author = this.refs.author.getDOMNode().value.trim();
|
||||
var text = this.refs.text.getDOMNode().value.trim();
|
||||
this.props.onCommentSubmit({author: author, text: text});
|
||||
this.refs.author.getDOMNode().value = '';
|
||||
this.refs.text.getDOMNode().value = '';
|
||||
}),
|
||||
render: function() {
|
||||
return (
|
||||
<form class="commentForm" onSubmit={this.handleSubmit}>
|
||||
<input type="text" placeholder="Your name" ref="author" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Say something..."
|
||||
ref="text"
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Now that the callbacks are in place, all we have to do is submit to the server and refresh the list:
|
||||
|
||||
```javascript{14-22}
|
||||
// tutorial19.js
|
||||
var CommentBox = React.createClass({
|
||||
loadCommentsFromServer: function() {
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
dataType: 'json',
|
||||
mimeType: 'textPlain',
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
handleCommentSubmit: React.autoBind(function(comment) {
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
data: comment,
|
||||
dataType: 'json',
|
||||
mimeType: 'textPlain',
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this)
|
||||
});
|
||||
}),
|
||||
getInitialState: function() {
|
||||
return {data: []};
|
||||
},
|
||||
componentWillMount: function() {
|
||||
this.loadCommentsFromServer();
|
||||
setInterval(
|
||||
this.loadCommentsFromServer.bind(this),
|
||||
this.props.pollInterval
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div class="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.state.data} />
|
||||
<CommentForm
|
||||
onCommentSubmit={this.handleCommentSubmit}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Optimization: optimistic updates
|
||||
|
||||
Our application is now feature complete but it feels slow to have to wait for the request to complete before your comment appears in the list. We can optimistically add this comment to the list to make the app feel faster.
|
||||
|
||||
```javascript{14-16}
|
||||
// tutorial20.js
|
||||
var CommentBox = React.createClass({
|
||||
loadCommentsFromServer: function() {
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
dataType: 'json',
|
||||
mimeType: 'textPlain',
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this)
|
||||
});
|
||||
},
|
||||
handleCommentSubmit: React.autoBind(function(comment) {
|
||||
var comments = this.state.data;
|
||||
comments.push(comment);
|
||||
this.setState({data: comments});
|
||||
$.ajax({
|
||||
url: this.props.url,
|
||||
data: comment,
|
||||
dataType: 'json',
|
||||
mimeType: 'textPlain',
|
||||
success: function(data) {
|
||||
this.setState({data: data});
|
||||
}.bind(this)
|
||||
});
|
||||
}),
|
||||
getInitialState: function() {
|
||||
return {data: []};
|
||||
},
|
||||
componentWillMount: function() {
|
||||
this.loadCommentsFromServer();
|
||||
setInterval(
|
||||
this.loadCommentsFromServer.bind(this),
|
||||
this.props.pollInterval
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
return (
|
||||
<div class="commentBox">
|
||||
<h1>Comments</h1>
|
||||
<CommentList data={this.state.data} />
|
||||
<CommentForm
|
||||
onCommentSubmit={this.handleCommentSubmit}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Congrats!
|
||||
|
||||
You have just built a comment box in a few simple steps. Learn more about React in the [reference](syntax.html) or start hacking! Good luck!
|
||||
44
docs/downloads.md
Normal file
44
docs/downloads.md
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
id: downloads
|
||||
title: Downloads
|
||||
layout: single
|
||||
---
|
||||
Download the starter kit to get everything you need to
|
||||
[get started with React](/react/docs/getting-started.html).
|
||||
|
||||
<div class="buttons-unit downloads">
|
||||
<a href="/react/downloads/react-{{site.react_version}}.zip" class="button">
|
||||
Download Starter Kit {{site.react_version}}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## Individual Downloads
|
||||
|
||||
#### <a href="http://fb/me/react-{{site.react_version}}.min.js">React Core {{site.react_version}} (production)</a>
|
||||
The compressed, production version of React core
|
||||
|
||||
#### <a href="http://fb/me/react-{{site.react_version}}.js">React Core {{site.react_version}} (development)</a>
|
||||
The uncompressed, development version of React core with inline documentation.
|
||||
|
||||
#### <a href="http://fb/me/JSXTransformer-{{site.react_version}}.js">JSX Transform</a>
|
||||
The JSX transformer used to support [XML syntax](/react/docs/syntax.html) in JavaScript.
|
||||
|
||||
## Bower
|
||||
|
||||
```sh
|
||||
$ bower install react
|
||||
```
|
||||
|
||||
## NPM
|
||||
|
||||
```sh
|
||||
$ npm install -g react-tools
|
||||
```
|
||||
|
||||
## Release Notes
|
||||
|
||||
**0.3** Initial public release.
|
||||
|
||||
**0.2** Standardize API & refactor component lifecycle. Normalize DOM interactions.
|
||||
|
||||
**0.1** Initial release.
|
||||
37
docs/extractCode.js
Normal file
37
docs/extractCode.js
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
var argv = require('optimist').argv;
|
||||
var fs = require('fs');
|
||||
|
||||
var CODE_SAMPLE = /```[\S]+\s*[\s\S]*?```/g;
|
||||
var PARTS = /```[\S]+\s*\/\/\s+(.+?)\n([\s\S]*?)```/;
|
||||
|
||||
function truncate(s, n) {
|
||||
n = n || 256
|
||||
if (s.length < n) {
|
||||
return s;
|
||||
}
|
||||
return s.substring(0, n) + '...';
|
||||
}
|
||||
|
||||
function main(dest, filenames) {
|
||||
if (!dest) {
|
||||
throw new Error('no dest provided');
|
||||
}
|
||||
filenames.map(function (filename) {
|
||||
var content = fs.readFileSync(filename).toString('utf8');
|
||||
var codeSamples = content.match(CODE_SAMPLE);
|
||||
|
||||
codeSamples.map(function (codeSample) {
|
||||
// Do a little jank preprocessing
|
||||
codeSample = codeSample.replace('<!--', '//').replace(' -->', '');
|
||||
var extracted = codeSample.match(PARTS);
|
||||
if (!extracted) {
|
||||
throw new Error('Code sample did not match correct format in ' + filename + ': ' + truncate(codeSample));
|
||||
}
|
||||
var filename = extracted[1];
|
||||
var content = extracted[2].replace(/\*\*/g, '');
|
||||
fs.writeFileSync(argv.dest + '/' + filename, content);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
main(argv.dest, argv._);
|
||||
BIN
docs/favicon.ico
Normal file
BIN
docs/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
BIN
docs/img/logo_og.png
Normal file
BIN
docs/img/logo_og.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
BIN
docs/img/logo_small.png
Normal file
BIN
docs/img/logo_small.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
BIN
docs/img/logo_small@2x.png
Normal file
BIN
docs/img/logo_small@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
BIN
docs/img/noise.png
Normal file
BIN
docs/img/noise.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user