[{"data":1,"prerenderedAt":997},["ShallowReactive",2],{"content-navigation":3,"docs-shell-navigation":42,"content-page:\u002Fcustom-algorithm":53,"content-surround:\u002Fcustom-algorithm":992},[4,8,34,38],{"title":5,"path":6,"stem":7},"Getting Started","\u002Fgetting-started","01.getting-started",{"title":9,"path":10,"stem":11,"children":12,"page":33},"Components","\u002Fcomponents","02.components",[13,17,21,25,29],{"title":14,"path":15,"stem":16},"Avatar","\u002Fcomponents\u002Favatar","02.components\u002F01.avatar",{"title":18,"path":19,"stem":20},"GradientAvatar","\u002Fcomponents\u002Fgradient-avatar","02.components\u002F02.gradient-avatar",{"title":22,"path":23,"stem":24},"InitialsAvatar","\u002Fcomponents\u002Finitials-avatar","02.components\u002F03.initials-avatar",{"title":26,"path":27,"stem":28},"IdenticonAvatar","\u002Fcomponents\u002Fidenticon-avatar","02.components\u002F04.identicon-avatar",{"title":30,"path":31,"stem":32},"FlowFieldAvatar","\u002Fcomponents\u002Fflow-field-avatar","02.components\u002F05.flow-field-avatar",false,{"title":35,"path":36,"stem":37},"Custom Algorithm","\u002Fcustom-algorithm","03.custom-algorithm",{"title":39,"path":40,"stem":41},"Engine Helpers","\u002Fengine","04.engine",[43,44,51,52],{"title":5,"path":6,"stem":7},{"title":9,"path":10,"stem":11,"children":45,"page":33},[46,47,48,49,50],{"title":14,"path":15,"stem":16},{"title":18,"path":19,"stem":20},{"title":22,"path":23,"stem":24},{"title":26,"path":27,"stem":28},{"title":30,"path":31,"stem":32},{"title":35,"path":36,"stem":37},{"title":39,"path":40,"stem":41},{"id":54,"title":35,"body":55,"description":987,"extension":988,"meta":989,"navigation":135,"path":36,"seo":990,"stem":37,"__hash__":991},"docs\u002F03.custom-algorithm.md",{"type":56,"value":57,"toc":981},"minimark",[58,62,75,80,260,280,284,291,347,351,783,796,799,934,938,977],[59,60,35],"h1",{"id":61},"custom-algorithm",[63,64,65,66,70,71,74],"p",{},"One of the core ideas behind ",[67,68,69],"code",{},"@maxnth\u002Fgestalt"," is that avatars are just deterministic drawing functions. You can write your own algorithm and plug it into the generic ",[67,72,73],{},"\u003CAvatar>"," component.",[76,77,79],"h2",{"id":78},"the-avataralgorithm-interface","The AvatarAlgorithm interface",[81,82,87],"pre",{"className":83,"code":84,"language":85,"meta":86,"style":86},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import type { AlgorithmRenderContext, AvatarAlgorithm } from '@maxnth\u002Fgestalt'\n\ninterface AlgorithmRenderContext {\n  ctx: CanvasLikeContext\n  size: number\n  seed: AvatarSeed\n}\n\ninterface AvatarAlgorithm {\n  name: string\n  render: (context: AlgorithmRenderContext, options?: unknown) => void\n}\n","ts","",[67,88,89,130,137,150,163,174,185,191,196,205,216,255],{"__ignoreMap":86},[90,91,94,98,101,105,109,112,115,118,121,124,127],"span",{"class":92,"line":93},"line",1,[90,95,97],{"class":96},"s7zQu","import",[90,99,100],{"class":96}," type",[90,102,104],{"class":103},"sMK4o"," {",[90,106,108],{"class":107},"sTEyZ"," AlgorithmRenderContext",[90,110,111],{"class":103},",",[90,113,114],{"class":107}," AvatarAlgorithm",[90,116,117],{"class":103}," }",[90,119,120],{"class":96}," from",[90,122,123],{"class":103}," '",[90,125,69],{"class":126},"sfazB",[90,128,129],{"class":103},"'\n",[90,131,133],{"class":92,"line":132},2,[90,134,136],{"emptyLinePlaceholder":135},true,"\n",[90,138,140,144,147],{"class":92,"line":139},3,[90,141,143],{"class":142},"spNyl","interface",[90,145,108],{"class":146},"sBMFI",[90,148,149],{"class":103}," {\n",[90,151,153,157,160],{"class":92,"line":152},4,[90,154,156],{"class":155},"swJcz","  ctx",[90,158,159],{"class":103},":",[90,161,162],{"class":146}," CanvasLikeContext\n",[90,164,166,169,171],{"class":92,"line":165},5,[90,167,168],{"class":155},"  size",[90,170,159],{"class":103},[90,172,173],{"class":146}," number\n",[90,175,177,180,182],{"class":92,"line":176},6,[90,178,179],{"class":155},"  seed",[90,181,159],{"class":103},[90,183,184],{"class":146}," AvatarSeed\n",[90,186,188],{"class":92,"line":187},7,[90,189,190],{"class":103},"}\n",[90,192,194],{"class":92,"line":193},8,[90,195,136],{"emptyLinePlaceholder":135},[90,197,199,201,203],{"class":92,"line":198},9,[90,200,143],{"class":142},[90,202,114],{"class":146},[90,204,149],{"class":103},[90,206,208,211,213],{"class":92,"line":207},10,[90,209,210],{"class":155},"  name",[90,212,159],{"class":103},[90,214,215],{"class":146}," string\n",[90,217,219,222,224,227,231,233,235,237,240,243,246,249,252],{"class":92,"line":218},11,[90,220,221],{"class":155},"  render",[90,223,159],{"class":103},[90,225,226],{"class":103}," (",[90,228,230],{"class":229},"sHdIc","context",[90,232,159],{"class":103},[90,234,108],{"class":146},[90,236,111],{"class":103},[90,238,239],{"class":229}," options",[90,241,242],{"class":103},"?:",[90,244,245],{"class":146}," unknown",[90,247,248],{"class":103},")",[90,250,251],{"class":142}," =>",[90,253,254],{"class":146}," void\n",[90,256,258],{"class":92,"line":257},12,[90,259,190],{"class":103},[261,262,263,270],"ul",{},[264,265,266,269],"li",{},[67,267,268],{},"name"," — a unique identifier for debugging and Storybook controls.",[264,271,272,275,276,279],{},[67,273,274],{},"render"," — the drawing function. It receives a ",[67,277,278],{},"CanvasLikeContext",", the internal render size in pixels, and the raw seed.",[76,281,283],{"id":282},"seed-handling","Seed handling",[63,285,286,287,290],{},"Use ",[67,288,289],{},"toSeed(seed)"," to normalize any string or number into a stable numeric value.",[81,292,294],{"className":83,"code":293,"language":85,"meta":86,"style":86},"import { toSeed } from '@maxnth\u002Fgestalt'\n\nconst numericSeed = toSeed('ada@example.com')\n",[67,295,296,315,319],{"__ignoreMap":86},[90,297,298,300,302,305,307,309,311,313],{"class":92,"line":93},[90,299,97],{"class":96},[90,301,104],{"class":103},[90,303,304],{"class":107}," toSeed",[90,306,117],{"class":103},[90,308,120],{"class":96},[90,310,123],{"class":103},[90,312,69],{"class":126},[90,314,129],{"class":103},[90,316,317],{"class":92,"line":132},[90,318,136],{"emptyLinePlaceholder":135},[90,320,321,324,327,330,333,336,339,342,344],{"class":92,"line":139},[90,322,323],{"class":142},"const",[90,325,326],{"class":107}," numericSeed ",[90,328,329],{"class":103},"=",[90,331,304],{"class":332},"s2Zo4",[90,334,335],{"class":107},"(",[90,337,338],{"class":103},"'",[90,340,341],{"class":126},"ada@example.com",[90,343,338],{"class":103},[90,345,346],{"class":107},")\n",[76,348,350],{"id":349},"example-polka-dot-algorithm","Example: polka-dot algorithm",[81,352,354],{"className":83,"code":353,"language":85,"meta":86,"style":86},"import type { AlgorithmRenderContext, AvatarAlgorithm } from '@maxnth\u002Fgestalt'\nimport { seededRandom, toSeed } from '@maxnth\u002Fgestalt'\n\nconst polkaAlgorithm: AvatarAlgorithm = {\n  name: 'polka',\n  render({ ctx, size, seed }: AlgorithmRenderContext) {\n    const random = seededRandom(toSeed(seed))\n    const dots = 12\n\n    ctx.fillStyle = '#f8fafc'\n    ctx.fillRect(0, 0, size, size)\n\n    ctx.fillStyle = '#6366f1'\n    for (let i = 0; i \u003C dots; i++) {\n      const x = random() * size\n      const y = random() * size\n      const r = random() * size * 0.12 + size * 0.04\n      ctx.beginPath()\n      ctx.arc(x, y, r, 0, Math.PI * 2)\n      ctx.fill()\n    }\n  },\n}\n",[67,355,356,380,403,407,423,439,468,493,506,510,530,559,563,581,622,644,662,696,710,754,766,772,778],{"__ignoreMap":86},[90,357,358,360,362,364,366,368,370,372,374,376,378],{"class":92,"line":93},[90,359,97],{"class":96},[90,361,100],{"class":96},[90,363,104],{"class":103},[90,365,108],{"class":107},[90,367,111],{"class":103},[90,369,114],{"class":107},[90,371,117],{"class":103},[90,373,120],{"class":96},[90,375,123],{"class":103},[90,377,69],{"class":126},[90,379,129],{"class":103},[90,381,382,384,386,389,391,393,395,397,399,401],{"class":92,"line":132},[90,383,97],{"class":96},[90,385,104],{"class":103},[90,387,388],{"class":107}," seededRandom",[90,390,111],{"class":103},[90,392,304],{"class":107},[90,394,117],{"class":103},[90,396,120],{"class":96},[90,398,123],{"class":103},[90,400,69],{"class":126},[90,402,129],{"class":103},[90,404,405],{"class":92,"line":139},[90,406,136],{"emptyLinePlaceholder":135},[90,408,409,411,414,416,418,421],{"class":92,"line":152},[90,410,323],{"class":142},[90,412,413],{"class":107}," polkaAlgorithm",[90,415,159],{"class":103},[90,417,114],{"class":146},[90,419,420],{"class":103}," =",[90,422,149],{"class":103},[90,424,425,427,429,431,434,436],{"class":92,"line":165},[90,426,210],{"class":155},[90,428,159],{"class":103},[90,430,123],{"class":103},[90,432,433],{"class":126},"polka",[90,435,338],{"class":103},[90,437,438],{"class":103},",\n",[90,440,441,443,446,449,451,454,456,459,462,464,466],{"class":92,"line":176},[90,442,221],{"class":155},[90,444,445],{"class":103},"({",[90,447,448],{"class":229}," ctx",[90,450,111],{"class":103},[90,452,453],{"class":229}," size",[90,455,111],{"class":103},[90,457,458],{"class":229}," seed",[90,460,461],{"class":103}," }:",[90,463,108],{"class":146},[90,465,248],{"class":103},[90,467,149],{"class":103},[90,469,470,473,476,478,480,482,485,487,490],{"class":92,"line":187},[90,471,472],{"class":142},"    const",[90,474,475],{"class":107}," random",[90,477,420],{"class":103},[90,479,388],{"class":332},[90,481,335],{"class":155},[90,483,484],{"class":332},"toSeed",[90,486,335],{"class":155},[90,488,489],{"class":107},"seed",[90,491,492],{"class":155},"))\n",[90,494,495,497,500,502],{"class":92,"line":193},[90,496,472],{"class":142},[90,498,499],{"class":107}," dots",[90,501,420],{"class":103},[90,503,505],{"class":504},"sbssI"," 12\n",[90,507,508],{"class":92,"line":198},[90,509,136],{"emptyLinePlaceholder":135},[90,511,512,515,518,521,523,525,528],{"class":92,"line":207},[90,513,514],{"class":107},"    ctx",[90,516,517],{"class":103},".",[90,519,520],{"class":107},"fillStyle",[90,522,420],{"class":103},[90,524,123],{"class":103},[90,526,527],{"class":126},"#f8fafc",[90,529,129],{"class":103},[90,531,532,534,536,539,541,544,546,549,551,553,555,557],{"class":92,"line":218},[90,533,514],{"class":107},[90,535,517],{"class":103},[90,537,538],{"class":332},"fillRect",[90,540,335],{"class":155},[90,542,543],{"class":504},"0",[90,545,111],{"class":103},[90,547,548],{"class":504}," 0",[90,550,111],{"class":103},[90,552,453],{"class":107},[90,554,111],{"class":103},[90,556,453],{"class":107},[90,558,346],{"class":155},[90,560,561],{"class":92,"line":257},[90,562,136],{"emptyLinePlaceholder":135},[90,564,566,568,570,572,574,576,579],{"class":92,"line":565},13,[90,567,514],{"class":107},[90,569,517],{"class":103},[90,571,520],{"class":107},[90,573,420],{"class":103},[90,575,123],{"class":103},[90,577,578],{"class":126},"#6366f1",[90,580,129],{"class":103},[90,582,584,587,589,592,595,597,599,602,604,607,609,611,613,616,619],{"class":92,"line":583},14,[90,585,586],{"class":96},"    for",[90,588,226],{"class":155},[90,590,591],{"class":142},"let",[90,593,594],{"class":107}," i",[90,596,420],{"class":103},[90,598,548],{"class":504},[90,600,601],{"class":103},";",[90,603,594],{"class":107},[90,605,606],{"class":103}," \u003C",[90,608,499],{"class":107},[90,610,601],{"class":103},[90,612,594],{"class":107},[90,614,615],{"class":103},"++",[90,617,618],{"class":155},") ",[90,620,621],{"class":103},"{\n",[90,623,625,628,631,633,635,638,641],{"class":92,"line":624},15,[90,626,627],{"class":142},"      const",[90,629,630],{"class":107}," x",[90,632,420],{"class":103},[90,634,475],{"class":332},[90,636,637],{"class":155},"() ",[90,639,640],{"class":103},"*",[90,642,643],{"class":107}," size\n",[90,645,647,649,652,654,656,658,660],{"class":92,"line":646},16,[90,648,627],{"class":142},[90,650,651],{"class":107}," y",[90,653,420],{"class":103},[90,655,475],{"class":332},[90,657,637],{"class":155},[90,659,640],{"class":103},[90,661,643],{"class":107},[90,663,665,667,670,672,674,676,678,680,683,686,689,691,693],{"class":92,"line":664},17,[90,666,627],{"class":142},[90,668,669],{"class":107}," r",[90,671,420],{"class":103},[90,673,475],{"class":332},[90,675,637],{"class":155},[90,677,640],{"class":103},[90,679,453],{"class":107},[90,681,682],{"class":103}," *",[90,684,685],{"class":504}," 0.12",[90,687,688],{"class":103}," +",[90,690,453],{"class":107},[90,692,682],{"class":103},[90,694,695],{"class":504}," 0.04\n",[90,697,699,702,704,707],{"class":92,"line":698},18,[90,700,701],{"class":107},"      ctx",[90,703,517],{"class":103},[90,705,706],{"class":332},"beginPath",[90,708,709],{"class":155},"()\n",[90,711,713,715,717,720,722,725,727,729,731,733,735,737,739,742,744,747,749,752],{"class":92,"line":712},19,[90,714,701],{"class":107},[90,716,517],{"class":103},[90,718,719],{"class":332},"arc",[90,721,335],{"class":155},[90,723,724],{"class":107},"x",[90,726,111],{"class":103},[90,728,651],{"class":107},[90,730,111],{"class":103},[90,732,669],{"class":107},[90,734,111],{"class":103},[90,736,548],{"class":504},[90,738,111],{"class":103},[90,740,741],{"class":107}," Math",[90,743,517],{"class":103},[90,745,746],{"class":107},"PI",[90,748,682],{"class":103},[90,750,751],{"class":504}," 2",[90,753,346],{"class":155},[90,755,757,759,761,764],{"class":92,"line":756},20,[90,758,701],{"class":107},[90,760,517],{"class":103},[90,762,763],{"class":332},"fill",[90,765,709],{"class":155},[90,767,769],{"class":92,"line":768},21,[90,770,771],{"class":103},"    }\n",[90,773,775],{"class":92,"line":774},22,[90,776,777],{"class":103},"  },\n",[90,779,781],{"class":92,"line":780},23,[90,782,190],{"class":103},[784,785,786],"blockquote",{},[63,787,788,789,792,793,795],{},"Note: ",[67,790,791],{},"seededRandom"," is exported from ",[67,794,69],{}," so your custom algorithms share the same deterministic PRNG as the built-in ones.",[63,797,798],{},"Use it like any other algorithm:",[81,800,804],{"className":801,"code":802,"language":803,"meta":86,"style":86},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003Cscript setup>\nimport { Avatar } from '@maxnth\u002Fgestalt'\nimport { polkaAlgorithm } from '.\u002Fpolka-algorithm'\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CAvatar seed=\"user-42\" :size=\"96\" :algorithm=\"polkaAlgorithm\" \u002F>\n\u003C\u002Ftemplate>\n","vue",[67,805,806,820,839,858,867,871,880,926],{"__ignoreMap":86},[90,807,808,811,814,817],{"class":92,"line":93},[90,809,810],{"class":103},"\u003C",[90,812,813],{"class":155},"script",[90,815,816],{"class":142}," setup",[90,818,819],{"class":103},">\n",[90,821,822,824,826,829,831,833,835,837],{"class":92,"line":132},[90,823,97],{"class":96},[90,825,104],{"class":103},[90,827,828],{"class":107}," Avatar",[90,830,117],{"class":103},[90,832,120],{"class":96},[90,834,123],{"class":103},[90,836,69],{"class":126},[90,838,129],{"class":103},[90,840,841,843,845,847,849,851,853,856],{"class":92,"line":139},[90,842,97],{"class":96},[90,844,104],{"class":103},[90,846,413],{"class":107},[90,848,117],{"class":103},[90,850,120],{"class":96},[90,852,123],{"class":103},[90,854,855],{"class":126},".\u002Fpolka-algorithm",[90,857,129],{"class":103},[90,859,860,863,865],{"class":92,"line":152},[90,861,862],{"class":103},"\u003C\u002F",[90,864,813],{"class":155},[90,866,819],{"class":103},[90,868,869],{"class":92,"line":165},[90,870,136],{"emptyLinePlaceholder":135},[90,872,873,875,878],{"class":92,"line":176},[90,874,810],{"class":103},[90,876,877],{"class":155},"template",[90,879,819],{"class":103},[90,881,882,885,887,889,891,894,897,899,902,904,906,909,911,914,916,918,921,923],{"class":92,"line":187},[90,883,884],{"class":103},"  \u003C",[90,886,14],{"class":155},[90,888,458],{"class":142},[90,890,329],{"class":103},[90,892,893],{"class":103},"\"",[90,895,896],{"class":126},"user-42",[90,898,893],{"class":103},[90,900,901],{"class":142}," :size",[90,903,329],{"class":103},[90,905,893],{"class":103},[90,907,908],{"class":126},"96",[90,910,893],{"class":103},[90,912,913],{"class":142}," :algorithm",[90,915,329],{"class":103},[90,917,893],{"class":103},[90,919,920],{"class":126},"polkaAlgorithm",[90,922,893],{"class":103},[90,924,925],{"class":103}," \u002F>\n",[90,927,928,930,932],{"class":92,"line":193},[90,929,862],{"class":103},[90,931,877],{"class":155},[90,933,819],{"class":103},[76,935,937],{"id":936},"tips","Tips",[261,939,940,946,956,966],{},[264,941,942,943,945],{},"Keep ",[67,944,274],{}," deterministic. The same seed must always paint the same output.",[264,947,948,949,952,953,517],{},"Do not read from external state like ",[67,950,951],{},"Date.now()"," or ",[67,954,955],{},"Math.random()",[264,957,286,958,961,962,965],{},[67,959,960],{},"ctx.fillRect",", ",[67,963,964],{},"ctx.fillStyle",", gradients, and paths freely — anything supported by a normal 2D context.",[264,967,968,969,972,973,976],{},"If you need advanced text metrics, cast ",[67,970,971],{},"ctx"," to ",[67,974,975],{},"CanvasRenderingContext2D"," inside your algorithm function.",[978,979,980],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":86,"searchDepth":139,"depth":139,"links":982},[983,984,985,986],{"id":78,"depth":132,"text":79},{"id":282,"depth":132,"text":283},{"id":349,"depth":132,"text":350},{"id":936,"depth":132,"text":937},"One of the core ideas behind @maxnth\u002Fgestalt is that avatars are just deterministic drawing functions. You can write your own algorithm and plug it into the generic \u003CAvatar> component.","md",{},{"title":35,"description":987},"uHNGrh6T3BDmP2LDCdfPt7D6iBOjVlZR4ERqJrX1ZXw",[993,995],{"title":30,"path":31,"stem":32,"description":994,"children":-1},"The \u003CFlowFieldAvatar> component renders deterministic streamlines through a seed-derived noise field.",{"title":39,"path":40,"stem":41,"description":996,"children":-1},"The deterministic engines that power the components are exposed as plain functions. Use them for downloads, server rendering, custom integrations, or framework-independent SVG generation.",1784287256267]