peity_vanilla_rails 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c48643fc2950ad8495f99384593c7fd1ee26732b64c9df86b62781b738a25ce
4
- data.tar.gz: c6ef11ccda4de91fd692c17902255a719b64cfb8038dbd0aefa02ffb13b107ab
3
+ metadata.gz: 53261d4741de90d14704c23e23624151184465c0e1a57edcd00b32b6751167e5
4
+ data.tar.gz: f7215991dffe2cc9756842981d36714b72c779cf7fabf9f3e522fda478b2a42d
5
5
  SHA512:
6
- metadata.gz: 77de0c81a7259fb311f37804511e85654e1bd91eca5dc3a487d2b49a8a5b433a2100eaa6af5ff5c012070188316e60f3af5e9079f8902377e901efd38777b7dd
7
- data.tar.gz: eab3b26b503ebf900d799a8cbdca94aee4acc85bc57fbba4144a9be393d03c889c0802d47931e9decfc44025d11161a3e5faab25db16c2a75933fef19276a6d6
6
+ metadata.gz: 38eb290c3931f3fcb6ddb0b0397e039793a15b1475915839b02575640b413cd48fecd97b0e327cfe8cf4992096af73c9e6c645fee297525bcf01e7792f0d00c6
7
+ data.tar.gz: ca345ad7e083cb26559c9605235718795e81a374ea819e6349f09f239475c254c028cc22ba3ebd7bdb94d7656edfa1c465427a87d46b4a4a73e5a3498f743a9b
data/README.md CHANGED
@@ -1,20 +1,41 @@
1
1
  # Peity Vanilla Rails
2
2
 
