mirror of
https://github.com/enso-org/enso.git
synced 2024-11-25 21:25:20 +03:00
Text Format Improvements (#10655)
- changes the font to match JSON viz - changes colour of symbols to #df8800 - shows selected formatting option as button icon ![text-format-imp-1](https://github.com/user-attachments/assets/81a74837-5ae1-44c2-a78e-c351d7f67736) - removes grid toolbar for single item visualizations <img width="320" alt="image" src="https://github.com/user-attachments/assets/b6de6f80-0222-40bf-bd74-4e70e8ad1c31"> - sort styling for narrow components - ![image](https://github.com/user-attachments/assets/2fb8b1f0-0071-4d9f-86b2-f15b0638f64b)
This commit is contained in:
parent
5366dd384f
commit
6189eb3a1c
@ -3,7 +3,7 @@ import DropdownMenu from '@/components/DropdownMenu.vue'
|
||||
import MenuButton from '@/components/MenuButton.vue'
|
||||
import SvgButton from '@/components/SvgButton.vue'
|
||||
import SvgIcon from '@/components/SvgIcon.vue'
|
||||
import { ref, watch } from 'vue'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { TextFormatOptions } from './visualizations/TableVisualization.vue'
|
||||
|
||||
const emit = defineEmits<{
|
||||
@ -13,18 +13,40 @@ const emit = defineEmits<{
|
||||
const textFormatterSelected = ref(TextFormatOptions.Partial)
|
||||
watch(textFormatterSelected, (selected) => emit('changeFormat', selected))
|
||||
|
||||
const buttonClass = computed(() => {
|
||||
return {
|
||||
full: isFormatOptionSelected(TextFormatOptions.On),
|
||||
partial: isFormatOptionSelected(TextFormatOptions.Partial),
|
||||
strikethrough: isFormatOptionSelected(TextFormatOptions.Off),
|
||||
}
|
||||
})
|
||||
|
||||
const isFormatOptionSelected = (option: TextFormatOptions): boolean =>
|
||||
option === textFormatterSelected.value
|
||||
|
||||
const open = ref(false)
|
||||
const toggleOpen = () => {
|
||||
open.value = !open.value
|
||||
}
|
||||
|
||||
const changeFormat = (option: TextFormatOptions) => {
|
||||
textFormatterSelected.value = option
|
||||
toggleOpen()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<DropdownMenu v-model:open="open" class="TextFormattingSelector">
|
||||
<template #button><SvgIcon name="paragraph" title="Text Display Options" /> </template>
|
||||
<template #button
|
||||
><div :class="buttonClass">
|
||||
<SvgIcon name="paragraph" title="Text Display Options" /></div
|
||||
></template>
|
||||
|
||||
<template #entries>
|
||||
<MenuButton
|
||||
class="full-format"
|
||||
class="full"
|
||||
:title="`Text displayed in monospace font and all whitespace characters displayed as symbols`"
|
||||
@click="() => emit('changeFormat', TextFormatOptions.On)"
|
||||
@click="() => changeFormat(TextFormatOptions.On)"
|
||||
>
|
||||
<SvgIcon name="paragraph" />
|
||||
<div class="title">Full whitespace rendering</div>
|
||||
@ -33,7 +55,7 @@ const open = ref(false)
|
||||
<MenuButton
|
||||
class="partial"
|
||||
:title="`Text displayed in monospace font, only multiple spaces displayed with ·`"
|
||||
@click="() => emit('changeFormat', TextFormatOptions.Partial)"
|
||||
@click="() => changeFormat(TextFormatOptions.Partial)"
|
||||
>
|
||||
<SvgIcon name="paragraph" />
|
||||
<div class="title">Partial whitespace rendering</div>
|
||||
@ -41,7 +63,7 @@ const open = ref(false)
|
||||
|
||||
<MenuButton
|
||||
class="off"
|
||||
@click="() => emit('changeFormat', TextFormatOptions.Off)"
|
||||
@click="() => changeFormat(TextFormatOptions.Off)"
|
||||
title="`No formatting applied to text`"
|
||||
>
|
||||
<div class="strikethrough">
|
||||
@ -99,7 +121,7 @@ const open = ref(false)
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.full-format {
|
||||
.full {
|
||||
stroke: black;
|
||||
fill: #000000;
|
||||
justify-content: flex-start;
|
||||
|
@ -16,6 +16,7 @@ const props = defineProps<{
|
||||
belowNode?: boolean
|
||||
/** If true, the visualization should display below the toolbar buttons. */
|
||||
belowToolbar?: boolean
|
||||
toolbarOverflow?: boolean
|
||||
}>()
|
||||
|
||||
const config = useVisualizationConfig()
|
||||
@ -87,6 +88,12 @@ const contentStyle = computed(() => {
|
||||
height: config.fullscreen ? undefined : `${config.height}px`,
|
||||
}
|
||||
})
|
||||
|
||||
const overFlowStyle = computed(() => {
|
||||
return {
|
||||
overflow: props.toolbarOverflow ? 'visible' : 'hidden',
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -160,10 +167,13 @@ const contentStyle = computed(() => {
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="$slots.toolbar && !config.isPreview" class="visualization-defined-toolbars">
|
||||
<div class="toolbar-wrapper">
|
||||
<div class="inner-toolbar"><slot name="toolbar"></slot></div>
|
||||
</div>
|
||||
<div
|
||||
v-if="$slots.toolbar && !config.isPreview"
|
||||
id="visualization-defined-toolbar"
|
||||
class="visualization-defined-toolbars"
|
||||
:style="overFlowStyle"
|
||||
>
|
||||
<div class="toolbar"><slot name="toolbar"></slot></div>
|
||||
</div>
|
||||
<div
|
||||
class="after-toolbars node-type"
|
||||
@ -252,6 +262,7 @@ const contentStyle = computed(() => {
|
||||
.after-toolbars {
|
||||
margin-left: auto;
|
||||
margin-right: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.node-type {
|
||||
@ -289,28 +300,7 @@ const contentStyle = computed(() => {
|
||||
}
|
||||
|
||||
.visualization-defined-toolbars {
|
||||
min-width: calc(100% - var(--permanent-toolbar-width));
|
||||
max-width: 100%;
|
||||
overflow-x: clip;
|
||||
overflow-y: visible;
|
||||
}
|
||||
|
||||
.toolbar-wrapper {
|
||||
position: relative;
|
||||
display: flex;
|
||||
border-radius: var(--radius-full);
|
||||
z-index: 20;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
border-radius: var(--radius-full);
|
||||
}
|
||||
max-width: calc(100% - var(--permanent-toolbar-width));
|
||||
}
|
||||
|
||||
.invisible {
|
||||
@ -328,26 +318,4 @@ const contentStyle = computed(() => {
|
||||
.VisualizationContainer :deep(> .toolbars > .toolbar > *) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.inner-toolbar {
|
||||
position: relative;
|
||||
display: flex;
|
||||
border-radius: var(--radius-full);
|
||||
gap: 12px;
|
||||
padding: 8px;
|
||||
z-index: 20;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
border-radius: var(--radius-full);
|
||||
background: var(--color-app-bg);
|
||||
backdrop-filter: var(--blur-app-bg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -260,31 +260,31 @@ function formatText(params: ICellRendererParams) {
|
||||
return params.value
|
||||
}
|
||||
const partialMappings = {
|
||||
'\r': '<span style="color: lightgrey">␍</span> <br>',
|
||||
'\n': '<span style="color: lightgrey;">␊</span> <br>',
|
||||
'\r': '<span style="color: #df8800">␍</span> <br>',
|
||||
'\n': '<span style="color: #df8800;">␊</span> <br>',
|
||||
'\t': '<span style="white-space: break-spaces;"> </span>',
|
||||
}
|
||||
const fullMappings = {
|
||||
'\r': '<span style="color: lightgrey">␍</span> <br>',
|
||||
'\n': '<span style="color: lightgrey">␊</span> <br>',
|
||||
'\t': '<span style="color: lightgrey; white-space: break-spaces;">→ </span>',
|
||||
'\r': '<span style="color: #df8800">␍</span> <br>',
|
||||
'\n': '<span style="color: #df8800">␊</span> <br>',
|
||||
'\t': '<span style="color: #df8800; white-space: break-spaces;">→ </span>',
|
||||
}
|
||||
|
||||
const replaceSpaces =
|
||||
textFormatterSelected.value === TextFormatOptions.On ?
|
||||
params.value.replaceAll(' ', '<span style="color: lightgrey">·</span>')
|
||||
params.value.replaceAll(' ', '<span style="color: #df8800">·</span>')
|
||||
: params.value.replace(/ {2,}/g, function (match: string) {
|
||||
return `<span style="color: lightgrey">${'·'.repeat(match.length)}</span>`
|
||||
return `<span style="color: #df8800">${'·'.repeat(match.length)}</span>`
|
||||
})
|
||||
|
||||
const replaceReturns = replaceSpaces.replace(
|
||||
/\r\n/g,
|
||||
'<span style="color: lightgrey">␍␊</span> <br>',
|
||||
'<span style="color: #df8800">␍␊</span> <br>',
|
||||
)
|
||||
|
||||
const renderOtherWhitespace = (match: string) => {
|
||||
return textFormatterSelected.value === TextFormatOptions.On && match != ' ' ?
|
||||
'<span style="color: lightgrey">☐</span>'
|
||||
'<span style="color: #df8800">☐</span>'
|
||||
: match
|
||||
}
|
||||
const newString = replaceReturns.replace(/[\s]/g, function (match: string) {
|
||||
@ -719,7 +719,7 @@ onUnmounted(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VisualizationContainer :belowToolbar="true" :overflow="true">
|
||||
<VisualizationContainer :belowToolbar="true" :overflow="true" :toolbarOverflow="true">
|
||||
<template #toolbar>
|
||||
<TextFormattingSelector @changeFormat="(i) => updateTextFormat(i)" />
|
||||
</template>
|
||||
@ -763,7 +763,7 @@ onUnmounted(() => {
|
||||
--ag-grid-size: 3px;
|
||||
--ag-list-item-height: 20px;
|
||||
flex-grow: 1;
|
||||
font-family: monospace;
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
.table-visualization-status-bar {
|
||||
|
Loading…
Reference in New Issue
Block a user