Move selection highlighting in builder preview in to client library and replace handlebars with mustache again
This commit is contained in:
parent
3ffeda9da9
commit
ce2bff5bab
|
@ -21,15 +21,6 @@ export default `<html>
|
||||||
|
|
||||||
// Extract data from message
|
// Extract data from message
|
||||||
const { selectedComponentId, page, screen } = JSON.parse(event.data)
|
const { selectedComponentId, page, screen } = JSON.parse(event.data)
|
||||||
|
|
||||||
// Update selected component style
|
|
||||||
if (selectedComponentStyle) {
|
|
||||||
document.head.removeChild(selectedComponentStyle)
|
|
||||||
}
|
|
||||||
selectedComponentStyle = document.createElement("style");
|
|
||||||
document.head.appendChild(selectedComponentStyle)
|
|
||||||
var selectedCss = '[data-bb-id="' + selectedComponentId + '"]' + '{border:2px solid #0055ff !important;}'
|
|
||||||
selectedComponentStyle.appendChild(document.createTextNode(selectedCss))
|
|
||||||
|
|
||||||
// Set some flags so the app knows we're in the builder
|
// Set some flags so the app knows we're in the builder
|
||||||
window["##BUDIBASE_IN_BUILDER##"] = true
|
window["##BUDIBASE_IN_BUILDER##"] = true
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"deep-equal": "^2.0.1",
|
"deep-equal": "^2.0.1",
|
||||||
"handlebars": "^4.7.6",
|
"mustache": "^4.0.1",
|
||||||
"regexparam": "^1.3.0",
|
"regexparam": "^1.3.0",
|
||||||
"svelte-spa-router": "^3.0.5"
|
"svelte-spa-router": "^3.0.5"
|
||||||
},
|
},
|
||||||
|
|
|
@ -20,11 +20,10 @@
|
||||||
$: children = definition._children
|
$: children = definition._children
|
||||||
$: id = definition._id
|
$: id = definition._id
|
||||||
$: enrichedProps = enrichProps(definition, $dataContext, $bindingStore)
|
$: enrichedProps = enrichProps(definition, $dataContext, $bindingStore)
|
||||||
|
$: selected = id === $builderStore.selectedComponentId
|
||||||
|
|
||||||
// Update component context
|
// Update component context
|
||||||
// ID is duplicated inside style so that the "styleable" helper can set
|
$: componentStore.set({ id, styles: { ...definition._styles, selected } })
|
||||||
// an ID data tag for unique reference to components
|
|
||||||
$: componentStore.set({ id, styles: { ...definition._styles, id } })
|
|
||||||
|
|
||||||
// Gets the component constructor for the specified component
|
// Gets the component constructor for the specified component
|
||||||
const getComponentConstructor = component => {
|
const getComponentConstructor = component => {
|
||||||
|
|
|
@ -1,4 +1,20 @@
|
||||||
import handlebars from "handlebars"
|
import mustache from "mustache"
|
||||||
|
|
||||||
|
// this is a much more liberal version of mustache's escape function
|
||||||
|
// ...just ignoring < and > to prevent tags from user input
|
||||||
|
// original version here https://github.com/janl/mustache.js/blob/4b7908f5c9fec469a11cfaed2f2bed23c84e1c5c/mustache.js#L78
|
||||||
|
const entityMap = {
|
||||||
|
"<": "<",
|
||||||
|
">": ">",
|
||||||
|
}
|
||||||
|
mustache.escape = text => {
|
||||||
|
if (text == null || typeof text !== "string") {
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
return text.replace(/[<>]/g, function fromEntityMap(s) {
|
||||||
|
return entityMap[s] || s
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Regex to test inputs with to see if they are likely candidates for mustache
|
// Regex to test inputs with to see if they are likely candidates for mustache
|
||||||
const looksLikeMustache = /{{.*}}/
|
const looksLikeMustache = /{{.*}}/
|
||||||
|
@ -15,7 +31,7 @@ export const enrichDataBinding = (input, context) => {
|
||||||
if (!looksLikeMustache.test(input)) {
|
if (!looksLikeMustache.test(input)) {
|
||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
return handlebars.render(input, context)
|
return mustache.render(input, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
/**
|
/**
|
||||||
* Helper to build a CSS string from a style object
|
* Helper to build a CSS string from a style object
|
||||||
*/
|
*/
|
||||||
const buildStyleString = styles => {
|
const buildStyleString = (styles, selected) => {
|
||||||
let str = ""
|
let str = ""
|
||||||
|
if (selected) {
|
||||||
|
styles.border = "2px solid #0055ff !important"
|
||||||
|
}
|
||||||
Object.entries(styles).forEach(([style, value]) => {
|
Object.entries(styles).forEach(([style, value]) => {
|
||||||
if (style && value != null) {
|
if (style && value != null) {
|
||||||
str += `${style}: ${value}; `
|
str += `${style}: ${value}; `
|
||||||
|
@ -20,6 +23,7 @@ export const styleable = (node, styles = {}) => {
|
||||||
|
|
||||||
// Creates event listeners and applies initial styles
|
// Creates event listeners and applies initial styles
|
||||||
const setupStyles = newStyles => {
|
const setupStyles = newStyles => {
|
||||||
|
const selected = newStyles.selected
|
||||||
const normalStyles = newStyles.normal || {}
|
const normalStyles = newStyles.normal || {}
|
||||||
const hoverStyles = {
|
const hoverStyles = {
|
||||||
...normalStyles,
|
...normalStyles,
|
||||||
|
@ -27,17 +31,16 @@ export const styleable = (node, styles = {}) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
applyNormalStyles = () => {
|
applyNormalStyles = () => {
|
||||||
node.style = buildStyleString(normalStyles)
|
node.style = buildStyleString(normalStyles, selected)
|
||||||
}
|
}
|
||||||
|
|
||||||
applyHoverStyles = () => {
|
applyHoverStyles = () => {
|
||||||
node.style = buildStyleString(hoverStyles)
|
node.style = buildStyleString(hoverStyles, selected)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add listeners to toggle hover styles
|
// Add listeners to toggle hover styles
|
||||||
node.addEventListener("mouseover", applyHoverStyles)
|
node.addEventListener("mouseover", applyHoverStyles)
|
||||||
node.addEventListener("mouseout", applyNormalStyles)
|
node.addEventListener("mouseout", applyNormalStyles)
|
||||||
node.setAttribute("data-bb-id", newStyles.id)
|
|
||||||
|
|
||||||
// Apply initial normal styles
|
// Apply initial normal styles
|
||||||
applyNormalStyles()
|
applyNormalStyles()
|
||||||
|
|
|
@ -829,18 +829,6 @@ graceful-fs@^4.1.6, graceful-fs@^4.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
|
||||||
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
|
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
|
||||||
|
|
||||||
handlebars@^4.7.6:
|
|
||||||
version "4.7.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e"
|
|
||||||
integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==
|
|
||||||
dependencies:
|
|
||||||
minimist "^1.2.5"
|
|
||||||
neo-async "^2.6.0"
|
|
||||||
source-map "^0.6.1"
|
|
||||||
wordwrap "^1.0.0"
|
|
||||||
optionalDependencies:
|
|
||||||
uglify-js "^3.1.4"
|
|
||||||
|
|
||||||
har-schema@^2.0.0:
|
har-schema@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
|
||||||
|
@ -1374,15 +1362,10 @@ minimatch@^3.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion "^1.1.7"
|
brace-expansion "^1.1.7"
|
||||||
|
|
||||||
minimist@^1.2.5:
|
mustache@^4.0.1:
|
||||||
version "1.2.5"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.0.1.tgz#d99beb031701ad433338e7ea65e0489416c854a2"
|
||||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
integrity sha512-yL5VE97+OXn4+Er3THSmTdCFCtx5hHWzrolvH+JObZnUYwuaG7XV+Ch4fR2cIrcYI0tFHxS7iyFYl14bW8y2sA==
|
||||||
|
|
||||||
neo-async@^2.6.0:
|
|
||||||
version "2.6.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
|
||||||
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
|
||||||
|
|
||||||
nwsapi@^2.2.0:
|
nwsapi@^2.2.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
|
@ -1841,7 +1824,7 @@ source-map-support@~0.5.10:
|
||||||
buffer-from "^1.0.0"
|
buffer-from "^1.0.0"
|
||||||
source-map "^0.6.0"
|
source-map "^0.6.0"
|
||||||
|
|
||||||
source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
|
source-map@^0.6.0, source-map@~0.6.1:
|
||||||
version "0.6.1"
|
version "0.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||||
|
@ -2011,11 +1994,6 @@ typedarray@^0.0.6:
|
||||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||||
|
|
||||||
uglify-js@^3.1.4:
|
|
||||||
version "3.12.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.12.1.tgz#78307f539f7b9ca5557babb186ea78ad30cc0375"
|
|
||||||
integrity sha512-o8lHP20KjIiQe5b/67Rh68xEGRrc2SRsCuuoYclXXoC74AfSRGblU1HKzJWH3HxPZ+Ort85fWHpSX7KwBUC9CQ==
|
|
||||||
|
|
||||||
universalify@^0.1.0:
|
universalify@^0.1.0:
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
|
||||||
|
@ -2135,11 +2113,6 @@ word-wrap@~1.2.3:
|
||||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
||||||
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
|
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
|
||||||
|
|
||||||
wordwrap@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
|
|
||||||
integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=
|
|
||||||
|
|
||||||
wrappy@1:
|
wrappy@1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
<script>
|
<script>
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
|
|
||||||
const { DataProvider } = getContext("sdk")
|
const { DataProvider, styleable } = getContext("sdk")
|
||||||
|
const component = getContext("component")
|
||||||
|
|
||||||
export let table
|
export let table
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DataProvider row={{ tableId: table }}>
|
<div use:styleable={$component.styles}>
|
||||||
<slot />
|
<DataProvider row={{ tableId: table }}>
|
||||||
</DataProvider>
|
<slot />
|
||||||
|
</DataProvider>
|
||||||
|
</div>
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount, getContext } from "svelte"
|
import { onMount, getContext } from "svelte"
|
||||||
|
|
||||||
const { API, screenStore, routeStore, DataProvider } = getContext("sdk")
|
const { API, screenStore, routeStore, DataProvider, styleable } = getContext(
|
||||||
|
"sdk"
|
||||||
|
)
|
||||||
|
const component = getContext("component")
|
||||||
|
|
||||||
export let table
|
export let table
|
||||||
|
|
||||||
|
@ -35,7 +38,9 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if row}
|
{#if row}
|
||||||
<DataProvider {row}>
|
<div use:styleable={$component.styles}>
|
||||||
<slot />
|
<DataProvider {row}>
|
||||||
</DataProvider>
|
<slot />
|
||||||
|
</DataProvider>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
Loading…
Reference in New Issue