deku 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +5 -0
  6. data/LICENSE +25 -0
  7. data/README.md +28 -0
  8. data/Rakefile +1 -0
  9. data/deku.gemspec +23 -0
  10. data/deps/node_modules/deku.js +2 -0
  11. data/deps/node_modules/deku/.editorconfig +16 -0
  12. data/deps/node_modules/deku/.zuul.yml +15 -0
  13. data/deps/node_modules/deku/History.md +290 -0
  14. data/deps/node_modules/deku/LICENSE.md +7 -0
  15. data/deps/node_modules/deku/Makefile +91 -0
  16. data/deps/node_modules/deku/README.md +293 -0
  17. data/deps/node_modules/deku/index.js +4072 -0
  18. data/deps/node_modules/deku/lib/application.js +85 -0
  19. data/deps/node_modules/deku/lib/index.js +28 -0
  20. data/deps/node_modules/deku/lib/render.js +1300 -0
  21. data/deps/node_modules/deku/lib/stringify.js +105 -0
  22. data/deps/node_modules/deku/lib/svg.js +107 -0
  23. data/deps/node_modules/deku/lib/utils.js +18 -0
  24. data/deps/node_modules/deku/lib/virtual.js +247 -0
  25. data/deps/node_modules/deku/node_modules/array-flatten/LICENSE +21 -0
  26. data/deps/node_modules/deku/node_modules/array-flatten/README.md +43 -0
  27. data/deps/node_modules/deku/node_modules/array-flatten/array-flatten.js +57 -0
  28. data/deps/node_modules/deku/node_modules/array-flatten/package.json +62 -0
  29. data/deps/node_modules/deku/node_modules/component-emitter/History.md +63 -0
  30. data/deps/node_modules/deku/node_modules/component-emitter/LICENSE +24 -0
  31. data/deps/node_modules/deku/node_modules/component-emitter/Readme.md +74 -0
  32. data/deps/node_modules/deku/node_modules/component-emitter/index.js +161 -0
  33. data/deps/node_modules/deku/node_modules/component-emitter/package.json +174 -0
  34. data/deps/node_modules/deku/node_modules/component-raf/.npmignore +2 -0
  35. data/deps/node_modules/deku/node_modules/component-raf/History.md +26 -0
  36. data/deps/node_modules/deku/node_modules/component-raf/Makefile +11 -0
  37. data/deps/node_modules/deku/node_modules/component-raf/Readme.md +46 -0
  38. data/deps/node_modules/deku/node_modules/component-raf/component.json +16 -0
  39. data/deps/node_modules/deku/node_modules/component-raf/example.html +43 -0
  40. data/deps/node_modules/deku/node_modules/component-raf/index.js +34 -0
  41. data/deps/node_modules/deku/node_modules/component-raf/package.json +164 -0
  42. data/deps/node_modules/deku/node_modules/component-type/.npmignore +3 -0
  43. data/deps/node_modules/deku/node_modules/component-type/Makefile +14 -0
  44. data/deps/node_modules/deku/node_modules/component-type/Readme.md +37 -0
  45. data/deps/node_modules/deku/node_modules/component-type/component.json +13 -0
  46. data/deps/node_modules/deku/node_modules/component-type/index.js +34 -0
  47. data/deps/node_modules/deku/node_modules/component-type/package.json +120 -0
  48. data/deps/node_modules/deku/node_modules/component-type/test/index.html +17 -0
  49. data/deps/node_modules/deku/node_modules/component-type/test/mocha.css +231 -0
  50. data/deps/node_modules/deku/node_modules/component-type/test/mocha.js +5340 -0
  51. data/deps/node_modules/deku/node_modules/component-type/test/tests.js +72 -0
  52. data/deps/node_modules/deku/node_modules/dom-pool/.npmignore +1 -0
  53. data/deps/node_modules/deku/node_modules/dom-pool/Pool.js +52 -0
  54. data/deps/node_modules/deku/node_modules/dom-pool/README.md +42 -0
  55. data/deps/node_modules/deku/node_modules/dom-pool/authors.txt +4 -0
  56. data/deps/node_modules/deku/node_modules/dom-pool/bower.json +26 -0
  57. data/deps/node_modules/deku/node_modules/dom-pool/package.json +46 -0
  58. data/deps/node_modules/deku/node_modules/dom-pool/tests.html +16 -0
  59. data/deps/node_modules/deku/node_modules/dom-pool/tests.js +102 -0
  60. data/deps/node_modules/deku/node_modules/dom-walk/.npmignore +3 -0
  61. data/deps/node_modules/deku/node_modules/dom-walk/LICENCE +19 -0
  62. data/deps/node_modules/deku/node_modules/dom-walk/Makefile +2 -0
  63. data/deps/node_modules/deku/node_modules/dom-walk/README.md +23 -0
  64. data/deps/node_modules/deku/node_modules/dom-walk/example/index.js +5 -0
  65. data/deps/node_modules/deku/node_modules/dom-walk/example/static/bundle.js +211 -0
  66. data/deps/node_modules/deku/node_modules/dom-walk/example/static/index.html +16 -0
  67. data/deps/node_modules/deku/node_modules/dom-walk/index.js +24 -0
  68. data/deps/node_modules/deku/node_modules/dom-walk/package.json +57 -0
  69. data/deps/node_modules/deku/node_modules/fast.js/.jshintignore +7 -0
  70. data/deps/node_modules/deku/node_modules/fast.js/.jshintrc +80 -0
  71. data/deps/node_modules/deku/node_modules/fast.js/.npmignore +6 -0
  72. data/deps/node_modules/deku/node_modules/fast.js/.travis.yml +3 -0
  73. data/deps/node_modules/deku/node_modules/fast.js/LICENSE.md +21 -0
  74. data/deps/node_modules/deku/node_modules/fast.js/README.md +552 -0
  75. data/deps/node_modules/deku/node_modules/fast.js/array/clone.js +21 -0
  76. data/deps/node_modules/deku/node_modules/fast.js/array/concat.js +32 -0
  77. data/deps/node_modules/deku/node_modules/fast.js/array/every.js +25 -0
  78. data/deps/node_modules/deku/node_modules/fast.js/array/fill.js +29 -0
  79. data/deps/node_modules/deku/node_modules/fast.js/array/filter.js +26 -0
  80. data/deps/node_modules/deku/node_modules/fast.js/array/forEach.js +21 -0
  81. data/deps/node_modules/deku/node_modules/fast.js/array/index.js +15 -0
  82. data/deps/node_modules/deku/node_modules/fast.js/array/indexOf.js +33 -0
  83. data/deps/node_modules/deku/node_modules/fast.js/array/lastIndexOf.js +29 -0
  84. data/deps/node_modules/deku/node_modules/fast.js/array/map.js +24 -0
  85. data/deps/node_modules/deku/node_modules/fast.js/array/pluck.js +24 -0
  86. data/deps/node_modules/deku/node_modules/fast.js/array/reduce.js +35 -0
  87. data/deps/node_modules/deku/node_modules/fast.js/array/reduceRight.js +35 -0
  88. data/deps/node_modules/deku/node_modules/fast.js/array/some.js +25 -0
  89. data/deps/node_modules/deku/node_modules/fast.js/bower.json +28 -0
  90. data/deps/node_modules/deku/node_modules/fast.js/clone.js +27 -0
  91. data/deps/node_modules/deku/node_modules/fast.js/dist/bench.html +15 -0
  92. data/deps/node_modules/deku/node_modules/fast.js/dist/bench.js +19900 -0
  93. data/deps/node_modules/deku/node_modules/fast.js/dist/fast.js +1450 -0
  94. data/deps/node_modules/deku/node_modules/fast.js/dist/fast.min.js +1 -0
  95. data/deps/node_modules/deku/node_modules/fast.js/filter.js +23 -0
  96. data/deps/node_modules/deku/node_modules/fast.js/forEach.js +22 -0
  97. data/deps/node_modules/deku/node_modules/fast.js/function/apply.js +19 -0
  98. data/deps/node_modules/deku/node_modules/fast.js/function/applyNoContext.js +29 -0
  99. data/deps/node_modules/deku/node_modules/fast.js/function/applyWithContext.js +29 -0
  100. data/deps/node_modules/deku/node_modules/fast.js/function/bind.js +71 -0
  101. data/deps/node_modules/deku/node_modules/fast.js/function/bindInternal3.js +11 -0
  102. data/deps/node_modules/deku/node_modules/fast.js/function/bindInternal4.js +11 -0
  103. data/deps/node_modules/deku/node_modules/fast.js/function/index.js +7 -0
  104. data/deps/node_modules/deku/node_modules/fast.js/function/partial.js +42 -0
  105. data/deps/node_modules/deku/node_modules/fast.js/function/partialConstructor.js +45 -0
  106. data/deps/node_modules/deku/node_modules/fast.js/function/try.js +35 -0
  107. data/deps/node_modules/deku/node_modules/fast.js/index.js +241 -0
  108. data/deps/node_modules/deku/node_modules/fast.js/map.js +23 -0
  109. data/deps/node_modules/deku/node_modules/fast.js/object/assign.js +34 -0
  110. data/deps/node_modules/deku/node_modules/fast.js/object/clone.js +25 -0
  111. data/deps/node_modules/deku/node_modules/fast.js/object/filter.js +28 -0
  112. data/deps/node_modules/deku/node_modules/fast.js/object/forEach.js +23 -0
  113. data/deps/node_modules/deku/node_modules/fast.js/object/index.js +11 -0
  114. data/deps/node_modules/deku/node_modules/fast.js/object/keys.js +17 -0
  115. data/deps/node_modules/deku/node_modules/fast.js/object/map.js +26 -0
  116. data/deps/node_modules/deku/node_modules/fast.js/object/reduce.js +37 -0
  117. data/deps/node_modules/deku/node_modules/fast.js/object/reduceRight.js +37 -0
  118. data/deps/node_modules/deku/node_modules/fast.js/object/values.js +20 -0
  119. data/deps/node_modules/deku/node_modules/fast.js/package.json +73 -0
  120. data/deps/node_modules/deku/node_modules/fast.js/reduce.js +24 -0
  121. data/deps/node_modules/deku/node_modules/fast.js/reduceRight.js +24 -0
  122. data/deps/node_modules/deku/node_modules/fast.js/string/index.js +3 -0
  123. data/deps/node_modules/deku/node_modules/fast.js/string/intern.js +56 -0
  124. data/deps/node_modules/deku/node_modules/get-uid/README.md +44 -0
  125. data/deps/node_modules/deku/node_modules/get-uid/index.js +6 -0
  126. data/deps/node_modules/deku/node_modules/get-uid/package.json +56 -0
  127. data/deps/node_modules/deku/node_modules/is-dom/HISTORY.md +2 -0
  128. data/deps/node_modules/deku/node_modules/is-dom/LICENSE +21 -0
  129. data/deps/node_modules/deku/node_modules/is-dom/README.md +32 -0
  130. data/deps/node_modules/deku/node_modules/is-dom/index.js +15 -0
  131. data/deps/node_modules/deku/node_modules/is-dom/package.json +62 -0
  132. data/deps/node_modules/deku/node_modules/object-path/.npmignore +7 -0
  133. data/deps/node_modules/deku/node_modules/object-path/.travis.yml +6 -0
  134. data/deps/node_modules/deku/node_modules/object-path/LICENSE +21 -0
  135. data/deps/node_modules/deku/node_modules/object-path/README.md +96 -0
  136. data/deps/node_modules/deku/node_modules/object-path/bower.json +17 -0
  137. data/deps/node_modules/deku/node_modules/object-path/component.json +22 -0
  138. data/deps/node_modules/deku/node_modules/object-path/index.js +269 -0
  139. data/deps/node_modules/deku/node_modules/object-path/package.json +89 -0
  140. data/deps/node_modules/deku/node_modules/object-path/test.js +510 -0
  141. data/deps/node_modules/deku/node_modules/per-frame/.npmignore +68 -0
  142. data/deps/node_modules/deku/node_modules/per-frame/History.md +32 -0
  143. data/deps/node_modules/deku/node_modules/per-frame/README.md +44 -0
  144. data/deps/node_modules/deku/node_modules/per-frame/component.json +13 -0
  145. data/deps/node_modules/deku/node_modules/per-frame/index.js +37 -0
  146. data/deps/node_modules/deku/node_modules/per-frame/package.json +143 -0
  147. data/deps/node_modules/deku/node_modules/per-frame/test/test.js +94 -0
  148. data/deps/node_modules/deku/node_modules/sliced/.npmignore +2 -0
  149. data/deps/node_modules/deku/node_modules/sliced/.travis.yml +4 -0
  150. data/deps/node_modules/deku/node_modules/sliced/History.md +30 -0
  151. data/deps/node_modules/deku/node_modules/sliced/LICENSE +22 -0
  152. data/deps/node_modules/deku/node_modules/sliced/Makefile +5 -0
  153. data/deps/node_modules/deku/node_modules/sliced/README.md +62 -0
  154. data/deps/node_modules/deku/node_modules/sliced/bench.js +95 -0
  155. data/deps/node_modules/deku/node_modules/sliced/component.json +14 -0
  156. data/deps/node_modules/deku/node_modules/sliced/index.js +1 -0
  157. data/deps/node_modules/deku/node_modules/sliced/lib/sliced.js +33 -0
  158. data/deps/node_modules/deku/node_modules/sliced/package.json +52 -0
  159. data/deps/node_modules/deku/node_modules/sliced/test/index.js +80 -0
  160. data/deps/node_modules/deku/package.json +67 -0
  161. data/lib/deku.rb +11 -0
  162. data/lib/deku/application.rb +16 -0
  163. data/lib/deku/component.rb +36 -0
  164. data/lib/deku/context.rb +38 -0
  165. data/lib/deku/element_node.rb +17 -0
  166. data/lib/deku/version.rb +4 -0
  167. metadata +278 -0
