├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── bower.json
├── example
├── dist
│ └── index.html
└── src
│ ├── Main.purs
│ └── Options.purs
├── package.json
└── src
└── Halogen
└── ECharts.purs
/.gitignore:
--------------------------------------------------------------------------------
1 | /.*
2 | !/.gitignore
3 | !/.travis.yml
4 | /bower_components/
5 | /node_modules/
6 | /output/
7 | /example/dist/test.js
8 | package-lock.json
9 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | dist: trusty
3 | sudo: required
4 | node_js: stable
5 | install:
6 | - npm install
7 | - npm install -g bower
8 | - bower install
9 | script:
10 | - npm run build
11 | - npm run example
12 | after_success:
13 | - >-
14 | test $TRAVIS_TAG &&
15 | echo $GITHUB_TOKEN | pulp login &&
16 | echo y | pulp publish --no-push
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # purescript-halogen-echarts
2 |
3 | [](https://github.com/slamdata/purescript-halogen-echarts/releases)
4 | [](https://travis-ci.org/slamdata/purescript-halogen-echarts)
5 |
6 | Halogen integration for Echarts via the `purescript-echarts` library.
7 |
8 | ## Installation
9 |
10 | ``` purescript
11 | bower install purescript-halogen-echarts
12 | ```
13 |
14 | ## Notes
15 |
16 | - `purescript-echarts` depends on the specific `echarts` version _~2.1.10_.
17 | - Please include the `echarts-all.js` file from `echarts` via `script` tag in your html, or concatenate it with the bundled JavaScript file.
18 |
19 | ## Example
20 |
21 | ```
22 | npm run example
23 | open example/dist/index.html
24 | ```
25 |
26 | ## Documentation
27 |
28 | Module documentation is [published on Pursuit](http://pursuit.purescript.org/packages/purescript-halogen-echarts).
29 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "purescript-halogen-echarts",
3 | "license": "Apache-2.0",
4 | "repository": {
5 | "type": "git",
6 | "url": "git://github.com/slamdata/purescript-halogen-echarts.git"
7 | },
8 | "ignore": [
9 | "**/.*",
10 | "bower_components",
11 | "node_modules",
12 | "output",
13 | "test",
14 | "bower.json",
15 | "package.json"
16 | ],
17 | "dependencies": {
18 | "purescript-halogen": "^3.1.1",
19 | "purescript-halogen-css": "^7.0.0",
20 | "purescript-echarts": "^10.1.0"
21 | },
22 | "devDependencies": {
23 | "purescript-random": "^3.0.0"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/example/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | purescript-halogen-echarts examples
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/example/src/Main.purs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import Prelude
4 |
5 | import Control.Monad.Aff (Aff)
6 | import Control.Monad.Eff (Eff)
7 | import Control.Monad.Eff.Class (liftEff)
8 | import Control.Monad.Eff.Random (randomInt, RANDOM)
9 | import Data.Array ((!!), length, snoc, sort, reverse, head, filter)
10 | import Data.Foldable (for_)
11 | import Data.Maybe (Maybe(..), maybe)
12 | import Data.Tuple.Nested ((/\))
13 | import ECharts.Monad (interpret)
14 | import Halogen as H
15 | import Halogen.Aff (runHalogenAff, awaitBody)
16 | import Halogen.ECharts as EC
17 | import Halogen.HTML as HH
18 | import Halogen.HTML.Events as HE
19 | import Halogen.VDom.Driver (runUI)
20 | import Options (options)
21 |
22 | randomInArray ∷ ∀ e a. Array a → Eff (random ∷ RANDOM|e) (Maybe a)
23 | randomInArray arr = do
24 | n ← randomInt 0 (length arr - 1)
25 | pure $ arr !! n
26 |
27 | type State =
28 | { arr ∷ Array Int }
29 |
30 |
31 | initialState ∷ ∀ a. a → State
32 | initialState _ = { arr: [ ] }
33 |
34 | data Query a
35 | = SetRandomOption Int a
36 | | AddChart a
37 | | RemoveChart Int a
38 | | HandleEChartsMessage Int EC.EChartsMessage a
39 |
40 | type Slot = Int
41 |
42 | type AppEffects = EC.EChartsEffects ( random ∷ RANDOM )
43 |
44 | type AffCharts = Aff AppEffects
45 |
46 | type HTML = H.ParentHTML Query EC.EChartsQuery Int AffCharts
47 | type DSL = H.ParentDSL State Query EC.EChartsQuery Int Void AffCharts
48 |
49 | comp ∷ H.Component HH.HTML Query Unit Void AffCharts
50 | comp = H.parentComponent
51 | { initialState
52 | , render
53 | , eval
54 | , receiver: const Nothing
55 | }
56 |
57 | render ∷ State → HTML
58 | render state =
59 | HH.div_
60 | $ [ HH.h1_ [ HH.text "purescript-halogen-echarts" ]
61 | , HH.button
62 | [ HE.onClick (HE.input_ AddChart) ]
63 | [ HH.text "Add chart" ]
64 | ]
65 | <> map renderOne state.arr
66 | where
67 | renderOne ix =
68 | HH.div_
69 | [ HH.div_
70 | [ HH.slot ix (EC.echarts Nothing) ({width: 400, height: 300} /\ unit)
71 | (Just <<< H.action <<< HandleEChartsMessage ix)
72 | ]
73 | , HH.button
74 | [ HE.onClick (HE.input_ (SetRandomOption ix)) ]
75 | [ HH.text "Set random option" ]
76 | , HH.button
77 | [ HE.onClick (HE.input_ (RemoveChart ix)) ]
78 | [ HH.text "Remove" ]
79 | ]
80 |
81 | eval ∷ Query ~> DSL
82 | eval (SetRandomOption ix next) = do
83 | mbopt ← liftEff $ randomInArray options
84 | for_ mbopt \opt →
85 | void $ H.query ix $ H.action $ EC.Reset $ interpret opt
86 | pure next
87 | eval (AddChart next) = do
88 | H.modify (\x → x{arr = snoc x.arr (maybe 0 (add one) $ head $ reverse $ sort x.arr)})
89 | pure next
90 | eval (RemoveChart ix next) = do
91 | H.modify (\x → x{arr = filter (_ /= ix) x.arr})
92 | pure next
93 | eval (HandleEChartsMessage ix EC.Initialized next) = do
94 | mbopt ← liftEff $ randomInArray options
95 | for_ mbopt \opt →
96 | void $ H.query ix $ H.action $ EC.Set $ interpret opt
97 | pure next
98 | eval (HandleEChartsMessage ix (EC.EventRaised evt) next) = do
99 | pure next
100 |
101 |
102 | main ∷ Eff AppEffects Unit
103 | main = runHalogenAff do
104 | body ← awaitBody
105 | runUI comp unit body
106 |
--------------------------------------------------------------------------------
/example/src/Options.purs:
--------------------------------------------------------------------------------
1 | module Options (options) where
2 |
3 | import Prelude
4 |
5 | import Data.Foldable as F
6 |
7 | import ECharts.Commands as E
8 | import ECharts.Types as ET
9 | import ECharts.Types.Phantom as ETP
10 | import ECharts.Monad (DSL')
11 |
12 | lineOptions ∷ DSL' ETP.OptionI
13 | lineOptions = do
14 | E.tooltip E.triggerAxis
15 | E.legend do
16 | E.leftLeft
17 | E.items
18 | $ map ET.strItem
19 | [ "email marketing"
20 | , "affiliate advertising"
21 | , "video ads"
22 | , "direct access"
23 | , "search engine"
24 | ]
25 | E.toolbox do
26 | E.shown
27 | E.leftRight
28 | E.topBottom
29 | E.feature do
30 | E.dataView do
31 | E.hidden
32 | E.readOnly false
33 | E.magicType do
34 | E.magics do
35 | E.magicStack
36 | E.magicTiled
37 | E.magicBar
38 | E.magicLine
39 | E.restore E.shown
40 | E.saveAsImage E.shown
41 | E.xAxis do
42 | E.axisType ET.Category
43 | E.disabledBoundaryGap
44 | E.items
45 | $ map ET.strItem
46 | [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" ]
47 | E.yAxis $ E.axisType $ ET.Value
48 | E.series do
49 | E.line do
50 | E.name "email marketing"
51 | E.items $ map ET.numItem [ 120.0, 132.0, 101.0, 134.0, 90.0, 230.0, 210.0 ]
52 | E.line do
53 | E.name "affiliate advertising"
54 | E.items $ map ET.numItem [ 220.0, 182.0, 191.0, 234.0, 290.0, 330.0, 310.0 ]
55 | E.line do
56 | E.name "video ads"
57 | E.stack "total"
58 | E.items $ map ET.numItem [ 150.0, 232.0, 201.0, 154.0, 190.0, 330.0, 410.0 ]
59 | E.line do
60 | E.name "direct access"
61 | E.items $ map ET.numItem [ 320.0, 332.0, 301.0, 334.0, 390.0, 330.0, 320.0 ]
62 |
63 | E.line do
64 | E.name "search engine"
65 | E.items $ map ET.numItem [ 820.0, 932.0, 901.0, 934.0, 1290.0, 1330.0, 1320.0 ]
66 |
67 |
68 | graphOptions ∷ DSL' ETP.OptionI
69 | graphOptions = do
70 | E.title $ E.text "Graph"
71 | E.tooltip $ pure unit
72 | E.animationDurationUpdate 1500
73 | E.animationEasingUpdateQuinticInOut
74 | E.series do
75 | E.graph do
76 | E.layoutNone
77 | E.symbolSize 50
78 | E.roam true
79 | E.label $ E.normalLabel E.shown
80 |
81 | E.edgeSymbols do
82 | E.circleEdgeSymbol
83 | E.arrowEdgeSymbol
84 | E.edgeSymbolSizes 4 10
85 |
86 | E.edgeLabel $ E.normalEdgeLabel $ E.textStyle $ E.fontSize 20
87 |
88 | E.lineStylePair$ E.normalLineStyle do
89 | E.opacity 0.9
90 | E.width 2
91 | E.curveness 0.0
92 |
93 | E.buildItems do
94 | E.addItem do
95 | E.name "one"
96 | E.x 300.0
97 | E.y 300.0
98 | E.addItem do
99 | E.name "two"
100 | E.x 600.0
101 | E.y 300.0
102 | E.addItem do
103 | E.name "three"
104 | E.x 450.0
105 | E.y 100.0
106 | E.addItem do
107 | E.name "four"
108 | E.x 450.0
109 | E.y 500.0
110 | E.buildLinks do
111 | E.addLink do
112 | E.sourceIx 0
113 | E.targetIx 1
114 | E.symbolSizes 5 20
115 | E.label $ E.normalLabel E.shown
116 | E.lineStylePair $ E.normalLineStyle do
117 | E.width 5
118 | E.curveness 0.2
119 | E.addLink do
120 | E.sourceName "two"
121 | E.targetName "three"
122 | E.label $ E.normalLabel E.shown
123 | E.lineStylePair$ E.normalLineStyle $ E.curveness 0.2
124 | E.addLink do
125 | E.sourceName "one"
126 | E.targetName "three"
127 | E.addLink do
128 | E.sourceName "two"
129 | E.targetName "three"
130 | E.addLink do
131 | E.sourceName "two"
132 | E.targetName "four"
133 | E.addLink do
134 | E.sourceName "one"
135 | E.targetName "four"
136 |
137 |
138 | radarOptions ∷ DSL' ETP.OptionI
139 | radarOptions = do
140 | E.radar do
141 | E.indicators do
142 | E.indicator do
143 | E.name "sales"
144 | E.max 6000.0
145 | E.indicator do
146 | E.name "Administration"
147 | E.max 16000.0
148 | E.indicator do
149 | E.name "IT"
150 | E.max 30000.0
151 | E.indicator do
152 | E.name "Development"
153 | E.max 52000.0
154 | E.indicator do
155 | E.name "Customer Support"
156 | E.max 38000.0
157 | E.indicator do
158 | E.name "Marketing"
159 | E.max 25000.0
160 | E.series $ E.radarSeries do
161 | E.name "budget vs spending"
162 | E.buildItems do
163 | E.addItem do
164 | E.name "Allocated"
165 | E.values [ 4300.0, 10000.0, 28000.0, 35000.0, 50000.0, 19000.0 ]
166 | E.addItem do
167 | E.name "Actual"
168 | E.values [ 5000.0, 14000.0, 28000.0, 31000.0, 42000.0, 21000.0 ]
169 |
170 | kOptions ∷ DSL' ETP.OptionI
171 | kOptions = do
172 | E.xAxis do
173 | E.axisType ET.Category
174 | E.items $ map ET.strItem ["2013/1/24", "2013/1/25", "2013/1/28", "2013/1/29", "2013/1/30" ]
175 | E.yAxis do
176 | E.axisType ET.Value
177 | E.min 2200.0
178 | E.scale true
179 | E.series $ E.candlestick do
180 | E.buildItems
181 | $ F.traverse_ (E.addItem <<< E.values)
182 | [ [ 2320.26, 2302.6, 2287.3, 2362.94 ]
183 | , [ 2300.00, 2291.3, 2288.26, 2308.38 ]
184 | , [ 2295.35, 2346.5, 2295.35, 2346.92 ]
185 | , [ 2347.22, 2358.98, 2337.35, 2363.8 ]
186 | , [ 2360.75, 2382.48, 2347.89, 2383.76 ]
187 | ]
188 |
189 |
190 | funnelOptions ∷ DSL' ETP.OptionI
191 | funnelOptions = do
192 | E.series $ E.funnel do
193 | E.ascending
194 | E.buildItems do
195 | E.addItem do
196 | E.name "foo"
197 | E.value 60.0
198 | E.addItem do
199 | E.name "bar"
200 | E.value 80.0
201 | E.addItem do
202 | E.name "baz"
203 | E.value 12.0
204 | E.addItem do
205 | E.name "quux"
206 | E.value 123.0
207 |
208 |
209 | options ∷ Array (DSL' ETP.OptionI)
210 | options =
211 | [ lineOptions
212 | , graphOptions
213 | , radarOptions
214 | , kOptions
215 | , funnelOptions
216 | ]
217 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "private": true,
3 | "scripts": {
4 | "clean": "rm -rf output .pulp-cache example/dist/test.js",
5 | "build": "pulp build -- --censor-lib --strict",
6 | "example": "pulp browserify --include example/src --to example/dist/test.js",
7 | "build:non-strict": "pulp build -- --censor-lib"
8 | },
9 | "dependencies": {
10 | "pulp": "^12.0.1",
11 | "purescript": "^0.11.6",
12 | "purescript-psa": "^0.5.1"
13 | },
14 | "devDependencies": {
15 | "echarts": "cryogenian/echarts#item-value-unshift-prebuild"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Halogen/ECharts.purs:
--------------------------------------------------------------------------------
1 | module Halogen.ECharts
2 | ( echarts
3 | , echarts'
4 | , EChartsState
5 | , EChartsQuery(..)
6 | , EChartsMessage(..)
7 | , EChartsEffects
8 | ) where
9 |
10 | import Prelude
11 |
12 | import CSS.Geometry (width, height)
13 | import CSS.Size (px)
14 | import Control.Monad.Aff.AVar (AVAR)
15 | import Control.Monad.Aff.Class (class MonadAff)
16 | import Control.Monad.Eff.Class (liftEff)
17 | import Control.Monad.Eff.Exception (EXCEPTION)
18 | import Control.Monad.Eff.Ref (REF)
19 | import DOM (DOM)
20 | import Data.Foldable (for_, traverse_)
21 | import Data.Foreign (Foreign)
22 | import Data.Int (toNumber)
23 | import Data.Maybe (Maybe(..), maybe)
24 | import Data.Traversable (for)
25 | import Data.Tuple.Nested (type (/\), (/\))
26 | import ECharts.Chart as EC
27 | import ECharts.Event as EE
28 | import ECharts.Theme as ETheme
29 | import ECharts.Types as ET
30 | import Halogen as H
31 | import Halogen.HTML as HH
32 | import Halogen.HTML.CSS (style)
33 | import Halogen.HTML.Properties as HP
34 | import Halogen.Query.EventSource as ES
35 |
36 | type EChartsState =
37 | { chart ∷ Maybe ET.Chart
38 | , width ∷ Int
39 | , height ∷ Int
40 | }
41 |
42 | data EChartsQuery a
43 | = Init (Maybe ETheme.Theme) a
44 | | HandleEvent ET.EChartsEvent (H.SubscribeStatus → a)
45 | | Dispose a
46 | | Set ET.Option a
47 | | Reset ET.Option a
48 | | Resize a
49 | | Clear a
50 | | SetDimensions { width ∷ Int, height ∷ Int } a
51 | | GetOptions (Maybe Foreign → a)
52 | | GetWidth (Int → a)
53 | | GetHeight (Int → a)
54 | | Dispatch ET.EChartsEvent a
55 |
56 | data EChartsMessage
57 | = Initialized
58 | | EventRaised ET.EChartsEvent
59 |
60 | type EChartsEffects eff =
61 | ( echarts ∷ ET.ECHARTS
62 | , dom ∷ DOM
63 | , avar ∷ AVAR
64 | , exception ∷ EXCEPTION
65 | , ref ∷ REF
66 | | eff
67 | )
68 |
69 | type Dimensions = { width ∷ Int, height ∷ Int }
70 |
71 | type HTML = H.ComponentHTML EChartsQuery
72 |
73 | type DSL g = H.ComponentDSL EChartsState EChartsQuery EChartsMessage g
74 |
75 | echarts
76 | ∷ ∀ eff g
77 | . Maybe ETheme.Theme
78 | → (MonadAff (EChartsEffects eff) g)
79 | ⇒ H.Component HH.HTML EChartsQuery (Dimensions /\ Unit) EChartsMessage g
80 | echarts theme =
81 | echarts' theme \(dim /\ _) →
82 | Just $ H.action $ SetDimensions dim
83 |
84 | echarts'
85 | ∷ ∀ eff g i
86 | . (MonadAff (EChartsEffects eff) g)
87 | ⇒ Maybe ETheme.Theme
88 | → (Dimensions /\ i → Maybe (EChartsQuery Unit))
89 | → H.Component HH.HTML EChartsQuery (Dimensions /\ i) EChartsMessage g
90 | echarts' theme receiver = H.lifecycleComponent
91 | { initialState: \({width, height} /\ _) → { width, height, chart: Nothing }
92 | , render
93 | , eval
94 | , initializer: Just (H.action $ Init theme)
95 | , finalizer: Nothing
96 | , receiver
97 | }
98 |
99 | render
100 | ∷ EChartsState → HTML
101 | render state =
102 | HH.div
103 | [ HP.ref $ H.RefLabel "echarts"
104 | , style do
105 | height $ px $ toNumber state.height
106 | width $ px $ toNumber state.width
107 | ]
108 | []
109 |
110 | eval
111 | ∷ ∀ eff g
112 | . (MonadAff (EChartsEffects eff) g)
113 | ⇒ EChartsQuery ~> (DSL g)
114 | eval (Init theme next) = do
115 | H.getHTMLElementRef (H.RefLabel "echarts")
116 | >>= traverse_ \el → do
117 | chart ← liftEff $ maybe EC.init EC.initWithTheme theme el
118 | H.modify _{ chart = Just chart }
119 | H.subscribe
120 | $ ES.eventSource (EE.listenAll chart)
121 | ( Just <<< H.request <<< HandleEvent )
122 | H.raise Initialized
123 | pure next
124 | eval (HandleEvent evt reply) = do
125 | H.raise $ EventRaised evt
126 | pure $ reply H.Listening
127 | eval (Dispose next) = do
128 | state ← H.get
129 | for_ state.chart $ liftEff <<< EC.dispose
130 | pure next
131 | eval (Set opts next) = do
132 | state ← H.get
133 | for_ state.chart $ liftEff <<< EC.setOption opts
134 | pure next
135 | eval (Reset opts next) = do
136 | state ← H.get
137 | for_ state.chart $ liftEff <<< EC.resetOption opts
138 | pure next
139 | eval (Resize next) = do
140 | state ← H.get
141 | for_ state.chart $ liftEff <<< EC.resize
142 | pure next
143 | eval (Clear next) = do
144 | state ← H.get
145 | for_ state.chart $ liftEff <<< EC.clear
146 | pure next
147 | eval (SetDimensions { width, height } next) = do
148 | state ← H.get
149 |
150 | -- Only trigger a resize is the dimensions have actually changed.
151 | when (width /= state.width || height /= state.height)
152 | do H.modify _{ width = width, height = height }
153 | for_ state.chart $ liftEff <<< EC.resize
154 | pure next
155 | eval (GetOptions continue) = do
156 | state ← H.get
157 | mbOptions ← for state.chart $ liftEff <<< EC.getOption
158 | pure $ continue mbOptions
159 | eval (GetWidth continue) = do
160 | map continue $ H.gets _.width
161 | eval (GetHeight continue) = do
162 | map continue $ H.gets _.height
163 | eval (Dispatch a next) = do
164 | state ← H.get
165 | for_ state.chart $ EE.dispatch a
166 | pure next
167 |
--------------------------------------------------------------------------------