@tomtom-org/maps-sdk-plugin-map-theme 0.3.5 → 0.3.6
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/dist/index.es.js +1 -1
- package/package.json +3 -2
package/dist/index.es.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{clampRgb as e,differenceEuclidean as t,differenceHueNaive as o,formatHex as r,modeHsl as s,modeLrgb as a,modeOklab as n,modeOklch as l,modeRgb as i,parse as c,useMode as h,wcagContrast as d,wcagLuminance as p}from"culori/fn";import{formatStyleHsl as u,hueDistance as m,toHsl as f}from"@tomtom-org/maps-sdk/map";h(i),h(a),h(s),h(n);var g=h(l),w=t("oklab"),k=(e,t)=>w(e,t)<.035,b=([e,t,o])=>({mode:"rgb",r:e/255,g:t/255,b:o/255}),M=["light","dark","auto"],v=(e,t)=>new RegExp(String.raw`prefers-color-scheme\s*:\s*${e}|\.(?:theme-)?${e}(?:-(?:mode|theme))?(?![\w-])|\[data-[\w-]+=["']?${e}["']?\]`,t),x=["light","dark"],C={light:v("light","i"),dark:v("dark","i")},S=v("(?:light|dark)","gi"),y=/^(?:(?::root|html|body)\s*)+$/,I=/^background(-color)?$/,E=/url\((?:"[^"]*"|'[^']*'|[^)]*)\)|"[^"]*"|'[^']*'/gi,$=new RegExp([/#[\da-f]{3,8}\b/,/\b(?:rgba?|hsla?|oklab|oklch)\([^()]*\)/,/\b[a-z]+\b/].map(({source:e})=>e).join("|"),"i"),R=new RegExp($,"gi"),z=/var\(\s*(--[\w-]+)\s*(?:,([^()]*(?:\([^()]*\)[^()]*)*))?\)/g,F=[[/^(background|fill|accent-color|caret-color)|^color$/,1],[/^(border|outline|stroke|column-rule|text-decoration)/,.3],[/shadow$/,.1]],O=/brand|primary|accent/i,q=e=>e.startsWith("--"),H=e=>""===e||e.split(",").some(e=>y.test(e.trim())),L=(e,t)=>`${H(e)?"":e}\0${t}`,j=e=>x.find(t=>e.some(e=>C[t].test(e))),A=(e,t,o)=>{const r=e[t];if(o.escaped)o.escaped=!1;else if("\\"===r)o.escaped=!0;else if(o.quote)r===o.quote&&(o.quote=void 0);else if('"'===r||"'"===r)o.quote=r;else if("("===r)o.parentheses++;else if(")"===r)o.parentheses=Math.max(0,o.parentheses-1);else if(o.parentheses||"{"!==r){if(!o.parentheses&&(";"===r||"}"===r)){const s=e.slice(o.start,t);return o.start=t+1,{text:s,closesRule:"}"===r}}}else o.preludes.push(e.slice(o.start,t).trim()),o.start=t+1},B=(e,t)=>{const o=e.indexOf(":"),r=t.at(-1);if(o<=0||void 0===r)return;const s=e.slice(0,o).trim();return{property:q(s)?s:s.toLowerCase(),value:e.slice(o+1).trim(),selector:r.replace(S,"").replace(/\s+/g," ").trim(),scheme:j(t)}},D=(e,t,o,r=0)=>r>8?e:e.replace(z,(e,s,a="")=>{const n=o.get(L(t,s))??o.get(L("",s));return D(n??a,t,o,r+1)}),N=(t,o,s)=>{for(const[a]of o.replace(E," ").matchAll(R)){const o=c(a);if(!o||(o.alpha??1)<1)continue;const n=e(o),l=r(n),i=t.get(l)??{hex:l,weight:0,color:g(n)};i.weight+=s,t.set(l,i)}},P=(e,t)=>q(e)?$.exec(t)?.[0]!==t.trim()?0:O.test(e)?1:.5:F.find(([t])=>t.test(e))?.[1]??0,T=(e,t)=>{const o=(e=>{const t=e.replace(/\/\*[\s\S]*?\*\//g,""),o={preludes:[],start:0,parentheses:0,escaped:!1},r=[];for(let s=0;s<t.length;s++){const e=A(t,s,o);if(!e)continue;const a=B(e.text,o.preludes);a&&r.push(a),e.closesRule&&o.preludes.pop()}return r})(e),r=({selector:e,property:t})=>L(e,t),s=new Set(o.filter(({scheme:e})=>e===t).map(r));return o.filter(e=>e.scheme?e.scheme===t:!s.has(r(e)))},V=e=>e.c<.03,W=(e,t)=>t.weight-e.weight,Y=e=>{const t=[];for(const r of[...e].toSorted(W)){const e=t.find(e=>{return t=e.color,s=r.color,V(t)||V(s)?V(t)&&V(s)&&Math.abs(t.l-s.l)<.06:Math.abs(o({h:t.h??0},{h:s.h??0}))<20&&Math.abs(t.l-s.l)<.2;var t,s});e?e.weight+=r.weight:t.push({...r})}return t.toSorted(W)},_=(e,t)=>{const o=(e=>{const[t,...o]=e,r=o.find(e=>Math.abs(e.color.l-t.color.l)>=.4);return r?[t,r,...o.filter(e=>e!==r)]:e})(e.filter(e=>V(e.color))),r=e.filter(e=>!V(e.color)),s=Math.min(t,Math.max(Math.min(o.length,2),t-r.length));return[...o.slice(0,s),...r.slice(0,t-s)].toSorted(W).map(e=>e.hex)},G=(e,t)=>{const o=e.filter(({property:e})=>I.test(e)),r=o.findLast(({selector:e})=>H(e)),s=/* @__PURE__ */new Map;r&&N(s,D(r.value,r.selector,t),1);const a=/* @__PURE__ */new Map;for(const{value:l,selector:i}of o)N(a,D(l,i,t),1);const[n]=s.size?s.values():[...a.values()].filter(e=>V(e.color)).toSorted(W);return n&&n.color.l<.5?"dark":"light"},J=(e,{mode:t="auto",colorCount:o=6}={})=>{const r=T(e,t),s=(e=>new Map(e.filter(({property:e})=>q(e)).map(({selector:e,property:t,value:o})=>[L(e,t),o])))(r),a=/* @__PURE__ */new Map;for(const{property:n,value:l,selector:i}of r){const e=D(l,i,s),t=P(n,e);t&&N(a,e,t)}return{colors:_(Y(a.values()),o),mode:"auto"===t?G(r,s):t}},K=(e,t={})=>J(e,t).colors,Q=[170,260],U=[150,280],X=[70,170],Z=(e,[t,o])=>void 0!==e.h&&e.h>=t&&e.h<=o,ee=(e,t,o)=>u({h:e,s:t,l:o}),te=e=>{const t=f(e);return t&&{...t,css:e,chroma:g(t).c}},oe=class{pool;dark;land;constructor(e,t){this.pool=[...e];const o=e.reduce((e,t)=>e+t.l,0)/e.length;var r;this.dark="dark"===t||"auto"===t&&o<.45,this.land=(r=this.take(this.pickLand())??e[0]).s<=.14?r:te(ee(r.h,.14,r.l))??r}pickLand(){const e=this.pool.filter(e=>e.s<=.4);return(e.length?e:this.pool).toSorted((e,t)=>this.dark?e.l-t.l:t.l-e.l)[0]}take(e){if(e)return this.pool.splice(this.pool.indexOf(e),1),e}takeMostColorful(e){const t=this.pool.filter(e).toSorted((e,t)=>t.chroma-e.chroma),o=t.find(e=>!Z(e,U)&&!Z(e,X));return this.take(o??t[0])}takeHue(e){const t=this.pool.filter(t=>t.s>=.12&&Z(t,e));return this.take(t.toSorted((e,t)=>t.s-e.s)[0])}takeMostContrasting(){const e=e=>d(e,this.land),t=this.pool.toSorted((t,o)=>e(o)-e(t))[0];return t&&e(t)>=4.5?this.take(t):void 0}shade(e,t={}){return ee(t.h??this.land.h,t.s??this.land.s,this.land.l+(this.dark?1:-1)*e)}labelShade(e,t){const o=this.shade(e,{s:t});return d(o,this.land)>=4.5?o:this.shade(-e,{s:t})}},re=(e,t={})=>{const o=e.map(te).filter(e=>void 0!==e),r=o.filter((e,t)=>!o.slice(0,t).some(t=>k(t,e)));if(!r.length)throw new RangeError("deriveMapColors needs at least one parseable CSS colour.");const s=new oe(r,t.mode??"auto"),{dark:a,land:n}=s,l=s.takeMostColorful(e=>e.s>=.2)??te(s.shade(a?.55:.45,{s:.7}))??n,i=(s.takeHue(Q)??s.takeHue(U))?.css??s.shade(a?.12:.14,{h:205,s:Math.max(.35,n.s)}),c=s.takeHue(X)?.css??s.shade(a?.08:.09,{h:110,s:Math.max(.18,.6*n.s)}),h=s.takeMostContrasting()?.css??s.labelShade(a?.8:.78,Math.min(n.s,.2)),p=((e,t)=>{const{dark:o,land:r}=e,s=e=>void 0!==e&&d(e,r)>=3,a=e.takeMostColorful(e=>e.s>=.3&&s(e)&&m(e,t)>=30);if(a)return a.css;const n=(t.h??0)+180;return(o?[.62,.7,.78]:[.38,.3,.22]).map(e=>te(ee(n,.7,e))).find(s)?.css??ee(n,.7,o?.85:.15)})(s,l),u=te(c)??n;return{land:n.css,water:i,vegetation:c,park:ee(u.h,u.s,u.l+(a?.04:.05)),artificial:s.shade(a?.04:.03),roadMajor:l.css,road:s.shade(a?.1:-.08,{s:.5*n.s}),roadOutline:s.shade(a?.24:.22,{s:.6*n.s}),label:h,labelHalo:s.shade(-.03),accent:p}},se=({land:e,label:t})=>p(t)>p(e)?"dark":"light",ae=(e,t={})=>{const{colors:o,mode:r}=J(e,t);if(!o.length)throw new RangeError("deriveMapColorsFromCss: the stylesheet paints with no opaque colour to take a theme from.");return re(o,{mode:r})},ne=(e,t)=>(e[0]-t[0])**2+(e[1]-t[1])**2+(e[2]-t[2])**2,le=(e,t)=>{let o=0,r=Number.POSITIVE_INFINITY;for(let s=0;s<t.length;s++){const a=ne(e,t[s]);a<r&&(r=a,o=s)}return o},ie=(e,t=6)=>{const o=(({data:e})=>{const t=Math.floor(e.length/4),o=Math.max(1,Math.floor(t/4096)),r=[];for(let s=0;s<t;s+=o){const t=4*s;e[t+3]<128||r.push([e[t],e[t+1],e[t+2]])}return r})(e);if(!o.length)return[];const{centroids:s,sizes:a}=((e,t)=>{let o=t,r=[];for(let s=0;s<8;s++){const t=o.map(()=>[0,0,0]);r=o.map(()=>0);for(const s of e){const e=le(s,o);r[e]++,t[e][0]+=s[0],t[e][1]+=s[1],t[e][2]+=s[2]}o=o.map((e,o)=>r[o]?t[o].map(e=>e/r[o]):e)}return{centroids:o,sizes:r}})(o,((e,t)=>{const o=e=>p(b(e)),r=[[...e.toSorted((e,t)=>o(e)-o(t))[Math.floor(e.length/2)]]];for(;r.length<t;){let t=e[0],o=-1;for(const s of e){const e=ne(s,r[le(s,r)]);e>o&&(o=e,t=s)}if(0===o)break;r.push([...t])}return r})(o,Math.min(t,o.length)));return((e,t)=>{const o=[];for(const[r,s]of e.entries()){if(!t[r])continue;const e=o.find(e=>k(b(e.rgb),b(s)));e?e.size+=t[r]:o.push({rgb:s,size:t[r]})}return o})(s,a).toSorted((e,t)=>t.size-e.size).map(e=>r(b(e.rgb)))},ce=64,he=async e=>{return"string"==typeof e?(t=e,new Promise((e,o)=>{const r=new Image;r.crossOrigin="anonymous",r.onload=()=>e(r),r.onerror=()=>o(/* @__PURE__ */new Error(`deriveMapColorsFromImage: could not load '${t}'.`)),r.src=t})):e instanceof Blob?createImageBitmap(e):e;var t},de=async(e,t={})=>{const o=(e=>"object"==typeof e&&"data"in e)(e)?e:await(async e=>{if("undefined"==typeof document)throw new TypeError("deriveMapColorsFromImage needs a DOM to decode images; pass ImagePixels instead.");const t=await he(e),o=document.createElement("canvas");o.width=ce,o.height=ce;const r=o.getContext("2d");if(!r)throw new Error("deriveMapColorsFromImage: no 2D canvas context available.");r.drawImage(t,0,0,ce,ce);try{return r.getImageData(0,0,ce,ce)}catch{throw new Error("deriveMapColorsFromImage: the image is not CORS-readable (canvas tainted). Serve it with Access-Control-Allow-Origin or pass a Blob/File.")}})(e),r=ie(o,t.colorCount);if(!r.length)throw new RangeError("deriveMapColorsFromImage: the image has no opaque pixels to take colours from.");return re(r,t)};export{K as cssColors,re as deriveMapColors,ae as deriveMapColorsFromCss,de as deriveMapColorsFromImage,ie as dominantColors,se as mapColorsLightDark,M as mapThemeModes};
|
|
1
|
+
import{clampRgb,differenceEuclidean,differenceHueNaive,formatHex,modeHsl,modeLrgb,modeOklab,modeOklch,modeRgb,parse,useMode,wcagContrast,wcagLuminance}from"culori/fn";import{formatStyleHsl,hueDistance,toHsl}from"@tomtom-org/maps-sdk/map";useMode(modeRgb),useMode(modeLrgb),useMode(modeHsl),useMode(modeOklab);var toOklch=useMode(modeOklch),oklabDistance=/* @__PURE__ */differenceEuclidean("oklab"),isSameColor=(e,t)=>oklabDistance(e,t)<.035,rgbFromBytes=([e,t,o])=>({mode:"rgb",r:e/255,g:t/255,b:o/255}),mapThemeModes=["light","dark","auto"],schemeMarker=(e,t)=>new RegExp(String.raw`prefers-color-scheme\s*:\s*${e}|\.(?:theme-)?${e}(?:-(?:mode|theme))?(?![\w-])|\[data-[\w-]+=["']?${e}["']?\]`,t),COLOR_SCHEMES=["light","dark"],SCHEME_MARKERS={light:/* @__PURE__ */schemeMarker("light","i"),dark:/* @__PURE__ */schemeMarker("dark","i")},ANY_SCHEME_MARKER=/* @__PURE__ */schemeMarker("(?:light|dark)","gi"),PAGE_ROOT=/^(?:(?::root|html|body)\s*)+$/,PAGE_BACKGROUND=/^background(-color)?$/,NON_PAINTING_TEXT=/url\((?:"[^"]*"|'[^']*'|[^)]*)\)|"[^"]*"|'[^']*'/gi,HEX_COLOR=/#[\da-f]{3,8}\b/,COLOR_FUNCTION=/\b(?:rgba?|hsla?|oklab|oklch)\([^()]*\)/,COLOR_NAME=/\b[a-z]+\b/,COLOR_TOKEN=/* @__PURE__ */(()=>new RegExp([HEX_COLOR,COLOR_FUNCTION,COLOR_NAME].map(({source:e})=>e).join("|"),"i"))(),COLOR_TOKENS=/* @__PURE__ */new RegExp(COLOR_TOKEN,"gi"),VARIABLE_REFERENCE=/var\(\s*(--[\w-]+)\s*(?:,([^()]*(?:\([^()]*\)[^()]*)*))?\)/g,USAGE_WEIGHTS=[[/^(background|fill|accent-color|caret-color)|^color$/,1],[/^(border|outline|stroke|column-rule|text-decoration)/,.3],[/shadow$/,.1]],BRAND_NAME=/brand|primary|accent/i,isCustomProperty=e=>e.startsWith("--"),isPageRoot=e=>""===e||e.split(",").some(e=>PAGE_ROOT.test(e.trim())),scopeKey=(e,t)=>`${isPageRoot(e)?"":e}\0${t}`,schemeOf=e=>COLOR_SCHEMES.find(t=>e.some(e=>SCHEME_MARKERS[t].test(e))),scanCharacter=(e,t,o)=>{const r=e[t];if(o.escaped)o.escaped=!1;else if("\\"===r)o.escaped=!0;else if(o.quote)r===o.quote&&(o.quote=void 0);else if('"'===r||"'"===r)o.quote=r;else if("("===r)o.parentheses++;else if(")"===r)o.parentheses=Math.max(0,o.parentheses-1);else if(o.parentheses||"{"!==r){if(!o.parentheses&&(";"===r||"}"===r)){const s=e.slice(o.start,t);return o.start=t+1,{text:s,closesRule:"}"===r}}}else o.preludes.push(e.slice(o.start,t).trim()),o.start=t+1},declarationOf=(e,t)=>{const o=e.indexOf(":"),r=t.at(-1);if(o<=0||void 0===r)return;const s=e.slice(0,o).trim();return{property:isCustomProperty(s)?s:s.toLowerCase(),value:e.slice(o+1).trim(),selector:r.replace(ANY_SCHEME_MARKER,"").replace(/\s+/g," ").trim(),scheme:schemeOf(t)}},resolveVariables=(e,t,o,r=0)=>r>8?e:e.replace(VARIABLE_REFERENCE,(e,s,a="")=>{const l=o.get(scopeKey(t,s))??o.get(scopeKey("",s));return resolveVariables(l??a,t,o,r+1)}),tally=(e,t,o)=>{for(const[r]of t.replace(NON_PAINTING_TEXT," ").matchAll(COLOR_TOKENS)){const t=parse(r);if(!t||(t.alpha??1)<1)continue;const s=clampRgb(t),a=formatHex(s),l=e.get(a)??{hex:a,weight:0,color:toOklch(s)};l.weight+=o,e.set(a,l)}},weightOf=(e,t)=>isCustomProperty(e)?COLOR_TOKEN.exec(t)?.[0]!==t.trim()?0:BRAND_NAME.test(e)?1:.5:USAGE_WEIGHTS.find(([t])=>t.test(e))?.[1]??0,isNeutral=e=>e.c<.03,byWeight=(e,t)=>t.weight-e.weight,mergeShades=e=>{const t=[];for(const o of[...e].toSorted(byWeight)){const e=t.find(e=>{return t=e.color,r=o.color,isNeutral(t)||isNeutral(r)?isNeutral(t)&&isNeutral(r)&&Math.abs(t.l-r.l)<.06:Math.abs(differenceHueNaive({h:t.h??0},{h:r.h??0}))<20&&Math.abs(t.l-r.l)<.2;var t,r});e?e.weight+=o.weight:t.push({...o})}return t.toSorted(byWeight)},pickSwatches=(e,t)=>{const o=(e=>{const[t,...o]=e,r=o.find(e=>Math.abs(e.color.l-t.color.l)>=.4);return r?[t,r,...o.filter(e=>e!==r)]:e})(e.filter(e=>isNeutral(e.color))),r=e.filter(e=>!isNeutral(e.color)),s=Math.min(t,Math.max(Math.min(o.length,2),t-r.length));return[...o.slice(0,s),...r.slice(0,t-s)].toSorted(byWeight).map(e=>e.hex)},pageMode=(e,t)=>{const o=e.filter(({property:e})=>PAGE_BACKGROUND.test(e)),r=o.findLast(({selector:e})=>isPageRoot(e)),s=/* @__PURE__ */new Map;r&&tally(s,resolveVariables(r.value,r.selector,t),1);const a=/* @__PURE__ */new Map;for(const{value:n,selector:i}of o)tally(a,resolveVariables(n,i,t),1);const[l]=s.size?s.values():[...a.values()].filter(e=>isNeutral(e.color)).toSorted(byWeight);return l&&l.color.l<.5?"dark":"light"},readStylesheet=(e,{mode:t="auto",colorCount:o=6}={})=>{const r=((e,t)=>{const o=(e=>{const t=e.replace(/\/\*[\s\S]*?\*\//g,""),o={preludes:[],start:0,parentheses:0,escaped:!1},r=[];for(let s=0;s<t.length;s++){const e=scanCharacter(t,s,o);if(!e)continue;const a=declarationOf(e.text,o.preludes);a&&r.push(a),e.closesRule&&o.preludes.pop()}return r})(e),r=({selector:e,property:t})=>scopeKey(e,t),s=new Set(o.filter(({scheme:e})=>e===t).map(r));return o.filter(e=>e.scheme?e.scheme===t:!s.has(r(e)))})(e,t),s=(e=>new Map(e.filter(({property:e})=>isCustomProperty(e)).map(({selector:e,property:t,value:o})=>[scopeKey(e,t),o])))(r),a=/* @__PURE__ */new Map;for(const{property:l,value:n,selector:i}of r){const e=resolveVariables(n,i,s),t=weightOf(l,e);t&&tally(a,e,t)}return{colors:pickSwatches(mergeShades(a.values()),o),mode:"auto"===t?pageMode(r,s):t}},cssColors=(e,t={})=>readStylesheet(e,t).colors,WATER_HUES=[170,260],WIDER_WATER_HUES=[150,280],VEGETATION_HUES=[70,170],isInHues=(e,[t,o])=>void 0!==e.h&&e.h>=t&&e.h<=o,hsl=(e,t,o)=>formatStyleHsl({h:e,s:t,l:o}),parseColor=e=>{const t=toHsl(e);return t&&{...t,css:e,chroma:toOklch(t).c}},RoleAssigner=class{pool;dark;land;constructor(e,t){this.pool=[...e];const o=e.reduce((e,t)=>e+t.l,0)/e.length;var r;this.dark="dark"===t||"auto"===t&&o<.45,this.land=(r=this.take(this.pickLand())??e[0]).s<=.14?r:parseColor(hsl(r.h,.14,r.l))??r}pickLand(){const e=this.pool.filter(e=>e.s<=.4);return(e.length?e:this.pool).toSorted((e,t)=>this.dark?e.l-t.l:t.l-e.l)[0]}take(e){if(e)return this.pool.splice(this.pool.indexOf(e),1),e}takeMostColorful(e){const t=this.pool.filter(e).toSorted((e,t)=>t.chroma-e.chroma),o=t.find(e=>!isInHues(e,WIDER_WATER_HUES)&&!isInHues(e,VEGETATION_HUES));return this.take(o??t[0])}takeHue(e){const t=this.pool.filter(t=>t.s>=.12&&isInHues(t,e));return this.take(t.toSorted((e,t)=>t.s-e.s)[0])}takeMostContrasting(){const e=e=>wcagContrast(e,this.land),t=this.pool.toSorted((t,o)=>e(o)-e(t))[0];return t&&e(t)>=4.5?this.take(t):void 0}shade(e,t={}){return hsl(t.h??this.land.h,t.s??this.land.s,this.land.l+(this.dark?1:-1)*e)}labelShade(e,t){const o=this.shade(e,{s:t});return wcagContrast(o,this.land)>=4.5?o:this.shade(-e,{s:t})}},deriveMapColors=(e,t={})=>{const o=e.map(parseColor).filter(e=>void 0!==e),r=o.filter((e,t)=>!o.slice(0,t).some(t=>isSameColor(t,e)));if(!r.length)throw new RangeError("deriveMapColors needs at least one parseable CSS colour.");const s=new RoleAssigner(r,t.mode??"auto"),{dark:a,land:l}=s,n=s.takeMostColorful(e=>e.s>=.2)??parseColor(s.shade(a?.55:.45,{s:.7}))??l,i=(s.takeHue(WATER_HUES)??s.takeHue(WIDER_WATER_HUES))?.css??s.shade(a?.12:.14,{h:205,s:Math.max(.35,l.s)}),c=s.takeHue(VEGETATION_HUES)?.css??s.shade(a?.08:.09,{h:110,s:Math.max(.18,.6*l.s)}),h=s.takeMostContrasting()?.css??s.labelShade(a?.8:.78,Math.min(l.s,.2)),d=((e,t)=>{const{dark:o,land:r}=e,s=e=>void 0!==e&&wcagContrast(e,r)>=3,a=e.takeMostColorful(e=>e.s>=.3&&s(e)&&hueDistance(e,t)>=30);if(a)return a.css;const l=(t.h??0)+180;return(o?[.62,.7,.78]:[.38,.3,.22]).map(e=>parseColor(hsl(l,.7,e))).find(s)?.css??hsl(l,.7,o?.85:.15)})(s,n),m=parseColor(c)??l;return{land:l.css,water:i,vegetation:c,park:hsl(m.h,m.s,m.l+(a?.04:.05)),artificial:s.shade(a?.04:.03),roadMajor:n.css,road:s.shade(a?.1:-.08,{s:.5*l.s}),roadOutline:s.shade(a?.24:.22,{s:.6*l.s}),label:h,labelHalo:s.shade(-.03),accent:d}},mapColorsLightDark=({land:e,label:t})=>wcagLuminance(t)>wcagLuminance(e)?"dark":"light",deriveMapColorsFromCss=(e,t={})=>{const{colors:o,mode:r}=readStylesheet(e,t);if(!o.length)throw new RangeError("deriveMapColorsFromCss: the stylesheet paints with no opaque colour to take a theme from.");return deriveMapColors(o,{mode:r})},squaredDistance=(e,t)=>(e[0]-t[0])**2+(e[1]-t[1])**2+(e[2]-t[2])**2,nearestIndex=(e,t)=>{let o=0,r=Number.POSITIVE_INFINITY;for(let s=0;s<t.length;s++){const a=squaredDistance(e,t[s]);a<r&&(r=a,o=s)}return o},dominantColors=(e,t=6)=>{const o=(({data:e})=>{const t=Math.floor(e.length/4),o=Math.max(1,Math.floor(t/4096)),r=[];for(let s=0;s<t;s+=o){const t=4*s;e[t+3]<128||r.push([e[t],e[t+1],e[t+2]])}return r})(e);if(!o.length)return[];const{centroids:r,sizes:s}=((e,t)=>{let o=t,r=[];for(let s=0;s<8;s++){const t=o.map(()=>[0,0,0]);r=o.map(()=>0);for(const s of e){const e=nearestIndex(s,o);r[e]++,t[e][0]+=s[0],t[e][1]+=s[1],t[e][2]+=s[2]}o=o.map((e,o)=>r[o]?t[o].map(e=>e/r[o]):e)}return{centroids:o,sizes:r}})(o,((e,t)=>{const o=e=>wcagLuminance(rgbFromBytes(e)),r=[[...e.toSorted((e,t)=>o(e)-o(t))[Math.floor(e.length/2)]]];for(;r.length<t;){let t=e[0],o=-1;for(const s of e){const e=squaredDistance(s,r[nearestIndex(s,r)]);e>o&&(o=e,t=s)}if(0===o)break;r.push([...t])}return r})(o,Math.min(t,o.length)));return((e,t)=>{const o=[];for(const[r,s]of e.entries()){if(!t[r])continue;const e=o.find(e=>isSameColor(rgbFromBytes(e.rgb),rgbFromBytes(s)));e?e.size+=t[r]:o.push({rgb:s,size:t[r]})}return o})(r,s).toSorted((e,t)=>t.size-e.size).map(e=>formatHex(rgbFromBytes(e.rgb)))},deriveMapColorsFromImage=async(e,t={})=>{const o=(e=>"object"==typeof e&&"data"in e)(e)?e:await(async e=>{if("undefined"==typeof document)throw new TypeError("deriveMapColorsFromImage needs a DOM to decode images; pass ImagePixels instead.");const t=await(async e=>{return"string"==typeof e?(t=e,new Promise((e,o)=>{const r=new Image;r.crossOrigin="anonymous",r.onload=()=>e(r),r.onerror=()=>o(/* @__PURE__ */new Error(`deriveMapColorsFromImage: could not load '${t}'.`)),r.src=t})):e instanceof Blob?createImageBitmap(e):e;var t})(e),o=document.createElement("canvas");o.width=64,o.height=64;const r=o.getContext("2d");if(!r)throw new Error("deriveMapColorsFromImage: no 2D canvas context available.");r.drawImage(t,0,0,64,64);try{return r.getImageData(0,0,64,64)}catch{throw new Error("deriveMapColorsFromImage: the image is not CORS-readable (canvas tainted). Serve it with Access-Control-Allow-Origin or pass a Blob/File.")}})(e),r=dominantColors(o,t.colorCount);if(!r.length)throw new RangeError("deriveMapColorsFromImage: the image has no opaque pixels to take colours from.");return deriveMapColors(r,t)};export{cssColors,deriveMapColors,deriveMapColorsFromCss,deriveMapColorsFromImage,dominantColors,mapColorsLightDark,mapThemeModes};
|
package/package.json
CHANGED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
"name": "@tomtom-org/maps-sdk-plugin-map-theme",
|
|
3
3
|
"author": "TomTom International B.V.",
|
|
4
4
|
"license": "See in LICENSE.txt",
|
|
5
|
-
"version": "0.3.
|
|
5
|
+
"version": "0.3.6",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"description": "Theme a TomTomMap from wherever a look comes from — a brand's colours, a website's, a described mood, an artist's palette, or an image — by assigning them to the SDK's map colours",
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
9
|
+
"sideEffects": false,
|
|
9
10
|
"peerDependencies": {
|
|
10
11
|
"@tomtom-org/maps-sdk": ">=0.64.0 <1.0.0 || >=1.0.0-rc.0 <1.0.0",
|
|
11
12
|
"culori": "^4.0.2"
|
|
@@ -19,7 +20,7 @@
|
|
|
19
20
|
"typescript": "^6.0.3",
|
|
20
21
|
"vite": "8.3.3",
|
|
21
22
|
"vitest": "^5.0.3",
|
|
22
|
-
"@tomtom-org/maps-sdk": "1.0.0-rc.
|
|
23
|
+
"@tomtom-org/maps-sdk": "1.0.0-rc.3"
|
|
23
24
|
},
|
|
24
25
|
"files": [
|
|
25
26
|
"dist",
|