3
- Sparklines are small but intense charts. This gem is a wrapper around [peity_vanilla](https://github.com/railsjazz/peity_vanilla) library. You can generate simple but informative charts with vanilla JS.
3
+ [![RailsJazz](https://github.com/igorkasyanchuk/rails_time_travel/blob/main/docs/my_other.svg?raw=true)](https://www.railsjazz.com)
4
4
 
5
- ![Sparklines Rails](docs/sparklines.png)
5
+ Sparklines are small but intense charts. This gem is a wrapper around [peity-vanilla](https://github.com/railsjazz/peity_vanilla) library. You can generate simple but informative charts with vanilla JS.
6
+
7
+ <img src="./docs/sparklines.png" height="400px"/>
6
8
 
7
9
  ## Usage
8
10
 
9
- 1. Add to `application.js`
11
+ 1. add gem to the `Gemfile`
12
+
13
+ ```ruby
14
+ gem "peity_vanilla_rails"
15
+ ```
16
+
17
+ 2. Add to `application.js`
18
+
19
+ ### For Assets Pipeline:
10
20
 
11
21
  ```javascript
12
- //= require peity_vanilla.js
22
+ //= require peity-vanilla-rails.js
13
23
  ```
14
24
 
15
- 2. Add charts in your code:
25
+ ### For Importmaps
16
26
 
17
- ```ruby
27
+ In `application.js`
28
+
29
+ ```js
30
+ import "peity-vanilla-rails";
31
+ ```
32
+
33
+ #### Note: After `peity-vanilla-rails.js` is imported, it will listen to changes of `peity` and `data-peity` attributes of every DOM element
34
+ Pure `peity-vanilla` library is also acessible via `peity-vanilla.js` for Assets Pipeline, and `import peity from "peity-vanilla"` for Importmaps
35
+
36
+ 3. Add charts in your code:
37
+
38
+ ```erb
18
39
  <h3>Line</h3>
19
40
  <%= peity_line_chart([115,123,234,-113,-43,-223,127,332,152,233]) %>
20
41
  <%= peity_line_chart(100.times.map{rand(100) * [1,-1].sample}, options: { width: 240, fill: 'lightgreen', stroke: 'blue' }) %>
@@ -36,16 +57,29 @@ Sparklines are small but intense charts. This gem is a wrapper around [peity_van
36
57
  <%= peity_donut_chart [236,300] %>
37
58
  ```
38
59
 
39
- ## Installation
40
- Add this line to your application's Gemfile:
60
+ ## More Examples
41
61
 
42
- ```ruby
43
- gem "peity_vanilla_rails"
44
- ```
62
+ Check the [original](https://github.com/railsjazz/peity_vanilla) page.
63
+
64
+ <img src="https://github.com/railsjazz/peity_vanilla/raw/main/docs/color.png"/>
65
+ <img src="https://github.com/railsjazz/peity_vanilla/raw/main/docs/custom.png"/>
66
+ <img src="https://github.com/railsjazz/peity_vanilla/raw/main/docs/animation.gif"/>
67
+
68
+ ```erb
69
+ <%= peity_line_chart([5,3,9,6,5,9,7,3,5,2,5,3,9,6,5,9,7,3,5,2], id: 'updating-chart') %>
45
70
 
46
- And then execute:
47
- ```bash
48
- $ bundle
71
+ <script>
72
+ var updatingChart = document.getElementById("updating-chart");
73
+
74
+ setInterval(function() {
75
+ var random = Math.round(Math.random() * 10)
76
+ var values = updatingChart.innerText.split(",")
77
+ values.shift()
78
+ values.push(random)
79
+
80
+ updatingChart.innerText = values.join(",")
81
+ }, 1000);
82
+ </script>
49
83
  ```
50
84
 
51
85
  ## Default Options
@@ -96,8 +130,14 @@ You can pass in `options` any of the attributes.
96
130
  </script>
97
131
  ```
98
132
 
133
+ ## TODO
134
+
135
+ - remote datasource and autoupdate
136
+
99
137
  ## Contributing
100
- Contribution directions go here.
138
+
139
+ You are welcome to contribute.
101
140
 
102
141
  ## License
142
+
103
143
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,503 @@
1
+ /*!
2
+ Peity Vanila Rails 0.2.0
3
+ Copyright © 2022 RailsJazz
4
+ https://railsjazz.com
5
+ */
6
+
7
+ /*!
8
+ Peity Vanila JS 0.0.8
9
+ Copyright © 2022 RailsJazz
10
+ https://railsjazz.com
11
+ */
12
+
13
+ const isFunction = (o) =>
14
+ o !== null && typeof o === "function" && !!o.apply;
15
+
16
+ const svgElement = (tag, attrs) => {
17
+ const element = document.createElementNS("http://www.w3.org/2000/svg", tag);
18
+ for (var attr in attrs) {
19
+ element.setAttribute(attr, attrs[attr]);
20
+ }
21
+ return element;
22
+ };
23
+
24
+ const svgSupported =
25
+ "createElementNS" in document && svgElement("svg", {}).createSVGRect();
26
+
27
+ class Peity {
28
+ static defaults = {};
29
+ static graphers = {};
30
+
31
+ constructor(element, type, options = {}) {
32
+ this.element = element;
33
+ this.type = type;
34
+ this.options = Object.assign(
35
+ {},
36
+ Peity.defaults[this.type],
37
+ JSON.parse(element.dataset["peity"] || "{}"),
38
+ options
39
+ );
40
+
41
+ if(this.element._peity) {
42
+ this.element._peity.destroy();
43
+ }
44
+ this.element._peity = this;
45
+ }
46
+
47
+ draw() {
48
+ const options = this.options;
49
+ Peity.graphers[this.type](this);
50
+ if (isFunction(options.after)) options.after.call(this, options);
51
+ }
52
+
53
+ fill() {
54
+ var fill = this.options.fill;
55
+
56
+ return isFunction(fill)
57
+ ? fill
58
+ : function (_, i) {
59
+ return fill[i % fill.length];
60
+ };
61
+ }
62
+
63
+ prepare(width, height) {
64
+ if (!this.svg) {
65
+ this.element.style.display = "none";
66
+ this.element.after(
67
+ (this.svg = svgElement("svg", {
68
+ class: "peity",
69
+ }))
70
+ );
71
+ }
72
+
73
+ this.svg.innerHTML = "";
74
+ this.svg.setAttribute("width", width);
75
+ this.svg.setAttribute("height", height);
76
+
77
+ return this.svg;
78
+ }
79
+
80
+ get values() {
81
+ return this.element.innerText
82
+ .split(this.options.delimiter)
83
+ .map((value) => parseFloat(value));
84
+ }
85
+
86
+ mount() {
87
+ if (!svgSupported) return;
88
+
89
+ this.element.addEventListener("DOMSubtreeModified", this.draw.bind(this));
90
+ this.draw();
91
+
92
+ this.mounted = true;
93
+ }
94
+
95
+ unmount() {
96
+ this.element.removeEventListener("DOMSubtreeModified", this.draw);
97
+ this.svg.remove();
98
+ this.mounted = false;
99
+ }
100
+
101
+ destroy() {
102
+ this.unmount();
103
+
104
+ delete this.element._peity;
105
+ }
106
+
107
+ static register(type, defaults, grapher) {
108
+ Peity.defaults[type] = defaults;
109
+ Peity.graphers[type] = grapher;
110
+ }
111
+ }
112
+
113
+ const renderer$2 = (peity) => {
114
+ if (!peity.options.delimiter) {
115
+ const delimiter = peity.element.innerText.match(/[^0-9\.]/);
116
+ peity.options.delimiter = delimiter ? delimiter[0] : ",";
117
+ }
118
+
119
+ let values = peity.values.map((n) => (n > 0 ? n : 0));
120
+
121
+ if (peity.options.delimiter == "/") {
122
+ let v1 = values[0];
123
+ let v2 = values[1];
124
+ values = [v1, Math.max(0, v2 - v1)];
125
+ }
126
+
127
+ let i = 0;
128
+ let length = values.length;
129
+ let sum = 0;
130
+
131
+ for (; i < length; i++) {
132
+ sum += values[i];
133
+ }
134
+
135
+ if (!sum) {
136
+ length = 2;
137
+ sum = 1;
138
+ values = [0, 1];
139
+ }
140
+
141
+ let diameter = peity.options.radius * 2;
142
+
143
+ const svg = peity.prepare(
144
+ peity.options.width || diameter,
145
+ peity.options.height || diameter
146
+ );
147
+
148
+ const width = svg.clientWidth;
149
+ const height = svg.clientHeight;
150
+ const cx = width / 2;
151
+ const cy = height / 2;
152
+
153
+ const radius = Math.min(cx, cy);
154
+ let innerRadius = peity.options.innerRadius;
155
+
156
+ if (peity.type == "donut" && !innerRadius) {
157
+ innerRadius = radius * 0.5;
158
+ }
159
+
160
+ const fill = peity.fill();
161
+
162
+ const scale = (value, radius) => {
163
+ const radians = (value / sum) * Math.PI * 2 - Math.PI / 2;
164
+
165
+ return [radius * Math.cos(radians) + cx, radius * Math.sin(radians) + cy];
166
+ };
167
+
168
+ let cumulative = 0;
169
+
170
+ for (i = 0; i < length; i++) {
171
+ const value = values[i];
172
+ const portion = value / sum;
173
+ let node;
174
+
175
+ if (portion == 0) continue;
176
+
177
+ if (portion == 1) {
178
+ if (innerRadius) {
179
+ const x2 = cx - 0.01;
180
+ const y1 = cy - radius;
181
+ const y2 = cy - innerRadius;
182
+
183
+ node = svgElement("path", {
184
+ d: [
185
+ "M",
186
+ cx,
187
+ y1,
188
+ "A",
189
+ radius,
190
+ radius,
191
+ 0,
192
+ 1,
193
+ 1,
194
+ x2,
195
+ y1,
196
+ "L",
197
+ x2,
198
+ y2,
199
+ "A",
200
+ innerRadius,
201
+ innerRadius,
202
+ 0,
203
+ 1,
204
+ 0,
205
+ cx,
206
+ y2,
207
+ ].join(" "),
208
+ "data-value": value,
209
+ });
210
+ } else {
211
+ node = svgElement("circle", {
212
+ cx: cx,
213
+ cy: cy,
214
+ "data-value": value,
215
+ r: radius,
216
+ });
217
+ }
218
+ } else {
219
+ const cumulativePlusValue = cumulative + value;
220
+
221
+ let d = ["M"].concat(
222
+ scale(cumulative, radius),
223
+ "A",
224
+ radius,
225
+ radius,
226
+ 0,
227
+ portion > 0.5 ? 1 : 0,
228
+ 1,
229
+ scale(cumulativePlusValue, radius),
230
+ "L"
231
+ );
232
+
233
+ if (innerRadius) {
234
+ d = d.concat(
235
+ scale(cumulativePlusValue, innerRadius),
236
+ "A",
237
+ innerRadius,
238
+ innerRadius,
239
+ 0,
240
+ portion > 0.5 ? 1 : 0,
241
+ 0,
242
+ scale(cumulative, innerRadius)
243
+ );
244
+ } else {
245
+ d.push(cx, cy);
246
+ }
247
+
248
+ cumulative += value;
249
+
250
+ node = svgElement("path", {
251
+ d: d.join(" "),
252
+ "data-value": value,
253
+ });
254
+ }
255
+
256
+ node.setAttribute("fill", fill.call(peity, value, i, values));
257
+
258
+ svg.append(node);
259
+ }
260
+ };
261
+
262
+ const defaults$2 = {
263
+ fill: ["#ff9900", "#fff4dd", "#ffc66e"],
264
+ radius: 8,
265
+ };
266
+
267
+ const renderer$1 = (peity) => {
268
+ const values = peity.values;
269
+ const max = Math.max.apply(
270
+ Math,
271
+ peity.options.max == undefined ? values : values.concat(peity.options.max)
272
+ );
273
+ const min = Math.min.apply(
274
+ Math,
275
+ peity.options.min == undefined ? values : values.concat(peity.options.min)
276
+ );
277
+
278
+ const svg = peity.prepare(peity.options.width, peity.options.height);
279
+ const width = svg.clientWidth;
280
+ const height = svg.clientHeight;
281
+ const diff = max - min;
282
+ const padding = peity.options.padding;
283
+ const fill = peity.fill();
284
+
285
+ const xScale = (input) => {
286
+ return (input * width) / values.length;
287
+ };
288
+
289
+ const yScale = (input) => {
290
+ return height - (diff ? ((input - min) / diff) * height : 1);
291
+ };
292
+
293
+ for (var i = 0; i < values.length; i++) {
294
+ let x = xScale(i + padding);
295
+ let w = xScale(i + 1 - padding) - x;
296
+ let value = values[i];
297
+ let valueY = yScale(value);
298
+ let y1 = valueY;
299
+ let y2 = valueY;
300
+ let h;
301
+
302
+ if (!diff) {
303
+ h = 1;
304
+ } else if (value < 0) {
305
+ y1 = yScale(Math.min(max, 0));
306
+ } else {
307
+ y2 = yScale(Math.max(min, 0));
308
+ }
309
+
310
+ h = y2 - y1;
311
+
312
+ if (h == 0) {
313
+ h = 1;
314
+ if (max > 0 && diff) y1--;
315
+ }
316
+
317
+ svg.append(
318
+ svgElement("rect", {
319
+ "data-value": value,
320
+ fill: fill.call(peity, value, i, values),
321
+ x: x,
322
+ y: y1,
323
+ width: w,
324
+ height: h,
325
+ })
326
+ );
327
+ }
328
+ };
329
+
330
+ const defaults$1 = {
331
+ delimiter: ",",
332
+ fill: ["#4D89F9"],
333
+ height: 16,
334
+ min: 0,
335
+ padding: 0.1,
336
+ width: 32,
337
+ };
338
+
339
+ const renderer = (peity) => {
340
+ const values = peity.values;
341
+ if (values.length == 1) values.push(values[0]);
342
+ const max = Math.max.apply(
343
+ Math,
344
+ peity.options.max == undefined ? values : values.concat(peity.options.max)
345
+ );
346
+ const min = Math.min.apply(
347
+ Math,
348
+ peity.options.min == undefined ? values : values.concat(peity.options.min)
349
+ );
350
+
351
+ const svg = peity.prepare(peity.options.width, peity.options.height);
352
+ const strokeWidth = peity.options.strokeWidth;
353
+ const width = svg.clientWidth;
354
+ const height = svg.clientHeight - strokeWidth;
355
+ const diff = max - min;
356
+
357
+ const xScale = (input) => {
358
+ return input * (width / (values.length - 1));
359
+ };
360
+
361
+ const yScale = (input) => {
362
+ let y = height;
363
+
364
+ if (diff) {
365
+ y -= ((input - min) / diff) * height;
366
+ }
367
+
368
+ return y + strokeWidth / 2;
369
+ };
370
+
371
+ let zero = yScale(Math.max(min, 0));
372
+ let coords = [0, zero];
373
+
374
+ for (var i = 0; i < values.length; i++) {
375
+ coords.push(xScale(i), yScale(values[i]));
376
+ }
377
+
378
+ coords.push(width, zero);
379
+
380
+ if (peity.options.fill) {
381
+ svg.append(
382
+ svgElement("polygon", {
383
+ fill: peity.options.fill,
384
+ points: coords.join(" "),
385
+ })
386
+ );
387
+ }
388
+
389
+ if (strokeWidth) {
390
+ svg.append(
391
+ svgElement("polyline", {
392
+ fill: "none",
393
+ points: coords.slice(2, coords.length - 2).join(" "),
394
+ stroke: peity.options.stroke,
395
+ "stroke-width": strokeWidth,
396
+ "stroke-linecap": "square",
397
+ })
398
+ );
399
+ }
400
+ };
401
+
402
+ const defaults = {
403
+ delimiter: ",",
404
+ fill: "#c6d9fd",
405
+ height: 16,
406
+ min: 0,
407
+ stroke: "#4d89f9",
408
+ strokeWidth: 1,
409
+ width: 32,
410
+ };
411
+
412
+ Peity.register("pie", defaults$2, renderer$2);
413
+ Peity.register("donut", defaults$2, renderer$2);
414
+ Peity.register("bar", defaults$1, renderer$1);
415
+ Peity.register("line", defaults, renderer);
416
+
417
+ const peity = function (element, type, options) {
418
+ const peity = new Peity(element, type, options);
419
+ peity.mount();
420
+
421
+ return peity;
422
+ };
423
+
424
+ peity.defaults = Peity.defaults;
425
+ peity.graphers = Peity.graphers;
426
+
427
+ const getPeityType = (node) => node.getAttribute('peity');
428
+
429
+ const elementFromNode = (node) => {
430
+ if (node.nodeType == Node.ELEMENT_NODE) {
431
+ return node;
432
+ }
433
+ };
434
+
435
+ const processNodeAdded = (node) => {
436
+ if (node.matches("[peity]")) {
437
+ peity(node, getPeityType(node));
438
+ }
439
+ };
440
+
441
+ const processNodeRemoved = (node) => {
442
+ if (node._peity) {
443
+ node._peity.destroy();
444
+ }
445
+ };
446
+
447
+ const processAttributeChanged = (mutation) => {
448
+ const node = mutation.target;
449
+ switch (mutation.attributeName) {
450
+ case "peity":
451
+ const type = getPeityType(node);
452
+ if (type) {
453
+ peity(node, type);
454
+ } else {
455
+ node._peity.unmount();
456
+ }
457
+ break;
458
+ case "data-peity":
459
+ if(node._peity) {
460
+ peity(node, node._peity.type);
461
+ }
462
+ break;
463
+ }
464
+ };
465
+
466
+ const callback = (mutationList, observer) => {
467
+ mutationList.forEach(function (mutation) {
468
+ switch (mutation.type) {
469
+ case "childList":
470
+ for (const node of Array.from(mutation.addedNodes)) {
471
+ const element = elementFromNode(node);
472
+ if (element) {
473
+ processNodeAdded(element);
474
+ }
475
+ }
476
+ for (const node of Array.from(mutation.removedNodes)) {
477
+ const element = elementFromNode(node);
478
+ if (element) {
479
+ processNodeRemoved(element);
480
+ }
481
+ }
482
+ break;
483
+ case "attributes":
484
+ processAttributeChanged(mutation);
485
+ break;
486
+ }
487
+ });
488
+ };
489
+
490
+ const observerOptions = {
491
+ childList: true,
492
+ attributes: true,
493
+ subtree: true,
494
+ };
495
+
496
+ const observer = new MutationObserver(callback);
497
+ observer.observe(document.documentElement, observerOptions);
498
+
499
+ for (const node of Array.from(document.documentElement.querySelectorAll('[peity]'))) {
500
+ processNodeAdded(node);
501
+ }
502
+
503
+ export { peity as default };
@@ -0,0 +1,11 @@
1
+ /*!
2
+ Peity Vanila Rails 0.2.0
3
+ Copyright © 2022 RailsJazz
4
+ https://railsjazz.com
5
+ */
6
+ var peity=function(){"use strict";
7
+ /*!
8
+ Peity Vanila JS 0.0.8
9
+ Copyright © 2022 RailsJazz
10
+ https://railsjazz.com
11
+ */const t=t=>null!==t&&"function"==typeof t&&!!t.apply,e=(t,e)=>{const i=document.createElementNS("http://www.w3.org/2000/svg",t);for(var n in e)i.setAttribute(n,e[n]);return i},i="createElementNS"in document&&e("svg",{}).createSVGRect();class n{static defaults={};static graphers={};constructor(t,e,i={}){this.element=t,this.type=e,this.options=Object.assign({},n.defaults[this.type],JSON.parse(t.dataset.peity||"{}"),i),this.element._peity&&this.element._peity.destroy(),this.element._peity=this}draw(){const e=this.options;n.graphers[this.type](this),t(e.after)&&e.after.call(this,e)}fill(){var e=this.options.fill;return t(e)?e:function(t,i){return e[i%e.length]}}prepare(t,i){return this.svg||(this.element.style.display="none",this.element.after(this.svg=e("svg",{class:"peity"}))),this.svg.innerHTML="",this.svg.setAttribute("width",t),this.svg.setAttribute("height",i),this.svg}get values(){return this.element.innerText.split(this.options.delimiter).map((t=>parseFloat(t)))}mount(){i&&(this.element.addEventListener("DOMSubtreeModified",this.draw.bind(this)),this.draw(),this.mounted=!0)}unmount(){this.element.removeEventListener("DOMSubtreeModified",this.draw),this.svg.remove(),this.mounted=!1}destroy(){this.unmount(),delete this.element._peity}static register(t,e,i){n.defaults[t]=e,n.graphers[t]=i}}const s=t=>{if(!t.options.delimiter){const e=t.element.innerText.match(/[^0-9\.]/);t.options.delimiter=e?e[0]:","}let i=t.values.map((t=>t>0?t:0));if("/"==t.options.delimiter){let t=i[0],e=i[1];i=[t,Math.max(0,e-t)]}let n=0,s=i.length,o=0;for(;n<s;n++)o+=i[n];o||(s=2,o=1,i=[0,1]);let r=2*t.options.radius;const a=t.prepare(t.options.width||r,t.options.height||r),l=a.clientWidth,h=a.clientHeight,p=l/2,c=h/2,d=Math.min(p,c);let u=t.options.innerRadius;"donut"!=t.type||u||(u=.5*d);const m=t.fill(),f=(t,e)=>{const i=t/o*Math.PI*2-Math.PI/2;return[e*Math.cos(i)+p,e*Math.sin(i)+c]};let g=0;for(n=0;n<s;n++){const s=i[n],r=s/o;let l;if(0!=r){if(1==r)if(u){const t=p-.01,i=c-d,n=c-u;l=e("path",{d:["M",p,i,"A",d,d,0,1,1,t,i,"L",t,n,"A",u,u,0,1,0,p,n].join(" "),"data-value":s})}else l=e("circle",{cx:p,cy:c,"data-value":s,r:d});else{const t=g+s;let i=["M"].concat(f(g,d),"A",d,d,0,r>.5?1:0,1,f(t,d),"L");u?i=i.concat(f(t,u),"A",u,u,0,r>.5?1:0,0,f(g,u)):i.push(p,c),g+=s,l=e("path",{d:i.join(" "),"data-value":s})}l.setAttribute("fill",m.call(t,s,n,i)),a.append(l)}}},o={fill:["#ff9900","#fff4dd","#ffc66e"],radius:8};n.register("pie",o,s),n.register("donut",o,s),n.register("bar",{delimiter:",",fill:["#4D89F9"],height:16,min:0,padding:.1,width:32},(t=>{const i=t.values,n=Math.max.apply(Math,null==t.options.max?i:i.concat(t.options.max)),s=Math.min.apply(Math,null==t.options.min?i:i.concat(t.options.min)),o=t.prepare(t.options.width,t.options.height),r=o.clientWidth,a=o.clientHeight,l=n-s,h=t.options.padding,p=t.fill(),c=t=>t*r/i.length,d=t=>a-(l?(t-s)/l*a:1);for(var u=0;u<i.length;u++){let r,a=c(u+h),m=c(u+1-h)-a,f=i[u],g=d(f),y=g,v=g;l?f<0?y=d(Math.min(n,0)):v=d(Math.max(s,0)):r=1,r=v-y,0==r&&(r=1,n>0&&l&&y--),o.append(e("rect",{"data-value":f,fill:p.call(t,f,u,i),x:a,y:y,width:m,height:r}))}})),n.register("line",{delimiter:",",fill:"#c6d9fd",height:16,min:0,stroke:"#4d89f9",strokeWidth:1,width:32},(t=>{const i=t.values;1==i.length&&i.push(i[0]);const n=Math.max.apply(Math,null==t.options.max?i:i.concat(t.options.max)),s=Math.min.apply(Math,null==t.options.min?i:i.concat(t.options.min)),o=t.prepare(t.options.width,t.options.height),r=t.options.strokeWidth,a=o.clientWidth,l=o.clientHeight-r,h=n-s,p=t=>{let e=l;return h&&(e-=(t-s)/h*l),e+r/2};let c=p(Math.max(s,0)),d=[0,c];for(var u=0;u<i.length;u++)d.push(u*(a/(i.length-1)),p(i[u]));d.push(a,c),t.options.fill&&o.append(e("polygon",{fill:t.options.fill,points:d.join(" ")})),r&&o.append(e("polyline",{fill:"none",points:d.slice(2,d.length-2).join(" "),stroke:t.options.stroke,"stroke-width":r,"stroke-linecap":"square"}))}));const r=function(t,e,i){const s=new n(t,e,i);return s.mount(),s};r.defaults=n.defaults,r.graphers=n.graphers;const a=t=>t.getAttribute("peity"),l=t=>{if(t.nodeType==Node.ELEMENT_NODE)return t},h=t=>{t.matches("[peity]")&&r(t,a(t))},p=t=>{t._peity&&t._peity.destroy()};new MutationObserver(((t,e)=>{t.forEach((function(t){switch(t.type){case"childList":for(const e of Array.from(t.addedNodes)){const t=l(e);t&&h(t)}for(const e of Array.from(t.removedNodes)){const t=l(e);t&&p(t)}break;case"attributes":(t=>{const e=t.target;switch(t.attributeName){case"peity":const t=a(e);t?r(e,t):e._peity.unmount();break;case"data-peity":e._peity&&r(e,e._peity.type)}})(t)}}))})).observe(document.documentElement,{childList:!0,attributes:!0,subtree:!0});for(const t of Array.from(document.documentElement.querySelectorAll("[peity]")))h(t);return r}();
@@ -0,0 +1,421 @@
1
+ /*!
2
+ Peity Vanila JS 0.0.8
3
+ Copyright © 2022 RailsJazz
4
+ https://railsjazz.com
5
+ */
6
+
7
+ const isFunction = (o) =>
8
+ o !== null && typeof o === "function" && !!o.apply;
9
+
10
+ const svgElement = (tag, attrs) => {
11
+ const element = document.createElementNS("http://www.w3.org/2000/svg", tag);
12
+ for (var attr in attrs) {
13
+ element.setAttribute(attr, attrs[attr]);
14
+ }
15
+ return element;
16
+ };
17
+
18
+ const svgSupported =
19
+ "createElementNS" in document && svgElement("svg", {}).createSVGRect();
20
+
21
+ class Peity {
22
+ static defaults = {};
23
+ static graphers = {};
24
+
25
+ constructor(element, type, options = {}) {
26
+ this.element = element;
27
+ this.type = type;
28
+ this.options = Object.assign(
29
+ {},
30
+ Peity.defaults[this.type],
31
+ JSON.parse(element.dataset["peity"] || "{}"),
32
+ options
33
+ );
34
+
35
+ if(this.element._peity) {
36
+ this.element._peity.destroy();
37
+ }
38
+ this.element._peity = this;
39
+ }
40
+
41
+ draw() {
42
+ const options = this.options;
43
+ Peity.graphers[this.type](this);
44
+ if (isFunction(options.after)) options.after.call(this, options);
45
+ }
46
+
47
+ fill() {
48
+ var fill = this.options.fill;
49
+
50
+ return isFunction(fill)
51
+ ? fill
52
+ : function (_, i) {
53
+ return fill[i % fill.length];
54
+ };
55
+ }
56
+
57
+ prepare(width, height) {
58
+ if (!this.svg) {
59
+ this.element.style.display = "none";
60
+ this.element.after(
61
+ (this.svg = svgElement("svg", {
62
+ class: "peity",
63
+ }))
64
+ );
65
+ }
66
+
67
+ this.svg.innerHTML = "";
68
+ this.svg.setAttribute("width", width);
69
+ this.svg.setAttribute("height", height);
70
+
71
+ return this.svg;
72
+ }
73
+
74
+ get values() {
75
+ return this.element.innerText
76
+ .split(this.options.delimiter)
77
+ .map((value) => parseFloat(value));
78
+ }
79
+
80
+ mount() {
81
+ if (!svgSupported) return;
82
+
83
+ this.element.addEventListener("DOMSubtreeModified", this.draw.bind(this));
84
+ this.draw();
85
+
86
+ this.mounted = true;
87
+ }
88
+
89
+ unmount() {
90
+ this.element.removeEventListener("DOMSubtreeModified", this.draw);
91
+ this.svg.remove();
92
+ this.mounted = false;
93
+ }
94
+
95
+ destroy() {
96
+ this.unmount();
97
+
98
+ delete this.element._peity;
99
+ }
100
+
101
+ static register(type, defaults, grapher) {
102
+ Peity.defaults[type] = defaults;
103
+ Peity.graphers[type] = grapher;
104
+ }
105
+ }
106
+
107
+ const renderer$2 = (peity) => {
108
+ if (!peity.options.delimiter) {
109
+ const delimiter = peity.element.innerText.match(/[^0-9\.]/);
110
+ peity.options.delimiter = delimiter ? delimiter[0] : ",";
111
+ }
112
+
113
+ let values = peity.values.map((n) => (n > 0 ? n : 0));
114
+
115
+ if (peity.options.delimiter == "/") {
116
+ let v1 = values[0];
117
+ let v2 = values[1];
118
+ values = [v1, Math.max(0, v2 - v1)];
119
+ }
120
+
121
+ let i = 0;
122
+ let length = values.length;
123
+ let sum = 0;
124
+
125
+ for (; i < length; i++) {
126
+ sum += values[i];
127
+ }
128
+
129
+ if (!sum) {
130
+ length = 2;
131
+ sum = 1;
132
+ values = [0, 1];
133
+ }
134
+
135
+ let diameter = peity.options.radius * 2;
136
+
137
+ const svg = peity.prepare(
138
+ peity.options.width || diameter,
139
+ peity.options.height || diameter
140
+ );
141
+
142
+ const width = svg.clientWidth;
143
+ const height = svg.clientHeight;
144
+ const cx = width / 2;
145
+ const cy = height / 2;
146
+
147
+ const radius = Math.min(cx, cy);
148
+ let innerRadius = peity.options.innerRadius;
149
+
150
+ if (peity.type == "donut" && !innerRadius) {
151
+ innerRadius = radius * 0.5;
152
+ }
153
+
154
+ const fill = peity.fill();
155
+
156
+ const scale = (value, radius) => {
157
+ const radians = (value / sum) * Math.PI * 2 - Math.PI / 2;
158
+
159
+ return [radius * Math.cos(radians) + cx, radius * Math.sin(radians) + cy];
160
+ };
161
+
162
+ let cumulative = 0;
163
+
164
+ for (i = 0; i < length; i++) {
165
+ const value = values[i];
166
+ const portion = value / sum;
167
+ let node;
168
+
169
+ if (portion == 0) continue;
170
+
171
+ if (portion == 1) {
172
+ if (innerRadius) {
173
+ const x2 = cx - 0.01;
174
+ const y1 = cy - radius;
175
+ const y2 = cy - innerRadius;
176
+
177
+ node = svgElement("path", {
178
+ d: [
179
+ "M",
180
+ cx,
181
+ y1,
182
+ "A",
183
+ radius,
184
+ radius,
185
+ 0,
186
+ 1,
187
+ 1,
188
+ x2,
189
+ y1,
190
+ "L",
191
+ x2,
192
+ y2,
193
+ "A",
194
+ innerRadius,
195
+ innerRadius,
196
+ 0,
197
+ 1,
198
+ 0,
199
+ cx,
200
+ y2,
201
+ ].join(" "),
202
+ "data-value": value,
203
+ });
204
+ } else {
205
+ node = svgElement("circle", {
206
+ cx: cx,
207
+ cy: cy,
208
+ "data-value": value,
209
+ r: radius,
210
+ });
211
+ }
212
+ } else {
213
+ const cumulativePlusValue = cumulative + value;
214
+
215
+ let d = ["M"].concat(
216
+ scale(cumulative, radius),
217
+ "A",
218
+ radius,
219
+ radius,
220
+ 0,
221
+ portion > 0.5 ? 1 : 0,
222
+ 1,
223
+ scale(cumulativePlusValue, radius),
224
+ "L"
225
+ );
226
+
227
+ if (innerRadius) {
228
+ d = d.concat(
229
+ scale(cumulativePlusValue, innerRadius),
230
+ "A",
231
+ innerRadius,
232
+ innerRadius,
233
+ 0,
234
+ portion > 0.5 ? 1 : 0,
235
+ 0,
236
+ scale(cumulative, innerRadius)
237
+ );
238
+ } else {
239
+ d.push(cx, cy);
240
+ }
241
+
242
+ cumulative += value;
243
+
244
+ node = svgElement("path", {
245
+ d: d.join(" "),
246
+ "data-value": value,
247
+ });
248
+ }
249
+
250
+ node.setAttribute("fill", fill.call(peity, value, i, values));
251
+
252
+ svg.append(node);
253
+ }
254
+ };
255
+
256
+ const defaults$2 = {
257
+ fill: ["#ff9900", "#fff4dd", "#ffc66e"],
258
+ radius: 8,
259
+ };
260
+
261
+ const renderer$1 = (peity) => {
262
+ const values = peity.values;
263
+ const max = Math.max.apply(
264
+ Math,
265
+ peity.options.max == undefined ? values : values.concat(peity.options.max)
266
+ );
267
+ const min = Math.min.apply(
268
+ Math,
269
+ peity.options.min == undefined ? values : values.concat(peity.options.min)
270
+ );
271
+
272
+ const svg = peity.prepare(peity.options.width, peity.options.height);
273
+ const width = svg.clientWidth;
274
+ const height = svg.clientHeight;
275
+ const diff = max - min;
276
+ const padding = peity.options.padding;
277
+ const fill = peity.fill();
278
+
279
+ const xScale = (input) => {
280
+ return (input * width) / values.length;
281
+ };
282
+
283
+ const yScale = (input) => {
284
+ return height - (diff ? ((input - min) / diff) * height : 1);
285
+ };
286
+
287
+ for (var i = 0; i < values.length; i++) {
288
+ let x = xScale(i + padding);
289
+ let w = xScale(i + 1 - padding) - x;
290
+ let value = values[i];
291
+ let valueY = yScale(value);
292
+ let y1 = valueY;
293
+ let y2 = valueY;
294
+ let h;
295
+
296
+ if (!diff) {
297
+ h = 1;
298
+ } else if (value < 0) {
299
+ y1 = yScale(Math.min(max, 0));
300
+ } else {
301
+ y2 = yScale(Math.max(min, 0));
302
+ }
303
+
304
+ h = y2 - y1;
305
+
306
+ if (h == 0) {
307
+ h = 1;
308
+ if (max > 0 && diff) y1--;
309
+ }
310
+
311
+ svg.append(
312
+ svgElement("rect", {
313
+ "data-value": value,
314
+ fill: fill.call(peity, value, i, values),
315
+ x: x,
316
+ y: y1,
317
+ width: w,
318
+ height: h,
319
+ })
320
+ );
321
+ }
322
+ };
323
+
324
+ const defaults$1 = {
325
+ delimiter: ",",
326
+ fill: ["#4D89F9"],
327
+ height: 16,
328
+ min: 0,
329
+ padding: 0.1,
330
+ width: 32,
331
+ };
332
+
333
+ const renderer = (peity) => {
334
+ const values = peity.values;
335
+ if (values.length == 1) values.push(values[0]);
336
+ const max = Math.max.apply(
337
+ Math,
338
+ peity.options.max == undefined ? values : values.concat(peity.options.max)
339
+ );
340
+ const min = Math.min.apply(
341
+ Math,
342
+ peity.options.min == undefined ? values : values.concat(peity.options.min)
343
+ );
344
+
345
+ const svg = peity.prepare(peity.options.width, peity.options.height);
346
+ const strokeWidth = peity.options.strokeWidth;
347
+ const width = svg.clientWidth;
348
+ const height = svg.clientHeight - strokeWidth;
349
+ const diff = max - min;
350
+
351
+ const xScale = (input) => {
352
+ return input * (width / (values.length - 1));
353
+ };
354
+
355
+ const yScale = (input) => {
356
+ let y = height;
357
+
358
+ if (diff) {
359
+ y -= ((input - min) / diff) * height;
360
+ }
361
+
362
+ return y + strokeWidth / 2;
363
+ };
364
+
365
+ let zero = yScale(Math.max(min, 0));
366
+ let coords = [0, zero];
367
+
368
+ for (var i = 0; i < values.length; i++) {
369
+ coords.push(xScale(i), yScale(values[i]));
370
+ }
371
+
372
+ coords.push(width, zero);
373
+
374
+ if (peity.options.fill) {
375
+ svg.append(
376
+ svgElement("polygon", {
377
+ fill: peity.options.fill,
378
+ points: coords.join(" "),
379
+ })
380
+ );
381
+ }
382
+
383
+ if (strokeWidth) {
384
+ svg.append(
385
+ svgElement("polyline", {
386
+ fill: "none",
387
+ points: coords.slice(2, coords.length - 2).join(" "),
388
+ stroke: peity.options.stroke,
389
+ "stroke-width": strokeWidth,
390
+ "stroke-linecap": "square",
391
+ })
392
+ );
393
+ }
394
+ };
395
+
396
+ const defaults = {
397
+ delimiter: ",",
398
+ fill: "#c6d9fd",
399
+ height: 16,
400
+ min: 0,
401
+ stroke: "#4d89f9",
402
+ strokeWidth: 1,
403
+ width: 32,
404
+ };
405
+
406
+ Peity.register("pie", defaults$2, renderer$2);
407
+ Peity.register("donut", defaults$2, renderer$2);
408
+ Peity.register("bar", defaults$1, renderer$1);
409
+ Peity.register("line", defaults, renderer);
410
+
411
+ const peity = function (element, type, options) {
412
+ const peity = new Peity(element, type, options);
413
+ peity.mount();
414
+
415
+ return peity;
416
+ };
417
+
418
+ peity.defaults = Peity.defaults;
419
+ peity.graphers = Peity.graphers;
420
+
421
+ export { peity as default };
@@ -0,0 +1,6 @@
1
+ var peity=function(){"use strict";
2
+ /*!
3
+ Peity Vanila JS 0.0.8
4
+ Copyright © 2022 RailsJazz
5
+ https://railsjazz.com
6
+ */const t=t=>null!==t&&"function"==typeof t&&!!t.apply,e=(t,e)=>{const i=document.createElementNS("http://www.w3.org/2000/svg",t);for(var n in e)i.setAttribute(n,e[n]);return i},i="createElementNS"in document&&e("svg",{}).createSVGRect();class n{static defaults={};static graphers={};constructor(t,e,i={}){this.element=t,this.type=e,this.options=Object.assign({},n.defaults[this.type],JSON.parse(t.dataset.peity||"{}"),i),this.element._peity&&this.element._peity.destroy(),this.element._peity=this}draw(){const e=this.options;n.graphers[this.type](this),t(e.after)&&e.after.call(this,e)}fill(){var e=this.options.fill;return t(e)?e:function(t,i){return e[i%e.length]}}prepare(t,i){return this.svg||(this.element.style.display="none",this.element.after(this.svg=e("svg",{class:"peity"}))),this.svg.innerHTML="",this.svg.setAttribute("width",t),this.svg.setAttribute("height",i),this.svg}get values(){return this.element.innerText.split(this.options.delimiter).map((t=>parseFloat(t)))}mount(){i&&(this.element.addEventListener("DOMSubtreeModified",this.draw.bind(this)),this.draw(),this.mounted=!0)}unmount(){this.element.removeEventListener("DOMSubtreeModified",this.draw),this.svg.remove(),this.mounted=!1}destroy(){this.unmount(),delete this.element._peity}static register(t,e,i){n.defaults[t]=e,n.graphers[t]=i}}const s=t=>{if(!t.options.delimiter){const e=t.element.innerText.match(/[^0-9\.]/);t.options.delimiter=e?e[0]:","}let i=t.values.map((t=>t>0?t:0));if("/"==t.options.delimiter){let t=i[0],e=i[1];i=[t,Math.max(0,e-t)]}let n=0,s=i.length,o=0;for(;n<s;n++)o+=i[n];o||(s=2,o=1,i=[0,1]);let l=2*t.options.radius;const a=t.prepare(t.options.width||l,t.options.height||l),r=a.clientWidth,h=a.clientHeight,p=r/2,d=h/2,c=Math.min(p,d);let u=t.options.innerRadius;"donut"!=t.type||u||(u=.5*c);const m=t.fill(),f=(t,e)=>{const i=t/o*Math.PI*2-Math.PI/2;return[e*Math.cos(i)+p,e*Math.sin(i)+d]};let g=0;for(n=0;n<s;n++){const s=i[n],l=s/o;let r;if(0!=l){if(1==l)if(u){const t=p-.01,i=d-c,n=d-u;r=e("path",{d:["M",p,i,"A",c,c,0,1,1,t,i,"L",t,n,"A",u,u,0,1,0,p,n].join(" "),"data-value":s})}else r=e("circle",{cx:p,cy:d,"data-value":s,r:c});else{const t=g+s;let i=["M"].concat(f(g,c),"A",c,c,0,l>.5?1:0,1,f(t,c),"L");u?i=i.concat(f(t,u),"A",u,u,0,l>.5?1:0,0,f(g,u)):i.push(p,d),g+=s,r=e("path",{d:i.join(" "),"data-value":s})}r.setAttribute("fill",m.call(t,s,n,i)),a.append(r)}}},o={fill:["#ff9900","#fff4dd","#ffc66e"],radius:8};n.register("pie",o,s),n.register("donut",o,s),n.register("bar",{delimiter:",",fill:["#4D89F9"],height:16,min:0,padding:.1,width:32},(t=>{const i=t.values,n=Math.max.apply(Math,null==t.options.max?i:i.concat(t.options.max)),s=Math.min.apply(Math,null==t.options.min?i:i.concat(t.options.min)),o=t.prepare(t.options.width,t.options.height),l=o.clientWidth,a=o.clientHeight,r=n-s,h=t.options.padding,p=t.fill(),d=t=>t*l/i.length,c=t=>a-(r?(t-s)/r*a:1);for(var u=0;u<i.length;u++){let l,a=d(u+h),m=d(u+1-h)-a,f=i[u],g=c(f),v=g,y=g;r?f<0?v=c(Math.min(n,0)):y=c(Math.max(s,0)):l=1,l=y-v,0==l&&(l=1,n>0&&r&&v--),o.append(e("rect",{"data-value":f,fill:p.call(t,f,u,i),x:a,y:v,width:m,height:l}))}})),n.register("line",{delimiter:",",fill:"#c6d9fd",height:16,min:0,stroke:"#4d89f9",strokeWidth:1,width:32},(t=>{const i=t.values;1==i.length&&i.push(i[0]);const n=Math.max.apply(Math,null==t.options.max?i:i.concat(t.options.max)),s=Math.min.apply(Math,null==t.options.min?i:i.concat(t.options.min)),o=t.prepare(t.options.width,t.options.height),l=t.options.strokeWidth,a=o.clientWidth,r=o.clientHeight-l,h=n-s,p=t=>{let e=r;return h&&(e-=(t-s)/h*r),e+l/2};let d=p(Math.max(s,0)),c=[0,d];for(var u=0;u<i.length;u++)c.push(u*(a/(i.length-1)),p(i[u]));c.push(a,d),t.options.fill&&o.append(e("polygon",{fill:t.options.fill,points:c.join(" ")})),l&&o.append(e("polyline",{fill:"none",points:c.slice(2,c.length-2).join(" "),stroke:t.options.stroke,"stroke-width":l,"stroke-linecap":"square"}))}));const l=function(t,e,i){const s=new n(t,e,i);return s.mount(),s};return l.defaults=n.defaults,l.graphers=n.graphers,l}();
@@ -0,0 +1,2 @@
1
+ pin 'peity-vanilla', to: 'peity-vanilla.esm.js'
2
+ pin 'peity-vanilla-rails', to: 'peity-vanilla-rails.esm.js'
@@ -1,15 +1,10 @@
1
1
  module PeityVanillaRails
2
2
  class Railtie < ::Rails::Engine
3
+ PRECOMPILE_ASSETS = %w( peity-vanilla-rails.esm.js peity-vanilla.esm.js )
3
4
  initializer "peity_vanilla_rails.importmap", before: "importmap" do |app|
4
- if defined?(Importmap)
5
- app.config.importmap.cache_sweepers << root.join("app/assets/javascripts")
6
- end
7
- end
8
-
9
- PRECOMPILE_ASSETS = Dir[root.join("app/assets/javascripts/**/*")]
10
- initializer 'peity_vanilla_rails.assets' do |app|
11
- if app.config.respond_to?(:assets)
5
+ if Rails.application.respond_to?(:importmap)
12
6
  app.config.assets.precompile += PRECOMPILE_ASSETS
7
+ app.config.importmap.paths << root.join("config/importmap.rb")
13
8
  end
14
9
  end
15
10
 
@@ -1,36 +1,28 @@
1
1
  module PeityVanillaRails
2
2
  module Helpers
3
-
4
- def peity_line_chart(data, options: {})
5
- peity_chart(data, "line", ",", options: options)
3
+
4
+ def peity_line_chart(data, id: nil, options: {})
5
+ peity_chart(data, "line", ",", id: id, options: options)
6
6
  end
7
7
 
8
- def peity_bar_chart(data, options: {})
9
- peity_chart(data, "bar", ",", options: options)
8
+ def peity_bar_chart(data, id: nil, options: {})
9
+ peity_chart(data, "bar", ",", id: id, options: options)
10
10
  end
11
11
 
12
- def peity_pie_chart(data, options: {})
13
- peity_chart(data, "pie", "/", options: options)
12
+ def peity_pie_chart(data, id: nil, options: {})
13
+ peity_chart(data, "pie", "/", id: id, options: options)
14
14
  end
15
15
 
16
- def peity_donut_chart(data, options: {})
17
- peity_chart(data, "donut", "/", options: options)
16
+ def peity_donut_chart(data, id: nil, options: {})
17
+ peity_chart(data, "donut", "/", id: id, options: options)
18
18
  end
19
19
 
20
- def peity_chart(value, type, delimiter, options: {})
20
+ def peity_chart(value, type, delimiter, id: nil, options: {})
21
21
  value = value.is_a?(Array) ? value.join(delimiter) : value
22
- id = "peity_charts_#{Digest::SHA1.hexdigest([Time.now, rand].join)}"
23
- [
24
- tag.span(class: 'peity_charts', id: id, "data-peity" => options.to_json) do
25
- value
26
- end,
27
- tag.script do
28
- %Q{
29
- peity(document.getElementById("#{id}"), "#{type}");
30
- }.html_safe
31
- end
32
- ].join.html_safe
33
- end
22
+ tag.span(id: id, class: 'peity_charts', peity: type, style: 'display: none;', data: { peity: options.to_json }) do
23
+ value
24
+ end
25
+ end
34
26
 
35
27
  end
36
28
  end
@@ -1,3 +1,3 @@
1
1
  module PeityVanillaRails
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: peity_vanilla_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Igor Kasyanchuk
8
+ - Liubomyr Manastyretskyi
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2022-04-30 00:00:00.000000000 Z
12
+ date: 2022-05-02 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: rails
@@ -69,6 +70,7 @@ dependencies:
69
70
  description: Sparklines are small but intense charts.
70
71
  email:
71
72
  - igorkasyanchuk@gmail.com
73
+ - manastyretskyi@gmail.com
72
74
  executables: []
73
75
  extensions: []
74
76
  extra_rdoc_files: []
@@ -76,8 +78,11 @@ files:
76
78
  - MIT-LICENSE
77
79
  - README.md
78
80
  - Rakefile
79
- - app/assets/javascripts/peity_vanilla.js
80
- - app/assets/javascripts/peity_vanilla.js.map
81
+ - app/assets/javascripts/peity-vanilla-rails.esm.js
82
+ - app/assets/javascripts/peity-vanilla-rails.min.js
83
+ - app/assets/javascripts/peity-vanilla.esm.js
84
+ - app/assets/javascripts/peity-vanilla.min.js
85
+ - config/importmap.rb
81
86
  - lib/peity_vanilla_rails.rb
82
87
  - lib/peity_vanilla_rails/engine.rb
83
88
  - lib/peity_vanilla_rails/helpers.rb
@@ -104,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
104
109
  - !ruby/object:Gem::Version
105
110
  version: '0'
106
111
  requirements: []
107
- rubygems_version: 3.2.3
112
+ rubygems_version: 3.3.7
108
113
  signing_key:
109
114
  specification_version: 4
110
115
  summary: Sparklines are small but intense charts.
@@ -1,2 +0,0 @@
1
- !function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var i,n=e();for(i in n)("object"==typeof exports?exports:t)[i]=n[i]}}(self,()=>(()=>{"use strict";function a(t,e,i){var n;if(s)return n=(t=t).dataset._peity,n=new r(t,e,Object.assign({},a.defaults[e],JSON.parse(t.dataset.peity||"{}"),i)),t.addEventListener("change",function(){n.draw()}),(t.dataset._peity=n).draw(),t}function r(t,e,i){this.$el=t,this.type=e,this.opts=i}var t=r.prototype,M=t.svgElement=function(t,e){var i,n=document.createElementNS("http://www.w3.org/2000/svg",t);for(i in e)n.setAttribute(i,e[i]);return n},s="createElementNS"in document&&M("svg",{}).createSVGRect();return t.draw=function(){var t=this.opts;a.graphers[this.type].call(this,t),t.after&&t.after.call(this,t)},t.isFunction=function(t){return null!==t&&"function"==typeof t&&!!t.apply},t.fill=function(){var i=this.opts.fill;return t.isFunction(i)?i:function(t,e){return i[e%i.length]}},t.prepare=function(t,e){return this.$svg||(this.$el.style.display="none",this.$el.after(this.$svg=M("svg",{class:"peity"}))),this.$svg.innerHTML="",this.$svg.setAttribute("width",t),this.$svg.setAttribute("height",e),this.$svg},t.values=function(){return this.$el.innerText.split(this.opts.delimiter).map(function(t){return parseFloat(t)})},a.defaults={},a.graphers={},a.register=function(t,e,i){this.defaults[t]=e,this.graphers[t]=i},a.register("pie",{fill:["#ff9900","#fff4dd","#ffc66e"],radius:8},function(t){t.delimiter||(l=this.$el.innerText.match(/[^0-9\.]/),t.delimiter=l?l[0]:",");for(var e=this.values().map(function(t){return 0<t?t:0}),i=("/"==t.delimiter&&(l=e[0],r=e[1],e=[l,Math.max(0,r-l)]),0),n=e.length,a=0;i<n;i++)a+=e[i];a||(n=2,e=[0,a=1]);for(var r=2*t.radius,s=this.prepare(t.width||r,t.height||r),l=s.clientWidth,r=s.clientHeight,h=l/2,o=r/2,u=Math.min(h,o),c=t.innerRadius,p=("donut"!=this.type||c||(c=.5*u),Math.PI),f=this.fill(),d=this.scale=function(t,e){t=t/a*p*2-p/2;return[e*Math.cos(t)+h,e*Math.sin(t)+o]},g=0,i=0;i<n;i++){var m,v,y=e[i],x=y/a;0!=x&&((x=1==x?c?M("path",{d:["M",h,v=o-u,"A",u,u,0,1,1,m=h-.01,v,"L",m,v=o-c,"A",c,c,0,1,0,h,v].join(" "),"data-value":y}):M("circle",{cx:h,cy:o,"data-value":y,r:u}):(m=g+y,v=["M"].concat(d(g,u),"A",u,u,0,.5<x?1:0,1,d(m,u),"L"),c?v=v.concat(d(m,c),"A",c,c,0,.5<x?1:0,0,d(g,c)):v.push(h,o),g+=y,M("path",{d:v.join(" "),"data-value":y}))).setAttribute("fill",f.call(this,y,i,e)),s.append(x))}}),a.register("donut",Object.assign(!0,{},a.defaults.pie),function(t){a.graphers.pie.call(this,t)}),a.register("bar",{delimiter:",",fill:["#4D89F9"],height:16,min:0,padding:.1,width:32},function(t){for(var e=this.values(),i=Math.max.apply(Math,null==t.max?e:e.concat(t.max)),n=Math.min.apply(Math,null==t.min?e:e.concat(t.min)),a=this.prepare(t.width,t.height),r=a.clientWidth,s=a.clientHeight,l=i-n,h=t.padding,o=this.fill(),u=this.x=function(t){return t*r/e.length},c=this.y=function(t){return s-(l?(t-n)/l*s:1)},p=0;p<e.length;p++){var f,d=u(p+h),g=u(p+1-h)-d,m=e[p],v=c(m),y=v;l?m<0?y=c(Math.min(i,0)):v=c(Math.max(n,0)):f=1,0==(f=v-y)&&(f=1,0<i&&l&&y--),a.append(M("rect",{"data-value":m,fill:o.call(this,m,p,e),x:d,y:y,width:g,height:f}))}}),a.register("line",{delimiter:",",fill:"#c6d9fd",height:16,min:0,stroke:"#4d89f9",strokeWidth:1,width:32},function(t){for(var e=this.values(),i=(1==e.length&&e.push(e[0]),Math.max.apply(Math,null==t.max?e:e.concat(t.max))),n=Math.min.apply(Math,null==t.min?e:e.concat(t.min)),a=this.prepare(t.width,t.height),r=t.strokeWidth,s=a.clientWidth,l=a.clientHeight-r,h=i-n,o=this.x=function(t){return t*(s/(e.length-1))},u=this.y=function(t){var e=l;return h&&(e-=(t-n)/h*l),e+r/2},i=u(Math.max(n,0)),c=[0,i],p=0;p<e.length;p++)c.push(o(p),u(e[p]));c.push(s,i),t.fill&&a.append(M("polygon",{fill:t.fill,points:c.join(" ")})),r&&a.append(M("polyline",{fill:"none",points:c.slice(2,c.length-2).join(" "),stroke:t.stroke,"stroke-width":r,"stroke-linecap":"square"}))}),window.peity=a,{}})());
2
- //# sourceMappingURL=peity_vanilla.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["webpack://piety_vanilla/webpack/universalModuleDefinition","webpack://piety_vanilla/./src/index.js"],"names":["root","factory","exports","module","define","amd","i","a","self","peity","element","type","options","chart","svgSupported","$this","dataset","Peity","Object","assign","defaults","JSON","parse","addEventListener","draw","$el","opts","this","PeityPrototype","prototype","svgElement","tag","attrs","attr","document","createElementNS","setAttribute","createSVGRect","graphers","call","after","isFunction","o","apply","fill","_","length","prepare","width","height","$svg","style","display","innerHTML","values","innerText","split","delimiter","map","value","parseFloat","register","grapher","radius","match","n","v1","v2","Math","max","sum","diameter","clientWidth","clientHeight","cx","cy","min","innerRadius","pi","PI","scale","radians","cos","sin","cumulative","cumulativePlusValue","d","portion","$node","y1","x2","y2","join","r","concat","push","append","pie","padding","undefined","diff","xScale","x","input","yScale","y","h","w","valueY","stroke","strokeWidth","zero","coords","points","slice","window"],"mappings":"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","file":"peity_vanilla.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse {\n\t\tvar a = factory();\n\t\tfor(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n\t}\n})(self, () => {\nreturn ","\"use strict\";\r\n\r\nvar peity = function(element, type, options) {\r\n if (svgSupported) {\r\n var $this = element\r\n var chart = $this.dataset['_peity']\r\n\r\n chart = new Peity(\r\n $this,\r\n type,\r\n Object.assign({},\r\n peity.defaults[type],\r\n JSON.parse($this.dataset['peity'] || '{}'),\r\n options)\r\n )\r\n\r\n $this.addEventListener(\"change\", function() { chart.draw() })\r\n $this.dataset['_peity'] = chart\r\n\r\n chart.draw()\r\n return $this;\r\n }\r\n};\r\n\r\nvar Peity = function($el, type, opts) {\r\n this.$el = $el\r\n this.type = type\r\n this.opts = opts\r\n}\r\n\r\nvar PeityPrototype = Peity.prototype\r\n\r\nvar svgElement = PeityPrototype.svgElement = function(tag, attrs) {\r\n var element = document.createElementNS('http://www.w3.org/2000/svg', tag)\r\n for(var attr in attrs) {\r\n element.setAttribute(attr, attrs[attr])\r\n }\r\n return element;\r\n}\r\n\r\n// https://gist.github.com/madrobby/3201472\r\nvar svgSupported = 'createElementNS' in document && svgElement('svg', {}).createSVGRect()\r\n\r\nPeityPrototype.draw = function() {\r\n var opts = this.opts\r\n peity.graphers[this.type].call(this, opts)\r\n if (opts.after) opts.after.call(this, opts)\r\n}\r\n\r\nPeityPrototype.isFunction = function(o) { return null !== o && \"function\" === typeof o && !!o.apply; }\r\n\r\nPeityPrototype.fill = function() {\r\n var fill = this.opts.fill\r\n\r\n return PeityPrototype.isFunction(fill)\r\n ? fill\r\n : function(_, i) { return fill[i % fill.length] }\r\n}\r\n\r\nPeityPrototype.prepare = function(width, height) {\r\n if (!this.$svg) {\r\n this.$el.style.display = 'none'\r\n this.$el.after(\r\n this.$svg = svgElement('svg', {\r\n \"class\": \"peity\"\r\n })\r\n )\r\n }\r\n\r\n this.$svg.innerHTML = \"\";\r\n this.$svg.setAttribute(\"width\", width)\r\n this.$svg.setAttribute(\"height\", height)\r\n\r\n return this.$svg;\r\n}\r\n\r\nPeityPrototype.values = function() {\r\n return this.$el.innerText.split(this.opts.delimiter).map(function(value) {\r\n return parseFloat(value)\r\n })\r\n}\r\n\r\npeity.defaults = {}\r\npeity.graphers = {}\r\n\r\npeity.register = function(type, defaults, grapher) {\r\n this.defaults[type] = defaults\r\n this.graphers[type] = grapher\r\n}\r\n\r\npeity.register(\r\n 'pie',\r\n {\r\n fill: ['#ff9900', '#fff4dd', '#ffc66e'],\r\n radius: 8\r\n },\r\n function(opts) {\r\n if (!opts.delimiter) {\r\n var delimiter = this.$el.innerText.match(/[^0-9\\.]/)\r\n opts.delimiter = delimiter ? delimiter[0] : \",\"\r\n }\r\n\r\n var values = this.values().map(function(n) {\r\n return n > 0 ? n : 0\r\n });\r\n\r\n if (opts.delimiter == \"/\") {\r\n var v1 = values[0]\r\n var v2 = values[1]\r\n values = [v1, Math.max(0, v2 - v1)]\r\n }\r\n\r\n var i = 0\r\n var length = values.length\r\n var sum = 0\r\n\r\n for (; i < length; i++) {\r\n sum += values[i]\r\n }\r\n\r\n if (!sum) {\r\n length = 2\r\n sum = 1\r\n values = [0, 1]\r\n }\r\n\r\n var diameter = opts.radius * 2\r\n\r\n var $svg = this.prepare(\r\n opts.width || diameter,\r\n opts.height || diameter\r\n )\r\n\r\n var width = $svg.clientWidth\r\n , height = $svg.clientHeight\r\n , cx = width / 2\r\n , cy = height / 2\r\n\r\n var radius = Math.min(cx, cy)\r\n , innerRadius = opts.innerRadius\r\n\r\n if (this.type == 'donut' && !innerRadius) {\r\n innerRadius = radius * 0.5\r\n }\r\n\r\n var pi = Math.PI\r\n var fill = this.fill()\r\n\r\n var scale = this.scale = function(value, radius) {\r\n var radians = value / sum * pi * 2 - pi / 2\r\n\r\n return [\r\n radius * Math.cos(radians) + cx,\r\n radius * Math.sin(radians) + cy\r\n ]\r\n }\r\n\r\n var cumulative = 0\r\n\r\n for (i = 0; i < length; i++) {\r\n var value = values[i]\r\n , portion = value / sum\r\n , $node\r\n\r\n if (portion == 0) continue\r\n\r\n if (portion == 1) {\r\n if (innerRadius) {\r\n var x2 = cx - 0.01\r\n , y1 = cy - radius\r\n , y2 = cy - innerRadius\r\n\r\n $node = svgElement('path', {\r\n d: [\r\n 'M', cx, y1,\r\n 'A', radius, radius, 0, 1, 1, x2, y1,\r\n 'L', x2, y2,\r\n 'A', innerRadius, innerRadius, 0, 1, 0, cx, y2\r\n ].join(' '),\r\n 'data-value': value,\r\n })\r\n } else {\r\n $node = svgElement('circle', {\r\n cx: cx,\r\n cy: cy,\r\n 'data-value': value,\r\n r: radius\r\n })\r\n }\r\n } else {\r\n var cumulativePlusValue = cumulative + value\r\n\r\n var d = ['M'].concat(\r\n scale(cumulative, radius),\r\n 'A', radius, radius, 0, portion > 0.5 ? 1 : 0, 1,\r\n scale(cumulativePlusValue, radius),\r\n 'L'\r\n )\r\n\r\n if (innerRadius) {\r\n d = d.concat(\r\n scale(cumulativePlusValue, innerRadius),\r\n 'A', innerRadius, innerRadius, 0, portion > 0.5 ? 1 : 0, 0,\r\n scale(cumulative, innerRadius)\r\n )\r\n } else {\r\n d.push(cx, cy)\r\n }\r\n\r\n cumulative += value\r\n\r\n $node = svgElement('path', {\r\n d: d.join(\" \"),\r\n 'data-value': value,\r\n })\r\n }\r\n\r\n $node.setAttribute('fill', fill.call(this, value, i, values))\r\n\r\n $svg.append($node)\r\n }\r\n }\r\n)\r\n\r\npeity.register(\r\n 'donut',\r\n Object.assign(true, {}, peity.defaults.pie),\r\n function(opts) {\r\n peity.graphers.pie.call(this, opts)\r\n }\r\n)\r\n\r\npeity.register(\r\n 'bar',\r\n {\r\n delimiter: \",\",\r\n fill: [\"#4D89F9\"],\r\n height: 16,\r\n min: 0,\r\n padding: 0.1,\r\n width: 32\r\n },\r\n function(opts) {\r\n var values = this.values()\r\n , max = Math.max.apply(Math, opts.max == undefined ? values : values.concat(opts.max))\r\n , min = Math.min.apply(Math, opts.min == undefined ? values : values.concat(opts.min))\r\n\r\n var $svg = this.prepare(opts.width, opts.height)\r\n , width = $svg.clientWidth\r\n , height = $svg.clientHeight\r\n , diff = max - min\r\n , padding = opts.padding\r\n , fill = this.fill()\r\n\r\n var xScale = this.x = function(input) {\r\n return input * width / values.length\r\n }\r\n\r\n var yScale = this.y = function(input) {\r\n return height - (\r\n diff\r\n ? ((input - min) / diff) * height\r\n : 1\r\n )\r\n }\r\n\r\n for (var i = 0; i < values.length; i++) {\r\n var x = xScale(i + padding)\r\n , w = xScale(i + 1 - padding) - x\r\n , value = values[i]\r\n , valueY = yScale(value)\r\n , y1 = valueY\r\n , y2 = valueY\r\n , h\r\n\r\n if (!diff) {\r\n h = 1\r\n } else if (value < 0) {\r\n y1 = yScale(Math.min(max, 0))\r\n } else {\r\n y2 = yScale(Math.max(min, 0))\r\n }\r\n\r\n h = y2 - y1\r\n\r\n if (h == 0) {\r\n h = 1\r\n if (max > 0 && diff) y1--\r\n }\r\n\r\n $svg.append(\r\n svgElement('rect', {\r\n 'data-value': value,\r\n fill: fill.call(this, value, i, values),\r\n x: x,\r\n y: y1,\r\n width: w,\r\n height: h\r\n })\r\n )\r\n }\r\n }\r\n);\r\n\r\npeity.register(\r\n \"line\",\r\n {\r\n delimiter: \",\",\r\n fill: \"#c6d9fd\",\r\n height: 16,\r\n min: 0,\r\n stroke: \"#4d89f9\",\r\n strokeWidth: 1,\r\n width: 32\r\n },\r\n function(opts) {\r\n var values = this.values()\r\n if (values.length == 1) values.push(values[0])\r\n var max = Math.max.apply(Math, opts.max == undefined ? values : values.concat(opts.max))\r\n , min = Math.min.apply(Math, opts.min == undefined ? values : values.concat(opts.min))\r\n\r\n var $svg = this.prepare(opts.width, opts.height)\r\n , strokeWidth = opts.strokeWidth\r\n , width = $svg.clientWidth\r\n , height = $svg.clientHeight - strokeWidth\r\n , diff = max - min\r\n\r\n var xScale = this.x = function(input) {\r\n return input * (width / (values.length - 1))\r\n }\r\n\r\n var yScale = this.y = function(input) {\r\n var y = height\r\n\r\n if (diff) {\r\n y -= ((input - min) / diff) * height\r\n }\r\n\r\n return y + strokeWidth / 2\r\n }\r\n\r\n var zero = yScale(Math.max(min, 0))\r\n , coords = [0, zero]\r\n\r\n for (var i = 0; i < values.length; i++) {\r\n coords.push(\r\n xScale(i),\r\n yScale(values[i])\r\n )\r\n }\r\n\r\n coords.push(width, zero)\r\n\r\n if (opts.fill) {\r\n $svg.append(\r\n svgElement('polygon', {\r\n fill: opts.fill,\r\n points: coords.join(' ')\r\n })\r\n )\r\n }\r\n\r\n if (strokeWidth) {\r\n $svg.append(\r\n svgElement('polyline', {\r\n fill: 'none',\r\n points: coords.slice(2, coords.length - 2).join(' '),\r\n stroke: opts.stroke,\r\n 'stroke-width': strokeWidth,\r\n 'stroke-linecap': 'square'\r\n })\r\n )\r\n }\r\n }\r\n);\r\n\r\n// rework?\r\nwindow.peity = peity;"],"sourceRoot":""}