pax_global_header 0000666 0000000 0000000 00000000064 13151101465 0014507 g ustar 00root root 0000000 0000000 52 comment=2205c0f65d9595df1b1fddd7b09c79102ae34401
preact-8.2.5/ 0000775 0000000 0000000 00000000000 13151101465 0013001 5 ustar 00root root 0000000 0000000 preact-8.2.5/.babelrc 0000664 0000000 0000000 00000000554 13151101465 0014400 0 ustar 00root root 0000000 0000000 {
"presets": [
[
"env",
{
"loose": true,
"exclude": [
"transform-es2015-typeof-symbol"
],
"targets": {
"browsers": [
"last 2 versions",
"IE >= 9"
]
}
}
]
],
"plugins": [
"transform-object-rest-spread",
"transform-react-jsx"
]
}
preact-8.2.5/.editorconfig 0000664 0000000 0000000 00000000354 13151101465 0015460 0 ustar 00root root 0000000 0000000 root = true
[*]
indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[{package.json,.*rc,*.yml}]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
preact-8.2.5/.gitignore 0000664 0000000 0000000 00000000211 13151101465 0014763 0 ustar 00root root 0000000 0000000 /node_modules
/npm-debug.log
.DS_Store
/dist
/_dev
/coverage
# Additional bundles
/devtools.js
/devtools.js.map
/debug.js
/debug.js.map
preact-8.2.5/.travis.yml 0000664 0000000 0000000 00000001311 13151101465 0015106 0 ustar 00root root 0000000 0000000 sudo: false
language: node_js
node_js:
- "6"
cache:
directories:
- node_modules
# Make chrome browser available for testing
before_install:
- export CHROME_BIN=chromium-browser
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
install:
- npm install
script:
- npm run build
- npm run test
- BROWSER=true COVERAGE=false FLAKEY=false PERFORMANCE=false npm run test:karma
- ./node_modules/coveralls/bin/coveralls.js < ./coverage/lcov.info
# Necessary to compile native modules for io.js v3 or Node.js v4
env:
- CXX=g++-4.8
# Necessary to compile native modules for io.js v3 or Node.js v4
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-4.8
preact-8.2.5/CODE_OF_CONDUCT.md 0000664 0000000 0000000 00000006217 13151101465 0015606 0 ustar 00root root 0000000 0000000 # Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello@preactjs.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
preact-8.2.5/LICENSE 0000664 0000000 0000000 00000002067 13151101465 0014013 0 ustar 00root root 0000000 0000000 The MIT License (MIT)
Copyright (c) 2017 Jason Miller
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
preact-8.2.5/README.md 0000664 0000000 0000000 00000072220 13151101465 0014263 0 ustar 00root root 0000000 0000000
Fast 3kB alternative to React, with the same ES2015 API.
**All the power of Virtual DOM components, without the overhead:**
- Familiar React API & patterns: [ES6 Class] and [Functional Components]
- Extensive React compatibility via a simple [preact-compat] alias
- Everything you need: JSX, VDOM, React DevTools, HMR, SSR..
- A highly optimized diff algorithm and seamless Server Side Rendering
- Transparent asynchronous rendering with a pluggable scheduler
- 🆕💥 **Instant no-config app bundling with [Preact CLI](https://github.com/developit/preact-cli)**
### 💁 More information at the [Preact Website ➞](https://preactjs.com)
---
- [Demos](#demos)
- [Libraries & Add-ons](#libraries--add-ons)
- [Getting Started](#getting-started)
- [Import what you need](#import-what-you-need)
- [Rendering JSX](#rendering-jsx)
- [Components](#components)
- [Props & State](#props--state)
- [Linked State](#linked-state)
- [Examples](#examples)
- [Extensions](#extensions)
- [Developer Tools](#developer-tools)
- [Backers](#backers)
- [Sponsors](#sponsors)
- [License](#license)
# Preact
[](http://npm.im/preact)
[](https://cdnjs.com/libraries/preact)
[](https://preact-slack.now.sh)
[](#backers)
[](#sponsors)
[](https://travis-ci.org/developit/preact)
[](https://coveralls.io/github/developit/preact)
[](https://unpkg.com/preact/dist/preact.min.js)
Preact supports modern browsers and IE9+:
[](https://saucelabs.com/u/preact)
---
## Demos
- [**ESBench**](http://esbench.com) is built using Preact.
- [**Nectarine.rocks**](http://nectarine.rocks) _([GitHub Project](https://github.com/developit/nectarine))_ :peach:
- [**Documentation Viewer**](https://documentation-viewer.firebaseapp.com) _([GitHub Project](https://github.com/developit/documentation-viewer))_
- [**TodoMVC**](https://preact-todomvc.surge.sh) _([GitHub Project](https://github.com/developit/preact-todomvc))_
- [**Hacker News Minimal**](https://developit.github.io/hn_minimal/) _([GitHub Project](https://github.com/developit/hn_minimal))_
- [**Preact Boilerplate**](https://preact-boilerplate.surge.sh) _([GitHub Project](https://github.com/developit/preact-boilerplate))_ :zap:
- [**Preact Offline Starter**](https://preact-starter.now.sh) _([GitHub Project](https://github.com/lukeed/preact-starter))_ :100:
- [**Preact PWA**](https://preact-pwa.appspot.com/) _([GitHub Project](https://github.com/ezekielchentnik/preact-pwa))_ :hamburger:
- [**Preact Mobx Starter**](https://awaw00.github.io/preact-mobx-starter/) _([GitHub Project](https://github.com/awaw00/preact-mobx-starter))_ :sunny:
- [**Preact Redux Example**](https://github.com/developit/preact-redux-example) :star:
- [**Flickr Browser**](http://codepen.io/developit/full/VvMZwK/) (@ CodePen)
- [**Animating Text**](http://codepen.io/developit/full/LpNOdm/) (@ CodePen)
- [**60FPS Rainbow Spiral**](http://codepen.io/developit/full/xGoagz/) (@ CodePen)
- [**Simple Clock**](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/) (@ JSFiddle)
- [**3D + ThreeJS**](http://codepen.io/developit/pen/PPMNjd?editors=0010) (@ CodePen)
- [**Stock Ticker**](http://codepen.io/developit/pen/wMYoBb?editors=0010) (@ CodePen)
- [**Create your Own!**](https://jsfiddle.net/developit/rs6zrh5f/embedded/result/) (@ JSFiddle)
- [**Preact Coffeescript**](https://github.com/crisward/preact-coffee)
- [**GuriVR**](https://gurivr.com) _([GitHub Project](https://github.com/opennewslabs/guri-vr))_
- [**V2EX Preact**](https://github.com/yanni4night/v2ex-preact)
- [**BigWebQuiz**](https://bigwebquiz.com/) _([GitHub Project](https://github.com/jakearchibald/big-web-quiz))_
- [**Color Picker**](https://colors.now.sh) _([GitHub Project](https://github.com/lukeed/colors-app))_ :art:
- [**Rainbow Explorer**](https://use-the-platform.com/rainbow-explorer/) _([GitHub Project](https://github.com/vaneenige/rainbow-explorer/))_ :rainbow:
- [**Offline Gallery**](https://use-the-platform.com/offline-gallery/) _([GitHub Project](https://github.com/vaneenige/offline-gallery/))_ :balloon:
- [**Periodic Weather**](https://use-the-platform.com/periodic-weather/) _([GitHub Project](https://github.com/vaneenige/periodic-weather/))_ :sunny:
- [**Play.cash**](https://play.cash) :notes:
- [**Rugby News Board**](http://nbrugby.com) _[(GitHub Project)](https://github.com/rugby-board/rugby-board-node)_
## Libraries & Add-ons
- :raised_hands: [**preact-compat**](https://git.io/preact-compat): use any React library with Preact *([full example](http://git.io/preact-compat-example))*
- :page_facing_up: [**preact-render-to-string**](https://git.io/preact-render-to-string): Universal rendering.
- :loop: [**preact-render-to-json**](https://git.io/preact-render-to-json): Render for Jest Snapshot testing.
- :earth_americas: [**preact-router**](https://git.io/preact-router): URL routing for your components
- :bookmark_tabs: [**preact-markup**](https://git.io/preact-markup): Render HTML & Custom Elements as JSX & Components
- :satellite: [**preact-portal**](https://git.io/preact-portal): Render Preact components into (a) SPACE :milky_way:
- :pencil: [**preact-richtextarea**](https://git.io/preact-richtextarea): Simple HTML editor component
- :bookmark: [**preact-token-input**](https://github.com/developit/preact-token-input): Text field that tokenizes input, for things like tags
- :card_index: [**preact-virtual-list**](https://github.com/developit/preact-virtual-list): Easily render lists with millions of rows ([demo](https://jsfiddle.net/developit/qqan9pdo/))
- :repeat: [**preact-cycle**](https://git.io/preact-cycle): Functional-reactive paradigm for Preact
- :triangular_ruler: [**preact-layout**](https://download.github.io/preact-layout/): Small and simple layout library
- :thought_balloon: [**preact-socrates**](https://github.com/matthewmueller/preact-socrates): Preact plugin for [Socrates](http://github.com/matthewmueller/socrates)
- :rowboat: [**preact-flyd**](https://github.com/xialvjun/preact-flyd): Use [flyd](https://github.com/paldepind/flyd) FRP streams in Preact + JSX
- :speech_balloon: [**preact-i18nline**](https://github.com/download/preact-i18nline): Integrates the ecosystem around [i18n-js](https://github.com/everydayhero/i18n-js) with Preact via [i18nline](https://github.com/download/i18nline).
- :microscope: [**preact-jsx-chai**](https://git.io/preact-jsx-chai): JSX assertion testing _(no DOM, right in Node)_
- :tophat: [**preact-classless-component**](https://github.com/ld0rman/preact-classless-component): create preact components without the class keyword
- :hammer: [**preact-hyperscript**](https://github.com/queckezz/preact-hyperscript): Hyperscript-like syntax for creating elements
- :white_check_mark: [**shallow-compare**](https://github.com/tkh44/shallow-compare): simplified `shouldComponentUpdate` helper.
- :shaved_ice: [**preact-codemod**](https://github.com/vutran/preact-codemod): Transform your React code to Preact.
- :construction_worker: [**preact-helmet**](https://github.com/download/preact-helmet): A document head manager for Preact
- :necktie: [**preact-delegate**](https://github.com/NekR/preact-delegate): Delegate DOM events
#### UI Component Libraries
> Want to prototype something or speed up your development? Try one of these toolkits:
- [**preact-material-components**](https://github.com/prateekbh/preact-material-components): Material Design Components for Preact ([website](https://prateekbh.github.io/preact-material-components/))
- [**preact-mdc**](https://github.com/BerndWessels/preact-mdc): Material Design Components for Preact ([demo](https://github.com/BerndWessels/preact-mdc-demo))
- [**preact-mui**](https://git.io/v1aVO): The MUI CSS Preact library.
- [**preact-photon**](https://git.io/preact-photon): build beautiful desktop UI with [photon](http://photonkit.com)
- [**preact-mdl**](https://git.io/preact-mdl): [Material Design Lite](https://getmdl.io) for Preact
- [**preact-weui**](https://github.com/afeiship/preact-weui): [Weui](https://github.com/afeiship/preact-weui) for Preact
---
## Getting Started
> 💁 _**Note:** You [don't need ES2015 to use Preact](https://github.com/developit/preact-in-es3)... but give it a try!_
The easiest way to get started with Preact is to install [Preact CLI](https://github.com/developit/preact-cli). This simple command-line tool wraps up the best possible Webpack and Babel setup for you, and even keeps you up-to-date as the underlying tools change. Best of all, it's easy to understand! It builds your app in a single command (`preact build`), doesn't need any configuration, and bakes in best-practises 🙌.
The following guide assumes you have some sort of ES2015 build set up using babel and/or webpack/browserify/gulp/grunt/etc.
You can also start with [preact-boilerplate] or a [CodePen Template](http://codepen.io/developit/pen/pgaROe?editors=0010).
### Import what you need
The `preact` module provides both named and default exports, so you can either import everything under a namespace of your choosing, or just what you need as locals:
##### Named:
```js
import { h, render, Component } from 'preact';
// Tell Babel to transform JSX into h() calls:
/** @jsx h */
```
##### Default:
```js
import preact from 'preact';
// Tell Babel to transform JSX into preact.h() calls:
/** @jsx preact.h */
```
> Named imports work well for highly structured applications, whereas the default import is quick and never needs to be updated when using different parts of the library.
>
> Instead of declaring the `@jsx` pragma in your code, it's best to configure it globally in a `.babelrc`:
>
> **For Babel 5 and prior:**
>
> ```json
> { "jsxPragma": "h" }
> ```
>
> **For Babel 6:**
>
> ```json
> {
> "plugins": [
> ["transform-react-jsx", { "pragma":"h" }]
> ]
> }
> ```
### Rendering JSX
Out of the box, Preact provides an `h()` function that turns your JSX into Virtual DOM elements _([here's how](http://jasonformat.com/wtf-is-jsx))_. It also provides a `render()` function that creates a DOM tree from that Virtual DOM.
To render some JSX, just import those two functions and use them like so:
```js
import { h, render } from 'preact';
render((
Hello, world!
), document.body);
```
This should seem pretty straightforward if you've used hyperscript or one of its many friends. If you're not, the short of it is that the h function import gets used in the final, transpiled code as a drop in replacement for React.createElement, and so needs to be imported even if you don't explicitly use it in the code you write. Also note that if you're the kind of person who likes writing your React code in "pure JavaScript" (you know who you are) you will need to use h(...) wherever you would otherwise use React.createElement.
Rendering hyperscript with a virtual DOM is pointless, though. We want to render components and have them updated when data changes - that's where the power of virtual DOM diffing shines. :star2:
### Components
Preact exports a generic `Component` class, which can be extended to build encapsulated, self-updating pieces of a User Interface. Components support all of the standard React [lifecycle methods], like `shouldComponentUpdate()` and `componentWillReceiveProps()`. Providing specific implementations of these methods is the preferred mechanism for controlling _when_ and _how_ components update.
Components also have a `render()` method, but unlike React this method is passed `(props, state)` as arguments. This provides an ergonomic means to destructure `props` and `state` into local variables to be referenced from JSX.
Let's take a look at a very simple `Clock` component, which shows the current time.
```js
import { h, render, Component } from 'preact';
class Clock extends Component {
render() {
let time = new Date().toLocaleTimeString();
return { time };
}
}
// render an instance of Clock into :
render(, document.body);
```
That's great. Running this produces the following HTML DOM structure:
```html
10:28:57 PM
```
In order to have the clock's time update every second, we need to know when `` gets mounted to the DOM. _If you've used HTML5 Custom Elements, this is similar to the `attachedCallback` and `detachedCallback` lifecycle methods._ Preact invokes the following lifecycle methods if they are defined for a Component:
| Lifecycle method | When it gets called |
|-----------------------------|--------------------------------------------------|
| `componentWillMount` | before the component gets mounted to the DOM |
| `componentDidMount` | after the component gets mounted to the DOM |
| `componentWillUnmount` | prior to removal from the DOM |
| `componentWillReceiveProps` | before new props get accepted |
| `shouldComponentUpdate` | before `render()`. Return `false` to skip render |
| `componentWillUpdate` | before `render()` |
| `componentDidUpdate` | after `render()` |
So, we want to have a 1-second timer start once the Component gets added to the DOM, and stop if it is removed. We'll create the timer and store a reference to it in `componentDidMount`, and stop the timer in `componentWillUnmount`. On each timer tick, we'll update the component's `state` object with a new time value. Doing this will automatically re-render the component.
```js
import { h, render, Component } from 'preact';
class Clock extends Component {
constructor() {
super();
// set initial time:
this.state = {
time: Date.now()
};
}
componentDidMount() {
// update time every second
this.timer = setInterval(() => {
this.setState({ time: Date.now() });
}, 1000);
}
componentWillUnmount() {
// stop when not renderable
clearInterval(this.timer);
}
render(props, state) {
let time = new Date(state.time).toLocaleTimeString();
return { time };
}
}
// render an instance of Clock into :
render(, document.body);
```
Now we have [a ticking clock](http://jsfiddle.net/developit/u9m5x0L7/embedded/result,js/)!
### Props & State
The concept (and nomenclature) for `props` and `state` is the same as in React. `props` are passed to a component by defining attributes in JSX, `state` is internal state. Changing either triggers a re-render, though by default Preact re-renders Components asynchronously for `state` changes and synchronously for `props` changes. You can tell Preact to render `prop` changes asynchronously by setting `options.syncComponentUpdates` to `false`.
---
## Linked State
One area Preact takes a little further than React is in optimizing state changes. A common pattern in ES2015 React code is to use Arrow functions within a `render()` method in order to update state in response to events. Creating functions enclosed in a scope on every render is inefficient and forces the garbage collector to do more work than is necessary.
One solution to this is to bind component methods declaratively.
Here is an example using [decko](http://git.io/decko):
```js
class Foo extends Component {
@bind
updateText(e) {
this.setState({ text: e.target.value });
}
render({ }, { text }) {
return ;
}
}
```
While this achieves much better runtime performance, it's still a lot of unnecessary code to wire up state to UI.
Fortunately there is a solution, in the form of a module called [linkstate](https://github.com/developit/linkstate). Calling `linkState(component, 'text')` returns a function that accepts an Event and uses it's associated value to update the given property in your component's state. Calls to `linkState()` with the same arguments are cached, so there is no performance penalty. Here is the previous example rewritten using _Linked State_:
```js
import linkState from 'linkstate';
class Foo extends Component {
render({ }, { text }) {
return ;
}
}
```
Simple and effective. It handles linking state from any input type, or an optional second parameter can be used to explicitly provide a keypath to the new state value.
> **Note:** In Preact 7 and prior, `linkState()` was built right into Component. In 8.0, it was moved to a separate module. You can restore the 7.x behavior by using linkstate as a polyfill - see [the linkstate docs](https://github.com/developit/linkstate#usage).
## Examples
Here is a somewhat verbose Preact `` component:
```js
class Link extends Component {
render(props, state) {
return {props.children};
}
}
```
Since this is ES6/ES2015, we can further simplify:
```js
class Link extends Component {
render({ href, children }) {
return ;
}
}
// or, for wide-open props support:
class Link extends Component {
render(props) {
return ;
}
}
// or, as a stateless functional component:
const Link = ({ children, ...props }) => (
{ children }
);
```
## Extensions
It is likely that some projects based on Preact would wish to extend Component with great new functionality.
Perhaps automatic connection to stores for a Flux-like architecture, or mixed-in context bindings to make it feel more like `React.createClass()`. Just use ES2015 inheritance:
```js
class BoundComponent extends Component {
constructor(props) {
super(props);
this.bind();
}
bind() {
this.binds = {};
for (let i in this) {
this.binds[i] = this[i].bind(this);
}
}
}
// example usage
class Link extends BoundComponent {
click() {
open(this.href);
}
render() {
let { click } = this.binds;
return { children };
}
}
```
The possibilities are pretty endless here. You could even add support for rudimentary mixins:
```js
class MixedComponent extends Component {
constructor() {
super();
(this.mixins || []).forEach( m => Object.assign(this, m) );
}
}
```
## Developer Tools
You can inspect and modify the state of your Preact UI components at runtime using the
[React Developer Tools](https://github.com/facebook/react-devtools) browser extension.
1. Install the [React Developer Tools](https://github.com/facebook/react-devtools) extension
2. Import the "preact/devtools" module in your app
3. Reload and go to the 'React' tab in the browser's development tools
```js
import { h, Component, render } from 'preact';
// Enable devtools. You can reduce the size of your app by only including this
// module in development builds. eg. In Webpack, wrap this with an `if (module.hot) {...}`
// check.
require('preact/devtools');
```
## Backers
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/preact#backer)]
## Sponsors
Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor](https://opencollective.com/preact#sponsor)]
## License
MIT
[](https://preactjs.com)
[preact-compat]: https://github.com/developit/preact-compat
[ES6 Class]: https://facebook.github.io/react/docs/reusable-components.html#es6-classes
[Functional Components]: https://facebook.github.io/react/blog/2015/10/07/react-v0.14.html#stateless-functional-components
[hyperscript]: https://github.com/dominictarr/hyperscript
[preact-boilerplate]: https://github.com/developit/preact-boilerplate
[lifecycle methods]: https://facebook.github.io/react/docs/component-specs.html
preact-8.2.5/config/ 0000775 0000000 0000000 00000000000 13151101465 0014246 5 ustar 00root root 0000000 0000000 preact-8.2.5/config/codemod-const.js 0000664 0000000 0000000 00000002241 13151101465 0017341 0 ustar 00root root 0000000 0000000 /* eslint no-console:0 */
/** Find constants (identified by ALL_CAPS_DECLARATIONS), and inline them globally.
* This is safe because Preact *only* uses global constants.
*/
export default (file, api) => {
let j = api.jscodeshift,
code = j(file.source),
constants = {},
found = 0;
code.find(j.VariableDeclaration)
.filter( decl => {
for (let i=decl.value.declarations.length; i--; ) {
let node = decl.value.declarations[i],
name = node.id && node.id.name,
init = node.init;
if (name && init && name.match(/^[A-Z0-9_$]+$/g) && !init.regex) {
if (init.type==='Literal') {
// console.log(`Inlining constant: ${name}=${init.raw}`);
found++;
constants[name] = init;
// remove declaration
decl.value.declarations.splice(i, 1);
// if it's the last, we'll remove the whole statement
return !decl.value.declarations.length;
}
}
}
return false;
})
.remove();
code.find(j.Identifier)
.filter( path => path.value.name && constants.hasOwnProperty(path.value.name) )
.replaceWith( path => (found++, constants[path.value.name]) );
return found ? code.toSource({ quote: 'single' }) : null;
};
preact-8.2.5/config/codemod-let-name.js 0000664 0000000 0000000 00000000670 13151101465 0017721 0 ustar 00root root 0000000 0000000 /**
* Restores var names transformed by babel's let block scoping
*/
export default (file, api) => {
let j = api.jscodeshift;
let code = j(file.source);
// @TODO unsafe, but without it we gain 20b gzipped: https://www.diffchecker.com/bVrOJWTO
code.findVariableDeclarators().filter(d => /^_i/.test(d.value.id.name)).renameTo('i');
code.findVariableDeclarators('_key').renameTo('key');
return code.toSource({ quote: 'single' });
};
preact-8.2.5/config/codemod-strip-tdz.js 0000664 0000000 0000000 00000002527 13151101465 0020162 0 ustar 00root root 0000000 0000000 /* eslint no-console:0 */
// parent node types that we don't want to remove pointless initializations from (because it breaks hoisting)
const BLOCKED = ['ForStatement', 'WhileStatement']; // 'IfStatement', 'SwitchStatement'
/** Removes var initialization to `void 0`, which Babel adds for TDZ strictness. */
export default (file, api) => {
let { jscodeshift } = api,
found = 0;
let code = jscodeshift(file.source)
.find(jscodeshift.VariableDeclaration)
.forEach(handleDeclaration);
function handleDeclaration(decl) {
let p = decl,
remove = true;
while ((p = p.parentPath)) {
if (~BLOCKED.indexOf(p.value.type)) {
remove = false;
break;
}
}
decl.value.declarations.filter(isPointless).forEach( node => {
if (remove===false) {
console.log(`> Skipping removal of undefined init for "${node.id.name}": within ${p.value.type}`);
}
else {
removeNodeInitialization(node);
}
});
}
function removeNodeInitialization(node) {
node.init = null;
found++;
}
function isPointless(node) {
let { init } = node;
if (init) {
if (init.type==='UnaryExpression' && init.operator==='void' && init.argument.value==0) {
return true;
}
if (init.type==='Identifier' && init.name==='undefined') {
return true;
}
}
return false;
}
return found ? code.toSource({ quote: 'single' }) : null;
};
preact-8.2.5/config/eslint-config.js 0000664 0000000 0000000 00000002555 13151101465 0017354 0 ustar 00root root 0000000 0000000 module.exports = {
parser: 'babel-eslint',
extends: 'eslint:recommended',
plugins: [
'react'
],
env: {
browser: true,
mocha: true,
node: true,
es6: true
},
parserOptions: {
ecmaFeatures: {
modules: true,
jsx: true
}
},
globals: {
sinon: true,
expect: true
},
rules: {
'react/jsx-uses-react': 2,
'react/jsx-uses-vars': 2,
'no-unused-vars': [1, { varsIgnorePattern: '^h$' }],
'no-cond-assign': 1,
'no-empty': 0,
'no-console': 1,
semi: 2,
camelcase: 0,
'comma-style': 2,
'comma-dangle': [2, 'never'],
indent: [2, 'tab', {SwitchCase: 1}],
'no-mixed-spaces-and-tabs': [2, 'smart-tabs'],
'no-trailing-spaces': [2, { skipBlankLines: true }],
'max-nested-callbacks': [2, 3],
'no-eval': 2,
'no-implied-eval': 2,
'no-new-func': 2,
'guard-for-in': 0,
eqeqeq: 0,
'no-else-return': 2,
'no-redeclare': 2,
'no-dupe-keys': 2,
radix: 2,
strict: [2, 'never'],
'no-shadow': 0,
'callback-return': [1, ['callback', 'cb', 'next', 'done']],
'no-delete-var': 2,
'no-undef-init': 2,
'no-shadow-restricted-names': 2,
'handle-callback-err': 0,
'no-lonely-if': 2,
'keyword-spacing': 2,
'constructor-super': 2,
'no-this-before-super': 2,
'no-dupe-class-members': 2,
'no-const-assign': 2,
'prefer-spread': 2,
'no-useless-concat': 2,
'no-var': 2,
'object-shorthand': 2,
'prefer-arrow-callback': 2
}
};
preact-8.2.5/config/properties.json 0000664 0000000 0000000 00000001134 13151101465 0017334 0 ustar 00root root 0000000 0000000 {
"props": {
"cname": 16,
"props": {
"$_dirty": "__d",
"$_disable": "__x",
"$_listeners": "__l",
"$_renderCallbacks": "__h",
"$__key": "__k",
"$__ref": "__r",
"$normalizedNodeName": "__n",
"$nextBase": "__b",
"$prevContext": "__c",
"$prevProps": "__p",
"$prevState": "__s",
"$_parentComponent": "__u",
"$_componentConstructor": "_componentConstructor",
"$__html": "__html",
"$_component": "_component",
"$__preactattr_": "__preactattr_"
}
},
"vars": {
"cname": -1,
"props": {}
}
} preact-8.2.5/config/rollup.config.devtools.js 0000664 0000000 0000000 00000001043 13151101465 0021221 0 ustar 00root root 0000000 0000000 import babel from 'rollup-plugin-babel';
export default {
input: 'devtools/index.js',
output: {
format: 'umd',
file: 'devtools.js',
name: 'preactDevTools',
sourcemap: true
},
external: ['preact'],
globals: {
preact: 'preact'
},
plugins: [
babel({
sourceMap: true,
exclude: 'node_modules/**',
babelrc: false,
presets: [
['env', {
modules: false,
loose: true,
exclude: ['transform-es2015-typeof-symbol'],
targets: {
browsers: ['last 2 versions', 'IE >= 9']
}
}]
]
})
]
};
preact-8.2.5/config/rollup.config.esm.js 0000664 0000000 0000000 00000000314 13151101465 0020146 0 ustar 00root root 0000000 0000000 import config from './rollup.config';
// ES output
config.output.format = 'es';
config.output.file = 'dist/preact.esm.js';
// remove memory() plugin
config.plugins.splice(0, 1);
export default config;
preact-8.2.5/config/rollup.config.js 0000664 0000000 0000000 00000001467 13151101465 0017375 0 ustar 00root root 0000000 0000000 import nodeResolve from 'rollup-plugin-node-resolve';
import babel from 'rollup-plugin-babel';
import memory from 'rollup-plugin-memory';
export default {
strict: true,
input: 'src/preact.js',
output: {
format: 'iife',
file: 'dist/preact.dev.js',
name: 'preact',
sourcemap: true
},
plugins: [
memory({
path: 'src/preact.js',
contents: `
import preact from './preact';
if (typeof module!='undefined') module.exports = preact;
else self.preact = preact;
`
}),
nodeResolve({
main: true
}),
babel({
sourceMap: true,
exclude: 'node_modules/**',
babelrc: false,
presets: [
['env', {
modules: false,
loose: true,
exclude: ['transform-es2015-typeof-symbol'],
targets: {
browsers: ['last 2 versions', 'IE >= 9']
}
}]
]
})
]
};
preact-8.2.5/debug/ 0000775 0000000 0000000 00000000000 13151101465 0014067 5 ustar 00root root 0000000 0000000 preact-8.2.5/debug/index.js 0000664 0000000 0000000 00000004756 13151101465 0015550 0 ustar 00root root 0000000 0000000 /* eslint-disable no-console */
if (process.env.NODE_ENV === 'development') {
const { options } = require('preact');
const oldVnodeOption = options.vnode;
options.vnode = function(vnode) {
const { nodeName, attributes, children } = vnode;
if (nodeName === void 0) {
console.error('Undefined component passed to preact.h()\n'+serializeVNode(vnode));
}
if (
attributes && attributes.ref !== void 0 &&
typeof attributes.ref !== 'function' &&
!('$$typeof' in vnode) // allow string refs when preact-compat is installed
) {
throw new Error(
`Component's "ref" property should be a function,` +
` but [${typeof attributes.ref}] passed\n` + serializeVNode(vnode)
);
}
{
const keys = {};
inspectChildren(children, (deepChild) => {
if (!deepChild || deepChild.key==null) return;
// In Preact, all keys are stored as object values, i.e. being strings
const key = deepChild.key + '';
if (keys.hasOwnProperty(key)) {
console.error(
'Following component has two or more children with the ' +
'same "key" attribute. This may cause glitches and misbehavior ' +
'in rendering process. Component: \n\n' +
serializeVNode(vnode)
);
// Return early to not spam the console
return true;
}
keys[key] = true;
});
}
if (oldVnodeOption) oldVnodeOption.call(this, vnode);
};
const inspectChildren = (children, inspect) => {
if (!Array.isArray(children)) {
children = [children];
}
return children.some((child, i) => {
if (Array.isArray(child)) {
return inspectChildren(child, inspect);
}
return inspect(child, i);
});
};
const serializeVNode = ({ nodeName, attributes, children }) => {
if (typeof nodeName==='function') {
nodeName = nodeName.name || nodeName.displayName;
}
let props = '';
if (attributes) {
for (let attr in attributes) {
if (attributes.hasOwnProperty(attr) && attr!=='children') {
let value = attributes[attr];
// If it is an object but doesn't have toString(), use Object.toString
if (typeof value==='function') {
value = `function ${value.displayName || value.name}() {}`;
}
if (Object(value) === value && !value.toString) {
value = Object.prototype.toString.call(value);
}
else {
value = value + '';
}
props += ` ${attr}=${JSON.stringify(value)}`;
}
}
}
return `<${nodeName}${props}${children && children.length ? ('>..'+nodeName+'>') : ' />'}`;
};
require('preact/devtools');
}
preact-8.2.5/devtools/ 0000775 0000000 0000000 00000000000 13151101465 0014640 5 ustar 00root root 0000000 0000000 preact-8.2.5/devtools/devtools.js 0000664 0000000 0000000 00000030046 13151101465 0017040 0 ustar 00root root 0000000 0000000 /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */
import { options } from 'preact';
// Internal helpers from preact
import { ATTR_KEY } from '../src/constants';
/**
* Return a ReactElement-compatible object for the current state of a preact
* component.
*/
function createReactElement(component) {
return {
type: component.constructor,
key: component.key,
ref: null, // Unsupported
props: component.props
};
}
/**
* Create a ReactDOMComponent-compatible object for a given DOM node rendered
* by preact.
*
* This implements the subset of the ReactDOMComponent interface that
* React DevTools requires in order to display DOM nodes in the inspector with
* the correct type and properties.
*
* @param {Node} node
*/
function createReactDOMComponent(node) {
const childNodes = node.nodeType === Node.ELEMENT_NODE ?
Array.from(node.childNodes) : [];
const isText = node.nodeType === Node.TEXT_NODE;
return {
// --- ReactDOMComponent interface
_currentElement: isText ? node.textContent : {
type: node.nodeName.toLowerCase(),
props: node[ATTR_KEY]
},
_renderedChildren: childNodes.map(child => {
if (child._component) {
return updateReactComponent(child._component);
}
return updateReactComponent(child);
}),
_stringText: isText ? node.textContent : null,
// --- Additional properties used by preact devtools
// A flag indicating whether the devtools have been notified about the
// existence of this component instance yet.
// This is used to send the appropriate notifications when DOM components
// are added or updated between composite component updates.
_inDevTools: false,
node
};
}
/**
* Return the name of a component created by a `ReactElement`-like object.
*
* @param {ReactElement} element
*/
function typeName(element) {
if (typeof element.type === 'function') {
return element.type.displayName || element.type.name;
}
return element.type;
}
/**
* Return a ReactCompositeComponent-compatible object for a given preact
* component instance.
*
* This implements the subset of the ReactCompositeComponent interface that
* the DevTools requires in order to walk the component tree and inspect the
* component's properties.
*
* See https://github.com/facebook/react-devtools/blob/e31ec5825342eda570acfc9bcb43a44258fceb28/backend/getData.js
*/
function createReactCompositeComponent(component) {
const _currentElement = createReactElement(component);
const node = component.base;
let instance = {
// --- ReactDOMComponent properties
getName() {
return typeName(_currentElement);
},
_currentElement: createReactElement(component),
props: component.props,
state: component.state,
forceUpdate: component.forceUpdate && component.forceUpdate.bind(component),
setState: component.setState && component.setState.bind(component),
// --- Additional properties used by preact devtools
node
};
// React DevTools exposes the `_instance` field of the selected item in the
// component tree as `$r` in the console. `_instance` must refer to a
// React Component (or compatible) class instance with `props` and `state`
// fields and `setState()`, `forceUpdate()` methods.
instance._instance = component;
// If the root node returned by this component instance's render function
// was itself a composite component, there will be a `_component` property
// containing the child component instance.
if (component._component) {
instance._renderedComponent = updateReactComponent(component._component);
} else {
// Otherwise, if the render() function returned an HTML/SVG element,
// create a ReactDOMComponent-like object for the DOM node itself.
instance._renderedComponent = updateReactComponent(node);
}
return instance;
}
/**
* Map of Component|Node to ReactDOMComponent|ReactCompositeComponent-like
* object.
*
* The same React*Component instance must be used when notifying devtools
* about the initial mount of a component and subsequent updates.
*/
let instanceMap = typeof Map==='function' && new Map();
/**
* Update (and create if necessary) the ReactDOMComponent|ReactCompositeComponent-like
* instance for a given preact component instance or DOM Node.
*
* @param {Component|Node} componentOrNode
*/
function updateReactComponent(componentOrNode) {
const newInstance = componentOrNode instanceof Node ?
createReactDOMComponent(componentOrNode) :
createReactCompositeComponent(componentOrNode);
if (instanceMap.has(componentOrNode)) {
let inst = instanceMap.get(componentOrNode);
Object.assign(inst, newInstance);
return inst;
}
instanceMap.set(componentOrNode, newInstance);
return newInstance;
}
function nextRootKey(roots) {
return '.' + Object.keys(roots).length;
}
/**
* Find all root component instances rendered by preact in `node`'s children
* and add them to the `roots` map.
*
* @param {DOMElement} node
* @param {[key: string] => ReactDOMComponent|ReactCompositeComponent}
*/
function findRoots(node, roots) {
Array.from(node.childNodes).forEach(child => {
if (child._component) {
roots[nextRootKey(roots)] = updateReactComponent(child._component);
} else {
findRoots(child, roots);
}
});
}
/**
* Create a bridge for exposing preact's component tree to React DevTools.
*
* It creates implementations of the interfaces that ReactDOM passes to
* devtools to enable it to query the component tree and hook into component
* updates.
*
* See https://github.com/facebook/react/blob/59ff7749eda0cd858d5ee568315bcba1be75a1ca/src/renderers/dom/ReactDOM.js
* for how ReactDOM exports its internals for use by the devtools and
* the `attachRenderer()` function in
* https://github.com/facebook/react-devtools/blob/e31ec5825342eda570acfc9bcb43a44258fceb28/backend/attachRenderer.js
* for how the devtools consumes the resulting objects.
*/
function createDevToolsBridge() {
// The devtools has different paths for interacting with the renderers from
// React Native, legacy React DOM and current React DOM.
//
// Here we emulate the interface for the current React DOM (v15+) lib.
// ReactDOMComponentTree-like object
const ComponentTree = {
getNodeFromInstance(instance) {
return instance.node;
},
getClosestInstanceFromNode(node) {
while (node && !node._component) {
node = node.parentNode;
}
return node ? updateReactComponent(node._component) : null;
}
};
// Map of root ID (the ID is unimportant) to component instance.
let roots = {};
findRoots(document.body, roots);
// ReactMount-like object
//
// Used by devtools to discover the list of root component instances and get
// notified when new root components are rendered.
const Mount = {
_instancesByReactRootID: roots,
// Stub - React DevTools expects to find this method and replace it
// with a wrapper in order to observe new root components being added
_renderNewRootComponent(/* instance, ... */) { }
};
// ReactReconciler-like object
const Reconciler = {
// Stubs - React DevTools expects to find these methods and replace them
// with wrappers in order to observe components being mounted, updated and
// unmounted
mountComponent(/* instance, ... */) { },
performUpdateIfNecessary(/* instance, ... */) { },
receiveComponent(/* instance, ... */) { },
unmountComponent(/* instance, ... */) { }
};
/** Notify devtools that a new component instance has been mounted into the DOM. */
const componentAdded = component => {
const instance = updateReactComponent(component);
if (isRootComponent(component)) {
instance._rootID = nextRootKey(roots);
roots[instance._rootID] = instance;
Mount._renderNewRootComponent(instance);
}
visitNonCompositeChildren(instance, childInst => {
childInst._inDevTools = true;
Reconciler.mountComponent(childInst);
});
Reconciler.mountComponent(instance);
};
/** Notify devtools that a component has been updated with new props/state. */
const componentUpdated = component => {
const prevRenderedChildren = [];
visitNonCompositeChildren(instanceMap.get(component), childInst => {
prevRenderedChildren.push(childInst);
});
// Notify devtools about updates to this component and any non-composite
// children
const instance = updateReactComponent(component);
Reconciler.receiveComponent(instance);
visitNonCompositeChildren(instance, childInst => {
if (!childInst._inDevTools) {
// New DOM child component
childInst._inDevTools = true;
Reconciler.mountComponent(childInst);
} else {
// Updated DOM child component
Reconciler.receiveComponent(childInst);
}
});
// For any non-composite children that were removed by the latest render,
// remove the corresponding ReactDOMComponent-like instances and notify
// the devtools
prevRenderedChildren.forEach(childInst => {
if (!document.body.contains(childInst.node)) {
instanceMap.delete(childInst.node);
Reconciler.unmountComponent(childInst);
}
});
};
/** Notify devtools that a component has been unmounted from the DOM. */
const componentRemoved = component => {
const instance = updateReactComponent(component);
visitNonCompositeChildren(childInst => {
instanceMap.delete(childInst.node);
Reconciler.unmountComponent(childInst);
});
Reconciler.unmountComponent(instance);
instanceMap.delete(component);
if (instance._rootID) {
delete roots[instance._rootID];
}
};
return {
componentAdded,
componentUpdated,
componentRemoved,
// Interfaces passed to devtools via __REACT_DEVTOOLS_GLOBAL_HOOK__.inject()
ComponentTree,
Mount,
Reconciler
};
}
/**
* Return `true` if a preact component is a top level component rendered by
* `render()` into a container Element.
*/
function isRootComponent(component) {
// `_parentComponent` is actually `__u` after minification
if (component._parentComponent || component.__u) {
// Component with a composite parent
return false;
}
if (component.base.parentElement && component.base.parentElement[ATTR_KEY]) {
// Component with a parent DOM element rendered by Preact
return false;
}
return true;
}
/**
* Visit all child instances of a ReactCompositeComponent-like object that are
* not composite components (ie. they represent DOM elements or text)
*
* @param {Component} component
* @param {(Component) => void} visitor
*/
function visitNonCompositeChildren(component, visitor) {
if (component._renderedComponent) {
if (!component._renderedComponent._component) {
visitor(component._renderedComponent);
visitNonCompositeChildren(component._renderedComponent, visitor);
}
} else if (component._renderedChildren) {
component._renderedChildren.forEach(child => {
visitor(child);
if (!child._component) visitNonCompositeChildren(child, visitor);
});
}
}
/**
* Create a bridge between the preact component tree and React's dev tools
* and register it.
*
* After this function is called, the React Dev Tools should be able to detect
* "React" on the page and show the component tree.
*
* This function hooks into preact VNode creation in order to expose functional
* components correctly, so it should be called before the root component(s)
* are rendered.
*
* Returns a cleanup function which unregisters the hooks.
*/
export function initDevTools() {
if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
// React DevTools are not installed
return;
}
// Notify devtools when preact components are mounted, updated or unmounted
const bridge = createDevToolsBridge();
const nextAfterMount = options.afterMount;
options.afterMount = component => {
bridge.componentAdded(component);
if (nextAfterMount) nextAfterMount(component);
};
const nextAfterUpdate = options.afterUpdate;
options.afterUpdate = component => {
bridge.componentUpdated(component);
if (nextAfterUpdate) nextAfterUpdate(component);
};
const nextBeforeUnmount = options.beforeUnmount;
options.beforeUnmount = component => {
bridge.componentRemoved(component);
if (nextBeforeUnmount) nextBeforeUnmount(component);
};
// Notify devtools about this instance of "React"
__REACT_DEVTOOLS_GLOBAL_HOOK__.inject(bridge);
return () => {
options.afterMount = nextAfterMount;
options.afterUpdate = nextAfterUpdate;
options.beforeUnmount = nextBeforeUnmount;
};
}
preact-8.2.5/devtools/index.js 0000664 0000000 0000000 00000000075 13151101465 0016307 0 ustar 00root root 0000000 0000000 import { initDevTools } from './devtools';
initDevTools();
preact-8.2.5/package.json 0000664 0000000 0000000 00000013134 13151101465 0015271 0 ustar 00root root 0000000 0000000 {
"name": "preact",
"version": "8.2.5",
"description": "Fast 3kb React alternative with the same ES6 API. Components & Virtual DOM.",
"main": "dist/preact.js",
"jsnext:main": "dist/preact.esm.js",
"module": "dist/preact.esm.js",
"dev:main": "dist/preact.dev.js",
"minified:main": "dist/preact.min.js",
"scripts": {
"clean": "rimraf dist/ devtools.js devtools.js.map debug.js debug.js.map",
"copy-flow-definition": "copyfiles -f src/preact.js.flow dist",
"copy-typescript-definition": "copyfiles -f src/preact.d.ts dist",
"build": "npm-run-all --silent clean transpile copy-flow-definition copy-typescript-definition strip optimize minify size",
"transpile:main": "rollup -c config/rollup.config.js",
"transpile:devtools": "rollup -c config/rollup.config.devtools.js",
"transpile:esm": "rollup -c config/rollup.config.esm.js",
"transpile:debug": "babel debug/ -o debug.js -s",
"transpile": "npm-run-all transpile:main transpile:esm transpile:devtools transpile:debug",
"optimize": "uglifyjs dist/preact.dev.js -c conditionals=false,sequences=false,loops=false,join_vars=false,collapse_vars=false --pure-funcs=Object.defineProperty --mangle-props --mangle-regex=\"/^(_|normalizedNodeName|nextBase|prev[CPS]|_parentC)/\" --name-cache config/properties.json -b width=120,quote_style=3 -o dist/preact.js -p relative --in-source-map dist/preact.dev.js.map --source-map dist/preact.js.map",
"minify": "uglifyjs dist/preact.js -c collapse_vars,evaluate,screw_ie8,unsafe,loops=false,keep_fargs=false,pure_getters,unused,dead_code -m -o dist/preact.min.js -p relative --in-source-map dist/preact.js.map --source-map dist/preact.min.js.map",
"strip:main": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.dev.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.dev.js && jscodeshift --run-in-band -s -t config/codemod-let-name.js dist/preact.dev.js",
"strip:esm": "jscodeshift --run-in-band -s -t config/codemod-strip-tdz.js dist/preact.esm.js && jscodeshift --run-in-band -s -t config/codemod-const.js dist/preact.esm.js && jscodeshift --run-in-band -s -t config/codemod-let-name.js dist/preact.esm.js",
"strip": "npm-run-all strip:main strip:esm",
"size": "node -e \"process.stdout.write('gzip size: ')\" && gzip-size --raw dist/preact.min.js",
"test": "npm-run-all lint --parallel test:mocha test:karma test:ts test:size",
"test:ts": "tsc -p test/ts/",
"test:mocha": "mocha --recursive --require babel-register test/shared test/node",
"test:karma": "karma start test/karma.conf.js --single-run",
"test:mocha:watch": "npm run test:mocha -- --watch",
"test:karma:watch": "npm run test:karma -- no-single-run",
"test:size": "bundlesize",
"lint": "eslint debug devtools src test",
"prepublish": "npm run build",
"smart-release": "npm run build && npm test && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish",
"release": "cross-env npm run smart-release",
"postinstall": "node -e \"console.log('\\u001b[35m\\u001b[1mLove Preact? You can now donate to our open collective:\\u001b[22m\\u001b[39m\\n > \\u001b[34mhttps://opencollective.com/preact/donate\\u001b[0m')\""
},
"eslintConfig": {
"extends": "./config/eslint-config.js"
},
"typings": "./dist/preact.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/developit/preact.git"
},
"files": [
"devtools",
"debug",
"src",
"dist",
"devtools.js",
"devtools.js.map",
"debug.js",
"debug.js.map",
"typings.json"
],
"keywords": [
"preact",
"react",
"virtual dom",
"vdom",
"components",
"virtual",
"dom"
],
"author": "Jason Miller ",
"license": "MIT",
"bugs": {
"url": "https://github.com/developit/preact/issues"
},
"homepage": "https://github.com/developit/preact",
"devDependencies": {
"babel-cli": "^6.24.1",
"babel-core": "^6.24.1",
"babel-eslint": "^7.2.3",
"babel-loader": "^7.0.0",
"babel-plugin-transform-object-rest-spread": "^6.23.0",
"babel-plugin-transform-react-jsx": "^6.24.1",
"babel-preset-env": "^1.5.1",
"bundlesize": "^0.13.2",
"chai": "^3.4.1",
"copyfiles": "^1.0.0",
"core-js": "^2.4.1",
"coveralls": "^2.11.15",
"cross-env": "^3.1.3",
"diff": "^3.0.0",
"eslint": "^3.0.0",
"eslint-plugin-react": "^6.0.0",
"gzip-size-cli": "^2.0.0",
"isparta-loader": "^2.0.0",
"jscodeshift": "^0.3.25",
"karma": "^1.1.0",
"karma-babel-preprocessor": "^5.2.2",
"karma-chai": "^0.1.0",
"karma-chai-sinon": "^0.1.5",
"karma-chrome-launcher": "^2.0.0",
"karma-coverage": "^1.0.0",
"karma-mocha": "^1.1.1",
"karma-mocha-reporter": "^2.0.4",
"karma-phantomjs-launcher": "^1.0.1",
"karma-sauce-launcher": "^1.1.0",
"karma-source-map-support": "^1.2.0",
"karma-sourcemap-loader": "^0.3.6",
"karma-webpack": "^2.0.3",
"mocha": "^3.0.1",
"npm-run-all": "^4.0.0",
"phantomjs-prebuilt": "^2.1.7",
"rimraf": "^2.5.3",
"rollup": "^0.48.2",
"rollup-plugin-babel": "^3.0.2",
"rollup-plugin-memory": "^2.0.0",
"rollup-plugin-node-resolve": "^3.0.0",
"sinon": "^2.2.0",
"sinon-chai": "^2.8.0",
"typescript": "^2.2.2",
"uglify-js": "^2.7.5",
"webpack": "^2.4.1"
},
"greenkeeper": {
"ignore": [
"babel-cli",
"babel-core",
"babel-eslint",
"babel-loader",
"jscodeshift",
"rollup-plugin-babel"
]
},
"bundlesize": [
{
"path": "./dist/preact.min.js",
"threshold": "4Kb"
}
]
}
preact-8.2.5/src/ 0000775 0000000 0000000 00000000000 13151101465 0013570 5 ustar 00root root 0000000 0000000 preact-8.2.5/src/clone-element.js 0000664 0000000 0000000 00000000376 13151101465 0016663 0 ustar 00root root 0000000 0000000 import { extend } from './util';
import { h } from './h';
export function cloneElement(vnode, props) {
return h(
vnode.nodeName,
extend(extend({}, vnode.attributes), props),
arguments.length>2 ? [].slice.call(arguments, 2) : vnode.children
);
}
preact-8.2.5/src/component.js 0000664 0000000 0000000 00000004432 13151101465 0016133 0 ustar 00root root 0000000 0000000 import { FORCE_RENDER } from './constants';
import { extend } from './util';
import { renderComponent } from './vdom/component';
import { enqueueRender } from './render-queue';
/** Base Component class.
* Provides `setState()` and `forceUpdate()`, which trigger rendering.
* @public
*
* @example
* class MyFoo extends Component {
* render(props, state) {
* return ;
* }
* }
*/
export function Component(props, context) {
this._dirty = true;
/** @public
* @type {object}
*/
this.context = context;
/** @public
* @type {object}
*/
this.props = props;
/** @public
* @type {object}
*/
this.state = this.state || {};
}
extend(Component.prototype, {
/** Returns a `boolean` indicating if the component should re-render when receiving the given `props` and `state`.
* @param {object} nextProps
* @param {object} nextState
* @param {object} nextContext
* @returns {Boolean} should the component re-render
* @name shouldComponentUpdate
* @function
*/
/** Update component state by copying properties from `state` to `this.state`.
* @param {object} state A hash of state properties to update with new values
* @param {function} callback A function to be called once component state is updated
*/
setState(state, callback) {
let s = this.state;
if (!this.prevState) this.prevState = extend({}, s);
extend(s, typeof state==='function' ? state(s, this.props) : state);
if (callback) (this._renderCallbacks = (this._renderCallbacks || [])).push(callback);
enqueueRender(this);
},
/** Immediately perform a synchronous re-render of the component.
* @param {function} callback A function to be called after component is re-rendered.
* @private
*/
forceUpdate(callback) {
if (callback) (this._renderCallbacks = (this._renderCallbacks || [])).push(callback);
renderComponent(this, FORCE_RENDER);
},
/** Accepts `props` and `state`, and returns a new Virtual DOM tree to build.
* Virtual DOM is generally constructed via [JSX](http://jasonformat.com/wtf-is-jsx).
* @param {object} props Props (eg: JSX attributes) received from parent element/component
* @param {object} state The component's current state
* @param {object} context Context object (if a parent component has provided context)
* @returns VNode
*/
render() {}
});
preact-8.2.5/src/constants.js 0000664 0000000 0000000 00000000521 13151101465 0016140 0 ustar 00root root 0000000 0000000 // render modes
export const NO_RENDER = 0;
export const SYNC_RENDER = 1;
export const FORCE_RENDER = 2;
export const ASYNC_RENDER = 3;
export const ATTR_KEY = '__preactattr_';
// DOM properties that should NOT have "px" added when numeric
export const IS_NON_DIMENSIONAL = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i;
preact-8.2.5/src/dom/ 0000775 0000000 0000000 00000000000 13151101465 0014347 5 ustar 00root root 0000000 0000000 preact-8.2.5/src/dom/index.js 0000664 0000000 0000000 00000006560 13151101465 0016023 0 ustar 00root root 0000000 0000000 import { IS_NON_DIMENSIONAL } from '../constants';
import options from '../options';
/** Create an element with the given nodeName.
* @param {String} nodeName
* @param {Boolean} [isSvg=false] If `true`, creates an element within the SVG namespace.
* @returns {Element} node
*/
export function createNode(nodeName, isSvg) {
let node = isSvg ? document.createElementNS('http://www.w3.org/2000/svg', nodeName) : document.createElement(nodeName);
node.normalizedNodeName = nodeName;
return node;
}
/** Remove a child node from its parent if attached.
* @param {Element} node The node to remove
*/
export function removeNode(node) {
let parentNode = node.parentNode;
if (parentNode) parentNode.removeChild(node);
}
/** Set a named attribute on the given Node, with special behavior for some names and event handlers.
* If `value` is `null`, the attribute/handler will be removed.
* @param {Element} node An element to mutate
* @param {string} name The name/key to set, such as an event or attribute name
* @param {any} old The last value that was set for this name/node pair
* @param {any} value An attribute value, such as a function to be used as an event handler
* @param {Boolean} isSvg Are we currently diffing inside an svg?
* @private
*/
export function setAccessor(node, name, old, value, isSvg) {
if (name==='className') name = 'class';
if (name==='key') {
// ignore
}
else if (name==='ref') {
if (old) old(null);
if (value) value(node);
}
else if (name==='class' && !isSvg) {
node.className = value || '';
}
else if (name==='style') {
if (!value || typeof value==='string' || typeof old==='string') {
node.style.cssText = value || '';
}
if (value && typeof value==='object') {
if (typeof old!=='string') {
for (let i in old) if (!(i in value)) node.style[i] = '';
}
for (let i in value) {
node.style[i] = typeof value[i]==='number' && IS_NON_DIMENSIONAL.test(i)===false ? (value[i]+'px') : value[i];
}
}
}
else if (name==='dangerouslySetInnerHTML') {
if (value) node.innerHTML = value.__html || '';
}
else if (name[0]=='o' && name[1]=='n') {
let useCapture = name !== (name=name.replace(/Capture$/, ''));
name = name.toLowerCase().substring(2);
if (value) {
if (!old) node.addEventListener(name, eventProxy, useCapture);
}
else {
node.removeEventListener(name, eventProxy, useCapture);
}
(node._listeners || (node._listeners = {}))[name] = value;
}
else if (name!=='list' && name!=='type' && !isSvg && name in node) {
setProperty(node, name, value==null ? '' : value);
if (value==null || value===false) node.removeAttribute(name);
}
else {
let ns = isSvg && (name !== (name = name.replace(/^xlink\:?/, '')));
if (value==null || value===false) {
if (ns) node.removeAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase());
else node.removeAttribute(name);
}
else if (typeof value!=='function') {
if (ns) node.setAttributeNS('http://www.w3.org/1999/xlink', name.toLowerCase(), value);
else node.setAttribute(name, value);
}
}
}
/** Attempt to set a DOM property to the given value.
* IE & FF throw for certain property-value combinations.
*/
function setProperty(node, name, value) {
try {
node[name] = value;
} catch (e) { }
}
/** Proxy an event to hooked event handlers
* @private
*/
function eventProxy(e) {
return this._listeners[e.type](options.event && options.event(e) || e);
}
preact-8.2.5/src/h.js 0000664 0000000 0000000 00000002743 13151101465 0014363 0 ustar 00root root 0000000 0000000 import { VNode } from './vnode';
import options from './options';
const stack = [];
const EMPTY_CHILDREN = [];
/** JSX/hyperscript reviver
* Benchmarks: https://esbench.com/bench/57ee8f8e330ab09900a1a1a0
* @see http://jasonformat.com/wtf-is-jsx
* @public
*/
export function h(nodeName, attributes) {
let children=EMPTY_CHILDREN, lastSimple, child, simple, i;
for (i=arguments.length; i-- > 2; ) {
stack.push(arguments[i]);
}
if (attributes && attributes.children!=null) {
if (!stack.length) stack.push(attributes.children);
delete attributes.children;
}
while (stack.length) {
if ((child = stack.pop()) && child.pop!==undefined) {
for (i=child.length; i--; ) stack.push(child[i]);
}
else {
if (typeof child==='boolean') child = null;
if ((simple = typeof nodeName!=='function')) {
if (child==null) child = '';
else if (typeof child==='number') child = String(child);
else if (typeof child!=='string') simple = false;
}
if (simple && lastSimple) {
children[children.length-1] += child;
}
else if (children===EMPTY_CHILDREN) {
children = [child];
}
else {
children.push(child);
}
lastSimple = simple;
}
}
let p = new VNode();
p.nodeName = nodeName;
p.children = children;
p.attributes = attributes==null ? undefined : attributes;
p.key = attributes==null ? undefined : attributes.key;
// if a "vnode hook" is defined, pass every created VNode to it
if (options.vnode!==undefined) options.vnode(p);
return p;
}
preact-8.2.5/src/options.js 0000664 0000000 0000000 00000001252 13151101465 0015621 0 ustar 00root root 0000000 0000000 /** Global options
* @public
* @namespace options {Object}
*/
export default {
/** If `true`, `prop` changes trigger synchronous component updates.
* @name syncComponentUpdates
* @type Boolean
* @default true
*/
//syncComponentUpdates: true,
/** Processes all created VNodes.
* @param {VNode} vnode A newly-created VNode to normalize/process
*/
//vnode(vnode) { }
/** Hook invoked after a component is mounted. */
// afterMount(component) { }
/** Hook invoked after the DOM is updated with a component's latest render. */
// afterUpdate(component) { }
/** Hook invoked immediately before a component is unmounted. */
// beforeUnmount(component) { }
};
preact-8.2.5/src/preact.d.ts 0000664 0000000 0000000 00000050074 13151101465 0015646 0 ustar 00root root 0000000 0000000 declare namespace preact {
interface ComponentProps | FunctionalComponent> {
children?:JSX.Element[];
key?:string | number | any;
ref?:(el: C) => void;
}
interface DangerouslySetInnerHTML {
__html: string;
}
interface PreactHTMLAttributes {
dangerouslySetInnerHTML?:DangerouslySetInnerHTML;
key?:string;
ref?:(el?: Element) => void;
}
interface VNode {
nodeName:ComponentConstructor|string;
attributes:{[name:string]:any};
children:VNode[];
key:string;
}
interface ComponentLifecycle {
componentWillMount?():void;
componentDidMount?():void;
componentWillUnmount?():void;
componentWillReceiveProps?(nextProps:PropsType,nextContext:any):void;
shouldComponentUpdate?(nextProps:PropsType,nextState:StateType,nextContext:any):boolean;
componentWillUpdate?(nextProps:PropsType,nextState:StateType,nextContext:any):void;
componentDidUpdate?(previousProps:PropsType,previousState:StateType,previousContext:any):void;
}
interface FunctionalComponent {
(props?:PropsType & ComponentProps, context?:any):JSX.Element;
displayName?:string;
defaultProps?:any;
}
interface ComponentConstructor {
new (props?:PropsType, context?: any):Component;
}
// Type alias for a component considered generally, whether stateless or stateful.
type AnyComponent = FunctionalComponent | typeof Component;
abstract class Component {
constructor(props?:PropsType, context?:any);
static displayName?:string;
static defaultProps?:any;
state:StateType;
props:PropsType & ComponentProps;
context:any;
base:HTMLElement;
linkState:(name:string) => (event: Event) => void;
setState(state:Pick, callback?:() => void):void;
setState(fn:(prevState:StateType, props:PropsType) => Pick, callback?:() => void):void;
forceUpdate(callback?:() => void): void;
abstract render(props?:PropsType & ComponentProps, state?:StateType, context?:any):JSX.Element|null;
}
interface Component extends ComponentLifecycle { }
function h(node:ComponentConstructor | FunctionalComponent, params:PropsType, ...children:(JSX.Element|JSX.Element[]|string)[]):JSX.Element;
function h(node:string, params:JSX.HTMLAttributes&JSX.SVGAttributes&{[propName: string]: any}, ...children:(JSX.Element|JSX.Element[]|string)[]):JSX.Element;
function render(node:JSX.Element, parent:Element|Document, mergeWith?:Element):Element;
function rerender():void;
function cloneElement(element:JSX.Element, props:any):JSX.Element;
var options:{
syncComponentUpdates?:boolean;
debounceRendering?:(render:() => void) => void;
vnode?:(vnode:VNode) => void;
event?:(event:Event) => Event;
};
}
declare module "preact" {
export = preact;
}
declare module "preact/devtools" {
// Empty. This module initializes the React Developer Tools integration
// when imported.
}
declare namespace JSX {
interface Element extends preact.VNode {
}
interface ElementClass extends preact.Component {
}
interface ElementAttributesProperty {
props:any;
}
interface SVGAttributes extends HTMLAttributes {
accentHeight?:number | string;
accumulate?:"none" | "sum";
additive?:"replace" | "sum";
alignmentBaseline?:"auto" | "baseline" | "before-edge" | "text-before-edge" | "middle" | "central" | "after-edge" | "text-after-edge" | "ideographic" | "alphabetic" | "hanging" | "mathematical" | "inherit";
allowReorder?:"no" | "yes";
alphabetic?:number | string;
amplitude?:number | string;
arabicForm?:"initial" | "medial" | "terminal" | "isolated";
ascent?:number | string;
attributeName?:string;
attributeType?:string;
autoReverse?:number | string;
azimuth?:number | string;
baseFrequency?:number | string;
baselineShift?:number | string;
baseProfile?:number | string;
bbox?:number | string;
begin?:number | string;
bias?:number | string;
by?:number | string;
calcMode?:number | string;
capHeight?:number | string;
clip?:number | string;
clipPath?:string;
clipPathUnits?:number | string;
clipRule?:number | string;
colorInterpolation?:number | string;
colorInterpolationFilters?:"auto" | "sRGB" | "linearRGB" | "inherit";
colorProfile?:number | string;
colorRendering?:number | string;
contentScriptType?:number | string;
contentStyleType?:number | string;
cursor?:number | string;
cx?:number | string;
cy?:number | string;
d?:string;
decelerate?:number | string;
descent?:number | string;
diffuseConstant?:number | string;
direction?:number | string;
display?:number | string;
divisor?:number | string;
dominantBaseline?:number | string;
dur?:number | string;
dx?:number | string;
dy?:number | string;
edgeMode?:number | string;
elevation?:number | string;
enableBackground?:number | string;
end?:number | string;
exponent?:number | string;
externalResourcesRequired?:number | string;
fill?:string;
fillOpacity?:number | string;
fillRule?:"nonzero" | "evenodd" | "inherit";
filter?:string;
filterRes?:number | string;
filterUnits?:number | string;
floodColor?:number | string;
floodOpacity?:number | string;
focusable?:number | string;
fontFamily?:string;
fontSize?:number | string;
fontSizeAdjust?:number | string;
fontStretch?:number | string;
fontStyle?:number | string;
fontVariant?:number | string;
fontWeight?:number | string;
format?:number | string;
from?:number | string;
fx?:number | string;
fy?:number | string;
g1?:number | string;
g2?:number | string;
glyphName?:number | string;
glyphOrientationHorizontal?:number | string;
glyphOrientationVertical?:number | string;
glyphRef?:number | string;
gradientTransform?:string;
gradientUnits?:string;
hanging?:number | string;
horizAdvX?:number | string;
horizOriginX?:number | string;
ideographic?:number | string;
imageRendering?:number | string;
in2?:number | string;
in?:string;
intercept?:number | string;
k1?:number | string;
k2?:number | string;
k3?:number | string;
k4?:number | string;
k?:number | string;
kernelMatrix?:number | string;
kernelUnitLength?:number | string;
kerning?:number | string;
keyPoints?:number | string;
keySplines?:number | string;
keyTimes?:number | string;
lengthAdjust?:number | string;
letterSpacing?:number | string;
lightingColor?:number | string;
limitingConeAngle?:number | string;
local?:number | string;
markerEnd?:string;
markerHeight?:number | string;
markerMid?:string;
markerStart?:string;
markerUnits?:number | string;
markerWidth?:number | string;
mask?:string;
maskContentUnits?:number | string;
maskUnits?:number | string;
mathematical?:number | string;
mode?:number | string;
numOctaves?:number | string;
offset?:number | string;
opacity?:number | string;
operator?:number | string;
order?:number | string;
orient?:number | string;
orientation?:number | string;
origin?:number | string;
overflow?:number | string;
overlinePosition?:number | string;
overlineThickness?:number | string;
paintOrder?:number | string;
panose1?:number | string;
pathLength?:number | string;
patternContentUnits?:string;
patternTransform?:number | string;
patternUnits?:string;
pointerEvents?:number | string;
points?:string;
pointsAtX?:number | string;
pointsAtY?:number | string;
pointsAtZ?:number | string;
preserveAlpha?:number | string;
preserveAspectRatio?:string;
primitiveUnits?:number | string;
r?:number | string;
radius?:number | string;
refX?:number | string;
refY?:number | string;
renderingIntent?:number | string;
repeatCount?:number | string;
repeatDur?:number | string;
requiredExtensions?:number | string;
requiredFeatures?:number | string;
restart?:number | string;
result?:string;
rotate?:number | string;
rx?:number | string;
ry?:number | string;
scale?:number | string;
seed?:number | string;
shapeRendering?:number | string;
slope?:number | string;
spacing?:number | string;
specularConstant?:number | string;
specularExponent?:number | string;
speed?:number | string;
spreadMethod?:string;
startOffset?:number | string;
stdDeviation?:number | string;
stemh?:number | string;
stemv?:number | string;
stitchTiles?:number | string;
stopColor?:string;
stopOpacity?:number | string;
strikethroughPosition?:number | string;
strikethroughThickness?:number | string;
string?:number | string;
stroke?:string;
strokeDasharray?:string | number;
strokeDashoffset?:string | number;
strokeLinecap?:"butt" | "round" | "square" | "inherit";
strokeLinejoin?:"miter" | "round" | "bevel" | "inherit";
strokeMiterlimit?:string;
strokeOpacity?:number | string;
strokeWidth?:number | string;
surfaceScale?:number | string;
systemLanguage?:number | string;
tableValues?:number | string;
targetX?:number | string;
targetY?:number | string;
textAnchor?:string;
textDecoration?:number | string;
textLength?:number | string;
textRendering?:number | string;
to?:number | string;
transform?:string;
u1?:number | string;
u2?:number | string;
underlinePosition?:number | string;
underlineThickness?:number | string;
unicode?:number | string;
unicodeBidi?:number | string;
unicodeRange?:number | string;
unitsPerEm?:number | string;
vAlphabetic?:number | string;
values?:string;
vectorEffect?:number | string;
version?:string;
vertAdvY?:number | string;
vertOriginX?:number | string;
vertOriginY?:number | string;
vHanging?:number | string;
vIdeographic?:number | string;
viewBox?:string;
viewTarget?:number | string;
visibility?:number | string;
vMathematical?:number | string;
widths?:number | string;
wordSpacing?:number | string;
writingMode?:number | string;
x1?:number | string;
x2?:number | string;
x?:number | string;
xChannelSelector?:string;
xHeight?:number | string;
xlinkActuate?:string;
xlinkArcrole?:string;
xlinkHref?:string;
xlinkRole?:string;
xlinkShow?:string;
xlinkTitle?:string;
xlinkType?:string;
xmlBase?:string;
xmlLang?:string;
xmlns?:string;
xmlnsXlink?:string;
xmlSpace?:string;
y1?:number | string;
y2?:number | string;
y?:number | string;
yChannelSelector?:string;
z?:number | string;
zoomAndPan?:string;
}
interface PathAttributes {
d:string;
}
interface EventHandler {
(event:E):void;
}
type ClipboardEventHandler = EventHandler;
type CompositionEventHandler = EventHandler;
type DragEventHandler = EventHandler;
type FocusEventHandler = EventHandler;
type KeyboardEventHandler = EventHandler;
type MouseEventHandler = EventHandler;
type TouchEventHandler = EventHandler;
type UIEventHandler = EventHandler;
type WheelEventHandler = EventHandler;
type AnimationEventHandler = EventHandler;
type TransitionEventHandler = EventHandler;
type GenericEventHandler = EventHandler;
interface DOMAttributes {
// Image Events
onLoad?:GenericEventHandler;
// Clipboard Events
onCopy?:ClipboardEventHandler;
onCut?:ClipboardEventHandler;
onPaste?:ClipboardEventHandler;
// Composition Events
onCompositionEnd?:CompositionEventHandler;
onCompositionStart?:CompositionEventHandler;
onCompositionUpdate?:CompositionEventHandler;
// Focus Events
onFocus?:FocusEventHandler;
onBlur?:FocusEventHandler;
// Form Events
onChange?:GenericEventHandler;
onInput?:GenericEventHandler;
onSearch?:GenericEventHandler;
onSubmit?:GenericEventHandler;
// Keyboard Events
onKeyDown?:KeyboardEventHandler;
onKeyPress?:KeyboardEventHandler;
onKeyUp?:KeyboardEventHandler;
// Media Events
onAbort?:GenericEventHandler;
onCanPlay?:GenericEventHandler;
onCanPlayThrough?:GenericEventHandler;
onDurationChange?:GenericEventHandler;
onEmptied?:GenericEventHandler;
onEncrypted?:GenericEventHandler;
onEnded?:GenericEventHandler;
onLoadedData?:GenericEventHandler;
onLoadedMetadata?:GenericEventHandler;
onLoadStart?:GenericEventHandler;
onPause?:GenericEventHandler;
onPlay?:GenericEventHandler;
onPlaying?:GenericEventHandler;
onProgress?:GenericEventHandler;
onRateChange?:GenericEventHandler;
onSeeked?:GenericEventHandler;
onSeeking?:GenericEventHandler;
onStalled?:GenericEventHandler;
onSuspend?:GenericEventHandler;
onTimeUpdate?:GenericEventHandler;
onVolumeChange?:GenericEventHandler;
onWaiting?:GenericEventHandler;
// MouseEvents
onClick?:MouseEventHandler;
onContextMenu?:MouseEventHandler;
onDblClick?: MouseEventHandler;
onDrag?:DragEventHandler;
onDragEnd?:DragEventHandler;
onDragEnter?:DragEventHandler;
onDragExit?:DragEventHandler;
onDragLeave?:DragEventHandler;
onDragOver?:DragEventHandler;
onDragStart?:DragEventHandler;
onDrop?:DragEventHandler;
onMouseDown?:MouseEventHandler;
onMouseEnter?:MouseEventHandler;
onMouseLeave?:MouseEventHandler;
onMouseMove?:MouseEventHandler;
onMouseOut?:MouseEventHandler;
onMouseOver?:MouseEventHandler;
onMouseUp?:MouseEventHandler;
// Selection Events
onSelect?:GenericEventHandler;
// Touch Events
onTouchCancel?:TouchEventHandler;
onTouchEnd?:TouchEventHandler;
onTouchMove?:TouchEventHandler;
onTouchStart?:TouchEventHandler;
// UI Events
onScroll?:UIEventHandler;
// Wheel Events
onWheel?:WheelEventHandler;
// Animation Events
onAnimationStart?:AnimationEventHandler;
onAnimationEnd?:AnimationEventHandler;
onAnimationIteration?:AnimationEventHandler;
// Transition Events
onTransitionEnd?:TransitionEventHandler;
}
interface HTMLAttributes extends preact.PreactHTMLAttributes, DOMAttributes {
// Standard HTML Attributes
accept?:string;
acceptCharset?:string;
accessKey?:string;
action?:string;
allowFullScreen?:boolean;
allowTransparency?:boolean;
alt?:string;
async?:boolean;
autocomplete?:string;
autofocus?:boolean;
autoPlay?:boolean;
capture?:boolean;
cellPadding?:number | string;
cellSpacing?:number | string;
charSet?:string;
challenge?:string;
checked?:boolean;
class?:string | { [key:string]: boolean };
className?:string | { [key:string]: boolean };
cols?:number;
colSpan?:number;
content?:string;
contentEditable?:boolean;
contextMenu?:string;
controls?:boolean;
coords?:string;
crossOrigin?:string;
data?:string;
dateTime?:string;
default?:boolean;
defer?:boolean;
dir?:string;
disabled?:boolean;
download?:any;
draggable?:boolean;
encType?:string;
form?:string;
formAction?:string;
formEncType?:string;
formMethod?:string;
formNoValidate?:boolean;
formTarget?:string;
frameBorder?:number | string;
headers?:string;
height?:number | string;
hidden?:boolean;
high?:number;
href?:string;
hrefLang?:string;
for?:string;
httpEquiv?:string;
icon?:string;
id?:string;
inputMode?:string;
integrity?:string;
is?:string;
keyParams?:string;
keyType?:string;
kind?:string;
label?:string;
lang?:string;
list?:string;
loop?:boolean;
low?:number;
manifest?:string;
marginHeight?:number;
marginWidth?:number;
max?:number | string;
maxLength?:number;
media?:string;
mediaGroup?:string;
method?:string;
min?:number | string;
minLength?:number;
multiple?:boolean;
muted?:boolean;
name?:string;
noValidate?:boolean;
open?:boolean;
optimum?:number;
pattern?:string;
placeholder?:string;
poster?:string;
preload?:string;
radioGroup?:string;
readOnly?:boolean;
rel?:string;
required?:boolean;
role?:string;
rows?:number;
rowSpan?:number;
sandbox?:string;
scope?:string;
scoped?:boolean;
scrolling?:string;
seamless?:boolean;
selected?:boolean;
shape?:string;
size?:number;
sizes?:string;
slot?:string;
span?:number;
spellCheck?:boolean;
src?:string;
srcset?:string;
srcDoc?:string;
srcLang?:string;
srcSet?:string;
start?:number;
step?:number | string;
style?:any;
summary?:string;
tabIndex?:number;
target?:string;
title?:string;
type?:string;
useMap?:string;
value?:string | string[];
width?:number | string;
wmode?:string;
wrap?:string;
// RDFa Attributes
about?:string;
datatype?:string;
inlist?:any;
prefix?:string;
property?:string;
resource?:string;
typeof?:string;
vocab?:string;
}
interface IntrinsicElements {
// HTML
a:HTMLAttributes;
abbr:HTMLAttributes;
address:HTMLAttributes;
area:HTMLAttributes;
article:HTMLAttributes;
aside:HTMLAttributes;
audio:HTMLAttributes;
b:HTMLAttributes;
base:HTMLAttributes;
bdi:HTMLAttributes;
bdo:HTMLAttributes;
big:HTMLAttributes;
blockquote:HTMLAttributes;
body:HTMLAttributes;
br:HTMLAttributes;
button:HTMLAttributes;
canvas:HTMLAttributes;
caption:HTMLAttributes;
cite:HTMLAttributes;
code:HTMLAttributes;
col:HTMLAttributes;
colgroup:HTMLAttributes;
data:HTMLAttributes;
datalist:HTMLAttributes;
dd:HTMLAttributes;
del:HTMLAttributes;
details:HTMLAttributes;
dfn:HTMLAttributes;
dialog:HTMLAttributes;
div:HTMLAttributes;
dl:HTMLAttributes;
dt:HTMLAttributes;
em:HTMLAttributes;
embed:HTMLAttributes;
fieldset:HTMLAttributes;
figcaption:HTMLAttributes;
figure:HTMLAttributes;
footer:HTMLAttributes;
form:HTMLAttributes;
h1:HTMLAttributes;
h2:HTMLAttributes;
h3:HTMLAttributes;
h4:HTMLAttributes;
h5:HTMLAttributes;
h6:HTMLAttributes;
head:HTMLAttributes;
header:HTMLAttributes;
hr:HTMLAttributes;
html:HTMLAttributes;
i:HTMLAttributes;
iframe:HTMLAttributes;
img:HTMLAttributes;
input:HTMLAttributes;
ins:HTMLAttributes;
kbd:HTMLAttributes;
keygen:HTMLAttributes;
label:HTMLAttributes;
legend:HTMLAttributes;
li:HTMLAttributes;
link:HTMLAttributes;
main:HTMLAttributes;
map:HTMLAttributes;
mark:HTMLAttributes;
menu:HTMLAttributes;
menuitem:HTMLAttributes;
meta:HTMLAttributes;
meter:HTMLAttributes;
nav:HTMLAttributes;
noscript:HTMLAttributes;
object:HTMLAttributes;
ol:HTMLAttributes;
optgroup:HTMLAttributes;
option:HTMLAttributes;
output:HTMLAttributes;
p:HTMLAttributes;
param:HTMLAttributes;
picture:HTMLAttributes;
pre:HTMLAttributes;
progress:HTMLAttributes;
q:HTMLAttributes;
rp:HTMLAttributes;
rt:HTMLAttributes;
ruby:HTMLAttributes;
s:HTMLAttributes;
samp:HTMLAttributes;
script:HTMLAttributes;
section:HTMLAttributes;
select:HTMLAttributes;
slot:HTMLAttributes;
small:HTMLAttributes;
source:HTMLAttributes;
span:HTMLAttributes;
strong:HTMLAttributes;
style:HTMLAttributes;
sub:HTMLAttributes;
summary:HTMLAttributes;
sup:HTMLAttributes;
table:HTMLAttributes;
tbody:HTMLAttributes;
td:HTMLAttributes;
textarea:HTMLAttributes;
tfoot:HTMLAttributes;
th:HTMLAttributes;
thead:HTMLAttributes;
time:HTMLAttributes;
title:HTMLAttributes;
tr:HTMLAttributes;
track:HTMLAttributes;
u:HTMLAttributes;
ul:HTMLAttributes;
"var":HTMLAttributes;
video:HTMLAttributes;
wbr:HTMLAttributes;
//SVG
svg:SVGAttributes;
animate:SVGAttributes;
circle:SVGAttributes;
clipPath:SVGAttributes;
defs:SVGAttributes;
ellipse:SVGAttributes;
feBlend:SVGAttributes;
feColorMatrix:SVGAttributes;
feComponentTransfer:SVGAttributes;
feComposite:SVGAttributes;
feConvolveMatrix:SVGAttributes;
feDiffuseLighting:SVGAttributes;
feDisplacementMap:SVGAttributes;
feFlood:SVGAttributes;
feGaussianBlur:SVGAttributes;
feImage:SVGAttributes;
feMerge:SVGAttributes;
feMergeNode:SVGAttributes;
feMorphology:SVGAttributes;
feOffset:SVGAttributes;
feSpecularLighting:SVGAttributes;
feTile:SVGAttributes;
feTurbulence:SVGAttributes;
filter:SVGAttributes;
foreignObject:SVGAttributes;
g:SVGAttributes;
image:SVGAttributes;
line:SVGAttributes;
linearGradient:SVGAttributes;
marker:SVGAttributes;
mask:SVGAttributes;
path:SVGAttributes;
pattern:SVGAttributes;
polygon:SVGAttributes;
polyline:SVGAttributes;
radialGradient:SVGAttributes;
rect:SVGAttributes;
stop:SVGAttributes;
symbol:SVGAttributes;
text:SVGAttributes;
tspan:SVGAttributes;
use:SVGAttributes;
}
}
preact-8.2.5/src/preact.js 0000664 0000000 0000000 00000000657 13151101465 0015414 0 ustar 00root root 0000000 0000000 import { h, h as createElement } from './h';
import { cloneElement } from './clone-element';
import { Component } from './component';
import { render } from './render';
import { rerender } from './render-queue';
import options from './options';
export default {
h,
createElement,
cloneElement,
Component,
render,
rerender,
options
};
export {
h,
createElement,
cloneElement,
Component,
render,
rerender,
options
};
preact-8.2.5/src/preact.js.flow 0000664 0000000 0000000 00000000420 13151101465 0016346 0 ustar 00root root 0000000 0000000 /* @flow */
import { createElement as h, cloneElement, Component, render } from 'react';
export { h, cloneElement, Component, render };
export default { h, cloneElement, Component, render };
declare export function rerender(): void;
declare export var options: Object;
preact-8.2.5/src/render-queue.js 0000664 0000000 0000000 00000001000 13151101465 0016516 0 ustar 00root root 0000000 0000000 import options from './options';
import { defer } from './util';
import { renderComponent } from './vdom/component';
/** Managed queue of dirty components to be re-rendered */
let items = [];
export function enqueueRender(component) {
if (!component._dirty && (component._dirty = true) && items.push(component)==1) {
(options.debounceRendering || defer)(rerender);
}
}
export function rerender() {
let p, list = items;
items = [];
while ( (p = list.pop()) ) {
if (p._dirty) renderComponent(p);
}
}
preact-8.2.5/src/render.js 0000664 0000000 0000000 00000001231 13151101465 0015402 0 ustar 00root root 0000000 0000000 import { diff } from './vdom/diff';
/** Render JSX into a `parent` Element.
* @param {VNode} vnode A (JSX) VNode to render
* @param {Element} parent DOM element to render into
* @param {Element} [merge] Attempt to re-use an existing DOM tree rooted at `merge`
* @public
*
* @example
* // render a div into :
* render(
hello!
, document.body);
*
* @example
* // render a "Thing" component into #foo:
* const Thing = ({ name }) => { name };
* render(, document.querySelector('#foo'));
*/
export function render(vnode, parent, merge) {
return diff(merge, vnode, {}, false, parent, false);
}
preact-8.2.5/src/util.js 0000664 0000000 0000000 00000000571 13151101465 0015106 0 ustar 00root root 0000000 0000000 /** Copy own-properties from `props` onto `obj`.
* @returns obj
* @private
*/
export function extend(obj, props) {
for (let i in props) obj[i] = props[i];
return obj;
}
/** Call a function asynchronously, as soon as possible.
* @param {Function} callback
*/
export const defer = typeof Promise=='function' ? Promise.resolve().then.bind(Promise.resolve()) : setTimeout;
preact-8.2.5/src/vdom/ 0000775 0000000 0000000 00000000000 13151101465 0014535 5 ustar 00root root 0000000 0000000 preact-8.2.5/src/vdom/component-recycler.js 0000664 0000000 0000000 00000002327 13151101465 0020707 0 ustar 00root root 0000000 0000000 import { Component } from '../component';
/** Retains a pool of Components for re-use, keyed on component name.
* Note: since component names are not unique or even necessarily available, these are primarily a form of sharding.
* @private
*/
const components = {};
/** Reclaim a component for later re-use by the recycler. */
export function collectComponent(component) {
let name = component.constructor.name;
(components[name] || (components[name] = [])).push(component);
}
/** Create a component. Normalizes differences between PFC's and classful Components. */
export function createComponent(Ctor, props, context) {
let list = components[Ctor.name],
inst;
if (Ctor.prototype && Ctor.prototype.render) {
inst = new Ctor(props, context);
Component.call(inst, props, context);
}
else {
inst = new Component(props, context);
inst.constructor = Ctor;
inst.render = doRender;
}
if (list) {
for (let i=list.length; i--; ) {
if (list[i].constructor===Ctor) {
inst.nextBase = list[i].nextBase;
list.splice(i, 1);
break;
}
}
}
return inst;
}
/** The `.render()` method for a PFC backing instance. */
function doRender(props, state, context) {
return this.constructor(props, context);
}
preact-8.2.5/src/vdom/component.js 0000664 0000000 0000000 00000017712 13151101465 0017105 0 ustar 00root root 0000000 0000000 import { SYNC_RENDER, NO_RENDER, FORCE_RENDER, ASYNC_RENDER, ATTR_KEY } from '../constants';
import options from '../options';
import { extend } from '../util';
import { enqueueRender } from '../render-queue';
import { getNodeProps } from './index';
import { diff, mounts, diffLevel, flushMounts, recollectNodeTree, removeChildren } from './diff';
import { createComponent, collectComponent } from './component-recycler';
import { removeNode } from '../dom/index';
/** Set a component's `props` (generally derived from JSX attributes).
* @param {Object} props
* @param {Object} [opts]
* @param {boolean} [opts.renderSync=false] If `true` and {@link options.syncComponentUpdates} is `true`, triggers synchronous rendering.
* @param {boolean} [opts.render=true] If `false`, no render will be triggered.
*/
export function setComponentProps(component, props, opts, context, mountAll) {
if (component._disable) return;
component._disable = true;
if ((component.__ref = props.ref)) delete props.ref;
if ((component.__key = props.key)) delete props.key;
if (!component.base || mountAll) {
if (component.componentWillMount) component.componentWillMount();
}
else if (component.componentWillReceiveProps) {
component.componentWillReceiveProps(props, context);
}
if (context && context!==component.context) {
if (!component.prevContext) component.prevContext = component.context;
component.context = context;
}
if (!component.prevProps) component.prevProps = component.props;
component.props = props;
component._disable = false;
if (opts!==NO_RENDER) {
if (opts===SYNC_RENDER || options.syncComponentUpdates!==false || !component.base) {
renderComponent(component, SYNC_RENDER, mountAll);
}
else {
enqueueRender(component);
}
}
if (component.__ref) component.__ref(component);
}
/** Render a Component, triggering necessary lifecycle events and taking High-Order Components into account.
* @param {Component} component
* @param {Object} [opts]
* @param {boolean} [opts.build=false] If `true`, component will build and store a DOM node if not already associated with one.
* @private
*/
export function renderComponent(component, opts, mountAll, isChild) {
if (component._disable) return;
let props = component.props,
state = component.state,
context = component.context,
previousProps = component.prevProps || props,
previousState = component.prevState || state,
previousContext = component.prevContext || context,
isUpdate = component.base,
nextBase = component.nextBase,
initialBase = isUpdate || nextBase,
initialChildComponent = component._component,
skip = false,
rendered, inst, cbase;
// if updating
if (isUpdate) {
component.props = previousProps;
component.state = previousState;
component.context = previousContext;
if (opts!==FORCE_RENDER
&& component.shouldComponentUpdate
&& component.shouldComponentUpdate(props, state, context) === false) {
skip = true;
}
else if (component.componentWillUpdate) {
component.componentWillUpdate(props, state, context);
}
component.props = props;
component.state = state;
component.context = context;
}
component.prevProps = component.prevState = component.prevContext = component.nextBase = null;
component._dirty = false;
if (!skip) {
rendered = component.render(props, state, context);
// context to pass to the child, can be updated via (grand-)parent component
if (component.getChildContext) {
context = extend(extend({}, context), component.getChildContext());
}
let childComponent = rendered && rendered.nodeName,
toUnmount, base;
if (typeof childComponent==='function') {
// set up high order component link
let childProps = getNodeProps(rendered);
inst = initialChildComponent;
if (inst && inst.constructor===childComponent && childProps.key==inst.__key) {
setComponentProps(inst, childProps, SYNC_RENDER, context, false);
}
else {
toUnmount = inst;
component._component = inst = createComponent(childComponent, childProps, context);
inst.nextBase = inst.nextBase || nextBase;
inst._parentComponent = component;
setComponentProps(inst, childProps, NO_RENDER, context, false);
renderComponent(inst, SYNC_RENDER, mountAll, true);
}
base = inst.base;
}
else {
cbase = initialBase;
// destroy high order component link
toUnmount = initialChildComponent;
if (toUnmount) {
cbase = component._component = null;
}
if (initialBase || opts===SYNC_RENDER) {
if (cbase) cbase._component = null;
base = diff(cbase, rendered, context, mountAll || !isUpdate, initialBase && initialBase.parentNode, true);
}
}
if (initialBase && base!==initialBase && inst!==initialChildComponent) {
let baseParent = initialBase.parentNode;
if (baseParent && base!==baseParent) {
baseParent.replaceChild(base, initialBase);
if (!toUnmount) {
initialBase._component = null;
recollectNodeTree(initialBase, false);
}
}
}
if (toUnmount) {
unmountComponent(toUnmount);
}
component.base = base;
if (base && !isChild) {
let componentRef = component,
t = component;
while ((t=t._parentComponent)) {
(componentRef = t).base = base;
}
base._component = componentRef;
base._componentConstructor = componentRef.constructor;
}
}
if (!isUpdate || mountAll) {
mounts.unshift(component);
}
else if (!skip) {
// Ensure that pending componentDidMount() hooks of child components
// are called before the componentDidUpdate() hook in the parent.
// Note: disabled as it causes duplicate hooks, see https://github.com/developit/preact/issues/750
// flushMounts();
if (component.componentDidUpdate) {
component.componentDidUpdate(previousProps, previousState, previousContext);
}
if (options.afterUpdate) options.afterUpdate(component);
}
if (component._renderCallbacks!=null) {
while (component._renderCallbacks.length) component._renderCallbacks.pop().call(component);
}
if (!diffLevel && !isChild) flushMounts();
}
/** Apply the Component referenced by a VNode to the DOM.
* @param {Element} dom The DOM node to mutate
* @param {VNode} vnode A Component-referencing VNode
* @returns {Element} dom The created/mutated element
* @private
*/
export function buildComponentFromVNode(dom, vnode, context, mountAll) {
let c = dom && dom._component,
originalComponent = c,
oldDom = dom,
isDirectOwner = c && dom._componentConstructor===vnode.nodeName,
isOwner = isDirectOwner,
props = getNodeProps(vnode);
while (c && !isOwner && (c=c._parentComponent)) {
isOwner = c.constructor===vnode.nodeName;
}
if (c && isOwner && (!mountAll || c._component)) {
setComponentProps(c, props, ASYNC_RENDER, context, mountAll);
dom = c.base;
}
else {
if (originalComponent && !isDirectOwner) {
unmountComponent(originalComponent);
dom = oldDom = null;
}
c = createComponent(vnode.nodeName, props, context);
if (dom && !c.nextBase) {
c.nextBase = dom;
// passing dom/oldDom as nextBase will recycle it if unused, so bypass recycling on L229:
oldDom = null;
}
setComponentProps(c, props, SYNC_RENDER, context, mountAll);
dom = c.base;
if (oldDom && dom!==oldDom) {
oldDom._component = null;
recollectNodeTree(oldDom, false);
}
}
return dom;
}
/** Remove a component from the DOM and recycle it.
* @param {Component} component The Component instance to unmount
* @private
*/
export function unmountComponent(component) {
if (options.beforeUnmount) options.beforeUnmount(component);
let base = component.base;
component._disable = true;
if (component.componentWillUnmount) component.componentWillUnmount();
component.base = null;
// recursively tear down & recollect high-order component children:
let inner = component._component;
if (inner) {
unmountComponent(inner);
}
else if (base) {
if (base[ATTR_KEY] && base[ATTR_KEY].ref) base[ATTR_KEY].ref(null);
component.nextBase = base;
removeNode(base);
collectComponent(component);
removeChildren(base);
}
if (component.__ref) component.__ref(null);
}
preact-8.2.5/src/vdom/diff.js 0000664 0000000 0000000 00000023252 13151101465 0016007 0 ustar 00root root 0000000 0000000 import { ATTR_KEY } from '../constants';
import { isSameNodeType, isNamedNode } from './index';
import { buildComponentFromVNode } from './component';
import { createNode, setAccessor } from '../dom/index';
import { unmountComponent } from './component';
import options from '../options';
import { removeNode } from '../dom/index';
/** Queue of components that have been mounted and are awaiting componentDidMount */
export const mounts = [];
/** Diff recursion count, used to track the end of the diff cycle. */
export let diffLevel = 0;
/** Global flag indicating if the diff is currently within an SVG */
let isSvgMode = false;
/** Global flag indicating if the diff is performing hydration */
let hydrating = false;
/** Invoke queued componentDidMount lifecycle methods */
export function flushMounts() {
let c;
while ((c=mounts.pop())) {
if (options.afterMount) options.afterMount(c);
if (c.componentDidMount) c.componentDidMount();
}
}
/** Apply differences in a given vnode (and it's deep children) to a real DOM Node.
* @param {Element} [dom=null] A DOM node to mutate into the shape of the `vnode`
* @param {VNode} vnode A VNode (with descendants forming a tree) representing the desired DOM structure
* @returns {Element} dom The created/mutated element
* @private
*/
export function diff(dom, vnode, context, mountAll, parent, componentRoot) {
// diffLevel having been 0 here indicates initial entry into the diff (not a subdiff)
if (!diffLevel++) {
// when first starting the diff, check if we're diffing an SVG or within an SVG
isSvgMode = parent!=null && parent.ownerSVGElement!==undefined;
// hydration is indicated by the existing element to be diffed not having a prop cache
hydrating = dom!=null && !(ATTR_KEY in dom);
}
let ret = idiff(dom, vnode, context, mountAll, componentRoot);
// append the element if its a new parent
if (parent && ret.parentNode!==parent) parent.appendChild(ret);
// diffLevel being reduced to 0 means we're exiting the diff
if (!--diffLevel) {
hydrating = false;
// invoke queued componentDidMount lifecycle methods
if (!componentRoot) flushMounts();
}
return ret;
}
/** Internals of `diff()`, separated to allow bypassing diffLevel / mount flushing. */
function idiff(dom, vnode, context, mountAll, componentRoot) {
let out = dom,
prevSvgMode = isSvgMode;
// empty values (null, undefined, booleans) render as empty Text nodes
if (vnode==null || typeof vnode==='boolean') vnode = '';
// Fast case: Strings & Numbers create/update Text nodes.
if (typeof vnode==='string' || typeof vnode==='number') {
// update if it's already a Text node:
if (dom && dom.splitText!==undefined && dom.parentNode && (!dom._component || componentRoot)) {
/* istanbul ignore if */ /* Browser quirk that can't be covered: https://github.com/developit/preact/commit/fd4f21f5c45dfd75151bd27b4c217d8003aa5eb9 */
if (dom.nodeValue!=vnode) {
dom.nodeValue = vnode;
}
}
else {
// it wasn't a Text node: replace it with one and recycle the old Element
out = document.createTextNode(vnode);
if (dom) {
if (dom.parentNode) dom.parentNode.replaceChild(out, dom);
recollectNodeTree(dom, true);
}
}
out[ATTR_KEY] = true;
return out;
}
// If the VNode represents a Component, perform a component diff:
let vnodeName = vnode.nodeName;
if (typeof vnodeName==='function') {
return buildComponentFromVNode(dom, vnode, context, mountAll);
}
// Tracks entering and exiting SVG namespace when descending through the tree.
isSvgMode = vnodeName==='svg' ? true : vnodeName==='foreignObject' ? false : isSvgMode;
// If there's no existing element or it's the wrong type, create a new one:
vnodeName = String(vnodeName);
if (!dom || !isNamedNode(dom, vnodeName)) {
out = createNode(vnodeName, isSvgMode);
if (dom) {
// move children into the replacement node
while (dom.firstChild) out.appendChild(dom.firstChild);
// if the previous Element was mounted into the DOM, replace it inline
if (dom.parentNode) dom.parentNode.replaceChild(out, dom);
// recycle the old element (skips non-Element node types)
recollectNodeTree(dom, true);
}
}
let fc = out.firstChild,
props = out[ATTR_KEY],
vchildren = vnode.children;
if (props==null) {
props = out[ATTR_KEY] = {};
for (let a=out.attributes, i=a.length; i--; ) props[a[i].name] = a[i].value;
}
// Optimization: fast-path for elements containing a single TextNode:
if (!hydrating && vchildren && vchildren.length===1 && typeof vchildren[0]==='string' && fc!=null && fc.splitText!==undefined && fc.nextSibling==null) {
if (fc.nodeValue!=vchildren[0]) {
fc.nodeValue = vchildren[0];
}
}
// otherwise, if there are existing or new children, diff them:
else if (vchildren && vchildren.length || fc!=null) {
innerDiffNode(out, vchildren, context, mountAll, hydrating || props.dangerouslySetInnerHTML!=null);
}
// Apply attributes/props from VNode to the DOM Element:
diffAttributes(out, vnode.attributes, props);
// restore previous SVG mode: (in case we're exiting an SVG namespace)
isSvgMode = prevSvgMode;
return out;
}
/** Apply child and attribute changes between a VNode and a DOM Node to the DOM.
* @param {Element} dom Element whose children should be compared & mutated
* @param {Array} vchildren Array of VNodes to compare to `dom.childNodes`
* @param {Object} context Implicitly descendant context object (from most recent `getChildContext()`)
* @param {Boolean} mountAll
* @param {Boolean} isHydrating If `true`, consumes externally created elements similar to hydration
*/
function innerDiffNode(dom, vchildren, context, mountAll, isHydrating) {
let originalChildren = dom.childNodes,
children = [],
keyed = {},
keyedLen = 0,
min = 0,
len = originalChildren.length,
childrenLen = 0,
vlen = vchildren ? vchildren.length : 0,
j, c, f, vchild, child;
// Build up a map of keyed children and an Array of unkeyed children:
if (len!==0) {
for (let i=0; i