@graphysdk/theme-botanical 0.0.0-stage → 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.
- package/LICENSE.md +17 -0
- package/README.md +59 -2
- package/dist/botanical.d.ts +16 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +1123 -0
- package/dist/page.d.ts +9 -0
- package/dist/renderer/area.d.ts +5 -0
- package/dist/renderer/bar.d.ts +7 -0
- package/dist/renderer/hand.d.ts +28 -0
- package/dist/renderer/ink.d.ts +35 -0
- package/dist/renderer/line.d.ts +5 -0
- package/dist/renderer/paint.d.ts +21 -0
- package/dist/renderer/plugins.d.ts +7 -0
- package/dist/renderer/point.d.ts +5 -0
- package/dist/renderer/shapes.d.ts +2 -0
- package/dist/renderer/slice.d.ts +7 -0
- package/dist/renderer/tile.d.ts +3 -0
- package/dist/renderer/trace.d.ts +24 -0
- package/dist/renderer/utils/paths.d.ts +7 -0
- package/dist/renderer/utils/projections.d.ts +16 -0
- package/dist/styles.d.ts +34 -0
- package/fonts.css +2 -0
- package/licenses/PolyForm-Free-Trial-1.0.0.md +93 -0
- package/licenses/PolyForm-NonCommercial-1.0.0.md +131 -0
- package/licenses/PolyForm-Small-Business-1.0.0.md +121 -0
- package/package.json +79 -3
- package/src/fonts.css.d.ts +2 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# License
|
|
2
|
+
|
|
3
|
+
This software is available under any of the following licenses, at your option,
|
|
4
|
+
depending on which one's conditions you meet:
|
|
5
|
+
|
|
6
|
+
- **PolyForm Noncommercial 1.0.0** — for noncommercial use (personal,
|
|
7
|
+
charitable, educational, research, government).
|
|
8
|
+
See [licenses/PolyForm-NonCommercial-1.0.0.md](licenses/PolyForm-NonCommercial-1.0.0.md)
|
|
9
|
+
|
|
10
|
+
- **PolyForm Small Business 1.0.0** — free commercial use for organizations
|
|
11
|
+
under the size thresholds defined in the license.
|
|
12
|
+
See [licenses/PolyForm-Small-Business-1.0.0.md](licenses/PolyForm-Small-Business-1.0.0.md)
|
|
13
|
+
|
|
14
|
+
- **PolyForm Free Trial 1.0.0** — a 32-day evaluation for anyone else.
|
|
15
|
+
See [licenses/PolyForm-Free-Trial-1.0.0.md](licenses/PolyForm-Free-Trial-1.0.0.md)
|
|
16
|
+
|
|
17
|
+
For commercial use beyond these terms, contact [hello@graphy.dev](mailto:hello@graphy.dev) or visit [https://graphy.dev](https://graphy.dev).
|
package/README.md
CHANGED
|
@@ -1,3 +1,60 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @graphysdk/theme-botanical
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
> **Beta.** This theme is on a `0.x` version line: a minor release may change its look. Use a caret range (`^0.1.0`) to take only patches.
|
|
4
|
+
|
|
5
|
+
A botanical theme for the Graphy charting SDK: graphs drawn as a page from a gardener's sketchbook, every shape outlined by hand in sepia ink with a watercolour wash inside, in leaf greens.
|
|
6
|
+
|
|
7
|
+
Learn more at [graphy.dev](https://graphy.dev).
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @graphysdk/theme-botanical @graphysdk/react
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Requires React 19. Its only peer is `@graphysdk/react`.
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
Pass the theme to `createGraphyKit` and import its fonts once. Every graph drawn through the kit's `GraphProvider` takes the theme; specs are written as usual.
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { createGraphyKit, GraphRenderer } from '@graphysdk/react';
|
|
23
|
+
import { botanical } from '@graphysdk/theme-botanical';
|
|
24
|
+
import '@graphysdk/theme-botanical/fonts.css';
|
|
25
|
+
|
|
26
|
+
const kit = createGraphyKit({ theme: botanical });
|
|
27
|
+
|
|
28
|
+
const spec = kit.pipe(
|
|
29
|
+
kit.createSpec({ x: 'quarter', y: 'revenue', color: 'region' }),
|
|
30
|
+
kit.geom.bar({ position: 'dodge' }),
|
|
31
|
+
kit.scale.x(),
|
|
32
|
+
kit.scale.y()
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
export function Revenue({ data }) {
|
|
36
|
+
return (
|
|
37
|
+
<kit.GraphProvider spec={spec} data={data}>
|
|
38
|
+
<GraphRenderer />
|
|
39
|
+
</kit.GraphProvider>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
A spec's own `styles()`, scales and `config()` sit above the theme, so a graph can still change anything. The theme is drawn for a graph about 600 pixels wide; `style.graph({ textScale: 1.5 })` scales its type for a larger one.
|
|
45
|
+
|
|
46
|
+
`fonts.css` loads Kalam for the handwriting and Cormorant Garamond for the italic notes from Google Fonts. To host the fonts yourself, leave the import out and load families named `Kalam` and `Cormorant Garamond` before the first graph is drawn.
|
|
47
|
+
|
|
48
|
+
## Docs
|
|
49
|
+
|
|
50
|
+
- [Botanical](https://docs.graphy.dev/sdk-next/themes/botanical)
|
|
51
|
+
|
|
52
|
+
## Feedback
|
|
53
|
+
|
|
54
|
+
This theme is released early to hear what works. Tell us on [Discord](https://discord.gg/yGmYCjkSr).
|
|
55
|
+
|
|
56
|
+
## Licence
|
|
57
|
+
|
|
58
|
+
This package is available under PolyForm Noncommercial, Small Business, or a 32-day Free Trial. Free Trial is local or internal evaluation only — it does not cover a public page. See [what you can do under the trial](https://docs.graphy.dev/licence/evaluation).
|
|
59
|
+
|
|
60
|
+
For a commercial licence, [talk to us](https://graphy.dev/license).
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Theme } from '@graphysdk/react';
|
|
2
|
+
/**
|
|
3
|
+
* Graphs as a page from a gardener's sketchbook: grained paper taped down at its corners with a sprig
|
|
4
|
+
* drawn along its foot, every shape outlined by hand in sepia ink with a watercolour wash inside. A bar
|
|
5
|
+
* is a leaf blade with a rib and veins, a line is a vine putting out a leaf at each reading, a point
|
|
6
|
+
* is a fallen leaf, a pie is a flower of petals round a seed head, and a heatmap is a seed tray.
|
|
7
|
+
* Groups take leaf greens set between a petal pink, a bark brown, a berry red and a muted gold. Drawn
|
|
8
|
+
* for the light scheme only.
|
|
9
|
+
*
|
|
10
|
+
* The hand is Kalam and the italic notes Cormorant Garamond. Import
|
|
11
|
+
* `@graphysdk/theme-botanical/fonts.css` once to load them.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const kit = createGraphyKit({ theme: botanical });
|
|
15
|
+
*/
|
|
16
|
+
export declare const botanical: Theme;
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let R=require("react"),o=require("@graphysdk/react"),u=require("react/jsx-runtime");var ke=/[a-df-zA-DF-Z]|[-+]?(?:\d+\.?\d*|\.\d+)(?:[eE][-+]?\d+)?/gu,Ee=/^[a-zA-Z]$/u,we=(e,t)=>e==="H"?"x":e==="V"?"y":t%2===0?"x":"y",Q=(e,t)=>{let r="",a=0;return(e.match(ke)??[]).map(n=>{if(Ee.test(n))return r=n.toUpperCase(),a=0,n;const s=we(r,a);return a+=1,String(Number(n)*(s==="x"?t.width:t.height))}).join(" ")},X=(e,t)=>{const r=(0,o.getX)(e),a=(0,o.getY)(e)??(0,o.getYMax)(e);return r===null||a===null?null:{x:(0,o.toViewBoxX)(r)*t.width,y:(0,o.toViewBoxY)(a)*t.height}},N=(e,t)=>{const r=(0,o.getX)(e),a=(0,o.getY)(e)??(0,o.getRadiusExtent)(e).outerRadius;if(r===null||a===null)return null;const n=(0,o.polarToUnit)(r,a),s=Math.min(t.width,t.height)/2;return{x:t.width/2+n.x*s,y:t.height/2-n.y*s}},be=e=>`${e.map((t,r)=>`${r===0?"M":"L"}${t.x},${t.y}`).join(" ")} Z`,P=e=>{let t=2166136261;for(let r=0;r<e.length;r+=1)t^=e.charCodeAt(r),t=Math.imul(t,16777619);return t>>>0},C=e=>{let t=e||1;return()=>{t=t+1831565813|0;let r=Math.imul(t^t>>>15,1|t);return r=r+Math.imul(r^r>>>7,61|r)^r,((r^r>>>14)>>>0)/4294967296}},Me=e=>{const t=[.035,.07,.13].map((a,n)=>({frequency:a*(.7+e()*.6),phase:e()*Math.PI*2,weight:1/(n+1)})),r=t.reduce((a,n)=>a+n.weight,0);return a=>t.reduce((n,s)=>n+s.weight*Math.sin(a*s.frequency+s.phase),0)/r},w=(e,{wander:t,seed:r,closed:a=!1,step:n=9,cornered:s=!1})=>{if(e.length<2)return"";const l=Me(C(r)),i=a?[...e,e[0]]:[...e],d=[],g=[];let h=0;for(let p=0;p<i.length-1;p+=1){const c=i[p],f=i[p+1],v=Math.hypot(f.x-c.x,f.y-c.y);if(v===0)continue;const M={x:-(f.y-c.y)/v,y:(f.x-c.x)/v},S=Math.max(1,Math.ceil(v/n)),k=[];for(let _=0;_<=S;_+=1){const b=_/S,B=t*Math.sin(Math.PI*b)*l(h+b*v);k.push({x:c.x+(f.x-c.x)*b+M.x*B,y:c.y+(f.y-c.y)*b+M.y*B})}g.push(k),d.push(...k.slice(0,-1)),h+=v}return s?`${g.map(p=>J(p,!1)).map((p,c)=>c===0?p:p.replace(/^M/u,"L")).join(" ")}${a?" Z":""}`:(a||d.push(i[i.length-1]),J(d,a))},m=e=>(Math.round(e*100)/100).toString(),J=(e,t)=>{const r=e.length,a=i=>t?e[(i+r)%r]:e[Math.max(0,Math.min(r-1,i))],n=a(0),s=[`M${m(n.x)},${m(n.y)}`],l=t?r:r-1;for(let i=0;i<l;i+=1){const[d,g,h,p]=[a(i-1),a(i),a(i+1),a(i+2)],c={x:g.x+(h.x-d.x)/6,y:g.y+(h.y-d.y)/6},f={x:h.x-(p.x-g.x)/6,y:h.y-(p.y-g.y)/6};s.push(`C${m(c.x)},${m(c.y)} ${m(f.x)},${m(f.y)} ${m(h.x)},${m(h.y)}`)}return`${s.join(" ")}${t?" Z":""}`},K=(e,t,r,a)=>{const n={x:Math.cos(a),y:Math.sin(a)},s={x:-n.y,y:n.x},l=(i,d)=>`${m(e.x+n.x*i+s.x*d)},${m(e.y+n.y*i+s.y*d)}`;return{blade:`M${l(0,0)} Q${l(t*.45,r)} ${l(t,0)} Q${l(t*.55,-r)} ${l(0,0)} Z`,rib:`M${l(0,0)} L${l(t*.8,0)}`}},ce=e=>`data:image/svg+xml,${encodeURIComponent(e)}`,Se=(e,t)=>ce(`<svg xmlns="http://www.w3.org/2000/svg" width="240" height="240"><filter id="g" x="0" y="0" width="100%" height="100%"><feTurbulence type="fractalNoise" baseFrequency="0.85" numOctaves="2" seed="4" stitchTiles="stitch"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1.6 1.05"/></filter><rect width="240" height="240" fill="${e}"/><rect width="240" height="240" fill="${t}" filter="url(#g)" opacity="0.07"/></svg>`),_e=74,je=22,ee=(e,t)=>{const r=C(t),a=_e/2,n=(s,l)=>Array.from({length:6},(i,d)=>{const g=-11+je*d/5;return`${(s+l*r()*3).toFixed(1)},${g.toFixed(1)}`});return`<polygon points="${[...n(-37,-1),...n(a,1).reverse()].join(" ")}" fill="${e}" fill-opacity="0.7" stroke="#B9A776" stroke-opacity="0.35" stroke-width="0.5"/>`},D=(e,t,r,a)=>`<svg x="${e}" y="${t}" width="1" height="1" overflow="visible"><g transform="${a}">${r}</g></svg>`,te=150,Pe=.95,Re=(e,t,r)=>{const a=C(r),n=Array.from({length:7},(d,g)=>{const h=g/6;return{x:h*te,y:-Math.sin(h*Math.PI*.9)*16-h*6}}),s=w(n,{wander:1.2,seed:r}),l=n.slice(1,-1).flatMap((d,g)=>{const h=g%2===0?-1:1,p=22-g*2.2+a()*4,c=-.35+h*(.95+a()*.25),{blade:f,rib:v}=K(d,p,p*.3,c);return[`<path d="${f}" fill="${t}" fill-opacity="0.55" stroke="${e}" stroke-width="0.85" stroke-linejoin="round"/>`,`<path d="${v}" fill="none" stroke="${e}" stroke-width="0.55" stroke-opacity="0.7"/>`]}),i=K(n[n.length-1]??{x:te,y:0},13,5,-.2);return`<path d="${s}" fill="none" stroke="${e}" stroke-width="1.1" stroke-linecap="round"/>`+l.join("")+`<path d="${i.blade}" fill="#C4607C" fill-opacity="0.45" stroke="${e}" stroke-width="0.85"/>`},Te=({ink:e,leaf:t,tape:r})=>ce('<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">'+D("0","0",ee(r,3),"translate(26 20) rotate(-36)")+D("100%","0",ee(r,9),"translate(-26 20) rotate(36)")+D("0","100%",Re(e,t,21),`translate(16 -8) scale(${Pe})`)+"</svg>"),y={paper:"#F4EEDD",raised:"#FBF8EE",text:"#1E2A21",secondary:"#4A5648",rule:"#CFC7B0",edge:"#BFB79E",ink:"#3A2C1E",tape:"#D9C89A"},ue="'Kalam', 'Comic Neue', ui-rounded, sans-serif",V="'Cormorant Garamond', 'Iowan Old Style', Georgia, serif",Le=ue,x={forest:"#2E5E3B",petal:"#C4607C",bark:"#5C4033",sage:"#6E8A5A",berry:"#8C2A3C",gold:"#9A7A1E",gentian:"#4A6A8C",leaf:"#4E8A4A"},We=[x.forest,x.petal,x.bark,x.sage,x.berry,x.gold,x.gentian,x.leaf],Ce=["#DDE6CC","#1C4A2B"],F=1.5,Ie=2,z=.75,j={textColor:y.text},T={textColor:y.secondary},$={fontFamily:ue},re={fontFamily:V,fontStyle:"italic"},I={...$,textColor:y.ink,fontWeight:400,fontSize:15,fill:y.paper,stroke:"transparent",strokeWidth:0,cornerRadius:0,paddingInline:2,paddingBlock:0,shadow:"none"},He={tokens:{graphBackground:y.paper,graphBorder:y.ink,geom:x.forest,geomBorder:y.secondary,textPrimary:y.text,textSecondary:y.secondary,ruleLine:y.ink,gridLine:y.rule,hoverAffordance:y.text,hoverGuideFill:"rgba(30, 42, 33, 0.06)",hoverGuideLine:y.secondary,tooltipBackground:y.raised,tooltipBorder:y.text,tooltipPrimaryRow:"rgba(46, 94, 59, 0.1)",annotationShape:x.gold,annotationArrow:y.text,differenceLabelBackground:y.paper},defaults:[o.style.graph({fill:{image:Se(y.paper,y.ink),fit:"tile",fallback:y.paper},overlay:{image:Te({ink:y.ink,leaf:x.sage,tape:y.tape}),fit:"stretch",fallback:"transparent"},strokeWidth:0,cornerRadius:2,shadow:{offsetX:0,offsetY:2,blur:10,color:"rgba(58, 44, 30, 0.18)"},fontFamily:Le,padding:{top:26,right:26,bottom:36,left:26}}),o.style.geom({shadow:"none"},{state:"hovered"}),o.style.geom.bar({stroke:y.paper,strokeWidth:1,cornerRadius:"none"}),o.style.geom.bar({stroke:y.text,strokeWidth:F},{state:"hovered"}),o.style.geom.line({strokeWidth:Ie,dashArray:[],lineCap:"round",lineJoin:"round"}),o.style.geom.area({fillAlpha:.55,strokeWidth:F,dashArray:[],lineCap:"round",lineJoin:"round"}),o.style.geom.point({size:8,stroke:y.paper,strokeWidth:1}),o.style.geom.tile({cornerRadius:0,stroke:y.paper,strokeWidth:1}),o.style.geom.tile({stroke:y.text,strokeWidth:F},{state:"hovered"}),o.style.geom.rule({stroke:y.secondary,strokeWidth:1,dashArray:[6,4]}),o.style.geom.rule.label({...j,fontWeight:400,fontSize:12.5}),o.style.gridLine({dashArray:[]}),o.style.gridLine.x({strokeWidth:0}),o.style.gridLine.y({strokeWidth:z}),o.style.panelBorder({strokeWidth:0}),o.style.panelBorder.bottom({stroke:y.ink,strokeWidth:1,dashArray:[]}),o.style.tickLine({strokeWidth:0}),o.style.tickLabel({...T,fontWeight:400,fontSize:14,lineHeight:1}),o.style.tickLabel.y({fontFamily:V,fontWeight:600,fontSize:13,lineHeight:1}),o.style.axisLabel({...T,...re,fontWeight:500,fontSize:16,lineHeight:1}),o.style.heading({...j,...$}),o.style.heading.h1({fontWeight:400,fontSize:28,lineHeight:1}),o.style.heading.h2({...T,...re,fontWeight:500,fontSize:19,lineHeight:1.1}),o.style.header({margin:{bottom:16}}),o.style.caption({...T,fontWeight:400,fontSize:12.5}),o.style.source({...T,fontWeight:400,fontSize:12}),o.style.dataLabel({...j,fontFamily:V,fontWeight:600,fontSize:13,lineHeight:1,paddingBlock:1,paddingInline:4,fill:"transparent"}),o.style.legendItem({...j,fontWeight:400,fontSize:15,fill:"transparent",stroke:"transparent"}),o.style.directLabel({fontWeight:700,fontSize:12.5}),o.style.headlineItem.number({...$,fontWeight:600,fontSize:32,lineHeight:1.1}),o.style.tooltip({strokeWidth:z,cornerRadius:0,paddingInline:10,paddingBlock:8,shadow:"none"}),o.style.tooltip.heading({...j,...$,fontWeight:700,fontSize:17,lineHeight:1.2}),o.style.tooltip.label({...T,fontWeight:400,fontSize:13,lineHeight:1.35}),o.style.tooltip.value({...j,fontWeight:700,fontSize:13,lineHeight:1.35}),o.style.legend.popover({strokeWidth:z,cornerRadius:0,shadow:"none"}),o.style.annotation.text({...I,fontSize:16,lineHeight:1.2}),o.style.annotation.pinnedNumber({fill:y.ink,stroke:y.paper,shadow:"none"}),o.style.annotation.pinnedNumber.label({...I}),o.style.annotation.comment({fill:y.ink,stroke:y.paper,shadow:"none"}),o.style.annotation.comment.label({...I}),o.style.annotation.differenceArrow({stroke:y.ink,strokeWidth:1.25}),o.style.annotation.differenceArrow.label({...I}),o.style.annotation.arrow({stroke:y.ink,strokeWidth:1.25,dashArray:[]}),o.style.annotation.shape({fill:x.sage,fillAlpha:.14,strokeWidth:0}),o.style.panelBorder.bottom({strokeWidth:0},{coord:"polar"}),o.style.geom.area({fillAlpha:.35},{coord:"polar"}),o.style.tickLabel({...j,fontWeight:700,textOutlineColor:y.paper,textOutlineWidth:3},{coord:"polar"})]},Y=y.ink;var ge=.6,pe=.7,$e=5,Oe=.35,Ne=e=>`${e}-${(0,R.useId)().replace(/[^a-zA-Z0-9]/gu,"")}`,G=({path:e,color:t,opacity:r})=>{const a=Ne("wash");return(0,u.jsxs)("g",{children:[(0,u.jsx)("clipPath",{id:a,children:(0,u.jsx)("path",{d:e})}),(0,u.jsx)("path",{d:e,fill:t,fillOpacity:r}),(0,u.jsx)("path",{d:e,fill:"none",stroke:t,strokeOpacity:Oe,strokeWidth:$e,clipPath:`url(#${a})`})]})},A=({path:e,width:t=1,opacity:r=1})=>(0,u.jsx)("path",{d:e,fill:"none",stroke:Y,strokeWidth:t,strokeOpacity:r,strokeLinecap:"round",strokeLinejoin:"round"}),U=({base:e,length:t,angle:r,color:a,opacity:n=1,washOpacity:s=.6})=>{const{blade:l,rib:i}=K(e,t,t*.32,r);return(0,u.jsxs)("g",{opacity:n,children:[(0,u.jsx)("path",{d:l,fill:a,fillOpacity:s,stroke:Y,strokeWidth:.8,strokeLinejoin:"round"}),(0,u.jsx)(A,{path:i,width:ge,opacity:pe})]})},L=e=>{const t=(0,o.useGeomStyleReader)(e);return(r,a)=>({color:(0,o.toPaintColor)(t.get("fill",r,a)),opacity:t.get("alpha",r,a),fillOpacity:t.get("fillAlpha",r,a),edge:t.get("stroke",r,a),edgeWidth:t.get("strokeWidth",r,a)})},fe=e=>{const t=(0,o.useGeomStyleReader)(e);return(r,a)=>{const n=t.get("strokeWidth",r,a);return{color:t.get("stroke",r,a),opacity:t.get("alpha",r,a)*t.get("strokeAlpha",r,a),width:n,dashArray:(0,o.toStrokeDasharray)(t.get("dashArray",r,a),n)}}},Ge=16,ae=(e,t)=>{const r=(0,o.createStableKeyGenerator)(e.data,e.mapping,e.id),a=[];return e.data.groupBy(o.GROUP_VARIABLES.group).forEach(n=>{const s=[...n],[l]=s,i=t(s);l===void 0||i===null||a.push({key:r(l),observation:l,path:i})}),a},Be=(e,t)=>{const r=e.flatMap(a=>{const n=(0,o.getX)(a),s=N(a,t);return n===null||s===null?[]:[{angle:n,point:s}]}).sort((a,n)=>a.angle-n.angle).map(({point:a})=>a);return r.length===0?null:be(r)},ye=({geom:e,observation:t,panel:r,project:a,color:n,opacity:s})=>{const l=a(t,r);return l===null?null:(0,u.jsx)("g",{"data-geom":e,children:(0,u.jsx)(U,{base:l,length:Ge,angle:-Math.PI/4,color:n,opacity:s})})},De=1.2,Fe=/^[ML\d\s.,eE+-]+$/u,ze=/[-+]?(?:\d+\.?\d*|\.\d+)(?:[eE][-+]?\d+)?/gu,Ke=e=>{if(!Fe.test(e))return null;const t=(e.match(ze)??[]).map(Number),r=[];for(let a=0;a+1<t.length;a+=2)r.push({x:t[a],y:t[a+1]});return r},ne=(e,t,r)=>{const a=Ke(e.replace(/\s*Z\s*$/u,""));return a===null||a.length<2?e:w(a,{wander:De,seed:t,closed:r})},ve=({layer:e,coordSystem:t,panel:r})=>{const a=L(e),n=(0,R.useMemo)(()=>{if(t===void 0)return ae(e,d=>Be(d,r)).map(d=>({...d,fill:d.path,edge:ne(d.path,P(d.key),!0)}));const{areaGenerator:s,lineGenerator:l}=(0,o.createAreaPathGenerators)(t,e.params),i=new Map;return ae(e,d=>{const g=(0,o.prepareAreaObservations)(d,e.params.missingValues),h=s(g),p=l(g);if(!h)return null;const c=Q(h,r);return p&&i.set(c,Q(p,r)),c}).map(d=>({...d,fill:d.path,edge:ne(i.get(d.path)??"",P(d.key),!1)}))},[e,t,r]);return r.width<=0||r.height<=0?null:(0,u.jsx)("g",{"data-geom":"area",children:n.map(({key:s,observation:l,fill:i,edge:d})=>{const g=a(l);return(0,u.jsxs)("g",{opacity:g.opacity,children:[(0,u.jsx)(G,{path:i,color:g.color,opacity:g.fillOpacity}),(0,u.jsx)(A,{path:d,width:g.edgeWidth})]},s)})})},xe=({layer:e,observation:t,panel:r,project:a})=>{const n=L(e)(t,"hovered");return(0,u.jsx)(ye,{geom:"area",observation:t,panel:r,project:a,color:n.color,opacity:n.opacity})},Ve=(0,o.defineGeomRenderer)("area",{coord:"cartesian",guideMode:"crosshair",swatchShape:"area",render:({layer:e,coordSystem:t,panelRect:r})=>t.type!=="cartesian"?null:(0,u.jsx)(ve,{layer:e,coordSystem:t,panel:r}),renderHover:({layer:e,primary:t,panelRect:r})=>(0,u.jsx)(xe,{layer:e,observation:t.observation,panel:r,project:X}),renderHoverCompanions:()=>null}),Xe=(0,o.defineGeomRenderer)("area",{coord:"polar",guideMode:"crosshair",swatchShape:"area",render:({layer:e,panelRect:t})=>(0,u.jsx)(ve,{layer:e,panel:t}),renderHover:({layer:e,primary:t,panelRect:r})=>(0,u.jsx)(xe,{layer:e,observation:t.observation,panel:r,project:N}),renderHoverCompanions:()=>null}),Ye=1.4,Ue=.8,qe=.6,W=13,Ze=14,Qe=6,Je=2,et={solo:{base:!0,value:!0},floor:{base:!0,value:!1},ceiling:{base:!1,value:!0},middle:{base:!1,value:!1}},tt={top:"bottom",bottom:"top",left:"right",right:"left"},rt=(e,t)=>t==="x"?((0,o.getYMax)(e)??(0,o.getY)(e)??0)>=((0,o.getYMin)(e)??0)?"top":"bottom":((0,o.getXMax)(e)??0)>=((0,o.getXMin)(e)??0)?"right":"left",at=(e,t,r)=>{const a=Math.max(0,e.width-r),n=Math.max(0,e.height-r);return t==="top"?{...e,y:e.y+e.height-n,height:n}:t==="bottom"?{...e,height:n}:t==="left"?{...e,x:e.x+e.width-a,width:a}:{...e,width:a}},nt=(e,t)=>t==="top"||t==="bottom"?{breadth:e.width,length:e.height}:{breadth:e.height,length:e.width},E=(e,t,r,a)=>{const{x:n,y:s,width:l,height:i}=e;return t==="top"?{x:n+r,y:s+i-a}:t==="bottom"?{x:n+r,y:s+a}:t==="right"?{x:n+a,y:s+r}:{x:n+l-a,y:s+r}},ot=(e,t,r,a)=>{const n=r/2,s=r*.36,l=[];for(let i=W*.8;i<a-W*.6;i+=W)for(const d of[-1,1]){const g=E(e,t,n,i),h=E(e,t,n+d*s*.55,i+W*.25),p=E(e,t,n+d*s,i+W*.6);l.push(`M${g.x},${g.y} Q${h.x},${h.y} ${p.x},${p.y}`)}return l.join(" ")},it=({layer:e,observation:t,seedKey:r,mainAxis:a,panel:n,state:s})=>{const l=L(e),i=(0,o.getBarRectBounds)(a,t);if(!i||i.width<=0||i.height<=0)return null;const d=l(t,s),g=et[(0,o.getStackRole)(t)],h=rt(t,a),p={x:i.x*n.width,y:i.y*n.height,width:i.width*n.width,height:i.height*n.height},c=[g.value?[]:[h],g.base?[]:[tt[h]]].flat().reduce((_,b)=>at(_,b,Je/2),p),{breadth:f,length:v}=nt(c,h);if(f<=0||v<=0)return null;const M=P(r),S=w([E(c,h,0,0),E(c,h,0,v),E(c,h,f,v),E(c,h,f,0)],{wander:Math.min(Ye,f/8),seed:M,closed:!0,cornered:!0}),k=f>=Qe&&v>8?w([E(c,h,f/2,1),E(c,h,f/2,v-3)],{wander:Ue,seed:M+1}):"";return(0,u.jsxs)("g",{opacity:d.opacity,children:[(0,u.jsx)(G,{path:S,color:d.color,opacity:d.fillOpacity*qe}),k!==""&&(0,u.jsx)(A,{path:k,width:.6*1.4,opacity:.7}),f>=Ze&&(0,u.jsx)(A,{path:ot(c,h,f,v),width:.6,opacity:.7*.8}),(0,u.jsx)(A,{path:S,width:d.edgeWidth})]})},oe=({layer:e,observations:t,mainAxis:r,panel:a,state:n})=>{const s=(0,R.useMemo)(()=>(0,o.createStableKeyGenerator)(e.data,e.mapping,e.id),[e.data,e.mapping,e.id]);return a.width<=0||a.height<=0?null:(0,u.jsx)("g",{"data-geom":"bar",children:Array.from(t,l=>{const i=s(l);return(0,u.jsx)(it,{layer:e,observation:l,seedKey:i,mainAxis:r,panel:a,state:n},i)})})},st=(0,o.defineGeomRenderer)("bar",{coord:"cartesian",guideMode:"band",swatchShape:"square",render:({layer:e,coordSystem:t,panelRect:r})=>(0,u.jsx)(oe,{layer:e,observations:e.data,mainAxis:(0,o.readMainAxis)(t),panel:r}),renderHover:({layer:e,coordSystem:t,primary:r,panelRect:a})=>(0,u.jsx)(oe,{layer:e,observations:[r.observation],mainAxis:(0,o.readMainAxis)(t),panel:a,state:"hovered"}),renderHoverCompanions:()=>null}),lt=1.2,dt=15,ht=20,ct=.75,ut=(e,t,r,a)=>{const n=(0,o.createStableKeyGenerator)(e.data,e.mapping,e.id),s=[];return e.data.groupBy(o.GROUP_VARIABLES.group).forEach(l=>{const i=[...l],[d]=i;if(d===void 0)return;const g=(r==="polar"?i.sort((p,c)=>((0,o.getX)(p)??0)-((0,o.getX)(c)??0)):i).flatMap(p=>{const c=a(p,t);return c===null?[]:[c]});if(g.length<2)return;const h=n(d);s.push({key:h,observation:d,points:g,stem:w(g,{wander:lt,seed:P(h),closed:r==="polar"})})}),s},gt=e=>{const t=[];let r=null;return e.forEach((a,n)=>{if(r!==null&&Math.hypot(a.x-r.x,a.y-r.y)<ht)return;const s=e[Math.max(0,n-1)],l=e[Math.min(e.length-1,n+1)],i=Math.atan2(l.y-s.y,l.x-s.x),d=t.length%2===0?-1:1;t.push({base:a,angle:i+d*(Math.PI/2-ct)}),r=a}),t},pt=({layer:e,panel:t,coord:r,project:a})=>{const n=fe(e),s=(0,R.useMemo)(()=>ut(e,t,r,a),[e,t,r,a]);return t.width<=0||t.height<=0?null:(0,u.jsx)("g",{"data-geom":"line",children:s.map(({key:l,observation:i,stem:d,points:g})=>{const h=n(i);return(0,u.jsxs)("g",{opacity:h.opacity,children:[(0,u.jsx)("path",{d,fill:"none",stroke:h.color,strokeWidth:h.width,strokeDasharray:h.dashArray,strokeLinecap:"round",strokeLinejoin:"round"}),gt(g).map(({base:p,angle:c},f)=>(0,u.jsx)(U,{base:p,length:dt,angle:c,color:h.color},f))]},l)})})},ft=({layer:e,observation:t,panel:r,project:a})=>{const n=fe(e)(t,"hovered");return(0,u.jsx)(ye,{geom:"line",observation:t,panel:r,project:a,color:n.color,opacity:n.opacity})},me=(e,t)=>(0,o.defineGeomRenderer)("line",{coord:e,guideMode:"crosshair",swatchShape:"line",render:({layer:r,panelRect:a})=>(0,u.jsx)(pt,{layer:r,panel:a,coord:e,project:t}),renderHover:({layer:r,primary:a,panelRect:n})=>(0,u.jsx)(ft,{layer:r,observation:a.observation,panel:n,project:t}),renderHoverCompanions:()=>null,getOverlayAnchor:({observation:r})=>{const a=(0,o.getX)(r),n=(0,o.getY)(r);return a===null||n===null?null:{x:a,y:n}}}),yt=me("cartesian",X),vt=me("polar",N),xt=2.6,mt=4,ie=({layer:e,observations:t,panel:r,project:a,state:n})=>{const s=(0,o.useGeomStyleReader)(e),l=L(e),i=(0,R.useMemo)(()=>(0,o.createStableKeyGenerator)(e.data,e.mapping,e.id),[e.data,e.mapping,e.id]),d=n==="hovered"?mt:0;return(0,u.jsx)("g",{"data-geom":"point",children:Array.from(t,g=>{const h=a(g,r);if(h===null)return null;const p=i(g),c=l(g,n),f=(s.get("size",g,n)+d)*xt,v=C(P(p))()*Math.PI*2;return(0,u.jsx)(U,{base:{x:h.x-Math.cos(v)*f/2,y:h.y-Math.sin(v)*f/2},length:f,angle:v,color:c.color,opacity:c.opacity,washOpacity:c.fillOpacity*.7},p)})})},Ae=(e,t)=>(0,o.defineGeomRenderer)("point",{coord:e,swatchShape:"circle",render:({layer:r,panelRect:a})=>(0,u.jsx)(ie,{layer:r,observations:r.data,panel:a,project:t}),renderHover:({layer:r,primary:a,panelRect:n})=>(0,u.jsx)(ie,{layer:r,observations:[a.observation],panel:n,project:t,state:"hovered"}),renderHoverCompanions:()=>null}),At=Ae("cartesian",X),kt=Ae("polar",N),Et=3,wt=1.6,bt=Math.PI/30,Mt=.6,St=.3,_t=.13,se=34,jt="#B08A2E",O=(e,t,r)=>{const a=(0,o.polarToUnit)(t,1);return{x:e.width/2+a.x*r,y:e.height/2-a.y*r}},le=(e,t,r,a)=>{const n=Math.max(1,Math.ceil(Math.abs(r-t)/bt));return Array.from({length:n+1},(s,l)=>O(e,t+(r-t)*l/n,a))},Pt=(e,t,r)=>{const{startAngle:a,endAngle:n}=(0,o.getAngleExtent)(e),{innerRadius:s,outerRadius:l}=(0,o.getRadiusExtent)(e);if(a===null||n===null||s===null||l===null)return null;const i=Math.min(t.width,t.height)/2,d=l*i,g=s*i;if(d<=0)return null;const h=Math.max(0,n-a),p=h>=2*Math.PI-1e-6?0:Math.min(Et/2/d,h/4),c=a+p,f=n-p,v=le(t,c,f,d),M=g>0?le(t,f,c,g):[O(t,0,0)],S=w([...v,...M],{wander:wt,seed:r,closed:!0,step:12}),k=Math.max(1,Math.round((f-c)/St)),_=g+(d-g)*.12,b=d-(d-g)*.14;return{outline:S,veins:Array.from({length:k},(B,q)=>{const Z=c+(f-c)*(q+.5)/k;return w([O(t,Z,_),O(t,Z,b)],{wander:.8,seed:r+q+1})}).join(" ")}},Rt=(e,t,r)=>{const a=C(r),n=Math.PI*(3-Math.sqrt(5));return Array.from({length:se},(s,l)=>{const i=t*.85*Math.sqrt((l+.5)/se),d=l*n+a()*.2,g=e.x+Math.cos(d)*i,h=e.y+Math.sin(d)*i;return`M${g.toFixed(2)},${h.toFixed(2)} h0.01`}).join(" ")},de=({layer:e,observations:t,panel:r,state:a})=>{const n=L(e),s=(0,R.useMemo)(()=>(0,o.createStableKeyGenerator)(e.data,e.mapping,e.id),[e.data,e.mapping,e.id]);if(r.width<=0||r.height<=0)return null;const l=Array.from(t,p=>{const c=s(p);return{key:c,observation:p,paint:n(p,a),petal:Pt(p,r,P(c))}}),i=l.map(({observation:p})=>(0,o.getRadiusExtent)(p)),d=a===void 0&&l.length>1&&i.every(({innerRadius:p,outerRadius:c})=>p===0&&c===i[0]?.outerRadius),g={x:r.width/2,y:r.height/2},h=Math.min(r.width,r.height)/2*_t;return(0,u.jsxs)("g",{"data-geom":"bar",children:[l.map(({key:p,paint:c,petal:f})=>f===null?null:(0,u.jsxs)("g",{opacity:c.opacity,children:[(0,u.jsx)(G,{path:f.outline,color:c.color,opacity:c.fillOpacity*Mt}),(0,u.jsx)(A,{path:f.veins,width:ge,opacity:pe*.8}),(0,u.jsx)(A,{path:f.outline,width:c.edgeWidth})]},p)),d&&(0,u.jsxs)("g",{children:[(0,u.jsx)("circle",{cx:g.x,cy:g.y,r:h,fill:jt,fillOpacity:.55}),(0,u.jsx)(A,{path:Rt(g,h,7),width:2.2}),(0,u.jsx)(A,{path:w(Array.from({length:13},(p,c)=>{const f=c/12*Math.PI*2;return{x:g.x+Math.cos(f)*h,y:g.y+Math.sin(f)*h}}),{wander:.8,seed:11})})]})]})},Tt=(0,o.defineGeomRenderer)("bar",{coord:"polar",guideMode:"band",swatchShape:"slice",render:({layer:e,panelRect:t})=>(0,u.jsx)(de,{layer:e,observations:e.data,panel:t}),renderHover:({layer:e,primary:t,panelRect:r})=>(0,u.jsx)(de,{layer:e,observations:[t.observation],panel:r,state:"hovered"}),renderHoverCompanions:()=>null}),H=3,Lt=1,Wt=({layer:e,observation:t,seedKey:r,panel:a,state:n})=>{const s=L(e),l=(0,o.getPaintedTileRect)(t);if(l===null)return null;const i=s(t,n),d=l.x*a.width+H/2,g=l.y*a.height+H/2,h=l.width*a.width-H,p=l.height*a.height-H;if(h<=0||p<=0)return null;const c=w([{x:d,y:g},{x:d+h,y:g},{x:d+h,y:g+p},{x:d,y:g+p}],{wander:Math.min(Lt,h/10,p/10),seed:P(r),closed:!0,cornered:!0});return(0,u.jsxs)("g",{opacity:i.opacity,children:[(0,u.jsx)(G,{path:c,color:i.color,opacity:i.fillOpacity*.85}),(0,u.jsx)(A,{path:c,width:n==="hovered"?i.edgeWidth:.8,opacity:.85})]})},he=({layer:e,observations:t,panel:r,state:a})=>{const n=(0,R.useMemo)(()=>(0,o.createStableCellKeyGenerator)(e.data,e.mapping,e.id),[e.data,e.mapping,e.id]);return r.width<=0||r.height<=0?null:(0,u.jsx)("g",{"data-geom":"tile",children:Array.from(t,s=>{const l=n(s);return(0,u.jsx)(Wt,{layer:e,observation:s,seedKey:l,panel:r,state:a},l)})})},Ct=(0,o.defineGeomRenderer)("tile",{coord:"cartesian",guideMode:null,swatchShape:"square",render:({layer:e,panelRect:t})=>(0,u.jsx)(he,{layer:e,observations:e.data,panel:t}),renderHover:({layer:e,primary:t,panelRect:r})=>(0,u.jsx)(he,{layer:e,observations:[t.observation],panel:r,state:"hovered"}),renderHoverCompanions:()=>null}),It=[st,Tt,Ct,yt,vt,Ve,Xe,At,kt],Ht=({fill:e,fillOpacity:t,...r})=>(0,u.jsx)(o.DefaultGeomCircle,{...r,fill:e,fillOpacity:.6,stroke:Y,strokeWidth:.9}),$t={Circle:Ht},Ot={name:"botanical",styles:He,palette:We,colormap:Ce,colorScheme:"light",plugins:It,shapes:$t};exports.botanical=Ot;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { botanical } from './botanical';
|