Skip to content

Commit

Permalink
docs: add props, slots, and events
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdehaven committed Jan 2, 2024
1 parent 74c72ea commit 3aeb083
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 19 deletions.
171 changes: 170 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Kong's open-source markdown renderer and live editor.
- [Installation](#installation)
- [Notes](#notes)
- [Props](#props)
- [Slots](#slots)
- [Events](#events)
- [Contributing \& Local Development](#contributing--local-development)
- [Development Sandbox](#development-sandbox)
- [Lint and fix](#lint-and-fix)
Expand All @@ -25,7 +27,7 @@ Kong's open-source markdown renderer and live editor.
- [ ] Possibly export separate bundles for syntax highlighting options
- [ ] Document theming instructions
- [ ] Light / Dark mode
- [ ] Default styles for markdown HTML elements
- [X] Default styles for markdown HTML elements

## Usage

Expand Down Expand Up @@ -55,6 +57,173 @@ Some users browse the web without access to a pointing device, and it is really
- required: `false`
- default: `''`

A Vue `ref<string>` from the host app that is bound to the markdown content in the host application. The value will be updated as the user edits the document and emitted via the `update:modelValue` event.

Alternatively, if you do not need a two-way binding, you can pass in the markdown content via the `modelValue` prop.

#### `editable`

- type: `Boolean`
- default: `false`

Is the user allowed to edit the document. Defaults to `false`.

In order to utilize the `edit`, `split`, and `preview` modes, this `editable` prop **must** be set to `true`.

> [!NOTE]
> If the `editable` prop is set to `false`, it will override the `mode` and force into read-only mode.
#### `mode`

- type: `'read' | 'edit' | 'split' | 'preview'`
- required: `false`
- default: `'read'`

The initial mode of the markdown component.

Mode | Description
:--- | :---
`read` | Read-only mode. The editor is not visible. An "Edit" button is visible if the `editable` prop is `true`.
`edit` | Edit-only mode. The rendered markdown preview is not visible. Requires the `editable` prop to be set to `true`.
`split` | Split-view mode. The component is showing a side-by-side editor and markdown preview. Requires the `editable` prop to be set to `true`.
`preview` | Markdown preview mode. The component is showing a preview of the rendered markdown content. Requires the `editable` prop to be set to `true`.

#### `tabSize`

- type: `Number`
- required: `false`
- default: `2`

The number of spaces to insert when a user tabs within the textarea. Defaults to `2` with a maximum value of `6`.

#### `theme`

- type: `'light' | 'dark'`
- required: `false`
- default: `'light'`

The theme used when the component initializes, one of `'light'` or `'dark'`. Defaults to `'light'`.

#### `maxHeight`

- type: `Number`
- required: `false`
- default: `300`

The maximum height of the component when not being displayed fullscreen. Defaults to `300` with a minimum value of `100`.

#### `fullscreenOffsetTop`

- type: `Number`
- required: `false`
- default: `0`

When the editor is in fullscreen, the top offset, in pixels.

#### `fullscreenZIndex`

- type: `Number`
- required: `false`
- default: `1001`

The `z-index` of the component when in fullscreen. Defaults to `1001`.

#### `mermaid`

- type: `Boolean`
- default: `true`

MermaidJs is a bit heavy when parsing the document nodes; set to `false` to opt-out of rendering Mermaid diagrams within code blocks. Defaults to `true`.

### Slots

#### `editor-actions`

A slot for providing editor actions to the markdown component, shown at the far-right of the toolbar.

The default slot provides `Save` and `Cancel` buttons as well as two methods, `save` and `cancel`, to trigger the built-in actions from your own component. Here's an example:

```vue
<MarkdownUi
v-model="content"
editable
@save="saveChanges"
>
<template #editor-actions="{ save }">
<!-- Call the provided `save` method when custom button is clicked -->
<button @click="save">Upload document</button>
</template>
</MarkdownUi>
<script setup lang="ts">
// When the `@save` event is emitted, POST the markdown content to the API
const saveChanges = async (markdownContent: string): Promise<void> => {
try {
const response = await fetch('https://example.com/documents/', {
method: 'POST',
headers: { 'Content-Type': 'text/markdown' },
body: markdownContent,
})
const result = await response.json()
console.log('Success:', result)
} catch (error) {
console.error('Error(saveChanges):', error);
}
}
</script>
```

#### `toolbar-right`

A slot for providing additional toolbar content to the markdown component, shown to the right of the editor shortcuts and to the left of the `editor-actions` slot (the Cancel and Save buttons).

#### `edit`

A slot for providing a custom element (i.e. `button`) that enables the `Edit` mode within the component. The slot exposes the `edit` method to trigger the built-in function.

When the `edit` button (native, or custom) is clicked, the component will automatically determine whether to enable `edit` or `split` mode based on the browser's viewport width. On larger screens, the editor will launch in `split` mode.

> [!NOTE]
> The `editable` prop must be set to `true` to enable this slot.
```vue
<MarkdownUi
v-model="content"
editable
>
<template #edit="{ edit }">
<!-- Call the provided `edit` method when custom button is clicked -->
<button @click="edit">Custom edit button</button>
</template>
</MarkdownUi>
```

### Events

#### `update:modelValue`

Emitted when the user modifies the raw markdown content in the editor. The event contains a payload `string` of the raw markdown content.

> [!NOTE]
> The `update:modelValue` event is debounced as the user is typing.
#### `save`

Emitted whenever the user triggers the `save` toolbar action. The event contains a payload `string` of the raw markdown content.

#### `cancel`

Emitted whenever the user triggers the `cancel` toolbar action, which also changes the component `mode` to `read`.

#### `mode`

Emitted whenever the component mode is changed. The event contains a payload `string` of the active mode: `read | edit | split | preview`

#### `fullscreen`

Emitted whenever the component is toggled in/out of fullscreen. The event contains a payload `boolean` indicating if fullscreen is enabled.

## Contributing & Local Development

To get started, install the package dependencies
Expand Down
5 changes: 5 additions & 0 deletions sandbox/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
Toolbar
</button>
</template> -->
<!-- <template #edit="{ edit }">
<button @click="edit">
Custom edit
</button>
</template> -->
</MarkdownUi>
</main>
</div>
Expand Down
39 changes: 21 additions & 18 deletions src/components/MarkdownUi.vue
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,10 @@
v-if="editable && currentMode === 'read'"
class="edit-button"
>
<slot name="edit">
<slot
:edit="edit"
name="edit"
>
<ToolbarButton
appearance="primary"
aria-label="Edit markdown document"
Expand Down Expand Up @@ -140,36 +143,31 @@ const props = defineProps({
type: String,
default: '',
},
/** Is the markdown document able to be edited by the user. Defaults to `false`. */
editable: {
type: Boolean,
default: false,
},
/** The mode used when the component initializes, one of 'read', 'edit', 'split', 'preview' */
mode: {
type: String as PropType<MarkdownMode>,
default: 'read',
validator: (mode: string): boolean => ['read', 'edit', 'split', 'preview'].includes(mode),
},
/** Optionally show the markdown editor */
editable: {
type: Boolean,
default: false,
},
/** The number of spaces to insert on tab. Defaults to 2, max of 10 */
/** The number of spaces to insert on tab. Defaults to 2, max of 6 */
tabSize: {
type: Number,
default: 2,
validator: (size: number): boolean => size >= 2 && size <= 6,
},
/** MermaidJs is heavy; allow it opting-out by passing false. Defaults to true. */
mermaid: {
type: Boolean,
default: true,
},
/** The theme used when the component initializes, one of 'light' or 'dark'. Defaults to 'light' */
theme: {
type: String as PropType<'light' | 'dark'>,
default: 'light',
validator: (theme: string): boolean => ['light', 'dark'].includes(theme),
},
/** The max height of the editor when not being displayed fullscreen. Defaults to 300, Minimum of 100. */
editorMaxHeight: {
/** The max height of the component when not being displayed fullscreen. Defaults to 300, Minimum of 100. */
maxHeight: {
type: Number,
default: 300,
validator: (height: number): boolean => height >= 100,
Expand All @@ -184,14 +182,19 @@ const props = defineProps({
type: Number,
default: 1001,
},
/** MermaidJs is heavy; allow it opting-out by passing false. Defaults to true. */
mermaid: {
type: Boolean,
default: true,
},
})
const emit = defineEmits<{
(e: 'update:modelValue', rawMarkdown: string): void
(e: 'mode', mode: MarkdownMode): void
(e: 'fullscreen', active: boolean): void
(e: 'save', rawMarkdown: string): void
(e: 'cancel'): void
(e: 'mode', mode: MarkdownMode): void
(e: 'fullscreen', active: boolean): void
}>()
const { init: initMarkdownIt, md } = composables.useMarkdownIt()
Expand Down Expand Up @@ -485,7 +488,7 @@ onUnmounted(() => {
// Calculate the max height of the `.markdown-panes` when fullscreen is true. 100vh, minus the toolbar height, minus 10px padding.
const fullscreenMarkdownPanesHeight = computed((): string => `calc(100vh - ${TOOLBAR_HEIGHT} - ${KUI_SPACE_60})`)
const markdownEditorMaxHeight = computed((): string => `${props.editorMaxHeight}px`)
const markdownPanesMaxHeight = computed((): string => `${props.maxHeight}px`)
</script>

<style lang="scss" scoped>
Expand Down Expand Up @@ -542,7 +545,7 @@ const markdownEditorMaxHeight = computed((): string => `${props.editorMaxHeight}
&.mode-edit,
&.mode-split {
.markdown-panes {
height: v-bind('markdownEditorMaxHeight'); // max-height in edit and split modes
height: v-bind('markdownPanesMaxHeight'); // max-height in edit and split modes
}
}
Expand Down

0 comments on commit 3aeb083

Please sign in to comment.