Comparing version 15.2.0 to 16.0.0
# CHANGELOG | ||
## 16.0.0 | ||
Nominal types `Nominal<string,"Bobril">`. | ||
`IBobrilStyleDef` is now not plain string but nominal type. | ||
`sprite` without color creates another nominal type `ColorlessSprite`. `spriteWithColor` now takes only `ColorlessSprite` type making it compile time type safe, function for evaluation could be also passed. | ||
New method `svg` allows to embed svg in JS source and then use it as `ColorlessSprite`. It is not expected to directly use `svg` method but instead `sprite` and bobril-build will load svg from disk and change that call to this method. | ||
New method `svgWithColor` allows to resize previously defined svg or recolor multiple colors not just `gray` for which you can still use `spriteWithColor`. | ||
When you need to use jQuery selectors with Bobril and you already have nice `key` in VDom to use with `bbseeker`, you can now enable automatic publishing of keys to classNames by `b.setKeysInClassNames(true); b.ignoreShouldChange();` without need to change your application. | ||
## 15.2.0 | ||
@@ -34,3 +48,3 @@ | ||
style={() => { | ||
let s = b.useStore(0); | ||
let s = b.useState(0); | ||
s((s() + 1) % 101); | ||
@@ -37,0 +51,0 @@ return { opacity: s() * 0.01 }; |
@@ -17,3 +17,3 @@ import "./src/ie11"; | ||
import { setAfterFrame, setBeforeFrame } from "./src/frameCallbacks"; | ||
import { deref, getRoots, setInvalidate, ignoreShouldChange, setBeforeInit } from "./src/core"; | ||
import { deref, getRoots, setInvalidate, ignoreShouldChange, setBeforeInit, setKeysInClassNames } from "./src/core"; | ||
import { getDnds } from "./src/dnd"; | ||
@@ -35,2 +35,3 @@ import { invalidateStyles } from "./src/cssInJs"; | ||
setBeforeInit, | ||
setKeysInClassNames, | ||
}; |
{ | ||
"name": "bobril", | ||
"version": "15.2.0", | ||
"version": "16.0.0", | ||
"description": "Component Oriented MVC Framework with virtual DOM and CSS", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
import { CSSStyles, CSSPseudoStyles, CSSStylesItem, CSSInlineStyles } from "./cssTypes"; | ||
import { | ||
applyDynamicStyle, | ||
ColorlessSprite, | ||
destroyDynamicStyle, | ||
@@ -196,2 +197,7 @@ IBobrilCacheNode, | ||
interface ISvgSprite { | ||
styleId: IBobrilStyleDef; | ||
svg: string; | ||
} | ||
interface IDynamicSprite extends ISprite { | ||
@@ -220,3 +226,3 @@ color: () => string; | ||
realName: string | null; | ||
parent?: IBobrilStyleDef | IBobrilStyleDef[]; | ||
parent?: string | IBobrilStyleDef | IBobrilStyleDef[]; | ||
style: CSSStyles | (() => [CSSStyles, CSSPseudoStyles]); | ||
@@ -243,2 +249,3 @@ pseudo?: CSSPseudoStyles; | ||
var dynamicSprites: IDynamicSprite[] = []; | ||
var svgSprites = new Map<string, ColorlessSprite>(); | ||
var bundledDynamicSprites: IResponsiveDynamicSprite[] = []; | ||
@@ -536,3 +543,3 @@ var imageCache: { [url: string]: HTMLImageElement | null } = newHashObj(); | ||
if (sd != undefined) { | ||
s = sd.realName!; | ||
s = sd.realName! as IBobrilStyleDef; | ||
} | ||
@@ -698,3 +705,3 @@ if (className == undefined) className = s; | ||
} else invalidateStyles(); | ||
return nameHint; | ||
return nameHint as IBobrilStyleDef; | ||
} | ||
@@ -810,3 +817,3 @@ | ||
let imagesWithCredentials = false; | ||
const colorLessSpriteMap = new Map<string, ISprite | IResponsiveSprite>(); | ||
const colorLessSpriteMap = new Map<string, ISprite | IResponsiveSprite | ISvgSprite>(); | ||
@@ -824,5 +831,6 @@ function loadImage(url: string, onload: (image: HTMLImageElement) => void) { | ||
export function sprite(url: string): ColorlessSprite; | ||
export function sprite( | ||
url: string, | ||
color?: string | (() => string), | ||
color: null | undefined, | ||
width?: number, | ||
@@ -832,2 +840,19 @@ height?: number, | ||
top?: number | ||
): ColorlessSprite; | ||
export function sprite( | ||
url: string, | ||
color: string | (() => string), | ||
width?: number, | ||
height?: number, | ||
left?: number, | ||
top?: number | ||
): IBobrilStyleDef; | ||
export function sprite( | ||
url: string, | ||
color?: string | (() => string) | null | undefined, | ||
width?: number, | ||
height?: number, | ||
left?: number, | ||
top?: number | ||
): IBobrilStyleDef { | ||
@@ -886,2 +911,81 @@ assert(allStyles[url] === undefined, "Wrong sprite url"); | ||
export function svg(content: string): ColorlessSprite { | ||
var key = content + ":1"; | ||
var styleId = svgSprites.get(key); | ||
if (styleId !== undefined) return styleId; | ||
styleId = buildSvgStyle(content, 1); | ||
var svgSprite: ISvgSprite = { | ||
styleId, | ||
svg: content, | ||
}; | ||
svgSprites.set(key, styleId); | ||
colorLessSpriteMap.set(styleId, svgSprite); | ||
return styleId; | ||
} | ||
/// Function can take colors as functions but they are evaluated immediately => use only in render like function | ||
export function svgWithColor( | ||
id: ColorlessSprite, | ||
colors: string | (() => string) | Record<string, string | (() => string)>, | ||
size: number = 1 | ||
): IBobrilStyleDef { | ||
var original = colorLessSpriteMap.get(id); | ||
if (DEBUG && (original == undefined || !("svg" in original))) throw new Error(id + " is not colorless svg"); | ||
var key = (original! as ISvgSprite).svg + ":" + size; | ||
if (isFunction(colors)) { | ||
colors = colors(); | ||
key += ":gray:" + colors; | ||
} else if (isString(colors)) { | ||
key += ":gray:" + colors; | ||
} else | ||
for (let ckey in colors) { | ||
if (hOP.call(colors, ckey)) { | ||
let val = colors[ckey]; | ||
if (isFunction(val)) val = val(); | ||
key += ":" + ckey + ":" + val; | ||
} | ||
} | ||
var styleId = svgSprites.get(key); | ||
if (styleId !== undefined) return styleId; | ||
var colorsMap = new Map<string, string>(); | ||
if (isString(colors)) { | ||
colorsMap.set("gray", colors); | ||
} else | ||
for (let ckey in colors) { | ||
if (hOP.call(colors, ckey)) { | ||
let val = colors[ckey]; | ||
if (isFunction(val)) val = val(); | ||
colorsMap.set(ckey, val as string); | ||
} | ||
} | ||
styleId = buildSvgStyle( | ||
(original! as ISvgSprite).svg.replace(/[\":][A-Z-]+[\";]/gi, (m) => { | ||
var c = colorsMap.get(m.substr(1, m.length - 2)); | ||
return c !== undefined ? m[0] + c + m[m.length - 1] : m; | ||
}), | ||
size | ||
); | ||
svgSprites.set(key, styleId); | ||
return styleId; | ||
} | ||
function buildSvgStyle(content: string, size: number): ColorlessSprite { | ||
var sizeStr = content.split('"', 1)[0]; | ||
var [width, height] = sizeStr!.split(" ").map((s) => parseFloat(s) * size); | ||
var backgroundImage = | ||
'url("data:image/svg+xml,' + | ||
encodeURIComponent( | ||
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="' + | ||
width + | ||
'" height="' + | ||
height + | ||
'" viewBox="0 0 ' + | ||
content + | ||
"</svg>" | ||
) + | ||
'")'; | ||
return styleDef({ width, height, backgroundImage }) as ColorlessSprite; | ||
} | ||
var bundlePath = (<any>window)["bobrilBPath"] || "bundle.png"; | ||
@@ -962,9 +1066,12 @@ var bundlePath2: [string, number][] = (<any>window)["bobrilBPath2"] || []; | ||
export function spriteWithColor(colorLessSprite: IBobrilStyleDef, color: string): IBobrilStyleDef { | ||
/// Function can take colors as functions but they are evaluated immediately => use only in render like function | ||
export function spriteWithColor(colorLessSprite: ColorlessSprite, color: string | (() => string)): IBobrilStyleDef { | ||
const original = colorLessSpriteMap.get(colorLessSprite); | ||
if (original == undefined) throw new Error(colorLessSprite + " is not colorless sprite"); | ||
if ("url" in original) { | ||
if (DEBUG && original == undefined) throw new Error(colorLessSprite + " is not colorless sprite"); | ||
if ("svg" in original!) { | ||
return svgWithColor(colorLessSprite, { gray: color }, 1); | ||
} else if ("url" in original!) { | ||
return sprite(original.url, color, original.width, original.height, original.left, original.top); | ||
} else { | ||
return spritebc(color, original.width, original.height, original.left, original.top); | ||
return spritebc(color, original!.width, original!.height, original!.left, original!.top); | ||
} | ||
@@ -971,0 +1078,0 @@ } |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
381513
9122