11<template >
2- <div
3- v-html =" purifiedHtml"
4- class =" prose
5- prose-p:my-0
6- prose-headings:my-0
7- prose-h1:text-[1.6rem]
8- prose-ul:my-0
9- prose-ol:my-0
10- prose-li:my-0
11- prose-pre:my-0
12- prose-hr:my-1
13- leading-tight
14- dark: dark:text-gray-300
15- dark:[& _th]:text-white
16- dark:[& _td]:text-white
17- dark:[& _thead]:border-b-gray-600
18- dark:[& _code]:text-white
19- dark:[& _h1]:text-white dark:[& _h2]:text-gray-100 dark:[& _h3]:text-gray-200
20- dark:[& _a]:text-white dark:[& _a:hover]:text-white
21- dark:[& _pre]:bg-black dark:[& _pre]:border dark:[& _border-slate-800]
22- dark:[& _strong]:text-white
23- dark:[& _em]:text-gray-400
24- dark:[& _del]:text-gray-600" >
25- </div >
26- </template >
27-
28- <script setup lang="ts">
29- import { computed } from ' vue' ;
30- import { marked } from " marked" ;
31- import DOMPurify from " dompurify" ;
32-
33- const props = defineProps <{ column: any ; record: any }>();
2+ <div >
3+ <div
4+ :class =" { 'overflow-hidden': !expanded && isOverflowing }"
5+ :style =" !expanded && isOverflowing ? computedMaxHeight : {}"
6+ >
7+ <div
8+ ref =" contentRef"
9+ v-html =" purifiedHtml"
10+ class =" prose
11+ prose-p:my-0
12+ prose-headings:my-0
13+ prose-h1:text-[1.6rem]
14+ prose-ul:my-0
15+ prose-ol:my-0
16+ prose-li:my-0
17+ prose-pre:my-0
18+ prose-hr:my-1
19+ prose-table:my-0
20+ leading-none
21+ dark: dark:text-gray-300
22+ dark:[& _th]:text-white
23+ dark:[& _td]:text-white
24+ dark:[& _thead]:border-b-gray-600
25+ dark:[& _code]:text-white
26+ dark:[& _h1]:text-white dark:[& _h2]:text-gray-100 dark:[& _h3]:text-gray-200
27+ dark:[& _a]:text-white dark:[& _a:hover]:text-white
28+ dark:[& _pre]:bg-black dark:[& _pre]:border dark:[& _border-slate-800]
29+ dark:[& _strong]:text-white
30+ dark:[& _em]:text-gray-400
31+ dark:[& _del]:text-gray-600"
32+ :class =" compactPreviewStyles"
33+ ></div >
34+ </div >
35+ <button
36+ v-if =" isOverflowing || expanded"
37+ @click =" expanded = !expanded"
38+ class =" mt-1 text-sm text-primary-600 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300 font-medium focus:outline-none hover:underline"
39+ >
40+ {{ expanded ? 'Show less' : 'Show more' }}
41+ </button >
42+ </div >
43+ </template >
44+
45+ <script setup lang="ts">
46+ import { computed , ref , watch , onMounted , onBeforeUnmount , nextTick } from ' vue' ;
47+ import { marked } from " marked" ;
48+ import DOMPurify from " dompurify" ;
3449
35- const purifiedHtml = computed (() => {
50+ const props = defineProps <{
51+ column: any ;
52+ record: any ;
53+ meta: {
54+ pluginInstanceId: string ;
55+ compactShowPreview? : boolean ;
56+ maxShowViewContainerHeightPx? : number ;
57+ }
58+ }>();
59+
60+ const compactPreviewStyles = computed (() => {
61+ if (props .meta .compactShowPreview ) {
62+ return `
63+ prose-ul:leading-[0.2]
64+ prose-ol:leading-[0.2]
65+ prose-li:leading-[1]
66+ prose-h1:leading-none
67+ prose-h2:leading-none
68+ prose-h3:leading-none
69+ prose-h1:text-[1.3rem]
70+ prose-h2:text-[1.2rem]
71+ prose-h3:text-[1.1rem]
72+ prose-blockquote:my-0
73+ `
74+ } else {
75+ return ' ' ;
76+ }
77+ });
78+
79+ const computedMaxHeight = computed (() => {
80+ if (props .meta .maxShowViewContainerHeightPx ) {
81+ return { maxHeight: ` ${props .meta .maxShowViewContainerHeightPx }px ` };
82+ }
83+ return {};
84+ });
85+
86+ const contentRef = ref <HTMLElement | null >(null );
87+ const expanded = ref (false );
88+ const isOverflowing = ref (false );
3689
90+ let resizeObserver: ResizeObserver | null = null ;
91+
92+ function checkOverflow() {
93+ if (! props .meta .maxShowViewContainerHeightPx || ! contentRef .value ) {
94+ isOverflowing .value = false ;
95+ return ;
96+ }
97+ isOverflowing .value = contentRef .value .scrollHeight > props .meta .maxShowViewContainerHeightPx ;
98+ }
99+
100+ function setupObserver() {
101+ resizeObserver ?.disconnect ();
102+ if (! props .meta .maxShowViewContainerHeightPx || ! contentRef .value ) return ;
103+
104+ resizeObserver = new ResizeObserver (() => checkOverflow ());
105+ resizeObserver .observe (contentRef .value );
106+ }
107+
108+ onMounted (async () => {
109+ await nextTick ();
110+ checkOverflow ();
111+ setupObserver ();
112+ });
113+
114+ onBeforeUnmount (() => {
115+ resizeObserver ?.disconnect ();
116+ });
117+
118+ const purifiedHtml = computed (() => {
37119 if (! props .record [props .column .name ]) return ' -' ;
38120 const html = marked (String (props .record [props .column .name ]));
39121 if (html instanceof Promise ) {
42124 }
43125 return DOMPurify .sanitize (html );
44126 });
127+
128+ // Re-check overflow whenever content changes
129+ watch (purifiedHtml , async () => {
130+ expanded .value = false ;
131+ await nextTick ();
132+ checkOverflow ();
133+ setupObserver ();
134+ });
45135 </script >
46136
0 commit comments