@@ -0,0 +1,7 @@
1
+ The MIT License (MIT) Copyright (c) 2015 Anthony Short
2
+
3
+ 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:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ 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.
@@ -0,0 +1,91 @@
1
+
2
+ #
3
+ # Binaries.
4
+ #
5
+
6
+ export PATH := ./node_modules/.bin:${PATH}
7
+ BIN := ./node_modules/.bin
8
+
9
+ #
10
+ # Wildcards.
11
+ #
12
+
13
+ lib = $(shell find lib/*.js)
14
+ js = $(shell find lib/*.js test/*.js)
15
+
16
+ #
17
+ # Default.
18
+ #
19
+
20
+ default: index.js
21
+
22
+ #
23
+ # Targets.
24
+ #
25
+
26
+ build.js: node_modules $(js)
27
+ @browserify test/index.js -t babelify > build.js
28
+
29
+ tests.js: node_modules $(js)
30
+ @browserify test/index.js -t babelify | bfc > tests.js
31
+
32
+ index.js: node_modules $(js)
33
+ @browserify -s deku lib/index.js | bfc > index.js
34
+
35
+ #
36
+ # Tests.
37
+ #
38
+
39
+ test: build.js
40
+ @$(BIN)/duo-test browser --commands 'make build.js'
41
+
42
+ test-phantom:
43
+ @$(BIN)/mochify --transform babelify --ui bdd ./test/index.js
44
+ .PHONY: test
45
+
46
+ test-cloud: tests.js
47
+ @TRAVIS_BUILD_NUMBER=$(CIRCLE_BUILD_NUM) zuul -- tests.js
48
+
49
+ test-lint: $(lib)
50
+ @$(BIN)/standard lib/*
51
+ .PHONY: test-lint
52
+
53
+ test-watch:
54
+ @$(BIN)/mochify --watch
55
+ .PHONY: watch
56
+
57
+ test-coverage:
58
+ @$(BIN)/mochify --cover
59
+ .PHONY: coverage
60
+
61
+ test-size: index.js
62
+ $(BIN)/minify index.js | gzip -9 | wc -c
63
+ .PHONY: test-size
64
+
65
+ #
66
+ # Tasks.
67
+ #
68
+
69
+ node_modules: package.json
70
+ @npm install
71
+
72
+ clean:
73
+ @-rm -rf build.js index.js tests.js
74
+ .PHONY: clean
75
+
76
+ distclean: clean
77
+ @-rm -rf components node_modules
78
+ .PHONY: distclean
79
+
80
+ #
81
+ # Releases.
82
+ #
83
+
84
+ release: clean index.js
85
+ bump $$VERSION && \
86
+ git changelog --tag $$VERSION && \
87
+ git commit --all -m "Release $$VERSION" && \
88
+ git tag $$VERSION && \
89
+ git push origin master --tags && \
90
+ npm publish
91
+ .PHONY: release
@@ -0,0 +1,293 @@
1
+ <h1 align="center">
2
+ <br>
3
+ <img width="237" src="http://f.cl.ly/items/1s0T2Z3F2z190M1x1x1Y/deku-logo.png" alt="got">
4
+ <br>
5
+ <br>
6
+ <br>
7
+ </h1>
8
+
9
+ [![version](https://img.shields.io/npm/v/deku.svg?style=flat-square)](https://www.npmjs.com/package/deku) [![Circle CI](https://img.shields.io/circleci/project/BrightFlair/PHP.Gt.svg?style=flat-square)](https://circleci.com/gh/segmentio/deku) [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://github.com/feross/standard)
10
+
11
+ A library for creating UI components using virtual DOM as an alternative to [React](https://github.com/facebook/react). Deku has a smaller footprint (~10kb), a functional API, and doesn't support legacy browsers.
12
+
13
+ To install:
14
+
15
+ ```
16
+ npm install deku
17
+ ```
18
+
19
+ > You can also use Duo, Bower or [download the files manually](https://github.com/segmentio/deku/releases).
20
+
21
+ [Components](https://github.com/segmentio/deku/blob/master/docs/guides/components.md) are just plain objects that have a render function instead of using classes or constructors:
22
+
23
+ ```js
24
+ // button.js
25
+ let propTypes = {
26
+ kind: {
27
+ type: 'string',
28
+ expects: ['submit', 'button']
29
+ }
30
+ }
31
+
32
+ function render (component) {
33
+ let {props, state} = component
34
+ return <button class="Button" type={props.kind}>{props.children}</button>
35
+ }
36
+
37
+ function afterUpdate (component, prevProps, prevState, setState) {
38
+ let {props, state} = component
39
+ if (!state.clicked) {
40
+ setState({ clicked: true })
41
+ }
42
+ }
43
+
44
+ export default {propTypes, render, afterUpdate}
45
+ ```
46
+
47
+ Components are then rendered by mounting it in a tree:
48
+
49
+ ```js
50
+ import Button from './button'
51
+ import {tree,render,renderString} from 'deku'
52
+
53
+ let app = tree(
54
+ <Button kind="submit">Hello World!</Button>
55
+ )
56
+
57
+ render(app, document.body)
58
+ ```
59
+
60
+ Trees can be rendered on the server too:
61
+
62
+ ```js
63
+ let str = renderString(app)
64
+ ```
65
+
66
+ ## Docs
67
+
68
+ * [Installing](https://github.com/segmentio/deku/blob/master/docs/guides/install.md)
69
+ * [Component Spec](https://github.com/segmentio/deku/blob/master/docs/guides/components.md)
70
+ * [Using JSX](https://github.com/segmentio/deku/blob/master/docs/guides/jsx.md)
71
+
72
+ ## Components
73
+
74
+ Each element of your UI can be broken into encapsulated components. These components manage the state for the UI element and tell it how to render. In Deku components are just plain objects:
75
+
76
+ ```js
77
+ function render (component) {
78
+ let {props, state} = component
79
+ return <button class="Button">{props.children}</button>
80
+ }
81
+
82
+ export default {render}
83
+ ```
84
+
85
+ There is no concept of classes or use of `this`. We can import this component using the standard module syntax:
86
+
87
+ ```js
88
+ import Button from './button'
89
+ ```
90
+
91
+ [Read more about components](https://github.com/segmentio/deku/blob/master/docs/guides/components.md)
92
+
93
+ ## Rendering Components
94
+
95
+ To render this to the DOM we need to create a `tree`. This is one of the other main differences between React and Deku. The `tree` will manage loading data, communicating between components and allows us to use plugins on the entire application.
96
+
97
+ ```js
98
+ import {element,tree} from 'deku'
99
+ var app = tree(<Button>Hello World</Button>)
100
+ ```
101
+
102
+ The `app` object has only a couple of methods:
103
+
104
+ * `.set(name, value)` to set environment data
105
+ * `.option(name, value)` to set rendering options
106
+ * `.mount(vnode)` to change the virtual element currently mounted
107
+ * `.use(fn)` to use a plugin. The function is called with the `app` object.
108
+
109
+ You can render this tree anyway you like, you just need a renderer for it. Let's use the DOM renderer for the client:
110
+
111
+ ```js
112
+ import Button from './button'
113
+ import {element,tree,render} from 'deku'
114
+
115
+ var app = tree(<Button>Hello World</Button>)
116
+ render(app, document.body)
117
+ ```
118
+
119
+ And render the same thing to a string on the server:
120
+
121
+ ```js
122
+ import koa from 'koa'
123
+ import {element,tree,renderString} from 'deku'
124
+
125
+ let app = koa()
126
+
127
+ app.use(function *() {
128
+ this.body = renderString(tree(<Button>Hello World</Button>))
129
+ })
130
+ ```
131
+
132
+ And you can isolate functionality by using plugins. These plugins can call `set` to add data to the tree that your components can then access through their props:
133
+
134
+ ```js
135
+ app.use(analytics)
136
+ app.use(router)
137
+ app.use(api(writeKey))
138
+ ```
139
+
140
+ ## Composition
141
+
142
+ You can compose components easily by just requiring them and using them in the render function:
143
+
144
+ ```js
145
+ import Button from './button'
146
+ import Sheet from './sheet'
147
+
148
+ function render (component) {
149
+ return (
150
+ <div class="MyCoolApp">
151
+ <Sheet>
152
+ <Button style="danger">One</Button>
153
+ <Button style="happy">Two</Button>
154
+ </Sheet>
155
+ </div>
156
+ )
157
+ }
158
+ ```
159
+
160
+ ## Event handlers
161
+
162
+ Deku doesn't use any form of synthetic events because we can just capture every event in newer browsers. There are special attributes you can add to virtual elements that act as hooks to add event listeners:
163
+
164
+ ```js
165
+ function render (component) {
166
+ let {props, state} = component
167
+ return <button onClick={clicked}>{props.children}</button>
168
+ }
169
+
170
+ function clicked () {
171
+ alert('You clicked it')
172
+ }
173
+ ```
174
+
175
+ You can [view all event handlers](https://github.com/segmentio/deku/blob/master/lib/render.js#L25) in code.
176
+
177
+ ## Lifecycle hooks
178
+
179
+ Just like the `render` function, component lifecycle hooks are just plain functions:
180
+
181
+ ```js
182
+ function afterUpdate (component, prevProps, prevState, setState) {
183
+ let {props, state} = component
184
+ if (!state.clicked) {
185
+ setState({ clicked: true })
186
+ }
187
+ }
188
+ ```
189
+
190
+ We have hooks for `beforeMount`, `afterMount`, `beforeUpdate`, `afterUpdate`, `beforeUnmount` and two new hooks - `beforeRender` and `afterRender` that are called on every pass, unlike the update hooks. We've found that these extra hooks have allowed us to write cleaner code and worry less about the state of the component.
191
+
192
+ [Learn more about the lifecycle hooks](https://github.com/segmentio/deku/blob/master/docs/guides/components.md)
193
+
194
+ ## Validation
195
+
196
+ You can validate the props sent to your component by defining a `propTypes` object:
197
+
198
+ ```js
199
+ let propTypes = {
200
+ style: {
201
+ type: 'string',
202
+ expects: ['submit', 'button']
203
+ },
204
+ danger: {
205
+ type: 'boolean',
206
+ optional: true
207
+ }
208
+ }
209
+ ```
210
+
211
+ To enable validation you just need to enable it on the tree:
212
+
213
+ ```js
214
+ app.option('validateProps', true)
215
+ ```
216
+
217
+ This is off by default and we've made it an option so that you can enable it just during development without needing a separate build.
218
+
219
+ Props can originate from anywhere in the outside world, it's useful to validate them. When validation is enabled you'll only be able to pass in props that are defined and they must conform to the `propTypes` spec.
220
+
221
+ ## External data and communication
222
+
223
+ It's often useful for components to have access to data from the outside world without needing to pass it down through components. You can set data on your `tree` and components can ask for it using `propTypes`.
224
+
225
+ First we set some data on the app:
226
+
227
+ ```js
228
+ app.set('currentUser', {
229
+ id: 12435,
230
+ username: 'anthonyshort',
231
+ name: 'Anthony Short'
232
+ })
233
+ ```
234
+
235
+ Then in our components we define the prop using the `source` option:
236
+
237
+ ```js
238
+ let propTypes = {
239
+ user: {
240
+ source: 'currentUser'
241
+ }
242
+ }
243
+ ```
244
+
245
+ Whenever we change that value in our app all components that depend on it will be re-rendered with the latest value. We use this pattern to pass functions down to interact with the API:
246
+
247
+ ```js
248
+ app.set('updateProject', function (project, updates) {
249
+ api.projects.update(project, updates)
250
+ })
251
+ ```
252
+
253
+ Which the component can access using `props.updateProject`. Although it may not be as complex or optimized as Relay and GraphQL it's extremely simple and covers most use cases we've run into so far. We even use this pattern to treat the router as a data source:
254
+
255
+ ```js
256
+ router.on('/projects/:id', function (params) {
257
+ let project = api.projects.get(params.id)
258
+ app.set('currentRoute', {
259
+ name: 'view project',
260
+ project: project
261
+ })
262
+ })
263
+ ```
264
+
265
+ This means we don't need to use some complex routing library. We just treat it like all other types of external data and components will render as needed.
266
+
267
+ ## Keys
268
+
269
+ Sometimes when you're rendering a list of items you want them to be moved instead of trashed during the diff. Deku supports this using the `key` attribute on components:
270
+
271
+ ```js
272
+ function render (component) {
273
+ let {items} = component.props
274
+ let projects = items.map(function (project) {
275
+ return <ProjectItem key={project.id} project={project} />
276
+ })
277
+ return <div class="ProjectsList">{projects}</div>
278
+ }
279
+ ```
280
+
281
+ At the moment we only support the `key` attribute on components for simplicity. Things become slightly more hairy when moving elements around within components. So far we haven't ran into a case where this has been a major problem.
282
+
283
+ ## Tests
284
+
285
+ [![Sauce Test Status](https://saucelabs.com/browser-matrix/deku.svg)](https://saucelabs.com/u/deku)
286
+
287
+ ## Developing
288
+
289
+ Deku is built with Browserify. You can run the tests in a browser by running `make test`.
290
+
291
+ ## License
292
+
293
+ MIT. See [LICENSE.md](http://github.com/segmentio/deku/blob/master/LICENSE.md)
@@ -0,0 +1,4072 @@
1
+ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.deku=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof _require=="function"&&_require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof _require=="function"&&_require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_require,module,exports){
2
+ /**
3
+ * Module dependencies.
4
+ */
5
+
6
+ var Emitter = _require('component-emitter')
7
+
8
+ /**
9
+ * Expose `scene`.
10
+ */
11
+
12
+ module.exports = Application
13
+
14
+ /**
15
+ * Create a new `Application`.
16
+ *
17
+ * @param {Object} element Optional initial element
18
+ */
19
+
20
+ function Application (element) {
21
+ if (!(this instanceof Application)) return new Application(element)
22
+ this.options = {}
23
+ this.sources = {}
24
+ this.element = element
25
+ }
26
+
27
+ /**
28
+ * Mixin `Emitter`.
29
+ */
30
+
31
+ Emitter(Application.prototype)
32
+
33
+ /**
34
+ * Add a plugin
35
+ *
36
+ * @param {Function} plugin
37
+ */
38
+
39
+ Application.prototype.use = function (plugin) {
40
+ plugin(this)
41
+ return this
42
+ }
43
+
44
+ /**
45
+ * Set an option
46
+ *
47
+ * @param {String} name
48
+ */
49
+
50
+ Application.prototype.option = function (name, val) {
51
+ this.options[name] = val
52
+ return this
53
+ }
54
+
55
+ /**
56
+ * Set value used somewhere in the IO network.
57
+ */
58
+
59
+ Application.prototype.set = function (name, data) {
60
+ this.sources[name] = data
61
+ this.emit('source', name, data)
62
+ return this
63
+ }
64
+
65
+ /**
66
+ * Mount a virtual element.
67
+ *
68
+ * @param {VirtualElement} element
69
+ */
70
+
71
+ Application.prototype.mount = function (element) {
72
+ this.element = element
73
+ this.emit('mount', element)
74
+ return this
75
+ }
76
+
77
+ /**
78
+ * Remove the world. Unmount everything.
79
+ */
80
+
81
+ Application.prototype.unmount = function () {
82
+ if (!this.element) return
83
+ this.element = null
84
+ this.emit('unmount')
85
+ return this
86
+ }
87
+
88
+ },{"component-emitter":9}],2:[function(_require,module,exports){
89
+ /**
90
+ * Create the application.
91
+ */
92
+
93
+ exports.tree =
94
+ exports.scene =
95
+ exports.deku = _require('./application')
96
+
97
+ /**
98
+ * Render scenes to the DOM.
99
+ */
100
+
101
+ if (typeof document !== 'undefined') {
102
+ exports.render = _require('./render')
103
+ }
104
+
105
+ /**
106
+ * Render scenes to a string
107
+ */
108
+
109
+ exports.renderString = _require('./stringify')
110
+
111
+ /**
112
+ * Create virtual elements.
113
+ */
114
+
115
+ exports.element =
116
+ exports.dom = _require('./virtual')
117
+
118
+ },{"./application":1,"./render":3,"./stringify":4,"./virtual":7}],3:[function(_require,module,exports){
119
+ /**
120
+ * Dependencies.
121
+ */
122
+
123
+ var raf = _require('component-raf')
124
+ var Pool = _require('dom-pool')
125
+ var walk = _require('dom-walk')
126
+ var isDom = _require('is-dom')
127
+ var uid = _require('get-uid')
128
+ var throttle = _require('per-frame')
129
+ var keypath = _require('object-path')
130
+ var type = _require('component-type')
131
+ var fast = _require('fast.js')
132
+ var utils = _require('./utils')
133
+ var svg = _require('./svg')
134
+ var defaults = utils.defaults
135
+ var forEach = fast.forEach
136
+ var assign = fast.assign
137
+ var reduce = fast.reduce
138
+
139
+ /**
140
+ * All of the events can bind to
141
+ */
142
+
143
+ var events = {
144
+ onBlur: 'blur',
145
+ onChange: 'change',
146
+ onClick: 'click',
147
+ onContextMenu: 'contextmenu',
148
+ onCopy: 'copy',
149
+ onCut: 'cut',
150
+ onDoubleClick: 'dblclick',
151
+ onDrag: 'drag',
152
+ onDragEnd: 'dragend',
153
+ onDragEnter: 'dragenter',
154
+ onDragExit: 'dragexit',
155
+ onDragLeave: 'dragleave',
156
+ onDragOver: 'dragover',
157
+ onDragStart: 'dragstart',
158
+ onDrop: 'drop',
159
+ onFocus: 'focus',
160
+ onInput: 'input',
161
+ onKeyDown: 'keydown',
162
+ onKeyUp: 'keyup',
163
+ onMouseDown: 'mousedown',
164
+ onMouseMove: 'mousemove',
165
+ onMouseOut: 'mouseout',
166
+ onMouseOver: 'mouseover',
167
+ onMouseUp: 'mouseup',
168
+ onPaste: 'paste',
169
+ onScroll: 'scroll',
170
+ onSubmit: 'submit',
171
+ onTouchCancel: 'touchcancel',
172
+ onTouchEnd: 'touchend',
173
+ onTouchMove: 'touchmove',
174
+ onTouchStart: 'touchstart'
175
+ }
176
+
177
+ /**
178
+ * These elements won't be pooled
179
+ */
180
+
181
+ var avoidPooling = ['input', 'textarea'];
182
+
183
+ /**
184
+ * Expose `dom`.
185
+ */
186
+
187
+ module.exports = render
188
+
189
+ /**
190
+ * Render an app to the DOM
191
+ *
192
+ * @param {Application} app
193
+ * @param {HTMLElement} container
194
+ * @param {Object} opts
195
+ *
196
+ * @return {Object}
197
+ */
198
+
199
+ function render (app, container, opts) {
200
+ var frameId
201
+ var isRendering
202
+ var rootId = 'root'
203
+ var currentElement
204
+ var currentNativeElement
205
+ var connections = {}
206
+ var entities = {}
207
+ var pools = {}
208
+ var handlers = {}
209
+ var children = {}
210
+ children[rootId] = {}
211
+
212
+ if (!isDom(container)) {
213
+ throw new Error('Container element must be a DOM element')
214
+ }
215
+
216
+ /**
217
+ * Rendering options. Batching is only ever really disabled
218
+ * when running tests, and pooling can be disabled if the user
219
+ * is doing something stupid with the DOM in their components.
220
+ */
221
+
222
+ var options = defaults(assign({}, app.options || {}, opts || {}), {
223
+ pooling: true,
224
+ batching: true,
225
+ validateProps: false
226
+ })
227
+
228
+ /**
229
+ * Listen to DOM events
230
+ */
231
+
232
+ addNativeEventListeners()
233
+
234
+ /**
235
+ * Watch for changes to the app so that we can update
236
+ * the DOM as needed.
237
+ */
238
+
239
+ app.on('unmount', onunmount)
240
+ app.on('mount', onmount)
241
+ app.on('source', onupdate)
242
+
243
+ /**
244
+ * If the app has already mounted an element, we can just
245
+ * render that straight away.
246
+ */
247
+
248
+ if (app.element) render()
249
+
250
+ /**
251
+ * Teardown the DOM rendering so that it stops
252
+ * rendering and everything can be garbage collected.
253
+ */
254
+
255
+ function teardown () {
256
+ removeNativeEventListeners()
257
+ removeNativeElement()
258
+ app.off('unmount', onunmount)
259
+ app.off('mount', onmount)
260
+ app.off('source', onupdate)
261
+ }
262
+
263
+ /**
264
+ * Swap the current rendered node with a new one that is rendered
265
+ * from the new virtual element mounted on the app.
266
+ *
267
+ * @param {VirtualElement} element
268
+ */
269
+
270
+ function onmount () {
271
+ invalidate()
272
+ }
273
+
274
+ /**
275
+ * If the app unmounts an element, we should clear out the current
276
+ * rendered element. This will remove all the entities.
277
+ */
278
+
279
+ function onunmount () {
280
+ removeNativeElement()
281
+ currentElement = null
282
+ }
283
+
284
+ /**
285
+ * Update all components that are bound to the source
286
+ *
287
+ * @param {String} name
288
+ * @param {*} data
289
+ */
290
+
291
+ function onupdate (name, data) {
292
+ connections[name](data)
293
+ }
294
+
295
+ /**
296
+ * Render and mount a component to the native dom.
297
+ *
298
+ * @param {Entity} entity
299
+ * @return {HTMLElement}
300
+ */
301
+
302
+ function mountEntity (entity) {
303
+ register(entity)
304
+ setSources(entity)
305
+ children[entity.id] = {}
306
+ entities[entity.id] = entity
307
+
308
+ // commit initial state and props.
309
+ commit(entity)
310
+
311
+ // callback before mounting.
312
+ trigger('beforeMount', entity, [entity.context])
313
+ trigger('beforeRender', entity, [entity.context])
314
+
315
+ // render virtual element.
316
+ var virtualElement = renderEntity(entity)
317
+ // create native element.
318
+ var nativeElement = toNative(entity.id, '0', virtualElement)
319
+
320
+ entity.virtualElement = virtualElement
321
+ entity.nativeElement = nativeElement
322
+
323
+ // callback after mounting.
324
+ trigger('afterRender', entity, [entity.context, nativeElement])
325
+ trigger('afterMount', entity, [entity.context, nativeElement, setState(entity)])
326
+
327
+ return nativeElement
328
+ }
329
+
330
+ /**
331
+ * Remove a component from the native dom.
332
+ *
333
+ * @param {Entity} entity
334
+ */
335
+
336
+ function unmountEntity (entityId) {
337
+ var entity = entities[entityId]
338
+ if (!entity) return
339
+ trigger('beforeUnmount', entity, [entity.context, entity.nativeElement])
340
+ unmountChildren(entityId)
341
+ removeAllEvents(entityId)
342
+ delete entities[entityId]
343
+ delete children[entityId]
344
+ }
345
+
346
+ /**
347
+ * Render the entity and make sure it returns a node
348
+ *
349
+ * @param {Entity} entity
350
+ *
351
+ * @return {VirtualTree}
352
+ */
353
+
354
+ function renderEntity (entity) {
355
+ var component = entity.component
356
+ if (!component.render) throw new Error('Component needs a render function')
357
+ var result = component.render(entity.context, setState(entity))
358
+ if (!result) throw new Error('Render function must return an element.')
359
+ return result
360
+ }
361
+
362
+ /**
363
+ * Whenever setState or setProps is called, we mark the entity
364
+ * as dirty in the renderer. This lets us optimize the re-rendering
365
+ * and skip components that definitely haven't changed.
366
+ *
367
+ * @param {Entity} entity
368
+ *
369
+ * @return {Function} A curried function for updating the state of an entity
370
+ */
371
+
372
+ function setState (entity) {
373
+ return function (nextState) {
374
+ updateEntityState(entity, nextState)
375
+ }
376
+ }
377
+
378
+ /**
379
+ * Tell the app it's dirty and needs to re-render. If batching is disabled
380
+ * we can just trigger a render immediately, otherwise we'll wait until
381
+ * the next available frame.
382
+ */
383
+
384
+ function invalidate () {
385
+ if (!options.batching) {
386
+ if (!isRendering) render()
387
+ } else {
388
+ if (!frameId) frameId = raf(render)
389
+ }
390
+ }
391
+
392
+ /**
393
+ * Update the DOM. If the update fails we stop the loop
394
+ * so we don't get errors on every frame.
395
+ *
396
+ * @api public
397
+ */
398
+
399
+ function render () {
400
+ // If this is called synchronously we need to
401
+ // cancel any pending future updates
402
+ clearFrame()
403
+
404
+ // If the rendering from the previous frame is still going,
405
+ // we'll just wait until the next frame. Ideally renders should
406
+ // not take over 16ms to stay within a single frame, but this should
407
+ // catch it if it does.
408
+ if (isRendering) {
409
+ frameId = raf(render)
410
+ return
411
+ } else {
412
+ isRendering = true
413
+ }
414
+
415
+ // 1. If there isn't a native element rendered for the current mounted element
416
+ // then we need to create it from scratch.
417
+ // 2. If a new element has been mounted, we should diff them.
418
+ // 3. We should update check all child components for changes.
419
+ if (!currentNativeElement) {
420
+ currentElement = app.element
421
+ currentNativeElement = toNative(rootId, '0', currentElement)
422
+ container.appendChild(currentNativeElement)
423
+ } else if (currentElement !== app.element) {
424
+ currentNativeElement = patch(rootId, currentElement, app.element, currentNativeElement)
425
+ currentElement = app.element
426
+ updateChildren(rootId)
427
+ } else {
428
+ updateChildren(rootId)
429
+ }
430
+
431
+ // Allow rendering again.
432
+ isRendering = false
433
+ }
434
+
435
+ /**
436
+ * Clear the current scheduled frame
437
+ */
438
+
439
+ function clearFrame () {
440
+ if (!frameId) return
441
+ raf.cancel(frameId)
442
+ frameId = 0
443
+ }
444
+
445
+ /**
446
+ * Update a component.
447
+ *
448
+ * The entity is just the data object for a component instance.
449
+ *
450
+ * @param {String} id Component instance id.
451
+ */
452
+
453
+ function updateEntity (entityId) {
454
+ var entity = entities[entityId]
455
+ setSources(entity)
456
+
457
+ if (!shouldUpdate(entity)) return updateChildren(entityId)
458
+
459
+ var currentTree = entity.virtualElement
460
+ var nextProps = entity.pendingProps
461
+ var nextState = entity.pendingState
462
+ var previousState = entity.context.state
463
+ var previousProps = entity.context.props
464
+
465
+ // hook before rendering. could modify state just before the render occurs.
466
+ trigger('beforeUpdate', entity, [entity.context, nextProps, nextState])
467
+ trigger('beforeRender', entity, [entity.context])
468
+
469
+ // commit state and props.
470
+ commit(entity)
471
+
472
+ // re-render.
473
+ var nextTree = renderEntity(entity)
474
+
475
+ // if the tree is the same we can just skip this component
476
+ // but we should still check the children to see if they're dirty.
477
+ // This allows us to memoize the render function of components.
478
+ if (nextTree === currentTree) return updateChildren(entityId)
479
+
480
+ // apply new virtual tree to native dom.
481
+ entity.nativeElement = patch(entityId, currentTree, nextTree, entity.nativeElement)
482
+ entity.virtualElement = nextTree
483
+ updateChildren(entityId)
484
+
485
+ // trigger render hook
486
+ trigger('afterRender', entity, [entity.context, entity.nativeElement])
487
+
488
+ // trigger afterUpdate after all children have updated.
489
+ trigger('afterUpdate', entity, [entity.context, previousProps, previousState, setState(entity)])
490
+ }
491
+
492
+ /**
493
+ * Update all the children of an entity.
494
+ *
495
+ * @param {String} id Component instance id.
496
+ */
497
+
498
+ function updateChildren (entityId) {
499
+ forEach(children[entityId], function (childId) {
500
+ updateEntity(childId)
501
+ })
502
+ }
503
+
504
+ /**
505
+ * Remove all of the child entities of an entity
506
+ *
507
+ * @param {Entity} entity
508
+ */
509
+
510
+ function unmountChildren (entityId) {
511
+ forEach(children[entityId], function (childId) {
512
+ unmountEntity(childId)
513
+ })
514
+ }
515
+
516
+ /**
517
+ * Remove the root element. If this is called synchronously we need to
518
+ * cancel any pending future updates.
519
+ */
520
+
521
+ function removeNativeElement () {
522
+ clearFrame()
523
+ removeElement(rootId, '0', currentNativeElement)
524
+ currentNativeElement = null
525
+ }
526
+
527
+ /**
528
+ * Create a native element from a virtual element.
529
+ *
530
+ * @param {String} entityId
531
+ * @param {String} path
532
+ * @param {Object} vnode
533
+ *
534
+ * @return {HTMLDocumentFragment}
535
+ */
536
+
537
+ function toNative (entityId, path, vnode) {
538
+ switch (vnode.type) {
539
+ case 'text': return toNativeText(vnode)
540
+ case 'element': return toNativeElement(entityId, path, vnode)
541
+ case 'component': return toNativeComponent(entityId, path, vnode)
542
+ }
543
+ }
544
+
545
+ /**
546
+ * Create a native text element from a virtual element.
547
+ *
548
+ * @param {Object} vnode
549
+ */
550
+
551
+ function toNativeText (vnode) {
552
+ return document.createTextNode(vnode.data)
553
+ }
554
+
555
+ /**
556
+ * Create a native element from a virtual element.
557
+ */
558
+
559
+ function toNativeElement (entityId, path, vnode) {
560
+ var attributes = vnode.attributes
561
+ var children = vnode.children
562
+ var tagName = vnode.tagName
563
+ var el
564
+
565
+ // create element either from pool or fresh.
566
+ if (!options.pooling || !canPool(tagName)) {
567
+ if (svg.isElement(tagName)) {
568
+ el = document.createElementNS(svg.namespace, tagName)
569
+ } else {
570
+ el = document.createElement(tagName)
571
+ }
572
+ } else {
573
+ var pool = getPool(tagName)
574
+ el = cleanup(pool.pop())
575
+ if (el.parentNode) el.parentNode.removeChild(el)
576
+ }
577
+
578
+ // set attributes.
579
+ forEach(attributes, function (value, name) {
580
+ setAttribute(entityId, path, el, name, value)
581
+ })
582
+
583
+ // store keys on the native element for fast event handling.
584
+ el.__entity__ = entityId
585
+ el.__path__ = path
586
+
587
+ // add children.
588
+ forEach(children, function (child, i) {
589
+ var childEl = toNative(entityId, path + '.' + i, child)
590
+ if (!childEl.parentNode) el.appendChild(childEl)
591
+ })
592
+
593
+ return el
594
+ }
595
+
596
+ /**
597
+ * Create a native element from a component.
598
+ */
599
+
600
+ function toNativeComponent (entityId, path, vnode) {
601
+ var child = new Entity(vnode.component, vnode.props)
602
+ children[entityId][path] = child.id
603
+ return mountEntity(child)
604
+ }
605
+
606
+ /**
607
+ * Patch an element with the diff from two trees.
608
+ */
609
+
610
+ function patch (entityId, prev, next, el) {
611
+ return diffNode('0', entityId, prev, next, el)
612
+ }
613
+
614
+ /**
615
+ * Create a diff between two tress of nodes.
616
+ */
617
+
618
+ function diffNode (path, entityId, prev, next, el) {
619
+ // Type changed. This could be from element->text, text->ComponentA,
620
+ // ComponentA->ComponentB etc. But NOT div->span. These are the same type
621
+ // (ElementNode) but different tag name.
622
+ if (prev.type !== next.type) return replaceElement(entityId, path, el, next)
623
+
624
+ switch (next.type) {
625
+ case 'text': return diffText(prev, next, el)
626
+ case 'element': return diffElement(path, entityId, prev, next, el)
627
+ case 'component': return diffComponent(path, entityId, prev, next, el)
628
+ }
629
+ }
630
+
631
+ /**
632
+ * Diff two text nodes and update the element.
633
+ */
634
+
635
+ function diffText (previous, current, el) {
636
+ if (current.data !== previous.data) el.data = current.data
637
+ return el
638
+ }
639
+
640
+ /**
641
+ * Diff the children of an ElementNode.
642
+ */
643
+
644
+ function diffChildren (path, entityId, prev, next, el) {
645
+ var positions = []
646
+ var hasKeys = false
647
+ var childNodes = Array.prototype.slice.apply(el.childNodes)
648
+ var leftKeys = reduce(prev.children, keyMapReducer, {})
649
+ var rightKeys = reduce(next.children, keyMapReducer, {})
650
+ var currentChildren = assign({}, children[entityId])
651
+
652
+ function keyMapReducer (acc, child) {
653
+ if (child.key != null) {
654
+ acc[child.key] = child
655
+ hasKeys = true
656
+ }
657
+ return acc
658
+ }
659
+
660
+ // Diff all of the nodes that have keys. This lets us re-used elements
661
+ // instead of overriding them and lets us move them around.
662
+ if (hasKeys) {
663
+
664
+ // Removals
665
+ forEach(leftKeys, function (leftNode, key) {
666
+ if (rightKeys[key] == null) {
667
+ var leftPath = path + '.' + leftNode.index
668
+ removeElement(
669
+ entityId,
670
+ leftPath,
671
+ childNodes[leftNode.index]
672
+ )
673
+ }
674
+ })
675
+
676
+ // Update nodes
677
+ forEach(rightKeys, function (rightNode, key) {
678
+ var leftNode = leftKeys[key]
679
+
680
+ // We only want updates for now
681
+ if (leftNode == null) return
682
+
683
+ var leftPath = path + '.' + leftNode.index
684
+
685
+ // Updated
686
+ positions[rightNode.index] = diffNode(
687
+ leftPath,
688
+ entityId,
689
+ leftNode,
690
+ rightNode,
691
+ childNodes[leftNode.index]
692
+ )
693
+ })
694
+
695
+ // Update the positions of all child components and event handlers
696
+ forEach(rightKeys, function (rightNode, key) {
697
+ var leftNode = leftKeys[key]
698
+
699
+ // We just want elements that have moved around
700
+ if (leftNode == null || leftNode.index === rightNode.index) return
701
+
702
+ var rightPath = path + '.' + rightNode.index
703
+ var leftPath = path + '.' + leftNode.index
704
+
705
+ // Update all the child component path positions to match
706
+ // the latest positions if they've changed. This is a bit hacky.
707
+ forEach(currentChildren, function (childId, childPath) {
708
+ if (leftPath === childPath) {
709
+ delete children[entityId][childPath]
710
+ children[entityId][rightPath] = childId
711
+ }
712
+ })
713
+ })
714
+
715
+ // Now add all of the new nodes last in case their path
716
+ // would have conflicted with one of the previous paths.
717
+ forEach(rightKeys, function (rightNode, key) {
718
+ var rightPath = path + '.' + rightNode.index
719
+ if (leftKeys[key] == null) {
720
+ positions[rightNode.index] = toNative(
721
+ entityId,
722
+ rightPath,
723
+ rightNode
724
+ )
725
+ }
726
+ })
727
+
728
+ } else {
729
+ var maxLength = Math.max(prev.children.length, next.children.length)
730
+
731
+ // Now diff all of the nodes that don't have keys
732
+ for (var i = 0; i < maxLength; i++) {
733
+ var leftNode = prev.children[i]
734
+ var rightNode = next.children[i]
735
+
736
+ // Removals
737
+ if (rightNode == null) {
738
+ removeElement(
739
+ entityId,
740
+ path + '.' + leftNode.index,
741
+ childNodes[leftNode.index]
742
+ )
743
+ }
744
+
745
+ // New Node
746
+ if (leftNode == null) {
747
+ positions[rightNode.index] = toNative(
748
+ entityId,
749
+ path + '.' + rightNode.index,
750
+ rightNode
751
+ )
752
+ }
753
+
754
+ // Updated
755
+ if (leftNode && rightNode) {
756
+ positions[leftNode.index] = diffNode(
757
+ path + '.' + leftNode.index,
758
+ entityId,
759
+ leftNode,
760
+ rightNode,
761
+ childNodes[leftNode.index]
762
+ )
763
+ }
764
+ }
765
+ }
766
+
767
+ // Reposition all the elements
768
+ forEach(positions, function (childEl, newPosition) {
769
+ var target = el.childNodes[newPosition]
770
+ if (childEl !== target) {
771
+ if (target) {
772
+ el.insertBefore(childEl, target)
773
+ } else {
774
+ el.appendChild(childEl)
775
+ }
776
+ }
777
+ })
778
+ }
779
+
780
+ /**
781
+ * Diff the attributes and add/remove them.
782
+ */
783
+
784
+ function diffAttributes (prev, next, el, entityId, path) {
785
+ var nextAttrs = next.attributes
786
+ var prevAttrs = prev.attributes
787
+
788
+ // add new attrs
789
+ forEach(nextAttrs, function (value, name) {
790
+ if (events[name] || !(name in prevAttrs) || prevAttrs[name] !== value) {
791
+ setAttribute(entityId, path, el, name, value)
792
+ }
793
+ })
794
+
795
+ // remove old attrs
796
+ forEach(prevAttrs, function (value, name) {
797
+ if (!(name in nextAttrs)) {
798
+ removeAttribute(entityId, path, el, name)
799
+ }
800
+ })
801
+ }
802
+
803
+ /**
804
+ * Update a component with the props from the next node. If
805
+ * the component type has changed, we'll just remove the old one
806
+ * and replace it with the new component.
807
+ */
808
+
809
+ function diffComponent (path, entityId, prev, next, el) {
810
+ if (next.component !== prev.component) {
811
+ return replaceElement(entityId, path, el, next)
812
+ } else {
813
+ var targetId = children[entityId][path]
814
+
815
+ // This is a hack for now
816
+ if (targetId) {
817
+ updateEntityProps(targetId, next.props)
818
+ }
819
+
820
+ return el
821
+ }
822
+ }
823
+
824
+ /**
825
+ * Diff two element nodes.
826
+ */
827
+
828
+ function diffElement (path, entityId, prev, next, el) {
829
+ if (next.tagName !== prev.tagName) return replaceElement(entityId, path, el, next)
830
+ diffAttributes(prev, next, el, entityId, path)
831
+ diffChildren(path, entityId, prev, next, el)
832
+ return el
833
+ }
834
+
835
+ /**
836
+ * Removes an element from the DOM and unmounts and components
837
+ * that are within that branch
838
+ *
839
+ * side effects:
840
+ * - removes element from the DOM
841
+ * - removes internal references
842
+ *
843
+ * @param {String} entityId
844
+ * @param {String} path
845
+ * @param {HTMLElement} el
846
+ */
847
+
848
+ function removeElement (entityId, path, el) {
849
+ var childrenByPath = children[entityId]
850
+ var childId = childrenByPath[path]
851
+ var entityHandlers = handlers[entityId] || {}
852
+ var removals = []
853
+
854
+ // If the path points to a component we should use that
855
+ // components element instead, because it might have moved it.
856
+ if (childId) {
857
+ var child = entities[childId]
858
+ el = child.nativeElement
859
+ unmountEntity(childId)
860
+ removals.push(path)
861
+ } else {
862
+
863
+ // Just remove the text node
864
+ if (!isElement(el)) return el.parentNode.removeChild(el)
865
+
866
+ // Then we need to find any components within this
867
+ // branch and unmount them.
868
+ forEach(childrenByPath, function (childId, childPath) {
869
+ if (childPath === path || isWithinPath(path, childPath)) {
870
+ unmountEntity(childId)
871
+ removals.push(childPath)
872
+ }
873
+ })
874
+
875
+ // Remove all events at this path or below it
876
+ forEach(entityHandlers, function (fn, handlerPath) {
877
+ if (handlerPath === path || isWithinPath(path, handlerPath)) {
878
+ removeEvent(entityId, handlerPath)
879
+ }
880
+ })
881
+ }
882
+
883
+ // Remove the paths from the object without touching the
884
+ // old object. This keeps the object using fast properties.
885
+ forEach(removals, function (path) {
886
+ delete children[entityId][path]
887
+ })
888
+
889
+ // Remove it from the DOM
890
+ el.parentNode.removeChild(el)
891
+
892
+ // Return all of the elements in this node tree to the pool
893
+ // so that the elements can be re-used.
894
+ if (options.pooling) {
895
+ walk(el, function (node) {
896
+ if (!isElement(node) || !canPool(node.tagName)) return
897
+ getPool(node.tagName.toLowerCase()).push(node)
898
+ })
899
+ }
900
+ }
901
+
902
+ /**
903
+ * Replace an element in the DOM. Removing all components
904
+ * within that element and re-rendering the new virtual node.
905
+ *
906
+ * @param {Entity} entity
907
+ * @param {String} path
908
+ * @param {HTMLElement} el
909
+ * @param {Object} vnode
910
+ *
911
+ * @return {void}
912
+ */
913
+
914
+ function replaceElement (entityId, path, el, vnode) {
915
+ var parent = el.parentNode
916
+ var index = Array.prototype.indexOf.call(parent.childNodes, el)
917
+
918
+ // remove the previous element and all nested components. This
919
+ // needs to happen before we create the new element so we don't
920
+ // get clashes on the component paths.
921
+ removeElement(entityId, path, el)
922
+
923
+ // then add the new element in there
924
+ var newEl = toNative(entityId, path, vnode)
925
+ var target = parent.childNodes[index]
926
+
927
+ if (target) {
928
+ parent.insertBefore(newEl, target)
929
+ } else {
930
+ parent.appendChild(newEl)
931
+ }
932
+
933
+ // update all `entity.nativeElement` references.
934
+ forEach(entities, function (entity) {
935
+ if (entity.nativeElement === el) {
936
+ entity.nativeElement = newEl
937
+ }
938
+ })
939
+
940
+ return newEl
941
+ }
942
+
943
+ /**
944
+ * Set the attribute of an element, performing additional transformations
945
+ * dependning on the attribute name
946
+ *
947
+ * @param {HTMLElement} el
948
+ * @param {String} name
949
+ * @param {String} value
950
+ */
951
+
952
+ function setAttribute (entityId, path, el, name, value) {
953
+ if (events[name]) {
954
+ addEvent(entityId, path, events[name], value)
955
+ return
956
+ }
957
+ switch (name) {
958
+ case 'value':
959
+ el.value = value
960
+ break
961
+ case 'innerHTML':
962
+ el.innerHTML = value
963
+ break
964
+ case svg.isAttribute(name):
965
+ el.setAttributeNS(svg.namespace, name, value)
966
+ break
967
+ default:
968
+ el.setAttribute(name, value)
969
+ break
970
+ }
971
+ }
972
+
973
+ /**
974
+ * Remove an attribute, performing additional transformations
975
+ * dependning on the attribute name
976
+ *
977
+ * @param {HTMLElement} el
978
+ * @param {String} name
979
+ */
980
+
981
+ function removeAttribute (entityId, path, el, name) {
982
+ if (events[name]) {
983
+ removeEvent(entityId, path, events[name])
984
+ return
985
+ }
986
+ el.removeAttribute(name)
987
+ }
988
+
989
+ /**
990
+ * Checks to see if one tree path is within
991
+ * another tree path. Example:
992
+ *
993
+ * 0.1 vs 0.1.1 = true
994
+ * 0.2 vs 0.3.5 = false
995
+ *
996
+ * @param {String} target
997
+ * @param {String} path
998
+ *
999
+ * @return {Boolean}
1000
+ */
1001
+
1002
+ function isWithinPath (target, path) {
1003
+ return path.indexOf(target + '.') === 0
1004
+ }
1005
+
1006
+ /**
1007
+ * Is the DOM node an element node
1008
+ *
1009
+ * @param {HTMLElement} el
1010
+ *
1011
+ * @return {Boolean}
1012
+ */
1013
+
1014
+ function isElement (el) {
1015
+ return !!el.tagName
1016
+ }
1017
+
1018
+ /**
1019
+ * Get the pool for a tagName, creating it if it
1020
+ * doesn't exist.
1021
+ *
1022
+ * @param {String} tagName
1023
+ *
1024
+ * @return {Pool}
1025
+ */
1026
+
1027
+ function getPool (tagName) {
1028
+ var pool = pools[tagName]
1029
+ if (!pool) {
1030
+ var poolOpts = svg.isElement(tagName) ?
1031
+ { namespace: svg.namespace, tagName: tagName } :
1032
+ { tagName: tagName }
1033
+ pool = pools[tagName] = new Pool(poolOpts)
1034
+ }
1035
+ return pool
1036
+ }
1037
+
1038
+ /**
1039
+ * Clean up previously used native element for reuse.
1040
+ *
1041
+ * @param {HTMLElement} el
1042
+ */
1043
+
1044
+ function cleanup (el) {
1045
+ removeAllChildren(el)
1046
+ removeAllAttributes(el)
1047
+ return el
1048
+ }
1049
+
1050
+ /**
1051
+ * Remove all the attributes from a node
1052
+ *
1053
+ * @param {HTMLElement} el
1054
+ */
1055
+
1056
+ function removeAllAttributes (el) {
1057
+ for (var i = el.attributes.length - 1; i >= 0; i--) {
1058
+ var name = el.attributes[i].name
1059
+ el.removeAttribute(name)
1060
+ }
1061
+ }
1062
+
1063
+ /**
1064
+ * Remove all the child nodes from an element
1065
+ *
1066
+ * @param {HTMLElement} el
1067
+ */
1068
+
1069
+ function removeAllChildren (el) {
1070
+ while (el.firstChild) el.removeChild(el.firstChild)
1071
+ }
1072
+
1073
+ /**
1074
+ * Trigger a hook on a component.
1075
+ *
1076
+ * @param {String} name Name of hook.
1077
+ * @param {Entity} entity The component instance.
1078
+ * @param {Array} args To pass along to hook.
1079
+ */
1080
+
1081
+ function trigger (name, entity, args) {
1082
+ if (typeof entity.component[name] !== 'function') return
1083
+ entity.component[name].apply(null, args)
1084
+ }
1085
+
1086
+ /**
1087
+ * Update an entity to match the latest rendered vode. We always
1088
+ * replace the props on the component when composing them. This
1089
+ * will trigger a re-render on all children below this point.
1090
+ *
1091
+ * @param {Entity} entity
1092
+ * @param {String} path
1093
+ * @param {Object} vnode
1094
+ *
1095
+ * @return {void}
1096
+ */
1097
+
1098
+ function updateEntityProps (entityId, nextProps) {
1099
+ var entity = entities[entityId]
1100
+ entity.pendingProps = nextProps
1101
+ entity.dirty = true
1102
+ invalidate()
1103
+ }
1104
+
1105
+ /**
1106
+ * Update component instance state.
1107
+ */
1108
+
1109
+ function updateEntityState (entity, nextState) {
1110
+ entity.pendingState = assign(entity.pendingState, nextState)
1111
+ entity.dirty = true
1112
+ invalidate()
1113
+ }
1114
+
1115
+ /**
1116
+ * Commit props and state changes to an entity.
1117
+ */
1118
+
1119
+ function commit (entity) {
1120
+ entity.context = {
1121
+ state: entity.pendingState,
1122
+ props: entity.pendingProps,
1123
+ id: entity.id
1124
+ }
1125
+ entity.pendingState = assign({}, entity.context.state)
1126
+ entity.pendingProps = assign({}, entity.context.props)
1127
+ validateProps(entity.context.props, entity.propTypes)
1128
+ entity.dirty = false
1129
+ }
1130
+
1131
+ /**
1132
+ * Try to avoid creating new virtual dom if possible.
1133
+ *
1134
+ * Later we may expose this so you can override, but not there yet.
1135
+ */
1136
+
1137
+ function shouldUpdate (entity) {
1138
+ if (!entity.dirty) return false
1139
+ if (!entity.component.shouldUpdate) return true
1140
+ var nextProps = entity.pendingProps
1141
+ var nextState = entity.pendingState
1142
+ var bool = entity.component.shouldUpdate(entity.context, nextProps, nextState)
1143
+ return bool
1144
+ }
1145
+
1146
+ /**
1147
+ * Register an entity.
1148
+ *
1149
+ * This is mostly to pre-preprocess component properties and values chains.
1150
+ *
1151
+ * The end result is for every component that gets mounted,
1152
+ * you create a set of IO nodes in the network from the `value` definitions.
1153
+ *
1154
+ * @param {Component} component
1155
+ */
1156
+
1157
+ function register (entity) {
1158
+ var component = entity.component
1159
+ // all entities for this component type.
1160
+ var entities = component.entities = component.entities || {}
1161
+ // add entity to component list
1162
+ entities[entity.id] = entity
1163
+
1164
+ // get 'class-level' sources.
1165
+ var sources = component.sources
1166
+ if (sources) return
1167
+
1168
+ var map = component.sourceToPropertyName = {}
1169
+ component.sources = sources = []
1170
+ var propTypes = component.propTypes
1171
+ for (var name in propTypes) {
1172
+ var data = propTypes[name]
1173
+ if (!data) continue
1174
+ if (!data.source) continue
1175
+ sources.push(data.source)
1176
+ map[data.source] = name
1177
+ }
1178
+
1179
+ // send value updates to all component instances.
1180
+ sources.forEach(function (source) {
1181
+ connections[source] = update
1182
+
1183
+ function update (data) {
1184
+ var prop = map[source]
1185
+ for (var entityId in entities) {
1186
+ var entity = entities[entityId]
1187
+ var changes = {}
1188
+ changes[prop] = data
1189
+ updateEntityProps(entityId, assign(entity.pendingProps, changes))
1190
+ }
1191
+ }
1192
+ })
1193
+ }
1194
+
1195
+ /**
1196
+ * Set the initial source value on the entity
1197
+ *
1198
+ * @param {Entity} entity
1199
+ */
1200
+
1201
+ function setSources (entity) {
1202
+ var component = entity.component
1203
+ var map = component.sourceToPropertyName
1204
+ var sources = component.sources
1205
+ sources.forEach(function (source) {
1206
+ var name = map[source]
1207
+ if (entity.pendingProps[name] != null) return
1208
+ entity.pendingProps[name] = app.sources[source] // get latest value plugged into global store
1209
+ })
1210
+ }
1211
+
1212
+ /**
1213
+ * Add all of the DOM event listeners
1214
+ */
1215
+
1216
+ function addNativeEventListeners () {
1217
+ forEach(events, function (eventType) {
1218
+ document.body.addEventListener(eventType, handleEvent, true)
1219
+ })
1220
+ }
1221
+
1222
+ /**
1223
+ * Add all of the DOM event listeners
1224
+ */
1225
+
1226
+ function removeNativeEventListeners () {
1227
+ forEach(events, function (eventType) {
1228
+ document.body.removeEventListener(eventType, handleEvent, true)
1229
+ })
1230
+ }
1231
+
1232
+ /**
1233
+ * Handle an event that has occured within the container
1234
+ *
1235
+ * @param {Event} event
1236
+ */
1237
+
1238
+ function handleEvent (event) {
1239
+ var target = event.target
1240
+ var entityId = target.__entity__
1241
+ var eventType = event.type
1242
+
1243
+ // Walk up the DOM tree and see if there is a handler
1244
+ // for this event type higher up.
1245
+ while (target && target.__entity__ === entityId) {
1246
+ var fn = keypath.get(handlers, [entityId, target.__path__, eventType])
1247
+ if (fn) {
1248
+ event.delegateTarget = target
1249
+ fn(event)
1250
+ break
1251
+ }
1252
+ target = target.parentNode
1253
+ }
1254
+ }
1255
+
1256
+ /**
1257
+ * Bind events for an element, and all it's rendered child elements.
1258
+ *
1259
+ * @param {String} path
1260
+ * @param {String} event
1261
+ * @param {Function} fn
1262
+ */
1263
+
1264
+ function addEvent (entityId, path, eventType, fn) {
1265
+ keypath.set(handlers, [entityId, path, eventType], throttle(function (e) {
1266
+ var entity = entities[entityId]
1267
+ if (entity) {
1268
+ fn.call(null, e, entity.context, setState(entity))
1269
+ } else {
1270
+ fn.call(null, e)
1271
+ }
1272
+ }))
1273
+ }
1274
+
1275
+ /**
1276
+ * Unbind events for a entityId
1277
+ *
1278
+ * @param {String} entityId
1279
+ */
1280
+
1281
+ function removeEvent (entityId, path, eventType) {
1282
+ var args = [entityId]
1283
+ if (path) args.push(path)
1284
+ if (eventType) args.push(eventType)
1285
+ keypath.del(handlers, args)
1286
+ }
1287
+
1288
+ /**
1289
+ * Unbind all events from an entity
1290
+ *
1291
+ * @param {Entity} entity
1292
+ */
1293
+
1294
+ function removeAllEvents (entityId) {
1295
+ keypath.del(handlers, [entityId])
1296
+ }
1297
+
1298
+ /**
1299
+ * Validate the current properties. These simple validations
1300
+ * make it easier to ensure the correct props are passed in.
1301
+ *
1302
+ * Available rules include:
1303
+ *
1304
+ * type: string | array | object | boolean | number | date | function
1305
+ * expects: [] An array of values this prop could equal
1306
+ * optional: Boolean
1307
+ */
1308
+
1309
+ function validateProps (props, rules) {
1310
+ if (!options.validateProps) return
1311
+
1312
+ // TODO: Only validate in dev mode
1313
+ forEach(rules, function (options, name) {
1314
+ if (name === 'children') return
1315
+ var value = props[name]
1316
+ var optional = (options.optional === true)
1317
+ if (optional && value == null) {
1318
+ return
1319
+ }
1320
+ if (!optional && value == null) {
1321
+ throw new Error('Missing prop named: ' + name)
1322
+ }
1323
+ if (options.type && type(value) !== options.type) {
1324
+ throw new Error('Invalid type for prop named: ' + name)
1325
+ }
1326
+ if (options.expects && options.expects.indexOf(value) < 0) {
1327
+ throw new Error('Invalid value for prop named: ' + name + '. Must be one of ' + options.expects.toString())
1328
+ }
1329
+ })
1330
+
1331
+ // Now check for props that haven't been defined
1332
+ forEach(props, function (value, key) {
1333
+ if (key === 'children') return
1334
+ if (!rules[key]) throw new Error('Unexpected prop named: ' + key)
1335
+ })
1336
+ }
1337
+
1338
+ /**
1339
+ * Used for debugging to inspect the current state without
1340
+ * us needing to explicitly manage storing/updating references.
1341
+ *
1342
+ * @return {Object}
1343
+ */
1344
+
1345
+ function inspect () {
1346
+ return {
1347
+ entities: entities,
1348
+ pools: pools,
1349
+ handlers: handlers,
1350
+ connections: connections,
1351
+ currentElement: currentElement,
1352
+ options: options,
1353
+ app: app,
1354
+ container: container,
1355
+ children: children
1356
+ }
1357
+ }
1358
+
1359
+ /**
1360
+ * Return an object that lets us completely remove the automatic
1361
+ * DOM rendering and export debugging tools.
1362
+ */
1363
+
1364
+ return {
1365
+ remove: teardown,
1366
+ inspect: inspect
1367
+ }
1368
+ }
1369
+
1370
+ /**
1371
+ * A rendered component instance.
1372
+ *
1373
+ * This manages the lifecycle, props and state of the component.
1374
+ * It's basically just a data object for more straightfoward lookup.
1375
+ *
1376
+ * @param {Component} component
1377
+ * @param {Object} props
1378
+ */
1379
+
1380
+ function Entity (component, props) {
1381
+ this.id = uid()
1382
+ this.component = component
1383
+ this.propTypes = component.propTypes || {}
1384
+ this.context = {}
1385
+ this.context.id = this.id;
1386
+ this.context.props = defaults(props || {}, component.defaultProps || {})
1387
+ this.context.state = this.component.initialState ? this.component.initialState() : {}
1388
+ this.pendingProps = assign({}, this.context.props)
1389
+ this.pendingState = assign({}, this.context.state)
1390
+ this.dirty = false
1391
+ this.virtualElement = null
1392
+ this.nativeElement = null
1393
+ this.displayName = component.name || 'Component'
1394
+ }
1395
+
1396
+ /**
1397
+ * Should we pool an element?
1398
+ */
1399
+
1400
+ function canPool(tagName) {
1401
+ return avoidPooling.indexOf(tagName) < 0
1402
+ }
1403
+
1404
+ /**
1405
+ * Get a nested node using a path
1406
+ *
1407
+ * @param {HTMLElement} el The root node '0'
1408
+ * @param {String} path The path string eg. '0.2.43'
1409
+ */
1410
+
1411
+ function getNodeAtPath(el, path) {
1412
+ var parts = path.split('.')
1413
+ parts.shift()
1414
+ while (parts.length) {
1415
+ el = el.childNodes[parts.pop()]
1416
+ }
1417
+ return el
1418
+ }
1419
+
1420
+ },{"./svg":5,"./utils":6,"component-raf":10,"component-type":11,"dom-pool":12,"dom-walk":13,"fast.js":41,"get-uid":57,"is-dom":58,"object-path":59,"per-frame":60}],4:[function(_require,module,exports){
1421
+ var utils = _require('./utils')
1422
+ var defaults = utils.defaults
1423
+
1424
+ /**
1425
+ * Expose `stringify`.
1426
+ */
1427
+
1428
+ module.exports = function (app) {
1429
+ if (!app.element) {
1430
+ throw new Error('No element mounted')
1431
+ }
1432
+
1433
+ /**
1434
+ * Render to string.
1435
+ *
1436
+ * @param {Component} component
1437
+ * @param {Object} [props]
1438
+ * @return {String}
1439
+ */
1440
+
1441
+ function stringify (component, optProps) {
1442
+ var propTypes = component.propTypes || {}
1443
+ var state = component.initialState ? component.initialState() : {}
1444
+ var props = defaults(optProps, component.defaultProps || {})
1445
+
1446
+ for (var name in propTypes) {
1447
+ var options = propTypes[name]
1448
+ if (options.source) {
1449
+ props[name] = app.sources[options.source]
1450
+ }
1451
+ }
1452
+
1453
+ if (component.beforeMount) component.beforeMount({ props: props, state: state })
1454
+ if (component.beforeRender) component.beforeRender({ props: props, state: state })
1455
+ var node = component.render({ props: props, state: state })
1456
+ return stringifyNode(node, '0')
1457
+ }
1458
+
1459
+ /**
1460
+ * Render a node to a string
1461
+ *
1462
+ * @param {Node} node
1463
+ * @param {Tree} tree
1464
+ *
1465
+ * @return {String}
1466
+ */
1467
+
1468
+ function stringifyNode (node, path) {
1469
+ switch (node.type) {
1470
+ case 'text': return node.data
1471
+ case 'element':
1472
+ var children = node.children
1473
+ var attributes = node.attributes
1474
+ var tagName = node.tagName
1475
+ var innerHTML = attributes.innerHTML
1476
+ var str = '<' + tagName + attrs(attributes) + '>'
1477
+
1478
+ if (innerHTML) {
1479
+ str += innerHTML
1480
+ } else {
1481
+ for (var i = 0, n = children.length; i < n; i++) {
1482
+ str += stringifyNode(children[i], path + '.' + i)
1483
+ }
1484
+ }
1485
+
1486
+ str += '</' + tagName + '>'
1487
+ return str
1488
+ case 'component': return stringify(node.component, node.props)
1489
+ }
1490
+
1491
+ throw new Error('Invalid type')
1492
+ }
1493
+
1494
+ return stringifyNode(app.element, '0')
1495
+ }
1496
+
1497
+ /**
1498
+ * HTML attributes to string.
1499
+ *
1500
+ * @param {Object} attributes
1501
+ * @return {String}
1502
+ * @api private
1503
+ */
1504
+
1505
+ function attrs (attributes) {
1506
+ var str = ''
1507
+ for (var key in attributes) {
1508
+ if (key === 'innerHTML') continue
1509
+ str += attr(key, attributes[key])
1510
+ }
1511
+ return str
1512
+ }
1513
+
1514
+ /**
1515
+ * HTML attribute to string.
1516
+ *
1517
+ * @param {String} key
1518
+ * @param {String} val
1519
+ * @return {String}
1520
+ * @api private
1521
+ */
1522
+
1523
+ function attr (key, val) {
1524
+ return ' ' + key + '="' + val + '"'
1525
+ }
1526
+
1527
+ },{"./utils":6}],5:[function(_require,module,exports){
1528
+ var fast = _require('fast.js')
1529
+ var indexOf = fast.indexOf
1530
+
1531
+ /**
1532
+ * This file lists the supported SVG elements used by the
1533
+ * renderer. We may add better SVG support in the future
1534
+ * that doesn't require whitelisting elements.
1535
+ */
1536
+
1537
+ exports.namespace = 'http://www.w3.org/2000/svg'
1538
+
1539
+ /**
1540
+ * Supported SVG elements
1541
+ *
1542
+ * @type {Array}
1543
+ */
1544
+
1545
+ exports.elements = [
1546
+ 'circle',
1547
+ 'defs',
1548
+ 'ellipse',
1549
+ 'g',
1550
+ 'line',
1551
+ 'linearGradient',
1552
+ 'mask',
1553
+ 'path',
1554
+ 'pattern',
1555
+ 'polygon',
1556
+ 'polyline',
1557
+ 'radialGradient',
1558
+ 'rect',
1559
+ 'stop',
1560
+ 'svg',
1561
+ 'text',
1562
+ 'tspan'
1563
+ ]
1564
+
1565
+ /**
1566
+ * Supported SVG attributes
1567
+ */
1568
+
1569
+ exports.attributes = [
1570
+ 'cx',
1571
+ 'cy',
1572
+ 'd',
1573
+ 'dx',
1574
+ 'dy',
1575
+ 'fill',
1576
+ 'fillOpacity',
1577
+ 'fontFamily',
1578
+ 'fontSize',
1579
+ 'fx',
1580
+ 'fy',
1581
+ 'gradientTransform',
1582
+ 'gradientUnits',
1583
+ 'markerEnd',
1584
+ 'markerMid',
1585
+ 'markerStart',
1586
+ 'offset',
1587
+ 'opacity',
1588
+ 'patternContentUnits',
1589
+ 'patternUnits',
1590
+ 'points',
1591
+ 'preserveAspectRatio',
1592
+ 'r',
1593
+ 'rx',
1594
+ 'ry',
1595
+ 'spreadMethod',
1596
+ 'stopColor',
1597
+ 'stopOpacity',
1598
+ 'stroke',
1599
+ 'strokeDasharray',
1600
+ 'strokeLinecap',
1601
+ 'strokeOpacity',
1602
+ 'strokeWidth',
1603
+ 'textAnchor',
1604
+ 'transform',
1605
+ 'version',
1606
+ 'viewBox',
1607
+ 'x1',
1608
+ 'x2',
1609
+ 'x',
1610
+ 'y1',
1611
+ 'y2',
1612
+ 'y'
1613
+ ]
1614
+
1615
+ /**
1616
+ * Is element's namespace SVG?
1617
+ *
1618
+ * @param {String} name
1619
+ */
1620
+
1621
+ exports.isElement = function (name) {
1622
+ return indexOf(exports.elements, name) !== -1
1623
+ }
1624
+
1625
+ /**
1626
+ * Are element's attributes SVG?
1627
+ *
1628
+ * @param {String} attr
1629
+ */
1630
+
1631
+ exports.isAttribute = function (attr) {
1632
+ return indexOf(exports.attributes, attr) !== -1
1633
+ }
1634
+
1635
+
1636
+ },{"fast.js":41}],6:[function(_require,module,exports){
1637
+ /**
1638
+ * The npm 'defaults' module but without clone because
1639
+ * it was requiring the 'Buffer' module which is huge.
1640
+ *
1641
+ * @param {Object} options
1642
+ * @param {Object} defaults
1643
+ *
1644
+ * @return {Object}
1645
+ */
1646
+
1647
+ exports.defaults = function(options, defaults) {
1648
+ Object.keys(defaults).forEach(function(key) {
1649
+ if (typeof options[key] === 'undefined') {
1650
+ options[key] = defaults[key]
1651
+ }
1652
+ })
1653
+ return options
1654
+ }
1655
+
1656
+ },{}],7:[function(_require,module,exports){
1657
+ /**
1658
+ * Module dependencies.
1659
+ */
1660
+
1661
+ var type = _require('component-type')
1662
+ var slice = _require('sliced')
1663
+ var flatten = _require('array-flatten')
1664
+
1665
+ /**
1666
+ * This function lets us create virtual nodes using a simple
1667
+ * syntax. It is compatible with JSX transforms so you can use
1668
+ * JSX to write nodes that will compile to this function.
1669
+ *
1670
+ * let node = virtual('div', { id: 'foo' }, [
1671
+ * virtual('a', { href: 'http://google.com' }, 'Google')
1672
+ * ])
1673
+ *
1674
+ * You can leave out the attributes or the children if either
1675
+ * of them aren't needed and it will figure out what you're
1676
+ * trying to do.
1677
+ */
1678
+
1679
+ module.exports = virtual
1680
+
1681
+ /**
1682
+ * Create virtual DOM trees.
1683
+ *
1684
+ * This creates the nicer API for the user.
1685
+ * It translates that friendly API into an actual tree of nodes.
1686
+ *
1687
+ * @param {String|Function} type
1688
+ * @param {Object} props
1689
+ * @param {Array} children
1690
+ * @return {Node}
1691
+ * @api public
1692
+ */
1693
+
1694
+ function virtual (type, props, children) {
1695
+ // Default to div with no args
1696
+ if (!type) {
1697
+ throw new Error('Element needs a type. https://gist.github.com/anthonyshort/77ced43b5defe39908af')
1698
+ }
1699
+
1700
+ // Skipped adding attributes and we're passing
1701
+ // in children instead.
1702
+ if (arguments.length === 2 && (typeof props === 'string' || Array.isArray(props))) {
1703
+ children = props
1704
+ props = {}
1705
+ }
1706
+
1707
+ // Account for JSX putting the children as multiple arguments.
1708
+ // This is essentially just the ES6 rest param
1709
+ if (arguments.length > 2 && Array.isArray(arguments[2]) === false) {
1710
+ children = slice(arguments, 2)
1711
+ }
1712
+
1713
+ children = children || []
1714
+ props = props || {}
1715
+
1716
+ // passing in a single child, you can skip
1717
+ // using the array
1718
+ if (!Array.isArray(children)) {
1719
+ children = [ children ]
1720
+ }
1721
+
1722
+ children = flatten(children, 1).reduce(normalize, [])
1723
+
1724
+ // pull the key out from the data.
1725
+ var key = 'key' in props ? String(props.key) : null
1726
+ delete props['key']
1727
+
1728
+ // if you pass in a function, it's a `Component` constructor.
1729
+ // otherwise it's an element.
1730
+ var node
1731
+ if (typeof type === 'string') {
1732
+ node = new ElementNode(type, props, key, children)
1733
+ } else {
1734
+ node = new ComponentNode(type, props, key, children)
1735
+ }
1736
+
1737
+ // set the unique ID
1738
+ node.index = 0
1739
+
1740
+ return node
1741
+ }
1742
+
1743
+ /**
1744
+ * Parse nodes into real `Node` objects.
1745
+ *
1746
+ * @param {Mixed} node
1747
+ * @param {Integer} index
1748
+ * @return {Node}
1749
+ * @api private
1750
+ */
1751
+
1752
+ function normalize (acc, node) {
1753
+ if (node == null) {
1754
+ return acc
1755
+ }
1756
+ if (typeof node === 'string' || typeof node === 'number') {
1757
+ var newNode = new TextNode(String(node))
1758
+ newNode.index = acc.length
1759
+ acc.push(newNode)
1760
+ } else {
1761
+ node.index = acc.length
1762
+ acc.push(node)
1763
+ }
1764
+ return acc
1765
+ }
1766
+
1767
+ /**
1768
+ * Initialize a new `ComponentNode`.
1769
+ *
1770
+ * @param {Component} component
1771
+ * @param {Object} props
1772
+ * @param {String} key Used for sorting/replacing during diffing.
1773
+ * @param {Array} children Child virtual nodes
1774
+ * @api public
1775
+ */
1776
+
1777
+ function ComponentNode (component, props, key, children) {
1778
+ this.key = key
1779
+ this.props = props
1780
+ this.type = 'component'
1781
+ this.component = component
1782
+ this.props.children = children || []
1783
+ }
1784
+
1785
+ /**
1786
+ * Initialize a new `ElementNode`.
1787
+ *
1788
+ * @param {String} tagName
1789
+ * @param {Object} attributes
1790
+ * @param {String} key Used for sorting/replacing during diffing.
1791
+ * @param {Array} children Child virtual dom nodes.
1792
+ * @api public
1793
+ */
1794
+
1795
+ function ElementNode (tagName, attributes, key, children) {
1796
+ this.type = 'element'
1797
+ this.attributes = parseAttributes(attributes)
1798
+ this.tagName = tagName
1799
+ this.children = children || []
1800
+ this.key = key
1801
+ }
1802
+
1803
+ /**
1804
+ * Initialize a new `TextNode`.
1805
+ *
1806
+ * This is just a virtual HTML text object.
1807
+ *
1808
+ * @param {String} text
1809
+ * @api public
1810
+ */
1811
+
1812
+ function TextNode (text) {
1813
+ this.type = 'text'
1814
+ this.data = String(text)
1815
+ }
1816
+
1817
+ /**
1818
+ * Parse attributes for some special cases.
1819
+ *
1820
+ * TODO: This could be more functional and allow hooks
1821
+ * into the processing of the attributes at a component-level
1822
+ *
1823
+ * @param {Object} attributes
1824
+ *
1825
+ * @return {Object}
1826
+ */
1827
+
1828
+ function parseAttributes (attributes) {
1829
+ // style: { 'text-align': 'left' }
1830
+ if (attributes.style) {
1831
+ attributes.style = parseStyle(attributes.style)
1832
+ }
1833
+
1834
+ // class: { foo: true, bar: false, baz: true }
1835
+ // class: ['foo', 'bar', 'baz']
1836
+ if (attributes.class) {
1837
+ attributes.class = parseClass(attributes.class)
1838
+ }
1839
+
1840
+ // Remove attributes with false values
1841
+ var filteredAttributes = {}
1842
+ for (var key in attributes) {
1843
+ var value = attributes[key]
1844
+ if (value == null || value === false) continue
1845
+ filteredAttributes[key] = value
1846
+ }
1847
+
1848
+ return filteredAttributes
1849
+ }
1850
+
1851
+ /**
1852
+ * Parse a block of styles into a string.
1853
+ *
1854
+ * TODO: this could do a lot more with vendor prefixing,
1855
+ * number values etc. Maybe there's a way to allow users
1856
+ * to hook into this?
1857
+ *
1858
+ * @param {Object} styles
1859
+ *
1860
+ * @return {String}
1861
+ */
1862
+
1863
+ function parseStyle (styles) {
1864
+ if (type(styles) === 'string') {
1865
+ return styles
1866
+ }
1867
+ var str = ''
1868
+ for (var name in styles) {
1869
+ var value = styles[name]
1870
+ str = str + name + ':' + value + ';'
1871
+ }
1872
+ return str;
1873
+ }
1874
+
1875
+ /**
1876
+ * Parse the class attribute so it's able to be
1877
+ * set in a more user-friendly way
1878
+ *
1879
+ * @param {String|Object|Array} value
1880
+ *
1881
+ * @return {String}
1882
+ */
1883
+
1884
+ function parseClass (value) {
1885
+ // { foo: true, bar: false, baz: true }
1886
+ if (type(value) === 'object') {
1887
+ var matched = []
1888
+ for (var key in value) {
1889
+ if (value[key]) matched.push(key)
1890
+ }
1891
+ value = matched
1892
+ }
1893
+
1894
+ // ['foo', 'bar', 'baz']
1895
+ if (type(value) === 'array') {
1896
+ if (value.length === 0) {
1897
+ return
1898
+ }
1899
+ value = value.join(' ')
1900
+ }
1901
+
1902
+ return value
1903
+ }
1904
+
1905
+ },{"array-flatten":8,"component-type":11,"sliced":61}],8:[function(_require,module,exports){
1906
+ /**
1907
+ * Recursive flatten function. Fastest implementation for array flattening.
1908
+ *
1909
+ * @param {Array} array
1910
+ * @param {Array} result
1911
+ * @param {Number} depth
1912
+ * @return {Array}
1913
+ */
1914
+ function flatten (array, result, depth) {
1915
+ for (var i = 0; i < array.length; i++) {
1916
+ if (depth > 0 && Array.isArray(array[i])) {
1917
+ flatten(array[i], result, depth - 1);
1918
+ } else {
1919
+ result.push(array[i]);
1920
+ }
1921
+ }
1922
+
1923
+ return result;
1924
+ }
1925
+
1926
+ /**
1927
+ * Flatten an array, with the ability to define a depth.
1928
+ *
1929
+ * @param {Array} array
1930
+ * @param {Number} depth
1931
+ * @return {Array}
1932
+ */
1933
+ module.exports = function (array, depth) {
1934
+ return flatten(array, [], depth || Infinity);
1935
+ };
1936
+
1937
+ },{}],9:[function(_require,module,exports){
1938
+
1939
+ /**
1940
+ * Expose `Emitter`.
1941
+ */
1942
+
1943
+ module.exports = Emitter;
1944
+
1945
+ /**
1946
+ * Initialize a new `Emitter`.
1947
+ *
1948
+ * @api public
1949
+ */
1950
+
1951
+ function Emitter(obj) {
1952
+ if (obj) return mixin(obj);
1953
+ };
1954
+
1955
+ /**
1956
+ * Mixin the emitter properties.
1957
+ *
1958
+ * @param {Object} obj
1959
+ * @return {Object}
1960
+ * @api private
1961
+ */
1962
+
1963
+ function mixin(obj) {
1964
+ for (var key in Emitter.prototype) {
1965
+ obj[key] = Emitter.prototype[key];
1966
+ }
1967
+ return obj;
1968
+ }
1969
+
1970
+ /**
1971
+ * Listen on the given `event` with `fn`.
1972
+ *
1973
+ * @param {String} event
1974
+ * @param {Function} fn
1975
+ * @return {Emitter}
1976
+ * @api public
1977
+ */
1978
+
1979
+ Emitter.prototype.on =
1980
+ Emitter.prototype.addEventListener = function(event, fn){
1981
+ this._callbacks = this._callbacks || {};
1982
+ (this._callbacks['$' + event] = this._callbacks['$' + event] || [])
1983
+ .push(fn);
1984
+ return this;
1985
+ };
1986
+
1987
+ /**
1988
+ * Adds an `event` listener that will be invoked a single
1989
+ * time then automatically removed.
1990
+ *
1991
+ * @param {String} event
1992
+ * @param {Function} fn
1993
+ * @return {Emitter}
1994
+ * @api public
1995
+ */
1996
+
1997
+ Emitter.prototype.once = function(event, fn){
1998
+ function on() {
1999
+ this.off(event, on);
2000
+ fn.apply(this, arguments);
2001
+ }
2002
+
2003
+ on.fn = fn;
2004
+ this.on(event, on);
2005
+ return this;
2006
+ };
2007
+
2008
+ /**
2009
+ * Remove the given callback for `event` or all
2010
+ * registered callbacks.
2011
+ *
2012
+ * @param {String} event
2013
+ * @param {Function} fn
2014
+ * @return {Emitter}
2015
+ * @api public
2016
+ */
2017
+
2018
+ Emitter.prototype.off =
2019
+ Emitter.prototype.removeListener =
2020
+ Emitter.prototype.removeAllListeners =
2021
+ Emitter.prototype.removeEventListener = function(event, fn){
2022
+ this._callbacks = this._callbacks || {};
2023
+
2024
+ // all
2025
+ if (0 == arguments.length) {
2026
+ this._callbacks = {};
2027
+ return this;
2028
+ }
2029
+
2030
+ // specific event
2031
+ var callbacks = this._callbacks['$' + event];
2032
+ if (!callbacks) return this;
2033
+
2034
+ // remove all handlers
2035
+ if (1 == arguments.length) {
2036
+ delete this._callbacks['$' + event];
2037
+ return this;
2038
+ }
2039
+
2040
+ // remove specific handler
2041
+ var cb;
2042
+ for (var i = 0; i < callbacks.length; i++) {
2043
+ cb = callbacks[i];
2044
+ if (cb === fn || cb.fn === fn) {
2045
+ callbacks.splice(i, 1);
2046
+ break;
2047
+ }
2048
+ }
2049
+ return this;
2050
+ };
2051
+
2052
+ /**
2053
+ * Emit `event` with the given args.
2054
+ *
2055
+ * @param {String} event
2056
+ * @param {Mixed} ...
2057
+ * @return {Emitter}
2058
+ */
2059
+
2060
+ Emitter.prototype.emit = function(event){
2061
+ this._callbacks = this._callbacks || {};
2062
+ var args = [].slice.call(arguments, 1)
2063
+ , callbacks = this._callbacks['$' + event];
2064
+
2065
+ if (callbacks) {
2066
+ callbacks = callbacks.slice(0);
2067
+ for (var i = 0, len = callbacks.length; i < len; ++i) {
2068
+ callbacks[i].apply(this, args);
2069
+ }
2070
+ }
2071
+
2072
+ return this;
2073
+ };
2074
+
2075
+ /**
2076
+ * Return array of callbacks for `event`.
2077
+ *
2078
+ * @param {String} event
2079
+ * @return {Array}
2080
+ * @api public
2081
+ */
2082
+
2083
+ Emitter.prototype.listeners = function(event){
2084
+ this._callbacks = this._callbacks || {};
2085
+ return this._callbacks['$' + event] || [];
2086
+ };
2087
+
2088
+ /**
2089
+ * Check if this emitter has `event` handlers.
2090
+ *
2091
+ * @param {String} event
2092
+ * @return {Boolean}
2093
+ * @api public
2094
+ */
2095
+
2096
+ Emitter.prototype.hasListeners = function(event){
2097
+ return !! this.listeners(event).length;
2098
+ };
2099
+
2100
+ },{}],10:[function(_require,module,exports){
2101
+ /**
2102
+ * Expose `requestAnimationFrame()`.
2103
+ */
2104
+
2105
+ exports = module.exports = window.requestAnimationFrame
2106
+ || window.webkitRequestAnimationFrame
2107
+ || window.mozRequestAnimationFrame
2108
+ || fallback;
2109
+
2110
+ /**
2111
+ * Fallback implementation.
2112
+ */
2113
+
2114
+ var prev = new Date().getTime();
2115
+ function fallback(fn) {
2116
+ var curr = new Date().getTime();
2117
+ var ms = Math.max(0, 16 - (curr - prev));
2118
+ var req = setTimeout(fn, ms);
2119
+ prev = curr;
2120
+ return req;
2121
+ }
2122
+
2123
+ /**
2124
+ * Cancel.
2125
+ */
2126
+
2127
+ var cancel = window.cancelAnimationFrame
2128
+ || window.webkitCancelAnimationFrame
2129
+ || window.mozCancelAnimationFrame
2130
+ || window.clearTimeout;
2131
+
2132
+ exports.cancel = function(id){
2133
+ cancel.call(window, id);
2134
+ };
2135
+
2136
+ },{}],11:[function(_require,module,exports){
2137
+ /**
2138
+ * toString ref.
2139
+ */
2140
+
2141
+ var toString = Object.prototype.toString;
2142
+
2143
+ /**
2144
+ * Return the type of `val`.
2145
+ *
2146
+ * @param {Mixed} val
2147
+ * @return {String}
2148
+ * @api public
2149
+ */
2150
+
2151
+ module.exports = function(val){
2152
+ switch (toString.call(val)) {
2153
+ case '[object Date]': return 'date';
2154
+ case '[object RegExp]': return 'regexp';
2155
+ case '[object Arguments]': return 'arguments';
2156
+ case '[object Array]': return 'array';
2157
+ case '[object Error]': return 'error';
2158
+ }
2159
+
2160
+ if (val === null) return 'null';
2161
+ if (val === undefined) return 'undefined';
2162
+ if (val !== val) return 'nan';
2163
+ if (val && val.nodeType === 1) return 'element';
2164
+
2165
+ val = val.valueOf
2166
+ ? val.valueOf()
2167
+ : Object.prototype.valueOf.apply(val)
2168
+
2169
+ return typeof val;
2170
+ };
2171
+
2172
+ },{}],12:[function(_require,module,exports){
2173
+ function Pool(params) {
2174
+ if (typeof params !== 'object') {
2175
+ throw new Error("Please pass parameters. Example -> new Pool({ tagName: \"div\" })");
2176
+ }
2177
+
2178
+ if (typeof params.tagName !== 'string') {
2179
+ throw new Error("Please specify a tagName. Example -> new Pool({ tagName: \"div\" })");
2180
+ }
2181
+
2182
+ this.storage = [];
2183
+ this.tagName = params.tagName.toLowerCase();
2184
+ this.namespace = params.namespace;
2185
+ }
2186
+
2187
+ Pool.prototype.push = function(el) {
2188
+ if (el.tagName.toLowerCase() !== this.tagName) {
2189
+ return;
2190
+ }
2191
+
2192
+ this.storage.push(el);
2193
+ };
2194
+
2195
+ Pool.prototype.pop = function(argument) {
2196
+ if (this.storage.length === 0) {
2197
+ return this.create();
2198
+ } else {
2199
+ return this.storage.pop();
2200
+ }
2201
+ };
2202
+
2203
+ Pool.prototype.create = function() {
2204
+ if (this.namespace) {
2205
+ return document.createElementNS(this.namespace, this.tagName);
2206
+ } else {
2207
+ return document.createElement(this.tagName);
2208
+ }
2209
+ };
2210
+
2211
+ Pool.prototype.allocate = function(size) {
2212
+ if (this.storage.length >= size) {
2213
+ return;
2214
+ }
2215
+
2216
+ var difference = size - this.storage.length;
2217
+ for (var poolAllocIter = 0; poolAllocIter < difference; poolAllocIter++) {
2218
+ this.storage.push(this.create());
2219
+ }
2220
+ };
2221
+
2222
+ if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
2223
+ module.exports = Pool;
2224
+ }
2225
+
2226
+ },{}],13:[function(_require,module,exports){
2227
+ var slice = Array.prototype.slice
2228
+
2229
+ module.exports = iterativelyWalk
2230
+
2231
+ function iterativelyWalk(nodes, cb) {
2232
+ if (!('length' in nodes)) {
2233
+ nodes = [nodes]
2234
+ }
2235
+
2236
+ nodes = slice.call(nodes)
2237
+
2238
+ while(nodes.length) {
2239
+ var node = nodes.shift(),
2240
+ ret = cb(node)
2241
+
2242
+ if (ret) {
2243
+ return ret
2244
+ }
2245
+
2246
+ if (node.childNodes && node.childNodes.length) {
2247
+ nodes = slice.call(node.childNodes).concat(nodes)
2248
+ }
2249
+ }
2250
+ }
2251
+
2252
+ },{}],14:[function(_require,module,exports){
2253
+ 'use strict';
2254
+
2255
+ /**
2256
+ * # Clone Array
2257
+ *
2258
+ * Clone an array or array like object (e.g. `arguments`).
2259
+ * This is the equivalent of calling `Array.prototype.slice.call(arguments)`, but
2260
+ * significantly faster.
2261
+ *
2262
+ * @param {Array} input The array or array-like object to clone.
2263
+ * @return {Array} The cloned array.
2264
+ */
2265
+ module.exports = function fastCloneArray (input) {
2266
+ var length = input.length,
2267
+ sliced = new Array(length),
2268
+ i;
2269
+ for (i = 0; i < length; i++) {
2270
+ sliced[i] = input[i];
2271
+ }
2272
+ return sliced;
2273
+ };
2274
+
2275
+ },{}],15:[function(_require,module,exports){
2276
+ 'use strict';
2277
+
2278
+ /**
2279
+ * # Concat
2280
+ *
2281
+ * Concatenate multiple arrays.
2282
+ *
2283
+ * > Note: This function is effectively identical to `Array.prototype.concat()`.
2284
+ *
2285
+ *
2286
+ * @param {Array|mixed} item, ... The item(s) to concatenate.
2287
+ * @return {Array} The array containing the concatenated items.
2288
+ */
2289
+ module.exports = function fastConcat () {
2290
+ var length = arguments.length,
2291
+ arr = [],
2292
+ i, item, childLength, j;
2293
+
2294
+ for (i = 0; i < length; i++) {
2295
+ item = arguments[i];
2296
+ if (Array.isArray(item)) {
2297
+ childLength = item.length;
2298
+ for (j = 0; j < childLength; j++) {
2299
+ arr.push(item[j]);
2300
+ }
2301
+ }
2302
+ else {
2303
+ arr.push(item);
2304
+ }
2305
+ }
2306
+ return arr;
2307
+ };
2308
+
2309
+ },{}],16:[function(_require,module,exports){
2310
+ 'use strict';
2311
+
2312
+ var bindInternal3 = _require('../function/bindInternal3');
2313
+
2314
+ /**
2315
+ * # Every
2316
+ *
2317
+ * A fast `.every()` implementation.
2318
+ *
2319
+ * @param {Array} subject The array (or array-like) to iterate over.
2320
+ * @param {Function} fn The visitor function.
2321
+ * @param {Object} thisContext The context for the visitor.
2322
+ * @return {Boolean} true if all items in the array passes the truth test.
2323
+ */
2324
+ module.exports = function fastEvery (subject, fn, thisContext) {
2325
+ var length = subject.length,
2326
+ iterator = thisContext !== undefined ? bindInternal3(fn, thisContext) : fn,
2327
+ i;
2328
+ for (i = 0; i < length; i++) {
2329
+ if (!iterator(subject[i], i, subject)) {
2330
+ return false;
2331
+ }
2332
+ }
2333
+ return true;
2334
+ };
2335
+
2336
+ },{"../function/bindInternal3":35}],17:[function(_require,module,exports){
2337
+ 'use strict';
2338
+
2339
+ /**
2340
+ * # Fill
2341
+ * Fill an array with values, optionally starting and stopping at a given index.
2342
+ *
2343
+ * > Note: unlike the specced Array.prototype.fill(), this version does not support
2344
+ * > negative start / end arguments.
2345
+ *
2346
+ * @param {Array} subject The array to fill.
2347
+ * @param {mixed} value The value to insert.
2348
+ * @param {Integer} start The start position, defaults to 0.
2349
+ * @param {Integer} end The end position, defaults to subject.length
2350
+ * @return {Array} The now filled subject.
2351
+ */
2352
+ module.exports = function fastFill (subject, value, start, end) {
2353
+ var length = subject.length,
2354
+ i;
2355
+ if (start === undefined) {
2356
+ start = 0;
2357
+ }
2358
+ if (end === undefined) {
2359
+ end = length;
2360
+ }
2361
+ for (i = start; i < end; i++) {
2362
+ subject[i] = value;
2363
+ }
2364
+ return subject;
2365
+ };
2366
+ },{}],18:[function(_require,module,exports){
2367
+ 'use strict';
2368
+
2369
+ var bindInternal3 = _require('../function/bindInternal3');
2370
+
2371
+ /**
2372
+ * # Filter
2373
+ *
2374
+ * A fast `.filter()` implementation.
2375
+ *
2376
+ * @param {Array} subject The array (or array-like) to filter.
2377
+ * @param {Function} fn The filter function.
2378
+ * @param {Object} thisContext The context for the filter.
2379
+ * @return {Array} The array containing the results.
2380
+ */
2381
+ module.exports = function fastFilter (subject, fn, thisContext) {
2382
+ var length = subject.length,
2383
+ result = [],
2384
+ iterator = thisContext !== undefined ? bindInternal3(fn, thisContext) : fn,
2385
+ i;
2386
+ for (i = 0; i < length; i++) {
2387
+ if (iterator(subject[i], i, subject)) {
2388
+ result.push(subject[i]);
2389
+ }
2390
+ }
2391
+ return result;
2392
+ };
2393
+
2394
+ },{"../function/bindInternal3":35}],19:[function(_require,module,exports){
2395
+ 'use strict';
2396
+
2397
+ var bindInternal3 = _require('../function/bindInternal3');
2398
+
2399
+ /**
2400
+ * # For Each
2401
+ *
2402
+ * A fast `.forEach()` implementation.
2403
+ *
2404
+ * @param {Array} subject The array (or array-like) to iterate over.
2405
+ * @param {Function} fn The visitor function.
2406
+ * @param {Object} thisContext The context for the visitor.
2407
+ */
2408
+ module.exports = function fastForEach (subject, fn, thisContext) {
2409
+ var length = subject.length,
2410
+ iterator = thisContext !== undefined ? bindInternal3(fn, thisContext) : fn,
2411
+ i;
2412
+ for (i = 0; i < length; i++) {
2413
+ iterator(subject[i], i, subject);
2414
+ }
2415
+ };
2416
+
2417
+ },{"../function/bindInternal3":35}],20:[function(_require,module,exports){
2418
+ 'use strict';
2419
+
2420
+ exports.clone = _require('./clone');
2421
+ exports.concat = _require('./concat');
2422
+ exports.every = _require('./every');
2423
+ exports.filter = _require('./filter');
2424
+ exports.forEach = _require('./forEach');
2425
+ exports.indexOf = _require('./indexOf');
2426
+ exports.lastIndexOf = _require('./lastIndexOf');
2427
+ exports.map = _require('./map');
2428
+ exports.pluck = _require('./pluck');
2429
+ exports.reduce = _require('./reduce');
2430
+ exports.reduceRight = _require('./reduceRight');
2431
+ exports.some = _require('./some');
2432
+ exports.fill = _require('./fill');
2433
+ },{"./clone":14,"./concat":15,"./every":16,"./fill":17,"./filter":18,"./forEach":19,"./indexOf":21,"./lastIndexOf":22,"./map":23,"./pluck":24,"./reduce":25,"./reduceRight":26,"./some":27}],21:[function(_require,module,exports){
2434
+ 'use strict';
2435
+
2436
+ /**
2437
+ * # Index Of
2438
+ *
2439
+ * A faster `Array.prototype.indexOf()` implementation.
2440
+ *
2441
+ * @param {Array} subject The array (or array-like) to search within.
2442
+ * @param {mixed} target The target item to search for.
2443
+ * @param {Number} fromIndex The position to start searching from, if known.
2444
+ * @return {Number} The position of the target in the subject, or -1 if it does not exist.
2445
+ */
2446
+ module.exports = function fastIndexOf (subject, target, fromIndex) {
2447
+ var length = subject.length,
2448
+ i = 0;
2449
+
2450
+ if (typeof fromIndex === 'number') {
2451
+ i = fromIndex;
2452
+ if (i < 0) {
2453
+ i += length;
2454
+ if (i < 0) {
2455
+ i = 0;
2456
+ }
2457
+ }
2458
+ }
2459
+
2460
+ for (; i < length; i++) {
2461
+ if (subject[i] === target) {
2462
+ return i;
2463
+ }
2464
+ }
2465
+ return -1;
2466
+ };
2467
+
2468
+ },{}],22:[function(_require,module,exports){
2469
+ 'use strict';
2470
+
2471
+ /**
2472
+ * # Last Index Of
2473
+ *
2474
+ * A faster `Array.prototype.lastIndexOf()` implementation.
2475
+ *
2476
+ * @param {Array} subject The array (or array-like) to search within.
2477
+ * @param {mixed} target The target item to search for.
2478
+ * @param {Number} fromIndex The position to start searching backwards from, if known.
2479
+ * @return {Number} The last position of the target in the subject, or -1 if it does not exist.
2480
+ */
2481
+ module.exports = function fastLastIndexOf (subject, target, fromIndex) {
2482
+ var length = subject.length,
2483
+ i = length - 1;
2484
+
2485
+ if (typeof fromIndex === 'number') {
2486
+ i = fromIndex;
2487
+ if (i < 0) {
2488
+ i += length;
2489
+ }
2490
+ }
2491
+ for (; i >= 0; i--) {
2492
+ if (subject[i] === target) {
2493
+ return i;
2494
+ }
2495
+ }
2496
+ return -1;
2497
+ };
2498
+
2499
+ },{}],23:[function(_require,module,exports){
2500
+ 'use strict';
2501
+
2502
+ var bindInternal3 = _require('../function/bindInternal3');
2503
+
2504
+ /**
2505
+ * # Map
2506
+ *
2507
+ * A fast `.map()` implementation.
2508
+ *
2509
+ * @param {Array} subject The array (or array-like) to map over.
2510
+ * @param {Function} fn The mapper function.
2511
+ * @param {Object} thisContext The context for the mapper.
2512
+ * @return {Array} The array containing the results.
2513
+ */
2514
+ module.exports = function fastMap (subject, fn, thisContext) {
2515
+ var length = subject.length,
2516
+ result = new Array(length),
2517
+ iterator = thisContext !== undefined ? bindInternal3(fn, thisContext) : fn,
2518
+ i;
2519
+ for (i = 0; i < length; i++) {
2520
+ result[i] = iterator(subject[i], i, subject);
2521
+ }
2522
+ return result;
2523
+ };
2524
+
2525
+ },{"../function/bindInternal3":35}],24:[function(_require,module,exports){
2526
+ 'use strict';
2527
+
2528
+ /**
2529
+ * # Pluck
2530
+ * Pluck the property with the given name from an array of objects.
2531
+ *
2532
+ * @param {Array} input The values to pluck from.
2533
+ * @param {String} field The name of the field to pluck.
2534
+ * @return {Array} The plucked array of values.
2535
+ */
2536
+ module.exports = function fastPluck (input, field) {
2537
+ var length = input.length,
2538
+ plucked = [],
2539
+ count = 0,
2540
+ value, i;
2541
+
2542
+ for (i = 0; i < length; i++) {
2543
+ value = input[i];
2544
+ if (value != null && value[field] !== undefined) {
2545
+ plucked[count++] = value[field];
2546
+ }
2547
+ }
2548
+ return plucked;
2549
+ };
2550
+ },{}],25:[function(_require,module,exports){
2551
+ 'use strict';
2552
+
2553
+ var bindInternal4 = _require('../function/bindInternal4');
2554
+
2555
+ /**
2556
+ * # Reduce
2557
+ *
2558
+ * A fast `.reduce()` implementation.
2559
+ *
2560
+ * @param {Array} subject The array (or array-like) to reduce.
2561
+ * @param {Function} fn The reducer function.
2562
+ * @param {mixed} initialValue The initial value for the reducer, defaults to subject[0].
2563
+ * @param {Object} thisContext The context for the reducer.
2564
+ * @return {mixed} The final result.
2565
+ */
2566
+ module.exports = function fastReduce (subject, fn, initialValue, thisContext) {
2567
+ var length = subject.length,
2568
+ iterator = thisContext !== undefined ? bindInternal4(fn, thisContext) : fn,
2569
+ i, result;
2570
+
2571
+ if (initialValue === undefined) {
2572
+ i = 1;
2573
+ result = subject[0];
2574
+ }
2575
+ else {
2576
+ i = 0;
2577
+ result = initialValue;
2578
+ }
2579
+
2580
+ for (; i < length; i++) {
2581
+ result = iterator(result, subject[i], i, subject);
2582
+ }
2583
+
2584
+ return result;
2585
+ };
2586
+
2587
+ },{"../function/bindInternal4":36}],26:[function(_require,module,exports){
2588
+ 'use strict';
2589
+
2590
+ var bindInternal4 = _require('../function/bindInternal4');
2591
+
2592
+ /**
2593
+ * # Reduce Right
2594
+ *
2595
+ * A fast `.reduceRight()` implementation.
2596
+ *
2597
+ * @param {Array} subject The array (or array-like) to reduce.
2598
+ * @param {Function} fn The reducer function.
2599
+ * @param {mixed} initialValue The initial value for the reducer, defaults to subject[0].
2600
+ * @param {Object} thisContext The context for the reducer.
2601
+ * @return {mixed} The final result.
2602
+ */
2603
+ module.exports = function fastReduce (subject, fn, initialValue, thisContext) {
2604
+ var length = subject.length,
2605
+ iterator = thisContext !== undefined ? bindInternal4(fn, thisContext) : fn,
2606
+ i, result;
2607
+
2608
+ if (initialValue === undefined) {
2609
+ i = length - 2;
2610
+ result = subject[length - 1];
2611
+ }
2612
+ else {
2613
+ i = length - 1;
2614
+ result = initialValue;
2615
+ }
2616
+
2617
+ for (; i >= 0; i--) {
2618
+ result = iterator(result, subject[i], i, subject);
2619
+ }
2620
+
2621
+ return result;
2622
+ };
2623
+
2624
+ },{"../function/bindInternal4":36}],27:[function(_require,module,exports){
2625
+ 'use strict';
2626
+
2627
+ var bindInternal3 = _require('../function/bindInternal3');
2628
+
2629
+ /**
2630
+ * # Some
2631
+ *
2632
+ * A fast `.some()` implementation.
2633
+ *
2634
+ * @param {Array} subject The array (or array-like) to iterate over.
2635
+ * @param {Function} fn The visitor function.
2636
+ * @param {Object} thisContext The context for the visitor.
2637
+ * @return {Boolean} true if at least one item in the array passes the truth test.
2638
+ */
2639
+ module.exports = function fastSome (subject, fn, thisContext) {
2640
+ var length = subject.length,
2641
+ iterator = thisContext !== undefined ? bindInternal3(fn, thisContext) : fn,
2642
+ i;
2643
+ for (i = 0; i < length; i++) {
2644
+ if (iterator(subject[i], i, subject)) {
2645
+ return true;
2646
+ }
2647
+ }
2648
+ return false;
2649
+ };
2650
+
2651
+ },{"../function/bindInternal3":35}],28:[function(_require,module,exports){
2652
+ 'use strict';
2653
+
2654
+ var cloneArray = _require('./array/clone');
2655
+ var cloneObject = _require('./object/clone');
2656
+
2657
+ /**
2658
+ * # Clone
2659
+ *
2660
+ * Clone an item. Primitive values will be returned directly,
2661
+ * arrays and objects will be shallow cloned. If you know the
2662
+ * type of input you're dealing with, call `.cloneArray()` or `.cloneObject()`
2663
+ * instead.
2664
+ *
2665
+ * @param {mixed} input The input to clone.
2666
+ * @return {mixed} The cloned input.
2667
+ */
2668
+ module.exports = function clone (input) {
2669
+ if (!input || typeof input !== 'object') {
2670
+ return input;
2671
+ }
2672
+ else if (Array.isArray(input)) {
2673
+ return cloneArray(input);
2674
+ }
2675
+ else {
2676
+ return cloneObject(input);
2677
+ }
2678
+ };
2679
+
2680
+ },{"./array/clone":14,"./object/clone":44}],29:[function(_require,module,exports){
2681
+ 'use strict';
2682
+
2683
+ var filterArray = _require('./array/filter'),
2684
+ filterObject = _require('./object/filter');
2685
+
2686
+ /**
2687
+ * # Filter
2688
+ *
2689
+ * A fast `.filter()` implementation.
2690
+ *
2691
+ * @param {Array|Object} subject The array or object to filter.
2692
+ * @param {Function} fn The filter function.
2693
+ * @param {Object} thisContext The context for the filter.
2694
+ * @return {Array|Object} The array or object containing the filtered results.
2695
+ */
2696
+ module.exports = function fastFilter (subject, fn, thisContext) {
2697
+ if (subject instanceof Array) {
2698
+ return filterArray(subject, fn, thisContext);
2699
+ }
2700
+ else {
2701
+ return filterObject(subject, fn, thisContext);
2702
+ }
2703
+ };
2704
+ },{"./array/filter":18,"./object/filter":45}],30:[function(_require,module,exports){
2705
+ 'use strict';
2706
+
2707
+ var forEachArray = _require('./array/forEach'),
2708
+ forEachObject = _require('./object/forEach');
2709
+
2710
+ /**
2711
+ * # ForEach
2712
+ *
2713
+ * A fast `.forEach()` implementation.
2714
+ *
2715
+ * @param {Array|Object} subject The array or object to iterate over.
2716
+ * @param {Function} fn The visitor function.
2717
+ * @param {Object} thisContext The context for the visitor.
2718
+ */
2719
+ module.exports = function fastForEach (subject, fn, thisContext) {
2720
+ if (subject instanceof Array) {
2721
+ return forEachArray(subject, fn, thisContext);
2722
+ }
2723
+ else {
2724
+ return forEachObject(subject, fn, thisContext);
2725
+ }
2726
+ };
2727
+ },{"./array/forEach":19,"./object/forEach":46}],31:[function(_require,module,exports){
2728
+ 'use strict';
2729
+
2730
+ var applyWithContext = _require('./applyWithContext');
2731
+ var applyNoContext = _require('./applyNoContext');
2732
+
2733
+ /**
2734
+ * # Apply
2735
+ *
2736
+ * Faster version of `Function::apply()`, optimised for 8 arguments or fewer.
2737
+ *
2738
+ *
2739
+ * @param {Function} subject The function to apply.
2740
+ * @param {Object} thisContext The context for the function, set to undefined or null if no context is required.
2741
+ * @param {Array} args The arguments for the function.
2742
+ * @return {mixed} The result of the function invocation.
2743
+ */
2744
+ module.exports = function fastApply (subject, thisContext, args) {
2745
+ return thisContext !== undefined ? applyWithContext(subject, thisContext, args) : applyNoContext(subject, args);
2746
+ };
2747
+
2748
+ },{"./applyNoContext":32,"./applyWithContext":33}],32:[function(_require,module,exports){
2749
+ 'use strict';
2750
+
2751
+ /**
2752
+ * Internal helper for applying a function without a context.
2753
+ */
2754
+ module.exports = function applyNoContext (subject, args) {
2755
+ switch (args.length) {
2756
+ case 0:
2757
+ return subject();
2758
+ case 1:
2759
+ return subject(args[0]);
2760
+ case 2:
2761
+ return subject(args[0], args[1]);
2762
+ case 3:
2763
+ return subject(args[0], args[1], args[2]);
2764
+ case 4:
2765
+ return subject(args[0], args[1], args[2], args[3]);
2766
+ case 5:
2767
+ return subject(args[0], args[1], args[2], args[3], args[4]);
2768
+ case 6:
2769
+ return subject(args[0], args[1], args[2], args[3], args[4], args[5]);
2770
+ case 7:
2771
+ return subject(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
2772
+ case 8:
2773
+ return subject(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
2774
+ default:
2775
+ return subject.apply(undefined, args);
2776
+ }
2777
+ };
2778
+
2779
+ },{}],33:[function(_require,module,exports){
2780
+ 'use strict';
2781
+
2782
+ /**
2783
+ * Internal helper for applying a function with a context.
2784
+ */
2785
+ module.exports = function applyWithContext (subject, thisContext, args) {
2786
+ switch (args.length) {
2787
+ case 0:
2788
+ return subject.call(thisContext);
2789
+ case 1:
2790
+ return subject.call(thisContext, args[0]);
2791
+ case 2:
2792
+ return subject.call(thisContext, args[0], args[1]);
2793
+ case 3:
2794
+ return subject.call(thisContext, args[0], args[1], args[2]);
2795
+ case 4:
2796
+ return subject.call(thisContext, args[0], args[1], args[2], args[3]);
2797
+ case 5:
2798
+ return subject.call(thisContext, args[0], args[1], args[2], args[3], args[4]);
2799
+ case 6:
2800
+ return subject.call(thisContext, args[0], args[1], args[2], args[3], args[4], args[5]);
2801
+ case 7:
2802
+ return subject.call(thisContext, args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
2803
+ case 8:
2804
+ return subject.call(thisContext, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
2805
+ default:
2806
+ return subject.apply(thisContext, args);
2807
+ }
2808
+ };
2809
+
2810
+ },{}],34:[function(_require,module,exports){
2811
+ 'use strict';
2812
+
2813
+ var applyWithContext = _require('./applyWithContext');
2814
+ var applyNoContext = _require('./applyNoContext');
2815
+
2816
+ /**
2817
+ * # Bind
2818
+ * Analogue of `Function::bind()`.
2819
+ *
2820
+ * ```js
2821
+ * var bind = require('fast.js').bind;
2822
+ * var bound = bind(myfunc, this, 1, 2, 3);
2823
+ *
2824
+ * bound(4);
2825
+ * ```
2826
+ *
2827
+ *
2828
+ * @param {Function} fn The function which should be bound.
2829
+ * @param {Object} thisContext The context to bind the function to.
2830
+ * @param {mixed} args, ... Additional arguments to pre-bind.
2831
+ * @return {Function} The bound function.
2832
+ */
2833
+ module.exports = function fastBind (fn, thisContext) {
2834
+ var boundLength = arguments.length - 2,
2835
+ boundArgs;
2836
+
2837
+ if (boundLength > 0) {
2838
+ boundArgs = new Array(boundLength);
2839
+ for (var i = 0; i < boundLength; i++) {
2840
+ boundArgs[i] = arguments[i + 2];
2841
+ }
2842
+ if (thisContext !== undefined) {
2843
+ return function () {
2844
+ var length = arguments.length,
2845
+ args = new Array(boundLength + length),
2846
+ i;
2847
+ for (i = 0; i < boundLength; i++) {
2848
+ args[i] = boundArgs[i];
2849
+ }
2850
+ for (i = 0; i < length; i++) {
2851
+ args[boundLength + i] = arguments[i];
2852
+ }
2853
+ return applyWithContext(fn, thisContext, args);
2854
+ };
2855
+ }
2856
+ else {
2857
+ return function () {
2858
+ var length = arguments.length,
2859
+ args = new Array(boundLength + length),
2860
+ i;
2861
+ for (i = 0; i < boundLength; i++) {
2862
+ args[i] = boundArgs[i];
2863
+ }
2864
+ for (i = 0; i < length; i++) {
2865
+ args[boundLength + i] = arguments[i];
2866
+ }
2867
+ return applyNoContext(fn, args);
2868
+ };
2869
+ }
2870
+ }
2871
+ if (thisContext !== undefined) {
2872
+ return function () {
2873
+ return applyWithContext(fn, thisContext, arguments);
2874
+ };
2875
+ }
2876
+ else {
2877
+ return function () {
2878
+ return applyNoContext(fn, arguments);
2879
+ };
2880
+ }
2881
+ };
2882
+
2883
+ },{"./applyNoContext":32,"./applyWithContext":33}],35:[function(_require,module,exports){
2884
+ 'use strict';
2885
+
2886
+ /**
2887
+ * Internal helper to bind a function known to have 3 arguments
2888
+ * to a given context.
2889
+ */
2890
+ module.exports = function bindInternal3 (func, thisContext) {
2891
+ return function (a, b, c) {
2892
+ return func.call(thisContext, a, b, c);
2893
+ };
2894
+ };
2895
+
2896
+ },{}],36:[function(_require,module,exports){
2897
+ 'use strict';
2898
+
2899
+ /**
2900
+ * Internal helper to bind a function known to have 4 arguments
2901
+ * to a given context.
2902
+ */
2903
+ module.exports = function bindInternal4 (func, thisContext) {
2904
+ return function (a, b, c, d) {
2905
+ return func.call(thisContext, a, b, c, d);
2906
+ };
2907
+ };
2908
+
2909
+ },{}],37:[function(_require,module,exports){
2910
+ 'use strict';
2911
+
2912
+ exports.apply = _require('./apply');
2913
+ exports.bind = _require('./bind');
2914
+ exports.partial = _require('./partial');
2915
+ exports.partialConstructor = _require('./partialConstructor');
2916
+ exports.try = _require('./try');
2917
+
2918
+ },{"./apply":31,"./bind":34,"./partial":38,"./partialConstructor":39,"./try":40}],38:[function(_require,module,exports){
2919
+ 'use strict';
2920
+
2921
+ var applyWithContext = _require('./applyWithContext');
2922
+
2923
+ /**
2924
+ * # Partial Application
2925
+ *
2926
+ * Partially apply a function. This is similar to `.bind()`,
2927
+ * but with one important difference - the returned function is not bound
2928
+ * to a particular context. This makes it easy to add partially
2929
+ * applied methods to objects. If you need to bind to a context,
2930
+ * use `.bind()` instead.
2931
+ *
2932
+ * > Note: This function does not support partial application for
2933
+ * constructors, for that see `partialConstructor()`
2934
+ *
2935
+ *
2936
+ * @param {Function} fn The function to partially apply.
2937
+ * @param {mixed} args, ... Arguments to pre-bind.
2938
+ * @return {Function} The partially applied function.
2939
+ */
2940
+ module.exports = function fastPartial (fn) {
2941
+ var boundLength = arguments.length - 1,
2942
+ boundArgs;
2943
+
2944
+ boundArgs = new Array(boundLength);
2945
+ for (var i = 0; i < boundLength; i++) {
2946
+ boundArgs[i] = arguments[i + 1];
2947
+ }
2948
+ return function () {
2949
+ var length = arguments.length,
2950
+ args = new Array(boundLength + length),
2951
+ i;
2952
+ for (i = 0; i < boundLength; i++) {
2953
+ args[i] = boundArgs[i];
2954
+ }
2955
+ for (i = 0; i < length; i++) {
2956
+ args[boundLength + i] = arguments[i];
2957
+ }
2958
+ return applyWithContext(fn, this, args);
2959
+ };
2960
+ };
2961
+
2962
+ },{"./applyWithContext":33}],39:[function(_require,module,exports){
2963
+ 'use strict';
2964
+
2965
+ var applyWithContext = _require('./applyWithContext');
2966
+
2967
+ /**
2968
+ * # Partial Constructor
2969
+ *
2970
+ * Partially apply a constructor function. The returned function
2971
+ * will work with or without the `new` keyword.
2972
+ *
2973
+ *
2974
+ * @param {Function} fn The constructor function to partially apply.
2975
+ * @param {mixed} args, ... Arguments to pre-bind.
2976
+ * @return {Function} The partially applied constructor.
2977
+ */
2978
+ module.exports = function fastPartialConstructor (fn) {
2979
+ var boundLength = arguments.length - 1,
2980
+ boundArgs;
2981
+
2982
+ boundArgs = new Array(boundLength);
2983
+ for (var i = 0; i < boundLength; i++) {
2984
+ boundArgs[i] = arguments[i + 1];
2985
+ }
2986
+ return function partialed () {
2987
+ var length = arguments.length,
2988
+ args = new Array(boundLength + length),
2989
+ i;
2990
+ for (i = 0; i < boundLength; i++) {
2991
+ args[i] = boundArgs[i];
2992
+ }
2993
+ for (i = 0; i < length; i++) {
2994
+ args[boundLength + i] = arguments[i];
2995
+ }
2996
+
2997
+ var thisContext = Object.create(fn.prototype),
2998
+ result = applyWithContext(fn, thisContext, args);
2999
+
3000
+ if (result != null && (typeof result === 'object' || typeof result === 'function')) {
3001
+ return result;
3002
+ }
3003
+ else {
3004
+ return thisContext;
3005
+ }
3006
+ };
3007
+ };
3008
+
3009
+ },{"./applyWithContext":33}],40:[function(_require,module,exports){
3010
+ 'use strict';
3011
+
3012
+ /**
3013
+ * # Try
3014
+ *
3015
+ * Allows functions to be optimised by isolating `try {} catch (e) {}` blocks
3016
+ * outside the function declaration. Returns either the result of the function or an Error
3017
+ * object if one was thrown. The caller should then check for `result instanceof Error`.
3018
+ *
3019
+ * ```js
3020
+ * var result = fast.try(myFunction);
3021
+ * if (result instanceof Error) {
3022
+ * console.log('something went wrong');
3023
+ * }
3024
+ * else {
3025
+ * console.log('result:', result);
3026
+ * }
3027
+ * ```
3028
+ *
3029
+ * @param {Function} fn The function to invoke.
3030
+ * @return {mixed} The result of the function, or an `Error` object.
3031
+ */
3032
+ module.exports = function fastTry (fn) {
3033
+ try {
3034
+ return fn();
3035
+ }
3036
+ catch (e) {
3037
+ if (!(e instanceof Error)) {
3038
+ return new Error(e);
3039
+ }
3040
+ else {
3041
+ return e;
3042
+ }
3043
+ }
3044
+ };
3045
+
3046
+ },{}],41:[function(_require,module,exports){
3047
+ 'use strict';
3048
+
3049
+ /**
3050
+ * # Constructor
3051
+ *
3052
+ * Provided as a convenient wrapper around Fast functions.
3053
+ *
3054
+ * ```js
3055
+ * var arr = fast([1,2,3,4,5,6]);
3056
+ *
3057
+ * var result = arr.filter(function (item) {
3058
+ * return item % 2 === 0;
3059
+ * });
3060
+ *
3061
+ * result instanceof Fast; // true
3062
+ * result.length; // 3
3063
+ * ```
3064
+ *
3065
+ *
3066
+ * @param {Array} value The value to wrap.
3067
+ */
3068
+ function Fast (value) {
3069
+ if (!(this instanceof Fast)) {
3070
+ return new Fast(value);
3071
+ }
3072
+ this.value = value || [];
3073
+ }
3074
+
3075
+ module.exports = exports = Fast;
3076
+
3077
+ Fast.array = _require('./array');
3078
+ Fast['function'] = Fast.fn = _require('./function');
3079
+ Fast.object = _require('./object');
3080
+ Fast.string = _require('./string');
3081
+
3082
+
3083
+ Fast.apply = Fast['function'].apply;
3084
+ Fast.bind = Fast['function'].bind;
3085
+ Fast.partial = Fast['function'].partial;
3086
+ Fast.partialConstructor = Fast['function'].partialConstructor;
3087
+ Fast['try'] = Fast.attempt = Fast['function']['try'];
3088
+
3089
+ Fast.assign = Fast.object.assign;
3090
+ Fast.cloneObject = Fast.object.clone; // @deprecated use fast.object.clone()
3091
+ Fast.keys = Fast.object.keys;
3092
+ Fast.values = Fast.object.values;
3093
+
3094
+
3095
+ Fast.clone = _require('./clone');
3096
+ Fast.map = _require('./map');
3097
+ Fast.filter = _require('./filter');
3098
+ Fast.forEach = _require('./forEach');
3099
+ Fast.reduce = _require('./reduce');
3100
+ Fast.reduceRight = _require('./reduceRight');
3101
+
3102
+
3103
+ Fast.cloneArray = Fast.array.clone; // @deprecated use fast.array.clone()
3104
+
3105
+ Fast.concat = Fast.array.concat;
3106
+ Fast.some = Fast.array.some;
3107
+ Fast.every = Fast.array.every;
3108
+ Fast.indexOf = Fast.array.indexOf;
3109
+ Fast.lastIndexOf = Fast.array.lastIndexOf;
3110
+ Fast.pluck = Fast.array.pluck;
3111
+ Fast.fill = Fast.array.fill;
3112
+
3113
+ Fast.intern = Fast.string.intern;
3114
+
3115
+
3116
+ /**
3117
+ * # Concat
3118
+ *
3119
+ * Concatenate multiple arrays.
3120
+ *
3121
+ * @param {Array|mixed} item, ... The item(s) to concatenate.
3122
+ * @return {Fast} A new Fast object, containing the results.
3123
+ */
3124
+ Fast.prototype.concat = function Fast$concat () {
3125
+ var length = this.value.length,
3126
+ arr = new Array(length),
3127
+ i, item, childLength, j;
3128
+
3129
+ for (i = 0; i < length; i++) {
3130
+ arr[i] = this.value[i];
3131
+ }
3132
+
3133
+ length = arguments.length;
3134
+ for (i = 0; i < length; i++) {
3135
+ item = arguments[i];
3136
+ if (Array.isArray(item)) {
3137
+ childLength = item.length;
3138
+ for (j = 0; j < childLength; j++) {
3139
+ arr.push(item[j]);
3140
+ }
3141
+ }
3142
+ else {
3143
+ arr.push(item);
3144
+ }
3145
+ }
3146
+ return new Fast(arr);
3147
+ };
3148
+
3149
+ /**
3150
+ * Fast Map
3151
+ *
3152
+ * @param {Function} fn The visitor function.
3153
+ * @param {Object} thisContext The context for the visitor, if any.
3154
+ * @return {Fast} A new Fast object, containing the results.
3155
+ */
3156
+ Fast.prototype.map = function Fast$map (fn, thisContext) {
3157
+ return new Fast(Fast.map(this.value, fn, thisContext));
3158
+ };
3159
+
3160
+ /**
3161
+ * Fast Filter
3162
+ *
3163
+ * @param {Function} fn The filter function.
3164
+ * @param {Object} thisContext The context for the filter function, if any.
3165
+ * @return {Fast} A new Fast object, containing the results.
3166
+ */
3167
+ Fast.prototype.filter = function Fast$filter (fn, thisContext) {
3168
+ return new Fast(Fast.filter(this.value, fn, thisContext));
3169
+ };
3170
+
3171
+ /**
3172
+ * Fast Reduce
3173
+ *
3174
+ * @param {Function} fn The reducer function.
3175
+ * @param {mixed} initialValue The initial value, if any.
3176
+ * @param {Object} thisContext The context for the reducer, if any.
3177
+ * @return {mixed} The final result.
3178
+ */
3179
+ Fast.prototype.reduce = function Fast$reduce (fn, initialValue, thisContext) {
3180
+ return Fast.reduce(this.value, fn, initialValue, thisContext);
3181
+ };
3182
+
3183
+
3184
+ /**
3185
+ * Fast Reduce Right
3186
+ *
3187
+ * @param {Function} fn The reducer function.
3188
+ * @param {mixed} initialValue The initial value, if any.
3189
+ * @param {Object} thisContext The context for the reducer, if any.
3190
+ * @return {mixed} The final result.
3191
+ */
3192
+ Fast.prototype.reduceRight = function Fast$reduceRight (fn, initialValue, thisContext) {
3193
+ return Fast.reduceRight(this.value, fn, initialValue, thisContext);
3194
+ };
3195
+
3196
+ /**
3197
+ * Fast For Each
3198
+ *
3199
+ * @param {Function} fn The visitor function.
3200
+ * @param {Object} thisContext The context for the visitor, if any.
3201
+ * @return {Fast} The Fast instance.
3202
+ */
3203
+ Fast.prototype.forEach = function Fast$forEach (fn, thisContext) {
3204
+ Fast.forEach(this.value, fn, thisContext);
3205
+ return this;
3206
+ };
3207
+
3208
+ /**
3209
+ * Fast Some
3210
+ *
3211
+ * @param {Function} fn The matcher predicate.
3212
+ * @param {Object} thisContext The context for the matcher, if any.
3213
+ * @return {Boolean} True if at least one element matches.
3214
+ */
3215
+ Fast.prototype.some = function Fast$some (fn, thisContext) {
3216
+ return Fast.some(this.value, fn, thisContext);
3217
+ };
3218
+
3219
+ /**
3220
+ * Fast Every
3221
+ *
3222
+ * @param {Function} fn The matcher predicate.
3223
+ * @param {Object} thisContext The context for the matcher, if any.
3224
+ * @return {Boolean} True if at all elements match.
3225
+ */
3226
+ Fast.prototype.every = function Fast$every (fn, thisContext) {
3227
+ return Fast.some(this.value, fn, thisContext);
3228
+ };
3229
+
3230
+ /**
3231
+ * Fast Index Of
3232
+ *
3233
+ * @param {mixed} target The target to lookup.
3234
+ * @param {Number} fromIndex The index to start searching from, if known.
3235
+ * @return {Number} The index of the item, or -1 if no match found.
3236
+ */
3237
+ Fast.prototype.indexOf = function Fast$indexOf (target, fromIndex) {
3238
+ return Fast.indexOf(this.value, target, fromIndex);
3239
+ };
3240
+
3241
+
3242
+ /**
3243
+ * Fast Last Index Of
3244
+ *
3245
+ * @param {mixed} target The target to lookup.
3246
+ * @param {Number} fromIndex The index to start searching from, if known.
3247
+ * @return {Number} The last index of the item, or -1 if no match found.
3248
+ */
3249
+ Fast.prototype.lastIndexOf = function Fast$lastIndexOf (target, fromIndex) {
3250
+ return Fast.lastIndexOf(this.value, target, fromIndex);
3251
+ };
3252
+
3253
+ /**
3254
+ * Reverse
3255
+ *
3256
+ * @return {Fast} A new Fast instance, with the contents reversed.
3257
+ */
3258
+ Fast.prototype.reverse = function Fast$reverse () {
3259
+ return new Fast(this.value.reverse());
3260
+ };
3261
+
3262
+ /**
3263
+ * Value Of
3264
+ *
3265
+ * @return {Array} The wrapped value.
3266
+ */
3267
+ Fast.prototype.valueOf = function Fast$valueOf () {
3268
+ return this.value;
3269
+ };
3270
+
3271
+ /**
3272
+ * To JSON
3273
+ *
3274
+ * @return {Array} The wrapped value.
3275
+ */
3276
+ Fast.prototype.toJSON = function Fast$toJSON () {
3277
+ return this.value;
3278
+ };
3279
+
3280
+ /**
3281
+ * Item Length
3282
+ */
3283
+ Object.defineProperty(Fast.prototype, 'length', {
3284
+ get: function () {
3285
+ return this.value.length;
3286
+ }
3287
+ });
3288
+
3289
+ },{"./array":20,"./clone":28,"./filter":29,"./forEach":30,"./function":37,"./map":42,"./object":47,"./reduce":53,"./reduceRight":54,"./string":55}],42:[function(_require,module,exports){
3290
+ 'use strict';
3291
+
3292
+ var mapArray = _require('./array/map'),
3293
+ mapObject = _require('./object/map');
3294
+
3295
+ /**
3296
+ * # Map
3297
+ *
3298
+ * A fast `.map()` implementation.
3299
+ *
3300
+ * @param {Array|Object} subject The array or object to map over.
3301
+ * @param {Function} fn The mapper function.
3302
+ * @param {Object} thisContext The context for the mapper.
3303
+ * @return {Array|Object} The array or object containing the results.
3304
+ */
3305
+ module.exports = function fastMap (subject, fn, thisContext) {
3306
+ if (subject instanceof Array) {
3307
+ return mapArray(subject, fn, thisContext);
3308
+ }
3309
+ else {
3310
+ return mapObject(subject, fn, thisContext);
3311
+ }
3312
+ };
3313
+ },{"./array/map":23,"./object/map":49}],43:[function(_require,module,exports){
3314
+ 'use strict';
3315
+
3316
+ /**
3317
+ * Analogue of Object.assign().
3318
+ * Copies properties from one or more source objects to
3319
+ * a target object. Existing keys on the target object will be overwritten.
3320
+ *
3321
+ * > Note: This differs from spec in some important ways:
3322
+ * > 1. Will throw if passed non-objects, including `undefined` or `null` values.
3323
+ * > 2. Does not support the curious Exception handling behavior, exceptions are thrown immediately.
3324
+ * > For more details, see:
3325
+ * > https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
3326
+ *
3327
+ *
3328
+ *
3329
+ * @param {Object} target The target object to copy properties to.
3330
+ * @param {Object} source, ... The source(s) to copy properties from.
3331
+ * @return {Object} The updated target object.
3332
+ */
3333
+ module.exports = function fastAssign (target) {
3334
+ var totalArgs = arguments.length,
3335
+ source, i, totalKeys, keys, key, j;
3336
+
3337
+ for (i = 1; i < totalArgs; i++) {
3338
+ source = arguments[i];
3339
+ keys = Object.keys(source);
3340
+ totalKeys = keys.length;
3341
+ for (j = 0; j < totalKeys; j++) {
3342
+ key = keys[j];
3343
+ target[key] = source[key];
3344
+ }
3345
+ }
3346
+ return target;
3347
+ };
3348
+
3349
+ },{}],44:[function(_require,module,exports){
3350
+ 'use strict';
3351
+
3352
+ /**
3353
+ * # Clone Object
3354
+ *
3355
+ * Shallow clone a simple object.
3356
+ *
3357
+ * > Note: Prototypes and non-enumerable properties will not be copied!
3358
+ *
3359
+ * @param {Object} input The object to clone.
3360
+ * @return {Object} The cloned object.
3361
+ */
3362
+ module.exports = function fastCloneObject (input) {
3363
+ var keys = Object.keys(input),
3364
+ total = keys.length,
3365
+ cloned = {},
3366
+ i, key;
3367
+
3368
+ for (i = 0; i < total; i++) {
3369
+ key = keys[i];
3370
+ cloned[key] = input[key];
3371
+ }
3372
+
3373
+ return cloned;
3374
+ };
3375
+
3376
+ },{}],45:[function(_require,module,exports){
3377
+ 'use strict';
3378
+
3379
+ var bindInternal3 = _require('../function/bindInternal3');
3380
+
3381
+ /**
3382
+ * # Filter
3383
+ *
3384
+ * A fast object `.filter()` implementation.
3385
+ *
3386
+ * @param {Object} subject The object to filter.
3387
+ * @param {Function} fn The filter function.
3388
+ * @param {Object} thisContext The context for the filter.
3389
+ * @return {Object} The new object containing the filtered results.
3390
+ */
3391
+ module.exports = function fastFilterObject (subject, fn, thisContext) {
3392
+ var keys = Object.keys(subject),
3393
+ length = keys.length,
3394
+ result = {},
3395
+ iterator = thisContext !== undefined ? bindInternal3(fn, thisContext) : fn,
3396
+ i, key;
3397
+ for (i = 0; i < length; i++) {
3398
+ key = keys[i];
3399
+ if (iterator(subject[key], key, subject)) {
3400
+ result[key] = subject[key];
3401
+ }
3402
+ }
3403
+ return result;
3404
+ };
3405
+
3406
+ },{"../function/bindInternal3":35}],46:[function(_require,module,exports){
3407
+ 'use strict';
3408
+
3409
+ var bindInternal3 = _require('../function/bindInternal3');
3410
+
3411
+ /**
3412
+ * # For Each
3413
+ *
3414
+ * A fast object `.forEach()` implementation.
3415
+ *
3416
+ * @param {Object} subject The object to iterate over.
3417
+ * @param {Function} fn The visitor function.
3418
+ * @param {Object} thisContext The context for the visitor.
3419
+ */
3420
+ module.exports = function fastForEachObject (subject, fn, thisContext) {
3421
+ var keys = Object.keys(subject),
3422
+ length = keys.length,
3423
+ iterator = thisContext !== undefined ? bindInternal3(fn, thisContext) : fn,
3424
+ key, i;
3425
+ for (i = 0; i < length; i++) {
3426
+ key = keys[i];
3427
+ iterator(subject[key], key, subject);
3428
+ }
3429
+ };
3430
+
3431
+ },{"../function/bindInternal3":35}],47:[function(_require,module,exports){
3432
+ 'use strict';
3433
+
3434
+ exports.assign = _require('./assign');
3435
+ exports.clone = _require('./clone');
3436
+ exports.filter = _require('./filter');
3437
+ exports.forEach = _require('./forEach');
3438
+ exports.map = _require('./map');
3439
+ exports.reduce = _require('./reduce');
3440
+ exports.reduceRight = _require('./reduceRight');
3441
+ exports.keys = _require('./keys');
3442
+ exports.values = _require('./values');
3443
+ },{"./assign":43,"./clone":44,"./filter":45,"./forEach":46,"./keys":48,"./map":49,"./reduce":50,"./reduceRight":51,"./values":52}],48:[function(_require,module,exports){
3444
+ 'use strict';
3445
+
3446
+ /**
3447
+ * Object.keys() shim for ES3 environments.
3448
+ *
3449
+ * @param {Object} obj The object to get keys for.
3450
+ * @return {Array} The array of keys.
3451
+ */
3452
+ module.exports = typeof Object.keys === "function" ? Object.keys : /* istanbul ignore next */ function fastKeys (obj) {
3453
+ var keys = [];
3454
+ for (var key in obj) {
3455
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
3456
+ keys.push(key);
3457
+ }
3458
+ }
3459
+ return keys;
3460
+ };
3461
+ },{}],49:[function(_require,module,exports){
3462
+ 'use strict';
3463
+
3464
+ var bindInternal3 = _require('../function/bindInternal3');
3465
+
3466
+ /**
3467
+ * # Map
3468
+ *
3469
+ * A fast object `.map()` implementation.
3470
+ *
3471
+ * @param {Object} subject The object to map over.
3472
+ * @param {Function} fn The mapper function.
3473
+ * @param {Object} thisContext The context for the mapper.
3474
+ * @return {Object} The new object containing the results.
3475
+ */
3476
+ module.exports = function fastMapObject (subject, fn, thisContext) {
3477
+ var keys = Object.keys(subject),
3478
+ length = keys.length,
3479
+ result = {},
3480
+ iterator = thisContext !== undefined ? bindInternal3(fn, thisContext) : fn,
3481
+ i, key;
3482
+ for (i = 0; i < length; i++) {
3483
+ key = keys[i];
3484
+ result[key] = iterator(subject[key], key, subject);
3485
+ }
3486
+ return result;
3487
+ };
3488
+
3489
+ },{"../function/bindInternal3":35}],50:[function(_require,module,exports){
3490
+ 'use strict';
3491
+
3492
+ var bindInternal4 = _require('../function/bindInternal4');
3493
+
3494
+ /**
3495
+ * # Reduce
3496
+ *
3497
+ * A fast object `.reduce()` implementation.
3498
+ *
3499
+ * @param {Object} subject The object to reduce over.
3500
+ * @param {Function} fn The reducer function.
3501
+ * @param {mixed} initialValue The initial value for the reducer, defaults to subject[0].
3502
+ * @param {Object} thisContext The context for the reducer.
3503
+ * @return {mixed} The final result.
3504
+ */
3505
+ module.exports = function fastReduceObject (subject, fn, initialValue, thisContext) {
3506
+ var keys = Object.keys(subject),
3507
+ length = keys.length,
3508
+ iterator = thisContext !== undefined ? bindInternal4(fn, thisContext) : fn,
3509
+ i, key, result;
3510
+
3511
+ if (initialValue === undefined) {
3512
+ i = 1;
3513
+ result = subject[keys[0]];
3514
+ }
3515
+ else {
3516
+ i = 0;
3517
+ result = initialValue;
3518
+ }
3519
+
3520
+ for (; i < length; i++) {
3521
+ key = keys[i];
3522
+ result = iterator(result, subject[key], key, subject);
3523
+ }
3524
+
3525
+ return result;
3526
+ };
3527
+
3528
+ },{"../function/bindInternal4":36}],51:[function(_require,module,exports){
3529
+ 'use strict';
3530
+
3531
+ var bindInternal4 = _require('../function/bindInternal4');
3532
+
3533
+ /**
3534
+ * # Reduce
3535
+ *
3536
+ * A fast object `.reduce()` implementation.
3537
+ *
3538
+ * @param {Object} subject The object to reduce over.
3539
+ * @param {Function} fn The reducer function.
3540
+ * @param {mixed} initialValue The initial value for the reducer, defaults to subject[0].
3541
+ * @param {Object} thisContext The context for the reducer.
3542
+ * @return {mixed} The final result.
3543
+ */
3544
+ module.exports = function fastReduceRightObject (subject, fn, initialValue, thisContext) {
3545
+ var keys = Object.keys(subject),
3546
+ length = keys.length,
3547
+ iterator = thisContext !== undefined ? bindInternal4(fn, thisContext) : fn,
3548
+ i, key, result;
3549
+
3550
+ if (initialValue === undefined) {
3551
+ i = length - 2;
3552
+ result = subject[keys[length - 1]];
3553
+ }
3554
+ else {
3555
+ i = length - 1;
3556
+ result = initialValue;
3557
+ }
3558
+
3559
+ for (; i >= 0; i--) {
3560
+ key = keys[i];
3561
+ result = iterator(result, subject[key], key, subject);
3562
+ }
3563
+
3564
+ return result;
3565
+ };
3566
+
3567
+ },{"../function/bindInternal4":36}],52:[function(_require,module,exports){
3568
+ 'use strict';
3569
+
3570
+ /**
3571
+ * # Values
3572
+ * Return all the (enumerable) property values for an object.
3573
+ * Like Object.keys() but for values.
3574
+ *
3575
+ * @param {Object} obj The object to retrieve values from.
3576
+ * @return {Array} An array containing property values.
3577
+ */
3578
+ module.exports = function fastValues (obj) {
3579
+ var keys = Object.keys(obj),
3580
+ length = keys.length,
3581
+ values = new Array(length);
3582
+
3583
+ for (var i = 0; i < length; i++) {
3584
+ values[i] = obj[keys[i]];
3585
+ }
3586
+ return values;
3587
+ };
3588
+ },{}],53:[function(_require,module,exports){
3589
+ 'use strict';
3590
+
3591
+ var reduceArray = _require('./array/reduce'),
3592
+ reduceObject = _require('./object/reduce');
3593
+
3594
+ /**
3595
+ * # Reduce
3596
+ *
3597
+ * A fast `.reduce()` implementation.
3598
+ *
3599
+ * @param {Array|Object} subject The array or object to reduce over.
3600
+ * @param {Function} fn The reducer function.
3601
+ * @param {mixed} initialValue The initial value for the reducer, defaults to subject[0].
3602
+ * @param {Object} thisContext The context for the reducer.
3603
+ * @return {Array|Object} The array or object containing the results.
3604
+ */
3605
+ module.exports = function fastReduce (subject, fn, initialValue, thisContext) {
3606
+ if (subject instanceof Array) {
3607
+ return reduceArray(subject, fn, initialValue, thisContext);
3608
+ }
3609
+ else {
3610
+ return reduceObject(subject, fn, initialValue, thisContext);
3611
+ }
3612
+ };
3613
+ },{"./array/reduce":25,"./object/reduce":50}],54:[function(_require,module,exports){
3614
+ 'use strict';
3615
+
3616
+ var reduceRightArray = _require('./array/reduceRight'),
3617
+ reduceRightObject = _require('./object/reduceRight');
3618
+
3619
+ /**
3620
+ * # Reduce Right
3621
+ *
3622
+ * A fast `.reduceRight()` implementation.
3623
+ *
3624
+ * @param {Array|Object} subject The array or object to reduce over.
3625
+ * @param {Function} fn The reducer function.
3626
+ * @param {mixed} initialValue The initial value for the reducer, defaults to subject[0].
3627
+ * @param {Object} thisContext The context for the reducer.
3628
+ * @return {Array|Object} The array or object containing the results.
3629
+ */
3630
+ module.exports = function fastReduceRight (subject, fn, initialValue, thisContext) {
3631
+ if (subject instanceof Array) {
3632
+ return reduceRightArray(subject, fn, initialValue, thisContext);
3633
+ }
3634
+ else {
3635
+ return reduceRightObject(subject, fn, initialValue, thisContext);
3636
+ }
3637
+ };
3638
+ },{"./array/reduceRight":26,"./object/reduceRight":51}],55:[function(_require,module,exports){
3639
+ 'use strict';
3640
+
3641
+ exports.intern = _require('./intern');
3642
+ },{"./intern":56}],56:[function(_require,module,exports){
3643
+ 'use strict';
3644
+
3645
+ // Compilers such as V8 use string interning to make string comparison very fast and efficient,
3646
+ // as efficient as comparing two references to the same object.
3647
+ //
3648
+ //
3649
+ // V8 does its best to intern strings automatically where it can, for instance:
3650
+ // ```js
3651
+ // var greeting = "hello world";
3652
+ // ```
3653
+ // With this, comparison will be very fast:
3654
+ // ```js
3655
+ // if (greeting === "hello world") {}
3656
+ // ```
3657
+ // However, there are several cases where V8 cannot intern the string, and instead
3658
+ // must resort to byte-wise comparison. This can be signficantly slower for long strings.
3659
+ // The most common example is string concatenation:
3660
+ // ```js
3661
+ // function subject () { return "world"; };
3662
+ // var greeting = "hello " + subject();
3663
+ // ```
3664
+ // In this case, V8 cannot intern the string. So this comparison is *much* slower:
3665
+ // ```js
3666
+ // if (greeting === "hello world") {}
3667
+ // ```
3668
+
3669
+
3670
+
3671
+ // At the moment, the fastest, safe way of interning a string is to
3672
+ // use it as a key in an object, and then use that key.
3673
+ //
3674
+ // Note: This technique comes courtesy of Petka Antonov - http://jsperf.com/istrn/11
3675
+ //
3676
+ // We create a container object in hash mode.
3677
+ // Most strings being interned will not be valid fast property names,
3678
+ // so we ensure hash mode now to avoid transitioning the object mode at runtime.
3679
+ var container = {'- ': true};
3680
+ delete container['- '];
3681
+
3682
+
3683
+ /**
3684
+ * Intern a string to make comparisons faster.
3685
+ *
3686
+ * > Note: This is a relatively expensive operation, you
3687
+ * shouldn't usually do the actual interning at runtime, instead
3688
+ * use this at compile time to make future work faster.
3689
+ *
3690
+ * @param {String} string The string to intern.
3691
+ * @return {String} The interned string.
3692
+ */
3693
+ module.exports = function fastIntern (string) {
3694
+ container[string] = true;
3695
+ var interned = Object.keys(container)[0];
3696
+ delete container[interned];
3697
+ return interned;
3698
+ };
3699
+ },{}],57:[function(_require,module,exports){
3700
+ /** generate unique id for selector */
3701
+ var counter = Date.now() % 1e9;
3702
+
3703
+ module.exports = function getUid(){
3704
+ return (Math.random() * 1e9 >>> 0) + (counter++);
3705
+ };
3706
+ },{}],58:[function(_require,module,exports){
3707
+ /*global window*/
3708
+
3709
+ /**
3710
+ * Check if object is dom node.
3711
+ *
3712
+ * @param {Object} val
3713
+ * @return {Boolean}
3714
+ * @api public
3715
+ */
3716
+
3717
+ module.exports = function isNode(val){
3718
+ if (!val || typeof val !== 'object') return false;
3719
+ if (window && 'object' == typeof window.Node) return val instanceof window.Node;
3720
+ return 'number' == typeof val.nodeType && 'string' == typeof val.nodeName;
3721
+ }
3722
+
3723
+ },{}],59:[function(_require,module,exports){
3724
+ (function (root, factory){
3725
+ 'use strict';
3726
+
3727
+ /*istanbul ignore next:cant test*/
3728
+ if (typeof module === 'object' && typeof module.exports === 'object') {
3729
+ module.exports = factory();
3730
+ } else if (typeof define === 'function' && define.amd) {
3731
+ // AMD. Register as an anonymous module.
3732
+ define([], factory);
3733
+ } else {
3734
+ // Browser globals
3735
+ root.objectPath = factory();
3736
+ }
3737
+ })(this, function(){
3738
+ 'use strict';
3739
+
3740
+ var
3741
+ toStr = Object.prototype.toString,
3742
+ _hasOwnProperty = Object.prototype.hasOwnProperty;
3743
+
3744
+ function isEmpty(value){
3745
+ if (!value) {
3746
+ return true;
3747
+ }
3748
+ if (isArray(value) && value.length === 0) {
3749
+ return true;
3750
+ } else {
3751
+ for (var i in value) {
3752
+ if (_hasOwnProperty.call(value, i)) {
3753
+ return false;
3754
+ }
3755
+ }
3756
+ return true;
3757
+ }
3758
+ }
3759
+
3760
+ function toString(type){
3761
+ return toStr.call(type);
3762
+ }
3763
+
3764
+ function isNumber(value){
3765
+ return typeof value === 'number' || toString(value) === "[object Number]";
3766
+ }
3767
+
3768
+ function isString(obj){
3769
+ return typeof obj === 'string' || toString(obj) === "[object String]";
3770
+ }
3771
+
3772
+ function isObject(obj){
3773
+ return typeof obj === 'object' && toString(obj) === "[object Object]";
3774
+ }
3775
+
3776
+ function isArray(obj){
3777
+ return typeof obj === 'object' && typeof obj.length === 'number' && toString(obj) === '[object Array]';
3778
+ }
3779
+
3780
+ function isBoolean(obj){
3781
+ return typeof obj === 'boolean' || toString(obj) === '[object Boolean]';
3782
+ }
3783
+
3784
+ function getKey(key){
3785
+ var intKey = parseInt(key);
3786
+ if (intKey.toString() === key) {
3787
+ return intKey;
3788
+ }
3789
+ return key;
3790
+ }
3791
+
3792
+ function set(obj, path, value, doNotReplace){
3793
+ if (isNumber(path)) {
3794
+ path = [path];
3795
+ }
3796
+ if (isEmpty(path)) {
3797
+ return obj;
3798
+ }
3799
+ if (isString(path)) {
3800
+ return set(obj, path.split('.').map(getKey), value, doNotReplace);
3801
+ }
3802
+ var currentPath = path[0];
3803
+
3804
+ if (path.length === 1) {
3805
+ var oldVal = obj[currentPath];
3806
+ if (oldVal === void 0 || !doNotReplace) {
3807
+ obj[currentPath] = value;
3808
+ }
3809
+ return oldVal;
3810
+ }
3811
+
3812
+ if (obj[currentPath] === void 0) {
3813
+ //check if we assume an array
3814
+ if(isNumber(path[1])) {
3815
+ obj[currentPath] = [];
3816
+ } else {
3817
+ obj[currentPath] = {};
3818
+ }
3819
+ }
3820
+
3821
+ return set(obj[currentPath], path.slice(1), value, doNotReplace);
3822
+ }
3823
+
3824
+ function del(obj, path) {
3825
+ if (isNumber(path)) {
3826
+ path = [path];
3827
+ }
3828
+
3829
+ if (isEmpty(obj)) {
3830
+ return void 0;
3831
+ }
3832
+
3833
+ if (isEmpty(path)) {
3834
+ return obj;
3835
+ }
3836
+ if(isString(path)) {
3837
+ return del(obj, path.split('.'));
3838
+ }
3839
+
3840
+ var currentPath = getKey(path[0]);
3841
+ var oldVal = obj[currentPath];
3842
+
3843
+ if(path.length === 1) {
3844
+ if (oldVal !== void 0) {
3845
+ if (isArray(obj)) {
3846
+ obj.splice(currentPath, 1);
3847
+ } else {
3848
+ delete obj[currentPath];
3849
+ }
3850
+ }
3851
+ } else {
3852
+ if (obj[currentPath] !== void 0) {
3853
+ return del(obj[currentPath], path.slice(1));
3854
+ }
3855
+ }
3856
+
3857
+ return obj;
3858
+ }
3859
+
3860
+ var objectPath = {};
3861
+
3862
+ objectPath.has = function (obj, path) {
3863
+ if (isEmpty(obj)) {
3864
+ return false;
3865
+ }
3866
+
3867
+ if (isNumber(path)) {
3868
+ path = [path];
3869
+ } else if (isString(path)) {
3870
+ path = path.split('.');
3871
+ }
3872
+
3873
+ if (isEmpty(path) || path.length === 0) {
3874
+ return false;
3875
+ }
3876
+
3877
+ for (var i = 0; i < path.length; i++) {
3878
+ var j = path[i];
3879
+ if ((isObject(obj) || isArray(obj)) && _hasOwnProperty.call(obj, j)) {
3880
+ obj = obj[j];
3881
+ } else {
3882
+ return false;
3883
+ }
3884
+ }
3885
+
3886
+ return true;
3887
+ };
3888
+
3889
+ objectPath.ensureExists = function (obj, path, value){
3890
+ return set(obj, path, value, true);
3891
+ };
3892
+
3893
+ objectPath.set = function (obj, path, value, doNotReplace){
3894
+ return set(obj, path, value, doNotReplace);
3895
+ };
3896
+
3897
+ objectPath.insert = function (obj, path, value, at){
3898
+ var arr = objectPath.get(obj, path);
3899
+ at = ~~at;
3900
+ if (!isArray(arr)) {
3901
+ arr = [];
3902
+ objectPath.set(obj, path, arr);
3903
+ }
3904
+ arr.splice(at, 0, value);
3905
+ };
3906
+
3907
+ objectPath.empty = function(obj, path) {
3908
+ if (isEmpty(path)) {
3909
+ return obj;
3910
+ }
3911
+ if (isEmpty(obj)) {
3912
+ return void 0;
3913
+ }
3914
+
3915
+ var value, i;
3916
+ if (!(value = objectPath.get(obj, path))) {
3917
+ return obj;
3918
+ }
3919
+
3920
+ if (isString(value)) {
3921
+ return objectPath.set(obj, path, '');
3922
+ } else if (isBoolean(value)) {
3923
+ return objectPath.set(obj, path, false);
3924
+ } else if (isNumber(value)) {
3925
+ return objectPath.set(obj, path, 0);
3926
+ } else if (isArray(value)) {
3927
+ value.length = 0;
3928
+ } else if (isObject(value)) {
3929
+ for (i in value) {
3930
+ if (_hasOwnProperty.call(value, i)) {
3931
+ delete value[i];
3932
+ }
3933
+ }
3934
+ } else {
3935
+ return objectPath.set(obj, path, null);
3936
+ }
3937
+ };
3938
+
3939
+ objectPath.push = function (obj, path /*, values */){
3940
+ var arr = objectPath.get(obj, path);
3941
+ if (!isArray(arr)) {
3942
+ arr = [];
3943
+ objectPath.set(obj, path, arr);
3944
+ }
3945
+
3946
+ arr.push.apply(arr, Array.prototype.slice.call(arguments, 2));
3947
+ };
3948
+
3949
+ objectPath.coalesce = function (obj, paths, defaultValue) {
3950
+ var value;
3951
+
3952
+ for (var i = 0, len = paths.length; i < len; i++) {
3953
+ if ((value = objectPath.get(obj, paths[i])) !== void 0) {
3954
+ return value;
3955
+ }
3956
+ }
3957
+
3958
+ return defaultValue;
3959
+ };
3960
+
3961
+ objectPath.get = function (obj, path, defaultValue){
3962
+ if (isNumber(path)) {
3963
+ path = [path];
3964
+ }
3965
+ if (isEmpty(path)) {
3966
+ return obj;
3967
+ }
3968
+ if (isEmpty(obj)) {
3969
+ return defaultValue;
3970
+ }
3971
+ if (isString(path)) {
3972
+ return objectPath.get(obj, path.split('.'), defaultValue);
3973
+ }
3974
+
3975
+ var currentPath = getKey(path[0]);
3976
+
3977
+ if (path.length === 1) {
3978
+ if (obj[currentPath] === void 0) {
3979
+ return defaultValue;
3980
+ }
3981
+ return obj[currentPath];
3982
+ }
3983
+
3984
+ return objectPath.get(obj[currentPath], path.slice(1), defaultValue);
3985
+ };
3986
+
3987
+ objectPath.del = function(obj, path) {
3988
+ return del(obj, path);
3989
+ };
3990
+
3991
+ return objectPath;
3992
+ });
3993
+
3994
+ },{}],60:[function(_require,module,exports){
3995
+ /**
3996
+ * Module Dependencies.
3997
+ */
3998
+
3999
+ var raf = _require('raf');
4000
+
4001
+ /**
4002
+ * Export `throttle`.
4003
+ */
4004
+
4005
+ module.exports = throttle;
4006
+
4007
+ /**
4008
+ * Executes a function at most once per animation frame. Kind of like
4009
+ * throttle, but it throttles at ~60Hz.
4010
+ *
4011
+ * @param {Function} fn - the Function to throttle once per animation frame
4012
+ * @return {Function}
4013
+ * @public
4014
+ */
4015
+
4016
+ function throttle(fn) {
4017
+ var rtn;
4018
+ var ignoring = false;
4019
+
4020
+ return function queue() {
4021
+ if (ignoring) return rtn;
4022
+ ignoring = true;
4023
+
4024
+ raf(function() {
4025
+ ignoring = false;
4026
+ });
4027
+
4028
+ rtn = fn.apply(this, arguments);
4029
+ return rtn;
4030
+ };
4031
+ }
4032
+
4033
+ },{"raf":10}],61:[function(_require,module,exports){
4034
+ module.exports = exports = _require('./lib/sliced');
4035
+
4036
+ },{"./lib/sliced":62}],62:[function(_require,module,exports){
4037
+
4038
+ /**
4039
+ * An Array.prototype.slice.call(arguments) alternative
4040
+ *
4041
+ * @param {Object} args something with a length
4042
+ * @param {Number} slice
4043
+ * @param {Number} sliceEnd
4044
+ * @api public
4045
+ */
4046
+
4047
+ module.exports = function (args, slice, sliceEnd) {
4048
+ var ret = [];
4049
+ var len = args.length;
4050
+
4051
+ if (0 === len) return ret;
4052
+
4053
+ var start = slice < 0
4054
+ ? Math.max(0, slice + len)
4055
+ : slice || 0;
4056
+
4057
+ if (sliceEnd !== undefined) {
4058
+ len = sliceEnd < 0
4059
+ ? sliceEnd + len
4060
+ : sliceEnd
4061
+ }
4062
+
4063
+ while (len-- > start) {
4064
+ ret[len - start] = args[len];
4065
+ }
4066
+
4067
+ return ret;
4068
+ }
4069
+
4070
+
4071
+ },{}]},{},[2])(2)
4072
+ });