feat(frontend): Add copy button option to app text display component (#1090)

* feat(frontend): Add copy button to app text

* feat(frontend): Add tooltip to component configs

* fix(frontend): Remove copy button text
This commit is contained in:
Ádám Kovács
2023-01-11 16:05:19 +01:00
committed by GitHub
parent dbd632375c
commit bdfc38d954
7 changed files with 61 additions and 31 deletions
@@ -1,4 +1,8 @@
<script lang="ts">
import { Clipboard } from 'lucide-svelte'
import { copyToClipboard } from '../../../../utils'
import Button from '../../../common/button/Button.svelte'
import Popover from '../../../Popover.svelte'
import type { AppInput } from '../../inputType'
import AlignWrapper from '../helpers/AlignWrapper.svelte'
import InputValue from '../helpers/InputValue.svelte'
@@ -14,8 +18,8 @@
let extraStyle: string | undefined = undefined
let result: string | undefined = undefined
let style: 'Title' | 'Subtitle' | 'Body' | 'Caption' | 'Label' | undefined = undefined
let copyButton: boolean
function getComponent() {
switch (style) {
@@ -53,6 +57,7 @@
<InputValue {id} input={configuration.extraStyle} bind:value={extraStyle} />
<InputValue {id} input={configuration.style} bind:value={style} />
<InputValue {id} input={configuration.copyButton} bind:value={copyButton} />
<RunnableWrapper flexWrap bind:componentInput {id} bind:result>
<AlignWrapper {horizontalAlignment} {verticalAlignment}>
@@ -60,13 +65,30 @@
<div class="text-gray-400 bg-gray-100 flex justify-center items-center h-full w-full">
No text
</div>
{:else}<svelte:element
this={component}
class="whitespace-pre-wrap {classes}"
style={extraStyle}
>
{String(result)}
</svelte:element>
{:else}
<div class="flex flex-wrap gap-2">
<svelte:element
this={component}
class="whitespace-pre-wrap {classes}"
style={extraStyle}
>
{String(result)}
</svelte:element>
{#if copyButton && result}
<Popover notClickable>
<Button
size="xs"
btnClasses="!px-2"
on:click={() => copyToClipboard(result)}
>
<Clipboard size={14} strokeWidth={2} />
</Button>
<svelte:fragment slot="text">
Copy to clipboard
</svelte:fragment>
</Popover>
{/if}
</div>
{/if}
</AlignWrapper>
</RunnableWrapper>
@@ -45,7 +45,6 @@
export function getValue(input: AppInput) {
if (input.type === 'template' && isCodeInjection(input.eval)) {
console.log(computeGlobalContext())
try {
return eval_like('`' + input.eval + '`', computeGlobalContext())
} catch (e) {
@@ -255,14 +255,18 @@ const display: ComponentSet = {
optionValuesKey: 'textStyleOptions',
value: 'Body'
},
extraStyle:
{
extraStyle: {
type: 'static',
fieldType: 'text',
value: '',
tooltip: 'CSS rules like "color: blue;"',
},
copyButton: {
type: 'static',
value: false,
fieldType: 'boolean',
onlyStatic: true,
},
},
card: false
},
@@ -151,7 +151,7 @@ declare const ${k} = ${JSON.stringify(v)};
<InputsSpecsEditor
shouldCapitalize={false}
bind:inputSpecs={component.componentInput.fields}
bind:inputSpecs={component.configuration}
userInputEnabled={component.type !== 'buttoncomponent'}
{rowColumns}
/>
@@ -1,25 +1,15 @@
<script lang="ts">
import { Badge, ToggleButton, ToggleButtonGroup } from '$lib/components/common'
import { capitalize } from '$lib/utils'
import { addWhitespaceBeforeCapitals, capitalize } from '$lib/utils'
import { faArrowRight, faPen, faTableCells, faUser } from '@fortawesome/free-solid-svg-icons'
import { fieldTypeToTsType } from '../../utils'
import InputsSpecEditor from './InputsSpecEditor.svelte'
import type {
ConnectedAppInput,
RowAppInput,
StaticAppInput,
UserAppInput
} from '../../inputType'
import { getContext } from 'svelte'
import type { AppEditorContext } from '../../types'
import type { AppEditorContext, BaseAppComponent } from '../../types'
import Tooltip from '$lib/components/Tooltip.svelte'
import Popup from '../../../common/popup/Popup.svelte'
import Popover from '../../../Popover.svelte'
import Popover from '$lib/components/Popover.svelte'
export let inputSpecs: Record<
string,
(StaticAppInput | ConnectedAppInput | UserAppInput | RowAppInput) & { onlyStatic?: boolean }
>
export let inputSpecs: BaseAppComponent['configuration']
export let userInputEnabled: boolean = true
export let staticOnly: boolean = false
export let shouldCapitalize: boolean = true
@@ -35,7 +25,12 @@
<div class="flex flex-col gap-1">
<div class="flex justify-between items-end gap-1">
<span class="text-sm font-semibold truncate">
{shouldCapitalize ? capitalize(inputSpecKey) : inputSpecKey}
{shouldCapitalize ? capitalize(addWhitespaceBeforeCapitals(inputSpecKey)) : inputSpecKey}
{#if input.tooltip}
<Tooltip>
{input.tooltip}
</Tooltip>
{/if}
</span>
<div class="flex gap-x-2 gap-y-1 flex-wrap justify-end items-center">
+4 -1
View File
@@ -57,7 +57,10 @@ export type Aligned = {
export interface BaseAppComponent extends Partial<Aligned> {
id: ComponentID
componentInput: AppInput | undefined
configuration: Record<string, (StaticAppInput | ConnectedAppInput | UserAppInput) & { onlyStatic?: boolean }>
configuration: Record<string, (StaticAppInput | ConnectedAppInput | UserAppInput) & {
onlyStatic?: boolean,
tooltip?: string
}>
card: boolean | undefined
/**
* If `true` then the wrapper will allow items to flow outside of it's borders.
+8 -1
View File
@@ -620,7 +620,9 @@ export function scriptLangToEditorLang(
}
}
export async function copyToClipboard(value: string, sendToast = true): Promise<boolean> {
export async function copyToClipboard(value?: string, sendToast = true): Promise<boolean> {
if(!value) { return false }
let success = false
if (navigator?.clipboard) {
success = await navigator.clipboard
@@ -647,6 +649,11 @@ export function capitalize(word: string): string {
return word ? word.charAt(0).toUpperCase() + word.slice(1) : ''
}
export function addWhitespaceBeforeCapitals(word?: string): string {
if (!word) { return '' }
return word.replace(/([A-Z])/g, ' $1').trim()
}
export function isCloudHosted(): boolean {
return get(page).url.hostname == 'app.windmill.dev'
}