@ -126,7 +126,9 @@ interface PalabrasOpts
ariaLabel : string | undefined ;
ariaLabel : string | undefined ;
onValueChange : OnChangeFn < PalabrasDocument > | undefined ;
onValueChange : OnChangeFn < PalabrasDocument > | undefined ;
onSelectionChange : OnChangeFn < PalabrasSelection | null > | undefined ;
onSelectionChange : OnChangeFn < PalabrasSelection | null > | undefined ;
onValueCommit : ( ( document : PalabrasDocument , reason : PalabrasCommitReason ) = > void ) | undefined ;
onValueCommit :
| ( ( document : PalabrasDocument , reason : PalabrasCommitReason ) = > void )
| undefined ;
onUploadImage : PalabrasOnUploadImage | undefined ;
onUploadImage : PalabrasOnUploadImage | undefined ;
insertableBlocks : readonly string [ ] | undefined ;
insertableBlocks : readonly string [ ] | undefined ;
languages : readonly LangSpec [ ] | undefined ;
languages : readonly LangSpec [ ] | undefined ;
@ -138,7 +140,8 @@ interface PalabrasContentOpts extends WithRefOpts {}
interface PalabrasPlaceholderOpts extends WithRefOpts { }
interface PalabrasPlaceholderOpts extends WithRefOpts { }
interface PalabrasToolbarOpts extends WithRefOpts { }
interface PalabrasToolbarOpts extends WithRefOpts { }
interface PalabrasToolbarGroupOpts extends WithRefOpts { }
interface PalabrasToolbarGroupOpts extends WithRefOpts { }
interface PalabrasBubbleMenuOpts extends WithRefOpts , ActiveProps < { side : PalabrasBubbleMenuSide } > { }
interface PalabrasBubbleMenuOpts
extends WithRefOpts , ActiveProps < { side : PalabrasBubbleMenuSide } > { }
interface PalabrasSlashMenuOpts extends WithRefOpts { }
interface PalabrasSlashMenuOpts extends WithRefOpts { }
interface PalabrasCommandButtonOpts
interface PalabrasCommandButtonOpts
extends
extends
@ -159,9 +162,7 @@ interface PalabrasFindReplaceOpts extends WithRefOpts {}
interface PalabrasHiddenInputOpts extends WithRefOpts { }
interface PalabrasHiddenInputOpts extends WithRefOpts { }
interface PalabrasStatusOpts extends WithRefOpts { }
interface PalabrasStatusOpts extends WithRefOpts { }
interface PalabrasDrawerOpts
interface PalabrasDrawerOpts
extends WithRefOpts ,
extends WithRefOpts , StateProps < { open : boolean } > , ActiveProps < { disabled : boolean } > { }
StateProps < { open : boolean } > ,
ActiveProps < { disabled : boolean } > { }
type PalabrasSelectionSyncSource =
type PalabrasSelectionSyncSource =
| 'selectionchange'
| 'selectionchange'
| 'pointer'
| 'pointer'
@ -419,8 +420,7 @@ export class PalabrasProvider {
id : opts.id ,
id : opts.id ,
ref : opts.ref ,
ref : opts.ref ,
owner : this ,
owner : this ,
context : PalabrasProvider.ctx ,
context : PalabrasProvider.ctx
syncAttrs : true
} ) ;
} ) ;
if ( this . field ) this . field . inputId . current = opts . contentId . current ;
if ( this . field ) this . field . inputId . current = opts . contentId . current ;
@ -2083,8 +2083,7 @@ export class PalabrasProvider {
this . ensureCaret ( ) ;
this . ensureCaret ( ) ;
const sel = this . selection ;
const sel = this . selection ;
const doc = this . history . present . document ;
const doc = this . history . present . document ;
const currentIdx =
const currentIdx = sel ? . anchor . path [ 0 ] ? ? Math . max ( 0 , doc . children . length - 1 ) ;
sel ? . anchor . path [ 0 ] ? ? Math . max ( 0 , doc . children . length - 1 ) ;
const current = doc . children [ currentIdx ] ;
const current = doc . children [ currentIdx ] ;
// Empty-paragraph heuristic — match what the slash menu treats
// Empty-paragraph heuristic — match what the slash menu treats
@ -2102,10 +2101,8 @@ export class PalabrasProvider {
if ( id === 'table' ) return this . applyCommand ( { type : 'insertTable' } ) ;
if ( id === 'table' ) return this . applyCommand ( { type : 'insertTable' } ) ;
if ( id === 'unordered-list' )
if ( id === 'unordered-list' )
return this . applyCommand ( { type : 'toggleList' , kind : 'unordered' } ) ;
return this . applyCommand ( { type : 'toggleList' , kind : 'unordered' } ) ;
if ( id === 'ordered-list' )
if ( id === 'ordered-list' ) return this . applyCommand ( { type : 'toggleList' , kind : 'ordered' } ) ;
return this . applyCommand ( { type : 'toggleList' , kind : 'ordered' } ) ;
if ( id === 'check-list' ) return this . applyCommand ( { type : 'toggleList' , kind : 'check' } ) ;
if ( id === 'check-list' )
return this . applyCommand ( { type : 'toggleList' , kind : 'check' } ) ;
if ( id === 'image' ) {
if ( id === 'image' ) {
const node = this . opts . ref . current ;
const node = this . opts . ref . current ;
const win = node ? . ownerDocument ? . defaultView ? ? undefined ;
const win = node ? . ownerDocument ? . defaultView ? ? undefined ;
@ -2329,7 +2326,10 @@ export class PalabrasProvider {
// The structural `samePalabrasDocument` below is an O(document) deep walk —
// The structural `samePalabrasDocument` below is an O(document) deep walk —
// catastrophic per keystroke with large base64 data-URLs — so only reach it
// catastrophic per keystroke with large base64 data-URLs — so only reach it
// when the external value genuinely differs (an external write).
// when the external value genuinely differs (an external write).
if ( externalDocument !== this . publishedExternal && ! samePalabrasDocument ( externalDocument , current . document ) ) {
if (
externalDocument !== this . publishedExternal &&
! samePalabrasDocument ( externalDocument , current . document )
) {
const nextState = createState ( externalDocument , externalSelection ) ;
const nextState = createState ( externalDocument , externalSelection ) ;
if ( ! samePalabrasDocument ( nextState . document , current . document ) ) {
if ( ! samePalabrasDocument ( nextState . document , current . document ) ) {
const limit = this . history . limit ;
const limit = this . history . limit ;
@ -2472,10 +2472,7 @@ export class PalabrasProvider {
// Scope to the block containing the current selection (or
// Scope to the block containing the current selection (or
// the explicitly-selected atomic block via image float
// the explicitly-selected atomic block via image float
// bar). No-op when neither is set.
// bar). No-op when neither is set.
const idx =
const idx = this . selectedBlockIndex ? ? this . opts . selection . current ? . anchor . path [ 0 ] ? ? - 1 ;
this . selectedBlockIndex ? ?
this . opts . selection . current ? . anchor . path [ 0 ] ? ?
- 1 ;
if ( idx < 0 ) return undefined ;
if ( idx < 0 ) return undefined ;
return { type : 'deleteBlock' , blockIndex : idx } ;
return { type : 'deleteBlock' , blockIndex : idx } ;
}
}
@ -2546,8 +2543,7 @@ export class PalabrasContentProvider {
owner : this ,
owner : this ,
onRefChange : ( el ) = > {
onRefChange : ( el ) = > {
this . provider . setContentRef ( el ) ;
this . provider . setContentRef ( el ) ;
} ,
}
syncAttrs : true
} ) ;
} ) ;
}
}
@ -2609,8 +2605,7 @@ export class PalabrasPlaceholderProvider {
this . runtimePart = this . provider . runtime . part ( 'placeholder' , {
this . runtimePart = this . provider . runtime . part ( 'placeholder' , {
id : opts.id ,
id : opts.id ,
ref : opts.ref ,
ref : opts.ref ,
owner : this ,
owner : this
syncAttrs : true
} ) ;
} ) ;
}
}
@ -2644,8 +2639,7 @@ export class PalabrasToolbarProvider {
owner : this ,
owner : this ,
props : {
props : {
disabled : ( ) = > this . provider . isDisabled
disabled : ( ) = > this . provider . isDisabled
} ,
}
syncAttrs : true
} ) ;
} ) ;
}
}
@ -2673,8 +2667,7 @@ export class PalabrasToolbarGroupProvider {
id : opts.id ,
id : opts.id ,
ref : opts.ref ,
ref : opts.ref ,
owner : this ,
owner : this ,
props : { } ,
props : { }
syncAttrs : true
} ) ;
} ) ;
}
}
@ -2709,8 +2702,7 @@ export class PalabrasBubbleMenuProvider {
selectionKind : ( ) = > this . provider . selectionKind ,
selectionKind : ( ) = > this . provider . selectionKind ,
side : ( ) = > this . opts . side . current ,
side : ( ) = > this . opts . side . current ,
disabled : ( ) = > this . provider . isDisabled
disabled : ( ) = > this . provider . isDisabled
} ,
}
syncAttrs : true
} ) ;
} ) ;
}
}
@ -2809,8 +2801,7 @@ export class PalabrasSlashMenuProvider {
activeIndex : ( ) = > this . provider . slashMenuActiveIndex ,
activeIndex : ( ) = > this . provider . slashMenuActiveIndex ,
disabled : ( ) = > this . provider . isDisabled ,
disabled : ( ) = > this . provider . isDisabled ,
readonly : ( ) = > this . provider . isReadonly
readonly : ( ) = > this . provider . isReadonly
} ,
}
syncAttrs : true
} ) ;
} ) ;
}
}
@ -2903,8 +2894,7 @@ export class PalabrasCommandButtonProvider {
active : ( ) = > this . isActive ,
active : ( ) = > this . isActive ,
disabled : ( ) = > this . isDisabled ,
disabled : ( ) = > this . isDisabled ,
toggle : ( ) = > isToggleCommand ( this . opts . command . current )
toggle : ( ) = > isToggleCommand ( this . opts . command . current )
} ,
}
syncAttrs : true
} ) ;
} ) ;
}
}
@ -3068,8 +3058,7 @@ export class PalabrasLinkEditorProvider {
activeLink : ( ) = > Boolean ( this . selectedLink ) ,
activeLink : ( ) = > Boolean ( this . selectedLink ) ,
disabled : ( ) = > this . provider . isDisabled || this . provider . isReadonly ,
disabled : ( ) = > this . provider . isDisabled || this . provider . isReadonly ,
invalid : ( ) = > Boolean ( this . error )
invalid : ( ) = > Boolean ( this . error )
} ,
}
syncAttrs : true
} ) ;
} ) ;
}
}
@ -3174,8 +3163,7 @@ export class PalabrasFindReplaceProvider {
disabled : ( ) = > this . provider . isDisabled ,
disabled : ( ) = > this . provider . isDisabled ,
readonly : ( ) = > this . provider . isReadonly ,
readonly : ( ) = > this . provider . isReadonly ,
hasMatches : ( ) = > this . provider . hasFindMatches
hasMatches : ( ) = > this . provider . hasFindMatches
} ,
}
syncAttrs : true
} ) ;
} ) ;
}
}
@ -3269,8 +3257,7 @@ export class PalabrasStatusProvider {
owner : this ,
owner : this ,
props : {
props : {
status : ( ) = > this . provider . status
status : ( ) = > this . provider . status
} ,
}
syncAttrs : true
} ) ;
} ) ;
}
}
@ -3329,8 +3316,7 @@ export class PalabrasDrawerProvider {
mode : ( ) = > this . mode ,
mode : ( ) = > this . mode ,
open : ( ) = > this . opts . open . current ,
open : ( ) = > this . opts . open . current ,
disabled : ( ) = > this . opts . disabled . current || this . provider . isDisabled
disabled : ( ) = > this . opts . disabled . current || this . provider . isDisabled
} ,
}
syncAttrs : true
} ) ;
} ) ;
}
}
@ -3360,8 +3346,7 @@ export class PalabrasDrawerProvider {
// solo se muestran los constructores; cuando ya tiene contenido,
// solo se muestran los constructores; cuando ya tiene contenido,
// las opciones del objeto".
// las opciones del objeto".
const currentIdx = sel ? . anchor . path [ 0 ] ? ? this . provider . selectedBlockIndex ? ? - 1 ;
const currentIdx = sel ? . anchor . path [ 0 ] ? ? this . provider . selectedBlockIndex ? ? - 1 ;
const currentNode =
const currentNode = currentIdx >= 0 ? this . provider . document . children [ currentIdx ] : undefined ;
currentIdx >= 0 ? this . provider . document . children [ currentIdx ] : undefined ;
const isEmptyTextBlock = isEmptyEditableTextBlock ( currentNode ) ;
const isEmptyTextBlock = isEmptyEditableTextBlock ( currentNode ) ;
// Atomic blocks (no inline format, no parent scopes)
// Atomic blocks (no inline format, no parent scopes)
@ -3470,8 +3455,7 @@ export class PalabrasDrawerProvider {
role : 'complementary' as const ,
role : 'complementary' as const ,
'data-palabras-drawer-mode' : this . mode ,
'data-palabras-drawer-mode' : this . mode ,
'data-open' : this . opts . open . current ? '' : undefined ,
'data-open' : this . opts . open . current ? '' : undefined ,
'data-disabled' :
'data-disabled' : this . opts . disabled . current || this . provider . isDisabled ? '' : undefined
this . opts . disabled . current || this . provider . isDisabled ? '' : undefined
} as const )
} as const )
) ;
) ;
}
}
@ -3596,12 +3580,7 @@ function isEmptyEditableTextBlock(block: unknown): boolean {
language? : string ;
language? : string ;
children? : readonly { type ? : string ; text? : string } [ ] ;
children? : readonly { type ? : string ; text? : string } [ ] ;
} ;
} ;
if (
if ( b . type !== 'paragraph' && b . type !== 'heading' && b . type !== 'quote' && b . type !== 'code' ) {
b . type !== 'paragraph' &&
b . type !== 'heading' &&
b . type !== 'quote' &&
b . type !== 'code'
) {
return false ;
return false ;
}
}
// A code block with a language already carries intent — even an
// A code block with a language already carries intent — even an
@ -3858,7 +3837,8 @@ function imageStatusSig(block: PalabrasBlock, status: ReadonlyMap<string, string
return ;
return ;
}
}
if ( b . type === 'table' ) {
if ( b . type === 'table' ) {
for ( const row of b . rows ) for ( const cell of row . cells ) for ( const child of cell . children ) visit ( child ) ;
for ( const row of b . rows )
for ( const cell of row . cells ) for ( const child of cell . children ) visit ( child ) ;
}
}
} ;
} ;
visit ( block ) ;
visit ( block ) ;