@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 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
- # Temporary Holding Version
1
+ # @graphysdk/theme-botanical
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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;
@@ -0,0 +1 @@
1
+ export { botanical } from './botanical';