mirror of
https://github.com/zadam/trilium.git
synced 2025-12-04 22:44:25 +01:00
Small improvements
This commit is contained in:
parent
64ab1c4116
commit
c46cf41842
@ -1,94 +1,103 @@
|
|||||||
import { View, type Locale } from 'ckeditor5';
|
import { View, type Locale } from 'ckeditor5';
|
||||||
import 'mathlive'; // Import side-effects only (registers the <math-field> tag)
|
import 'mathlive'; // Import side-effects only (registers the <math-field> tag)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface describing the custom <math-field> element.
|
||||||
|
*/
|
||||||
|
interface MathFieldElement extends HTMLElement {
|
||||||
|
value: string;
|
||||||
|
readOnly: boolean;
|
||||||
|
mathVirtualKeyboardPolicy: string;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wrapper for the MathLive <math-field> component.
|
* A wrapper for the MathLive <math-field> component.
|
||||||
* Uses 'any' typing to avoid TypeScript module resolution errors.
|
|
||||||
*/
|
*/
|
||||||
export default class MathLiveInputView extends View {
|
export default class MathLiveInputView extends View {
|
||||||
/**
|
/**
|
||||||
* The current LaTeX value.
|
* The current LaTeX value.
|
||||||
* @observable
|
* @observable
|
||||||
*/
|
*/
|
||||||
public declare value: string | null;
|
public declare value: string | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read-only state.
|
* Read-only state.
|
||||||
* @observable
|
* @observable
|
||||||
*/
|
*/
|
||||||
public declare isReadOnly: boolean;
|
public declare isReadOnly: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to the DOM element (typed as any to prevent TS errors).
|
* Reference to the DOM element.
|
||||||
*/
|
* Typed as MathFieldElement | null for proper TS support.
|
||||||
public mathfield: any = null;
|
*/
|
||||||
|
public mathfield: MathFieldElement | null = null;
|
||||||
|
|
||||||
constructor( locale: Locale ) {
|
constructor( locale: Locale ) {
|
||||||
super( locale );
|
super( locale );
|
||||||
|
|
||||||
this.set( 'value', null );
|
this.set( 'value', null );
|
||||||
this.set( 'isReadOnly', false );
|
this.set( 'isReadOnly', false );
|
||||||
|
|
||||||
this.setTemplate( {
|
this.setTemplate( {
|
||||||
tag: 'div',
|
tag: 'div',
|
||||||
attributes: {
|
attributes: {
|
||||||
class: [ 'ck', 'ck-mathlive-input' ]
|
class: [ 'ck', 'ck-mathlive-input' ]
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
public override render(): void {
|
public override render(): void {
|
||||||
super.render();
|
super.render();
|
||||||
|
|
||||||
// 1. Create element using DOM API instead of Class constructor
|
// 1. Create element with the specific type
|
||||||
// This avoids "Module has no exported member" errors.
|
const mathfield = document.createElement( 'math-field' ) as MathFieldElement;
|
||||||
const mathfield = document.createElement( 'math-field' ) as any;
|
|
||||||
|
|
||||||
// 2. Configure Options
|
// 2. Configure Options
|
||||||
mathfield.mathVirtualKeyboardPolicy = 'manual';
|
mathfield.mathVirtualKeyboardPolicy = 'manual';
|
||||||
|
|
||||||
// Disable sounds
|
// Disable sounds
|
||||||
const MathfieldElement = customElements.get( 'math-field' );
|
const MathfieldConstructor = customElements.get( 'math-field' );
|
||||||
if ( MathfieldElement ) {
|
if ( MathfieldConstructor ) {
|
||||||
( MathfieldElement as any ).soundsDirectory = null;
|
( MathfieldConstructor as any ).soundsDirectory = null;
|
||||||
( MathfieldElement as any ).plonkSound = null;
|
( MathfieldConstructor as any ).plonkSound = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Set Initial State
|
// 3. Set Initial State
|
||||||
mathfield.value = this.value ?? '';
|
mathfield.value = this.value ?? '';
|
||||||
mathfield.readOnly = this.isReadOnly;
|
mathfield.readOnly = this.isReadOnly;
|
||||||
|
|
||||||
// 4. Bind Events (DOM -> Observable)
|
// 4. Bind Events (DOM -> Observable)
|
||||||
mathfield.addEventListener( 'input', () => {
|
mathfield.addEventListener( 'input', () => {
|
||||||
const val = mathfield.value;
|
const val = mathfield.value;
|
||||||
this.value = val.length ? val : null;
|
this.value = val.length ? val : null;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// 5. Bind Events (Observable -> DOM)
|
// 5. Bind Events (Observable -> DOM)
|
||||||
this.on( 'change:value', ( _evt, _name, nextValue ) => {
|
this.on( 'change:value', ( _evt, _name, nextValue ) => {
|
||||||
if ( mathfield.value !== nextValue ) {
|
if ( mathfield.value !== nextValue ) {
|
||||||
mathfield.value = nextValue ?? '';
|
mathfield.value = nextValue ?? '';
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
this.on( 'change:isReadOnly', ( _evt, _name, nextValue ) => {
|
this.on( 'change:isReadOnly', ( _evt, _name, nextValue ) => {
|
||||||
mathfield.readOnly = nextValue;
|
mathfield.readOnly = nextValue;
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// 6. Mount
|
// 6. Mount
|
||||||
this.element?.appendChild( mathfield );
|
this.element?.appendChild( mathfield );
|
||||||
this.mathfield = mathfield;
|
this.mathfield = mathfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
public focus(): void {
|
public focus(): void {
|
||||||
this.mathfield?.focus();
|
this.mathfield?.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override destroy(): void {
|
public override destroy(): void {
|
||||||
if ( this.mathfield ) {
|
if ( this.mathfield ) {
|
||||||
this.mathfield.remove();
|
this.mathfield.remove();
|
||||||
this.mathfield = null;
|
this.mathfield = null;
|
||||||
}
|
}
|
||||||
super.destroy();
|
super.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,51 +4,51 @@ import { LabeledFieldView, createLabeledTextarea, type Locale, type TextareaView
|
|||||||
* A labeled textarea view for direct LaTeX code editing.
|
* A labeled textarea view for direct LaTeX code editing.
|
||||||
*/
|
*/
|
||||||
export default class RawLatexInputView extends LabeledFieldView<TextareaView> {
|
export default class RawLatexInputView extends LabeledFieldView<TextareaView> {
|
||||||
/**
|
/**
|
||||||
* The current LaTeX value.
|
* The current LaTeX value.
|
||||||
* @observable
|
* @observable
|
||||||
*/
|
*/
|
||||||
public declare value: string;
|
public declare value: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the input is in read-only mode.
|
* Whether the input is in read-only mode.
|
||||||
* @observable
|
* @observable
|
||||||
*/
|
*/
|
||||||
public declare isReadOnly: boolean;
|
public declare isReadOnly: boolean;
|
||||||
|
|
||||||
constructor( locale: Locale ) {
|
constructor( locale: Locale ) {
|
||||||
super( locale, createLabeledTextarea );
|
super( locale, createLabeledTextarea );
|
||||||
|
|
||||||
this.set( 'value', '' );
|
this.set( 'value', '' );
|
||||||
this.set( 'isReadOnly', false );
|
this.set( 'isReadOnly', false );
|
||||||
|
|
||||||
const fieldView = this.fieldView;
|
const fieldView = this.fieldView;
|
||||||
|
|
||||||
// 1. Sync: DOM (Textarea) -> Observable
|
// 1. Sync: DOM (Textarea) -> Observable
|
||||||
// We listen to the native 'input' event on the child view
|
fieldView.on( 'input', () => {
|
||||||
fieldView.on( 'input', () => {
|
// We cast strictly to HTMLTextAreaElement to access '.value' safely
|
||||||
if ( fieldView.element ) {
|
const textarea = fieldView.element as HTMLTextAreaElement;
|
||||||
this.value = fieldView.element.value;
|
if ( textarea ) {
|
||||||
}
|
this.value = textarea.value;
|
||||||
} );
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
// 2. Sync: Observable -> DOM (Textarea)
|
// 2. Sync: Observable -> DOM (Textarea)
|
||||||
this.on( 'change:value', () => {
|
this.on( 'change:value', () => {
|
||||||
// Check for difference to avoid cursor jumping or unnecessary updates
|
const textarea = fieldView.element as HTMLTextAreaElement;
|
||||||
if ( fieldView.element && fieldView.element.value !== this.value ) {
|
// Check for difference to avoid cursor jumping
|
||||||
fieldView.element.value = this.value;
|
if ( textarea && textarea.value !== this.value ) {
|
||||||
}
|
textarea.value = this.value;
|
||||||
} );
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
// 3. Sync: ReadOnly State
|
// 3. Sync: ReadOnly State
|
||||||
this.on( 'change:isReadOnly', () => {
|
this.on( 'change:isReadOnly', ( _evt, _name, nextValue ) => {
|
||||||
if ( fieldView.element ) {
|
fieldView.isReadOnly = nextValue;
|
||||||
fieldView.element.readOnly = this.isReadOnly;
|
} );
|
||||||
}
|
}
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
public override render(): void {
|
public override render(): void {
|
||||||
super.render();
|
super.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user