feat(frontend): add markdown component (#1959)

* feat(frontend): add markdown component

* feat(frontend): add markdown component

* feat(frontend): switch library to fix build

* feat(frontend): fix md display

* feat(frontend): add a compact prop

* feat(frontend): Size as list
This commit is contained in:
Faton Ramadani
2023-07-31 17:54:43 +02:00
committed by GitHub
parent b479cd6fca
commit a69aa2275f
8 changed files with 1982 additions and 39 deletions
+1850 -37
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -98,6 +98,7 @@
"svelte-autosize": "^1.0.1",
"svelte-chartjs": "^3.1.0",
"svelte-dnd-action": "^0.9.22",
"svelte-exmarkdown": "^2.1.0",
"svelte-portal": "^2.2.0",
"svelte-timezone-picker": "^2.0.3",
"tailwind-merge": "^1.13.2",
@@ -0,0 +1,79 @@
<script lang="ts">
import { getContext } from 'svelte'
import { initConfig, initOutput } from '../../editor/appUtils'
import type { AppInput } from '../../inputType'
import type { AppViewerContext, ComponentCustomCSS, RichConfigurations } from '../../types'
import { concatCustomCss } from '../../utils'
import RunnableWrapper from '../helpers/RunnableWrapper.svelte'
import Markdown from 'svelte-exmarkdown'
import { classNames } from '$lib/utils'
import { components } from '../../editor/component'
import ResolveConfig from '../helpers/ResolveConfig.svelte'
export let id: string
export let componentInput: AppInput | undefined
export let initializing: boolean | undefined = undefined
export let customCss: ComponentCustomCSS<'mardowncomponent'> | undefined = undefined
export let render: boolean
export let configuration: RichConfigurations
const { app, worldStore } = getContext<AppViewerContext>('AppViewerContext')
const resolvedConfig = initConfig(
components['mardowncomponent'].initialData.configuration,
configuration
)
const outputs = initOutput($worldStore, id, {
result: undefined,
loading: false
})
let result: string | undefined = undefined
$: css = concatCustomCss($app.css?.mardowncomponent, customCss)
const proseMapping = {
sm: 'prose-sm',
Default: 'prose-base',
lg: 'prose-lg',
xl: 'prose-xl',
'2xl': 'prose-2xl'
}
</script>
{#each Object.keys(components['mardowncomponent'].initialData.configuration) as key (key)}
<ResolveConfig
{id}
{key}
bind:resolvedConfig={resolvedConfig[key]}
configuration={configuration[key]}
/>
{/each}
<div
on:pointerdown={(e) => {
e?.preventDefault()
}}
class={classNames(
'h-full w-full overflow-y-auto prose',
resolvedConfig?.size ? proseMapping[resolvedConfig.size] : '',
css?.container?.class
)}
>
<RunnableWrapper
{outputs}
{render}
autoRefresh
{componentInput}
{id}
bind:initializing
bind:result
>
{#if result}
{#key result}
<Markdown md={result} />
{/key}
{/if}
</RunnableWrapper>
</div>
@@ -13,3 +13,4 @@ export { default as AppText } from './AppText.svelte'
export { default as AppTimeseries } from './AppTimeseries.svelte'
export { default as PlotlyHtml } from './PlotlyHtml.svelte'
export { default as VegaLiteHtml } from './VegaLiteHtml.svelte'
export { default as AppMarkdown } from './AppMarkdown.svelte'
@@ -20,6 +20,7 @@
AppScatterChart,
AppTimeseries,
AppHtml,
AppMarkdown,
AppSliderInputs,
AppFormButton,
VegaLiteHtml,
@@ -205,6 +206,15 @@
componentInput={component.componentInput}
{render}
/>
{:else if component.type === 'mardowncomponent'}
<AppMarkdown
id={component.id}
customCss={component.customCss}
bind:initializing
componentInput={component.componentInput}
configuration={component.configuration}
{render}
/>
{:else if component.type === 'vegalitecomponent'}
<VegaLiteHtml
configuration={component.configuration}
@@ -39,7 +39,8 @@ import {
Download,
PanelLeft,
PanelTopInactive,
ListIcon
ListIcon,
Heading1
} from 'lucide-svelte'
import type {
Aligned,
@@ -73,6 +74,7 @@ export type CurrencyComponent = BaseComponent<'currencycomponent'>
export type SliderComponent = BaseComponent<'slidercomponent'>
export type RangeComponent = BaseComponent<'rangecomponent'>
export type HtmlComponent = BaseComponent<'htmlcomponent'>
export type MarkdownComponent = BaseComponent<'mardowncomponent'>
export type VegaLiteComponent = BaseComponent<'vegalitecomponent'>
export type PlotlyComponent = BaseComponent<'plotlycomponent'>
export type TimeseriesComponent = BaseComponent<'timeseriescomponent'>
@@ -154,6 +156,7 @@ export type TypedComponent =
| BarChartComponent
| TimeseriesComponent
| HtmlComponent
| MarkdownComponent
| TableComponent
| TextComponent
| ButtonComponent
@@ -277,7 +280,8 @@ export const selectOptions = {
'polarArea',
'radar',
'scatter'
] as ChartType[]
] as ChartType[],
prose: ['sm', 'Default', 'lg', 'xl', '2xl']
}
const labels = {
none: 'Do nothing',
@@ -1006,6 +1010,37 @@ Hello \${ctx.username}
configuration: {}
}
},
mardowncomponent: {
name: 'Markdown',
icon: Heading1,
documentationLink: `${documentationBaseUrl}#html`,
dims: '1:2-1:2' as AppComponentDimensions,
customCss: {
container: { class: '', style: '' }
},
initialData: {
componentInput: {
type: 'static',
fieldType: 'template',
value: `# This is a header
## This is a subheader
This is a paragraph.
* This is a list
* With two items`
},
configuration: {
size: {
fieldType: 'select',
type: 'static',
selectOptions: selectOptions.prose,
value: 'Default',
onlyStatic: true,
tooltip: 'See Tailwind documentation: https://tailwindcss.com/docs/typography-plugin'
}
}
}
},
vegalitecomponent: {
name: 'Vega Lite',
icon: PieChart,
@@ -58,6 +58,7 @@ const display: ComponentSet = {
'imagecomponent',
'mapcomponent',
'htmlcomponent',
'mardowncomponent',
'pdfcomponent',
'displaycomponent',
'jobidlogcomponent',
@@ -570,6 +570,9 @@ export const quickStyleProperties: Record<
backgroundGrouping
]
},
mardowncomponent: {
container: containerDefaultProps
},
iconcomponent: {
container: containerDefaultProps,
icon: [