@@ -81,6 +81,43 @@ const textColor = computed(() => noteTextColor(isDark.value));
8181const borderColor = computed (() => noteBorderColor (isDark .value , props .selected ));
8282const dividerColor = computed (() => noteDividerColor (isDark .value ));
8383
84+ function sizeToCSS(size : string ): string {
85+ if (/ ^ -? \d + (\. \d + )? $ / .test (size .trim ())) {
86+ return ` ${size }px ` ;
87+ }
88+ return size ;
89+ }
90+
91+ const headHeightCSS = computed (() => {
92+ const h = props .model .head .height .value ;
93+ const collapsed = props .model .collapsing .collapsed .value ;
94+ if (! props .model .head .enabled .value ) return undefined ;
95+ if (collapsed ) {
96+ const c = h .collapsed ;
97+ if (c === " Auto" || c === " Minimum" ) {
98+ if (numEnabledSections .value === 1 ) return " 0px" ;
99+ return sizeToCSS (h .expanded );
100+ }
101+ return sizeToCSS (c );
102+ }
103+ return sizeToCSS (h .expanded );
104+ });
105+
106+ const bodyHeightCSS = computed (() => {
107+ const h = props .model .body .height .value ;
108+ const collapsed = props .model .collapsing .collapsed .value ;
109+ if (! props .model .body .enabled .value ) return undefined ;
110+ if (collapsed ) {
111+ const c = h .collapsed ;
112+ if (c === " Auto" || c === " Minimum" ) {
113+ if (numEnabledSections .value === 1 ) return " 0px" ;
114+ return sizeToCSS (h .expanded );
115+ }
116+ return sizeToCSS (c );
117+ }
118+ return sizeToCSS (h .expanded );
119+ });
120+
84121const headFrag = computed (() => props .model .head .value .value );
85122const bodyFrag = computed (() => props .model .body .value .value );
86123
@@ -159,6 +196,7 @@ let hasDragged = false;
159196
160197function onPointerDown(e : PointerEvent ) {
161198 if (e .button !== 0 ) return ;
199+ if (isEditing .value ) return ;
162200 e .stopPropagation ();
163201
164202 if (e .shiftKey ) {
@@ -231,13 +269,15 @@ let resizeStartWidth = 0;
231269let resizeStartHeight = 0 ;
232270let resizeStartPosX = 0 ;
233271let resizeStartPosY = 0 ;
272+ let resizingSection: " head" | " body" | null = null ;
234273
235274function onResizePointerDown(e : PointerEvent , handle : ResizeHandle ) {
236275 if (e .button !== 0 ) return ;
237276 if (props .model .readOnly .value ) return ;
238277 e .stopPropagation ();
239278 resizePointerId = e .pointerId ;
240279 resizeHandle = handle ;
280+ resizingSection = null ;
241281 resizeStartX = e .clientX ;
242282 resizeStartY = e .clientY ;
243283 const widthVal = (props .model .width as any )?.value ?? props .model .width ;
@@ -253,12 +293,78 @@ function onResizePointerDown(e: PointerEvent, handle: ResizeHandle) {
253293 el .setPointerCapture (e .pointerId );
254294}
255295
296+ function onSectionResizePointerDown(e : PointerEvent , section : " head" | " body" ) {
297+ if (e .button !== 0 ) return ;
298+ if (props .model .readOnly .value ) return ;
299+ e .stopPropagation ();
300+ resizePointerId = e .pointerId ;
301+ resizeHandle = " s" ;
302+ resizingSection = section ;
303+ resizeStartX = e .clientX ;
304+ resizeStartY = e .clientY ;
305+ const sectionMap = props .model .rawMap .get (section ) as import (" yjs" ).Map <unknown >;
306+ const hMap = sectionMap .get (" height" ) as import (" yjs" ).Map <string >;
307+ const hVal = hMap .get (" expanded" ) ?? " Auto" ;
308+ resizeStartHeight = hVal === " Auto" || hVal === " Minimum" ? 80 : parseFloat (hVal );
309+ isDragging .value = true ;
310+ const el = e .currentTarget as HTMLElement ;
311+ el .setPointerCapture (e .pointerId );
312+ }
313+
314+ function onSectionCornerResizePointerDown(e : PointerEvent , handle : ResizeHandle , section : " head" | " body" ) {
315+ if (e .button !== 0 ) return ;
316+ if (props .model .readOnly .value ) return ;
317+ e .stopPropagation ();
318+ resizePointerId = e .pointerId ;
319+ resizeHandle = handle ;
320+ resizingSection = section ;
321+ resizeStartX = e .clientX ;
322+ resizeStartY = e .clientY ;
323+ const widthVal = (props .model .width as any )?.value ?? props .model .width ;
324+ const w = widthVal ?.expanded ;
325+ resizeStartWidth = w === " Auto" ? 160 : parseFloat (w ?? " 160" );
326+ const sectionMap = props .model .rawMap .get (section ) as import (" yjs" ).Map <unknown >;
327+ const hMap = sectionMap .get (" height" ) as import (" yjs" ).Map <string >;
328+ const hVal = hMap .get (" expanded" ) ?? " Auto" ;
329+ resizeStartHeight = hVal === " Auto" || hVal === " Minimum" ? 80 : parseFloat (hVal );
330+ resizeStartPosX = props .model .pos .value .x ;
331+ resizeStartPosY = props .model .pos .value .y ;
332+ isDragging .value = true ;
333+ const el = e .currentTarget as HTMLElement ;
334+ el .setPointerCapture (e .pointerId );
335+ }
336+
256337function onResizePointerMove(e : PointerEvent ) {
257338 if (resizePointerId !== e .pointerId || ! resizeHandle ) return ;
258339 const z = props .zoom || 1 ;
259340 const dx = (e .clientX - resizeStartX ) / z ;
260341 const dy = (e .clientY - resizeStartY ) / z ;
261342
343+ if (resizingSection ) {
344+ const nextHeight = Math .max (
345+ 40 ,
346+ Math .round (resizeStartHeight + dy ),
347+ );
348+ const sectionMap = props .model .rawMap .get (resizingSection ) as import (" yjs" ).Map <unknown >;
349+ const hMap = sectionMap .get (" height" ) as import (" yjs" ).Map <string >;
350+ hMap .set (" expanded" , String (nextHeight ));
351+
352+ const isWest = resizeHandle .includes (" w" );
353+ if (isWest || resizeHandle .includes (" e" )) {
354+ const nextWidth = Math .max (
355+ 80 ,
356+ Math .round (isWest ? resizeStartWidth - dx : resizeStartWidth + dx ),
357+ );
358+ const widthMap = props .model .rawMap .get (" width" ) as import (" yjs" ).Map <string >;
359+ widthMap .set (" expanded" , String (nextWidth ));
360+ if (isWest ) {
361+ const posMap = props .model .rawMap .get (" pos" ) as import (" yjs" ).Map <number >;
362+ posMap .set (" x" , Math .round (resizeStartPosX + dx ));
363+ }
364+ }
365+ return ;
366+ }
367+
262368 const isWest = resizeHandle .includes (" w" );
263369 const nextWidth = Math .max (
264370 80 ,
@@ -291,6 +397,7 @@ function onResizePointerUp(e: PointerEvent) {
291397 if (resizePointerId !== e .pointerId ) return ;
292398 resizePointerId = null ;
293399 resizeHandle = null ;
400+ resizingSection = null ;
294401 isDragging .value = false ;
295402 const el = e .currentTarget as HTMLElement ;
296403 if (el .releasePointerCapture ) {
@@ -337,9 +444,9 @@ function onContextMenu(e: MouseEvent) {
337444 <div
338445 v-if =" model.head.enabled.value && !model.collapsing.collapsed.value"
339446 class =" flex"
340- style =" min- height : 36.45px "
447+ : style =" { height: headHeightCSS, minHeight: ' 36.45px' } "
341448 >
342- <div class =" flex-1" @pointerdown .stop @focusin =" emit('edit-start')" >
449+ <div class =" flex-1" @dblclick .stop = " emit('edit-start') " @focusin =" emit('edit-start')" >
343450 <NoteTiptapEditor
344451 :fragment =" headFrag ! "
345452 :editable =" isEditing && ! model .readOnly .value "
@@ -374,20 +481,38 @@ function onContextMenu(e: MouseEvent) {
374481 v-if =" model.resizable.value && !model.readOnly.value && props.selected"
375482 class =" absolute z-[2147483646] cursor-ns-resize"
376483 style =" top : -3px ; left : 0 ; right : 0 ; height : 7px ;"
377- @pointerdown =" (e: PointerEvent) => onResizePointerDown (e, 's ')"
484+ @pointerdown =" (e: PointerEvent) => onSectionResizePointerDown (e, 'head ')"
378485 @pointermove =" onResizePointerMove"
379486 @pointerup =" onResizePointerUp"
380487 @pointercancel =" onResizePointerUp"
381488 />
489+ <template v-if =" model .resizable .value && ! model .readOnly .value && props .selected && ! isFlexChild " >
490+ <div
491+ class =" absolute z-[2147483647] h-2.5 w-2.5 rounded-full"
492+ style =" left : 0% ; top : 0% ; background-color : #2196f3 ; transform : translate (-50% , -50% );"
493+ @pointerdown =" (e: PointerEvent) => onSectionCornerResizePointerDown(e, 'sw', 'head')"
494+ @pointermove =" onResizePointerMove"
495+ @pointerup =" onResizePointerUp"
496+ @pointercancel =" onResizePointerUp"
497+ />
498+ <div
499+ class =" absolute z-[2147483647] h-2.5 w-2.5 rounded-full"
500+ style =" left : 100% ; top : 0% ; background-color : #2196f3 ; transform : translate (-50% , -50% );"
501+ @pointerdown =" (e: PointerEvent) => onSectionCornerResizePointerDown(e, 'se', 'head')"
502+ @pointermove =" onResizePointerMove"
503+ @pointerup =" onResizePointerUp"
504+ @pointercancel =" onResizePointerUp"
505+ />
506+ </template >
382507 </div >
383508
384509 <!-- body section -->
385510 <div
386511 v-if =" model.body.enabled.value && !model.collapsing.collapsed.value"
387512 class =" flex"
388- style =" min- height : 36.45px "
513+ : style =" { height: bodyHeightCSS, minHeight: ' 36.45px' } "
389514 >
390- <div class =" flex-1" @pointerdown .stop @focusin =" emit('edit-start')" >
515+ <div class =" flex-1" @dblclick .stop = " emit('edit-start') " @focusin =" emit('edit-start')" >
391516 <NoteTiptapEditor
392517 :fragment =" bodyFrag ! "
393518 :editable =" isEditing && ! model .readOnly .value "
@@ -422,11 +547,29 @@ function onContextMenu(e: MouseEvent) {
422547 v-if =" model.resizable.value && !model.readOnly.value && props.selected"
423548 class =" absolute z-[2147483646] cursor-ns-resize"
424549 style =" top : -3px ; left : 0 ; right : 0 ; height : 7px ;"
425- @pointerdown =" (e: PointerEvent) => onResizePointerDown (e, 's ')"
550+ @pointerdown =" (e: PointerEvent) => onSectionResizePointerDown (e, 'body ')"
426551 @pointermove =" onResizePointerMove"
427552 @pointerup =" onResizePointerUp"
428553 @pointercancel =" onResizePointerUp"
429554 />
555+ <template v-if =" model .resizable .value && ! model .readOnly .value && props .selected && ! isFlexChild " >
556+ <div
557+ class =" absolute z-[2147483647] h-2.5 w-2.5 rounded-full"
558+ style =" left : 0% ; top : 0% ; background-color : #2196f3 ; transform : translate (-50% , -50% );"
559+ @pointerdown =" (e: PointerEvent) => onSectionCornerResizePointerDown(e, 'sw', 'body')"
560+ @pointermove =" onResizePointerMove"
561+ @pointerup =" onResizePointerUp"
562+ @pointercancel =" onResizePointerUp"
563+ />
564+ <div
565+ class =" absolute z-[2147483647] h-2.5 w-2.5 rounded-full"
566+ style =" left : 100% ; top : 0% ; background-color : #2196f3 ; transform : translate (-50% , -50% );"
567+ @pointerdown =" (e: PointerEvent) => onSectionCornerResizePointerDown(e, 'se', 'body')"
568+ @pointermove =" onResizePointerMove"
569+ @pointerup =" onResizePointerUp"
570+ @pointercancel =" onResizePointerUp"
571+ />
572+ </template >
430573 </div >
431574
432575 <!-- container section -->
0 commit comments