Add in-preview editing of buttons and add settings bar for buttons

This commit is contained in:
Andrew Kingston 2021-10-28 15:29:48 +01:00
parent 234f53d37a
commit 387831b799
6 changed files with 45 additions and 33 deletions

View File

@ -245,7 +245,9 @@
"name": "Button", "name": "Button",
"description": "A basic html button that is ready for styling", "description": "A basic html button that is ready for styling",
"icon": "Button", "icon": "Button",
"editable": true,
"illegalChildren": ["section"], "illegalChildren": ["section"],
"showSettingsBar": true,
"settings": [ "settings": [
{ {
"type": "text", "type": "text",
@ -254,6 +256,7 @@
}, },
{ {
"type": "select", "type": "select",
"showInBar": true,
"label": "Variant", "label": "Variant",
"key": "type", "key": "type",
"options": [ "options": [
@ -282,6 +285,7 @@
{ {
"type": "select", "type": "select",
"label": "Size", "label": "Size",
"showInBar": true,
"key": "size", "key": "size",
"options": [ "options": [
{ {
@ -306,11 +310,18 @@
{ {
"type": "boolean", "type": "boolean",
"label": "Quiet", "label": "Quiet",
"key": "quiet" "key": "quiet",
"showInBar": true,
"barIcon": "VisibilityOff",
"barTitle": "Quiet variant",
"barSeparator": false
}, },
{ {
"type": "boolean", "type": "boolean",
"label": "Disabled", "label": "Disabled",
"showInBar": true,
"barIcon": "NoEdit",
"barTitle": "Disable button",
"key": "disabled" "key": "disabled"
}, },
{ {

View File

@ -2,7 +2,7 @@
import { getContext } from "svelte" import { getContext } from "svelte"
import "@spectrum-css/button/dist/index-vars.css" import "@spectrum-css/button/dist/index-vars.css"
const { styleable } = getContext("sdk") const { styleable, builderStore } = getContext("sdk")
const component = getContext("component") const component = getContext("component")
export let disabled = false export let disabled = false
@ -11,16 +11,35 @@
export let size = "M" export let size = "M"
export let type = "primary" export let type = "primary"
export let quiet = false export let quiet = false
let node
$: $component.editing && node?.focus()
$: componentText = getComponentText(text, $builderStore, $component)
const getComponentText = (text, builderState, componentState) => {
if (!builderState.inBuilder || componentState.editing) {
return text || " "
}
return text || componentState.name || "Placeholder text"
}
const updateText = e => {
builderStore.actions.updateProp("text", e.target.textContent)
}
</script> </script>
<button <button
class={`spectrum-Button spectrum-Button--size${size} spectrum-Button--${type}`} class={`spectrum-Button spectrum-Button--size${size} spectrum-Button--${type}`}
class:spectrum-Button--quiet={quiet} class:spectrum-Button--quiet={quiet}
disabled={disabled || false} {disabled}
use:styleable={$component.styles} use:styleable={$component.styles}
on:click={onClick} on:click={onClick}
class:editing={$component.editing}
contenteditable={$component.editing}
on:blur={$component.editing ? updateText : null}
> >
{text || ""} {componentText}
</button> </button>
<style> <style>

View File

@ -47,17 +47,12 @@
// Convert contenteditable HTML to text and save // Convert contenteditable HTML to text and save
const updateText = e => { const updateText = e => {
const html = e.target.innerHTML const sanitized = e.target.innerHTML.replace(/<br>/gi, "\n")
const sanitized = html
.replace(/<\/div><div>/gi, "\n")
.replace(/<div>/gi, "")
.replace(/<\/div>/gi, "")
.replace(/<br>/gi, "")
builderStore.actions.updateProp("text", sanitized) builderStore.actions.updateProp("text", sanitized)
} }
</script> </script>
<div <h1
bind:this={node} bind:this={node}
contenteditable={$component.editing} contenteditable={$component.editing}
use:styleable={styles} use:styleable={styles}
@ -69,10 +64,10 @@
on:blur={$component.editing ? updateText : null} on:blur={$component.editing ? updateText : null}
> >
{componentText} {componentText}
</div> </h1>
<style> <style>
div { h1 {
white-space: pre-wrap; white-space: pre-wrap;
font-weight: 600; font-weight: 600;
} }

View File

@ -46,15 +46,8 @@
} }
} }
// Convert contenteditable HTML to text and save
const updateText = e => { const updateText = e => {
const html = e.target.innerHTML builderStore.actions.updateProp("text", e.target.textContent)
const sanitized = html
.replace(/<\/div><div>/gi, "\n")
.replace(/<div>/gi, "")
.replace(/<\/div>/gi, "")
.replace(/<br>/gi, "")
builderStore.actions.updateProp("text", sanitized)
} }
</script> </script>
@ -106,7 +99,6 @@
div { div {
color: var(--spectrum-alias-text-color); color: var(--spectrum-alias-text-color);
transition: color 130ms ease-in-out; transition: color 130ms ease-in-out;
white-space: pre-wrap;
} }
a:not(.placeholder):hover { a:not(.placeholder):hover {
color: var(--spectrum-link-primary-m-text-color-hover) !important; color: var(--spectrum-link-primary-m-text-color-hover) !important;

View File

@ -46,17 +46,12 @@
// Convert contenteditable HTML to text and save // Convert contenteditable HTML to text and save
const updateText = e => { const updateText = e => {
const html = e.target.innerHTML const sanitized = e.target.innerHTML.replace(/<br>/gi, "\n")
const sanitized = html
.replace(/<\/div><div>/gi, "\n")
.replace(/<div>/gi, "")
.replace(/<\/div>/gi, "")
.replace(/<br>/gi, "")
builderStore.actions.updateProp("text", sanitized) builderStore.actions.updateProp("text", sanitized)
} }
</script> </script>
<div <p
bind:this={node} bind:this={node}
contenteditable={$component.editing} contenteditable={$component.editing}
use:styleable={styles} use:styleable={styles}
@ -68,10 +63,10 @@
on:blur={$component.editing ? updateText : null} on:blur={$component.editing ? updateText : null}
> >
{componentText} {componentText}
</div> </p>
<style> <style>
div { p {
display: inline-block; display: inline-block;
white-space: pre-wrap; white-space: pre-wrap;
margin: 0; margin: 0;

View File

@ -110,7 +110,7 @@
prop={setting.key} prop={setting.key}
value={option.value} value={option.value}
icon={option.barIcon} icon={option.barIcon}
title={option.barTitle} title={option.barTitle || option.label}
/> />
{/each} {/each}
{:else} {:else}
@ -124,7 +124,7 @@
<SettingsButton <SettingsButton
prop={setting.key} prop={setting.key}
icon={setting.barIcon} icon={setting.barIcon}
title={setting.barTitle} title={setting.barTitle || setting.label}
bool bool
/> />
{:else if setting.type === "color"} {:else if setting.type === "color"}