@malva-ui/editor 0.1.13 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/fesm2022/malva-ui-editor-ai.mjs +17 -0
- package/fesm2022/malva-ui-editor-ai.mjs.map +1 -0
- package/fesm2022/malva-ui-editor.mjs +10227 -0
- package/fesm2022/malva-ui-editor.mjs.map +1 -0
- package/package.json +35 -26
- package/types/malva-ui-editor-ai.d.ts +1 -0
- package/types/malva-ui-editor.d.ts +2995 -0
- package/ai/index.d.ts +0 -12
- package/ai/malva-ui-editor-ai.d.ts +0 -5
- package/esm2022/ai/index.js +0 -12
- package/esm2022/ai/index.js.map +0 -1
- package/esm2022/ai/malva-ui-editor-ai.js +0 -5
- package/esm2022/ai/malva-ui-editor-ai.js.map +0 -1
- package/esm2022/index.js +0 -37
- package/esm2022/index.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-actions.js +0 -69
- package/esm2022/lib/ai/editor-ai-actions.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-context.js +0 -612
- package/esm2022/lib/ai/editor-ai-context.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-menu.js +0 -288
- package/esm2022/lib/ai/editor-ai-menu.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-review-bar.js +0 -223
- package/esm2022/lib/ai/editor-ai-review-bar.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-stream.js +0 -677
- package/esm2022/lib/ai/editor-ai-stream.js.map +0 -1
- package/esm2022/lib/ai/editor-ai-suggestions.js +0 -751
- package/esm2022/lib/ai/editor-ai-suggestions.js.map +0 -1
- package/esm2022/lib/ai/editor-ai.tokens.js +0 -10
- package/esm2022/lib/ai/editor-ai.tokens.js.map +0 -1
- package/esm2022/lib/ai/editor-ai.types.js +0 -1
- package/esm2022/lib/ai/editor-ai.types.js.map +0 -1
- package/esm2022/lib/editor/editor.js +0 -985
- package/esm2022/lib/editor/editor.js.map +0 -1
- package/esm2022/lib/editor-extension-preflight.js +0 -83
- package/esm2022/lib/editor-extension-preflight.js.map +0 -1
- package/esm2022/lib/editor-serialization.js +0 -152
- package/esm2022/lib/editor-serialization.js.map +0 -1
- package/esm2022/lib/editor-toolbar-context.js +0 -259
- package/esm2022/lib/editor-toolbar-context.js.map +0 -1
- package/esm2022/lib/editor.tokens.js +0 -10
- package/esm2022/lib/editor.tokens.js.map +0 -1
- package/esm2022/lib/editor.types.js +0 -48
- package/esm2022/lib/editor.types.js.map +0 -1
- package/esm2022/lib/extensions/editor-block-handle.js +0 -760
- package/esm2022/lib/extensions/editor-block-handle.js.map +0 -1
- package/esm2022/lib/extensions/editor-extensions.js +0 -321
- package/esm2022/lib/extensions/editor-extensions.js.map +0 -1
- package/esm2022/lib/extensions/editor-markdown-compatibility.js +0 -162
- package/esm2022/lib/extensions/editor-markdown-compatibility.js.map +0 -1
- package/esm2022/lib/extensions/editor-upload-placeholder.js +0 -156
- package/esm2022/lib/extensions/editor-upload-placeholder.js.map +0 -1
- package/esm2022/lib/status/editor-status.js +0 -64
- package/esm2022/lib/status/editor-status.js.map +0 -1
- package/esm2022/lib/toolbar/editor-alignment.js +0 -203
- package/esm2022/lib/toolbar/editor-alignment.js.map +0 -1
- package/esm2022/lib/toolbar/editor-block-insert.js +0 -101
- package/esm2022/lib/toolbar/editor-block-insert.js.map +0 -1
- package/esm2022/lib/toolbar/editor-color-control.js +0 -71
- package/esm2022/lib/toolbar/editor-color-control.js.map +0 -1
- package/esm2022/lib/toolbar/editor-command-button.js +0 -115
- package/esm2022/lib/toolbar/editor-command-button.js.map +0 -1
- package/esm2022/lib/toolbar/editor-heading.js +0 -266
- package/esm2022/lib/toolbar/editor-heading.js.map +0 -1
- package/esm2022/lib/toolbar/editor-highlight.js +0 -84
- package/esm2022/lib/toolbar/editor-highlight.js.map +0 -1
- package/esm2022/lib/toolbar/editor-image-upload-dialog.js +0 -289
- package/esm2022/lib/toolbar/editor-image-upload-dialog.js.map +0 -1
- package/esm2022/lib/toolbar/editor-image-upload.js +0 -315
- package/esm2022/lib/toolbar/editor-image-upload.js.map +0 -1
- package/esm2022/lib/toolbar/editor-inline-marks.js +0 -124
- package/esm2022/lib/toolbar/editor-inline-marks.js.map +0 -1
- package/esm2022/lib/toolbar/editor-link.js +0 -265
- package/esm2022/lib/toolbar/editor-link.js.map +0 -1
- package/esm2022/lib/toolbar/editor-list.js +0 -249
- package/esm2022/lib/toolbar/editor-list.js.map +0 -1
- package/esm2022/lib/toolbar/editor-table.js +0 -292
- package/esm2022/lib/toolbar/editor-table.js.map +0 -1
- package/esm2022/lib/toolbar/editor-text-color.js +0 -82
- package/esm2022/lib/toolbar/editor-text-color.js.map +0 -1
- package/esm2022/lib/toolbar/editor-toolbar-widget.js +0 -41
- package/esm2022/lib/toolbar/editor-toolbar-widget.js.map +0 -1
- package/esm2022/lib/toolbar/editor-toolbar.defs.js +0 -60
- package/esm2022/lib/toolbar/editor-toolbar.defs.js.map +0 -1
- package/esm2022/lib/toolbar/editor-toolbar.js +0 -826
- package/esm2022/lib/toolbar/editor-toolbar.js.map +0 -1
- package/esm2022/lib/toolbar/editor-undo-redo.js +0 -72
- package/esm2022/lib/toolbar/editor-undo-redo.js.map +0 -1
- package/esm2022/lib/toolbar/editor-zoom.js +0 -330
- package/esm2022/lib/toolbar/editor-zoom.js.map +0 -1
- package/esm2022/lib/upload/editor-image-upload-coordinator.js +0 -480
- package/esm2022/lib/upload/editor-image-upload-coordinator.js.map +0 -1
- package/esm2022/malva-ui-editor.js +0 -5
- package/esm2022/malva-ui-editor.js.map +0 -1
- package/index.d.ts +0 -35
- package/lib/ai/editor-ai-actions.d.ts +0 -27
- package/lib/ai/editor-ai-context.d.ts +0 -307
- package/lib/ai/editor-ai-menu.d.ts +0 -142
- package/lib/ai/editor-ai-review-bar.d.ts +0 -116
- package/lib/ai/editor-ai-stream.d.ts +0 -207
- package/lib/ai/editor-ai-suggestions.d.ts +0 -219
- package/lib/ai/editor-ai.tokens.d.ts +0 -10
- package/lib/ai/editor-ai.types.d.ts +0 -176
- package/lib/editor/editor.d.ts +0 -243
- package/lib/editor-extension-preflight.d.ts +0 -23
- package/lib/editor-serialization.d.ts +0 -74
- package/lib/editor-toolbar-context.d.ts +0 -116
- package/lib/editor.tokens.d.ts +0 -6
- package/lib/editor.types.d.ts +0 -194
- package/lib/extensions/editor-block-handle.d.ts +0 -59
- package/lib/extensions/editor-extensions.d.ts +0 -165
- package/lib/extensions/editor-markdown-compatibility.d.ts +0 -11
- package/lib/extensions/editor-upload-placeholder.d.ts +0 -75
- package/lib/status/editor-status.d.ts +0 -24
- package/lib/toolbar/editor-alignment.d.ts +0 -61
- package/lib/toolbar/editor-block-insert.d.ts +0 -26
- package/lib/toolbar/editor-color-control.d.ts +0 -32
- package/lib/toolbar/editor-command-button.d.ts +0 -29
- package/lib/toolbar/editor-heading.d.ts +0 -68
- package/lib/toolbar/editor-highlight.d.ts +0 -21
- package/lib/toolbar/editor-image-upload-dialog.d.ts +0 -96
- package/lib/toolbar/editor-image-upload.d.ts +0 -71
- package/lib/toolbar/editor-inline-marks.d.ts +0 -30
- package/lib/toolbar/editor-link.d.ts +0 -78
- package/lib/toolbar/editor-list.d.ts +0 -67
- package/lib/toolbar/editor-table.d.ts +0 -133
- package/lib/toolbar/editor-text-color.d.ts +0 -21
- package/lib/toolbar/editor-toolbar-widget.d.ts +0 -19
- package/lib/toolbar/editor-toolbar.d.ts +0 -157
- package/lib/toolbar/editor-toolbar.defs.d.ts +0 -35
- package/lib/toolbar/editor-undo-redo.d.ts +0 -26
- package/lib/toolbar/editor-zoom.d.ts +0 -108
- package/lib/upload/editor-image-upload-coordinator.d.ts +0 -55
- package/malva-ui-editor.d.ts +0 -5
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"editor-toolbar.js","sourceRoot":"","sources":["../../../../../../libs/editor/src/lib/toolbar/editor-toolbar.ts"],"names":[],"mappings":"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","sourcesContent":["import { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport type { BooleanInput } from '@angular/cdk/coercion';\nimport { DOCUMENT, isPlatformBrowser, NgTemplateOutlet } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n Directive,\n ElementRef,\n effect,\n inject,\n input,\n Injectable,\n PLATFORM_ID,\n signal,\n viewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport type { TemplateRef } from '@angular/core';\nimport type { Editor } from '@tiptap/core';\nimport type { Signal, WritableSignal } from '@angular/core';\nimport { LucideEllipsis } from '@lucide/angular';\nimport type {\n MlvEditorError,\n MlvEditorFormat,\n MlvEditorImageUploadControl,\n} from '../editor.types';\nimport { MlvFade, MlvResizeObserverService } from '@malva-ui/cdk/utils';\nimport { MlvButton, MlvButtonIcon } from '@malva-ui/core/button';\nimport { MlvListItem } from '@malva-ui/core/list';\nimport { MlvMenu, MlvMenuItem, MlvMenuTrigger } from '@malva-ui/core/menu';\nimport { MlvToolbar } from '@malva-ui/core/toolbar';\nimport { MlvDivider } from '@malva-ui/core/divider';\nimport { MlvTooltip } from '@malva-ui/core/tooltip';\nimport { MLV_EDITOR_I18N } from '@malva-ui/i18n';\nimport {\n MLV_EDITOR_OVERLAY_REGISTRY,\n MLV_EDITOR_TOOLBAR_CONTEXT,\n MLV_EDITOR_TOOLBAR_ROVING,\n MLV_EDITOR_TOOLBAR_REVISION,\n MlvEditorOverlayRegistry,\n MlvEditorToolbarRovingRegistry,\n MlvEditorToolbarRevision,\n type MlvEditorToolbarContext,\n} from '../editor-toolbar-context';\nimport { MlvEditorAlignment } from './editor-alignment';\nimport { MlvEditorBlockInsert } from './editor-block-insert';\nimport { MlvEditorHeading } from './editor-heading';\nimport { MlvEditorHighlight } from './editor-highlight';\nimport { MlvEditorInlineMarks } from './editor-inline-marks';\nimport { MlvEditorList } from './editor-list';\nimport { MlvEditorLink } from './editor-link';\nimport { MlvEditorImageUpload } from './editor-image-upload';\nimport { MlvEditorTable } from './editor-table';\nimport { MlvEditorUndoRedo } from './editor-undo-redo';\nimport { MlvEditorZoom } from './editor-zoom';\nimport { MlvEditorTextColor } from './editor-text-color';\nimport { MlvEditorToolbarWidget } from './editor-toolbar-widget';\n\n/** @internal Named roving-focus root used by editor and compatibility toolbar shells. */\n@Directive({\n selector: '[mlvEditorToolbarRoot]',\n exportAs: 'mlvEditorToolbarRoot',\n host: {\n class: 'mlv-editor-toolbar',\n '[class.mlv-editor-toolbar--narrow]': 'narrow()',\n role: 'toolbar',\n '[attr.aria-label]': 'resolvedAriaLabel()',\n '[attr.aria-orientation]': 'orientation()',\n '[attr.aria-disabled]': 'disabled() || null',\n '(keydown)': 'handleKeydown($event)',\n },\n})\nexport class MlvEditorToolbarRoot {\n /** Whether the toolbar has entered its compact overflow layout. */\n readonly narrow = signal(false);\n /** Accessible toolbar name. */\n readonly ariaLabel = input<string | undefined>(undefined);\n /** Whether the composite toolbar is unavailable. */\n readonly disabled = input<boolean, BooleanInput>(false, {\n transform: coerceBooleanProperty,\n });\n /** Keyboard-navigation axis. */\n readonly orientation = input<'horizontal' | 'vertical'>('horizontal');\n /** Whether arrow navigation wraps at the boundaries. */\n readonly wrap = input<boolean, BooleanInput>(true, {\n transform: coerceBooleanProperty,\n });\n /** @internal Editor-scoped focus registry. */\n private readonly _registry = inject(MLV_EDITOR_TOOLBAR_ROVING);\n /** @internal Transaction state that re-evaluates disabled toolbar widgets. */\n private readonly _revision = inject(MLV_EDITOR_TOOLBAR_REVISION, {\n optional: true,\n });\n /** @internal Optional localized defaults. */\n private readonly _i18n = inject(MLV_EDITOR_I18N, { optional: true });\n /** @internal Actual composite-root element. */\n private readonly _element = inject<ElementRef<HTMLElement>>(ElementRef);\n /** @internal Root teardown lifecycle. */\n private readonly _destroyRef = inject(DestroyRef);\n /** @internal Avoids DOM observers during server rendering. */\n private readonly _isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n /** @internal Shared observer abstraction for responsive width changes. */\n private readonly _resizeObserver = inject(MlvResizeObserverService);\n\n constructor() {\n effect(() => {\n this._revision?.();\n this._registry.setDisabled(this.disabled());\n });\n if (this._isBrowser) {\n this._destroyRef.onDestroy(\n this._registry.connect(this._element.nativeElement),\n );\n this._resizeObserver\n .observe(this._element)\n .pipe(takeUntilDestroyed(this._destroyRef))\n .subscribe((entries) => {\n const width = entries[entries.length - 1]?.contentRect.width;\n if (width !== undefined && width > 0) this.narrow.set(width < 640);\n });\n }\n }\n\n /** @internal Resolves the user or localized toolbar label. */\n protected resolvedAriaLabel(): string {\n return this.ariaLabel() ?? this._i18n?.().toolbarLabel ?? 'Editor toolbar';\n }\n\n /** @internal Handles roving navigation from the host metadata event binding. */\n protected handleKeydown(event: KeyboardEvent): void {\n if (this.disabled()) return;\n const target = event.target instanceof HTMLElement ? event.target : null;\n if (!target) return;\n if (event.key === 'Home' || event.key === 'End') {\n event.preventDefault();\n this._registry.focusBoundary(event.key === 'Home' ? 'start' : 'end');\n return;\n }\n const direction =\n this.orientation() === 'vertical'\n ? event.key === 'ArrowUp'\n ? -1\n : event.key === 'ArrowDown'\n ? 1\n : undefined\n : event.key === 'ArrowLeft'\n ? -1\n : event.key === 'ArrowRight'\n ? 1\n : undefined;\n if (!direction) return;\n event.preventDefault();\n this._registry.move(target, direction, this.wrap());\n }\n}\n\n/** @internal Responsive menu containing commands removed from the primary row. */\n@Component({\n selector: 'mlv-editor-toolbar-overflow',\n imports: [\n MlvButton,\n MlvButtonIcon,\n MlvTooltip,\n LucideEllipsis,\n MlvListItem,\n MlvMenu,\n MlvMenuItem,\n MlvMenuTrigger,\n MlvEditorToolbarWidget,\n ],\n template: `\n <button\n mlvButton\n mlvEditorToolbarWidget\n type=\"button\"\n shape=\"circle\"\n variant=\"transparent\"\n [attr.aria-label]=\"_copy().moreFormatting\"\n [disabled]=\"_context.disabled()\"\n [mlvMenuTrigger]=\"_menu\"\n [menuTriggerDisabled]=\"_context.disabled()\"\n [mlvTooltip]=\"_copy().moreFormatting\"\n (menuOpened)=\"_registerOverlay()\"\n (menuClosed)=\"_unregisterOverlay()\"\n >\n <svg mlvButtonIcon lucideEllipsis aria-hidden=\"true\" />\n </button>\n <mlv-menu #_menu [label]=\"_copy().moreFormatting\">\n @if (_supported('toggleBold')) {\n <mlv-list-item\n mlvMenuItem\n [disabled]=\"_commandDisabled(_canBold)\"\n [attr.aria-current]=\"_context.isActive('bold') ? 'true' : null\"\n (itemClick)=\"_run(_bold)\"\n >{{ _copy().bold }}</mlv-list-item\n >\n }\n @if (_supported('toggleItalic')) {\n <mlv-list-item\n mlvMenuItem\n [disabled]=\"_commandDisabled(_canItalic)\"\n [attr.aria-current]=\"_context.isActive('italic') ? 'true' : null\"\n (itemClick)=\"_run(_italic)\"\n >{{ _copy().italic }}</mlv-list-item\n >\n }\n @if (_supported('toggleStrike')) {\n <mlv-list-item\n mlvMenuItem\n [disabled]=\"_commandDisabled(_canStrike)\"\n [attr.aria-current]=\"_context.isActive('strike') ? 'true' : null\"\n (itemClick)=\"_run(_strike)\"\n >{{ _copy().strike }}</mlv-list-item\n >\n }\n @if (_supported('toggleUnderline')) {\n <mlv-list-item\n mlvMenuItem\n [disabled]=\"_commandDisabled(_canUnderline)\"\n [attr.aria-current]=\"_context.isActive('underline') ? 'true' : null\"\n (itemClick)=\"_run(_underline)\"\n >{{ _copy().underline }}</mlv-list-item\n >\n }\n @if (_supported('setTextAlign')) {\n @for (alignment of _alignments(); track alignment.value) {\n <mlv-list-item\n mlvMenuItem\n [disabled]=\"_commandDisabled(_canAlign(alignment.value))\"\n [attr.aria-current]=\"\n _context.isActive('paragraph', { textAlign: alignment.value })\n ? 'true'\n : null\n \"\n (itemClick)=\"_run(_align(alignment.value))\"\n >{{ alignment.label }}</mlv-list-item\n >\n }\n }\n @if (_supported('toggleBlockquote')) {\n <mlv-list-item\n mlvMenuItem\n [disabled]=\"_commandDisabled(_canBlockquote)\"\n [attr.aria-current]=\"_context.isActive('blockquote') ? 'true' : null\"\n (itemClick)=\"_run(_blockquote)\"\n >{{ _copy().blockquote }}</mlv-list-item\n >\n }\n @if (_supported('toggleCodeBlock')) {\n <mlv-list-item\n mlvMenuItem\n [disabled]=\"_commandDisabled(_canCodeBlock)\"\n [attr.aria-current]=\"_context.isActive('codeBlock') ? 'true' : null\"\n (itemClick)=\"_run(_codeBlock)\"\n >{{ _copy().codeBlock }}</mlv-list-item\n >\n }\n @if (_supported('setHorizontalRule')) {\n <mlv-list-item\n mlvMenuItem\n [disabled]=\"_commandDisabled(_canHorizontalRule)\"\n (itemClick)=\"_run(_horizontalRule)\"\n >{{ _copy().horizontalRule }}</mlv-list-item\n >\n }\n </mlv-menu>\n `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'mlv-editor-toolbar__overflow',\n '[hidden]': '!_root.narrow()',\n },\n})\nexport class MlvEditorToolbarOverflow {\n /** @protected Responsive state owned by the enclosing toolbar root. */\n protected readonly _root = inject(MlvEditorToolbarRoot);\n /** @protected Editor-scoped command state. */\n protected readonly _context = inject(MLV_EDITOR_TOOLBAR_CONTEXT);\n /** @private Command-state invalidation signal. */\n private readonly _revision = inject(MLV_EDITOR_TOOLBAR_REVISION, {\n optional: true,\n });\n /** @private Roving coordinator used to recover focus after wide layout returns. */\n private readonly _roving = inject(MLV_EDITOR_TOOLBAR_ROVING);\n /** @private Detached overlay registry. */\n private readonly _overlays = inject<MlvEditorOverlayRegistry>(\n MLV_EDITOR_OVERLAY_REGISTRY,\n );\n /** @private Document used after a browser menu opens. */\n private readonly _document = inject(DOCUMENT);\n /** @private Teardown scope for a currently open menu. */\n private readonly _destroyRef = inject(DestroyRef);\n /** @private Optional reactive localized editor copy. */\n private readonly _i18n = inject(MLV_EDITOR_I18N, { optional: true });\n /** @protected Rendered overflow menu. */\n protected readonly _menu = viewChild.required<MlvMenu>('_menu');\n /** @protected Trigger that owns the overflow menu. */\n protected readonly _trigger = viewChild.required(MlvMenuTrigger);\n /** @private Current detached-overlay registration. */\n private _unregister: (() => void) | undefined;\n /** @private Guards queued registration after close. */\n private _menuOpen = false;\n /** @private Previous responsive state used to identify a narrow-to-wide edge. */\n private _wasNarrow = false;\n\n /** @protected Formatting order retained when controls move into overflow. */\n protected readonly _alignments = computed(() => [\n { value: 'left', label: this._copy().alignLeft },\n { value: 'center', label: this._copy().alignCenter },\n { value: 'right', label: this._copy().alignRight },\n { value: 'justify', label: this._copy().alignJustify },\n ]);\n /** @protected Reactive localized copy for every overflow command. */\n protected readonly _copy = computed(() => {\n const copy = this._i18n?.();\n return {\n moreFormatting: copy?.moreFormatting ?? 'More formatting',\n bold: copy?.bold ?? 'Bold',\n italic: copy?.italic ?? 'Italic',\n strike: copy?.strike ?? 'Strike-through',\n underline: copy?.underline ?? 'Underline',\n alignLeft: copy?.alignLeft ?? 'Align left',\n alignCenter: copy?.alignCenter ?? 'Align center',\n alignRight: copy?.alignRight ?? 'Align right',\n alignJustify: copy?.alignJustify ?? 'Justify',\n blockquote: copy?.blockquote ?? 'Blockquote',\n codeBlock: copy?.codeBlock ?? 'Code block',\n horizontalRule: copy?.horizontalRule ?? 'Horizontal rule',\n };\n });\n\n /** @protected Bold toggle command. */\n protected readonly _bold = (editor: Editor): boolean =>\n editor.chain().focus().toggleBold().run();\n /** @protected Italic toggle command. */\n protected readonly _italic = (editor: Editor): boolean =>\n editor.chain().focus().toggleItalic().run();\n /** @protected Strike toggle command. */\n protected readonly _strike = (editor: Editor): boolean =>\n editor.chain().focus().toggleStrike().run();\n /** @protected Underline toggle command. */\n protected readonly _underline = (editor: Editor): boolean =>\n editor.chain().focus().toggleUnderline().run();\n /** @protected Blockquote toggle command. */\n protected readonly _blockquote = (editor: Editor): boolean =>\n editor.chain().focus().toggleBlockquote().run();\n /** @protected Code-block toggle command. */\n protected readonly _codeBlock = (editor: Editor): boolean =>\n editor.chain().focus().toggleCodeBlock().run();\n /** @protected Horizontal-rule insertion command. */\n protected readonly _horizontalRule = (editor: Editor): boolean =>\n editor.chain().focus().setHorizontalRule().run();\n /** @protected Non-mutating bold capability check. */\n protected readonly _canBold = (editor: Editor): boolean =>\n editor.can().chain().toggleBold().run();\n /** @protected Non-mutating italic capability check. */\n protected readonly _canItalic = (editor: Editor): boolean =>\n editor.can().chain().toggleItalic().run();\n /** @protected Non-mutating strike capability check. */\n protected readonly _canStrike = (editor: Editor): boolean =>\n editor.can().chain().toggleStrike().run();\n /** @protected Non-mutating underline capability check. */\n protected readonly _canUnderline = (editor: Editor): boolean =>\n editor.can().chain().toggleUnderline().run();\n /** @protected Non-mutating blockquote capability check. */\n protected readonly _canBlockquote = (editor: Editor): boolean =>\n editor.can().chain().toggleBlockquote().run();\n /** @protected Non-mutating code-block capability check. */\n protected readonly _canCodeBlock = (editor: Editor): boolean =>\n editor.can().chain().toggleCodeBlock().run();\n /** @protected Non-mutating horizontal-rule capability check. */\n protected readonly _canHorizontalRule = (editor: Editor): boolean =>\n editor.can().chain().setHorizontalRule().run();\n\n constructor() {\n effect(() => {\n const narrow = this._root.narrow();\n const wasNarrow = this._wasNarrow;\n this._wasNarrow = narrow;\n if (narrow || !wasNarrow || !this._menuOpen) return;\n this._menu().close();\n queueMicrotask(() => this._roving.focusBoundary('start'));\n });\n this._destroyRef.onDestroy(() => this._unregisterOverlay());\n }\n\n /** @protected Whether the active extension set registered a command. */\n protected _supported(command: string): boolean {\n this._revision?.();\n const editor = this._context.editor();\n if (!editor) return false;\n return (\n typeof (editor.commands as unknown as Record<string, unknown>)[\n command\n ] === 'function'\n );\n }\n\n /** @protected Alignment command factory. */\n protected _align(value: string): (editor: Editor) => boolean {\n return (editor) => editor.chain().focus().setTextAlign(value).run();\n }\n\n /** @protected Non-mutating alignment capability factory. */\n protected _canAlign(value: string): (editor: Editor) => boolean {\n return (editor) => editor.can().chain().setTextAlign(value).run();\n }\n\n /** @protected Whether the command is blocked or unsupported. */\n protected _commandDisabled(command: (editor: Editor) => boolean): boolean {\n this._revision?.();\n if (this._context.disabled() || this._context.readonly()) return true;\n try {\n return !this._context.can(command);\n } catch {\n return true;\n }\n }\n\n /** @protected Executes one overflow command through the context guard. */\n protected _run(command: (editor: Editor) => boolean): void {\n this._context.run(command);\n }\n\n /** @protected Registers the detached overflow panel with composite focus. */\n protected _registerOverlay(): void {\n this._menuOpen = true;\n queueMicrotask(() => {\n if (!this._menuOpen) return;\n const panel = this._document.getElementById(this._menu().panelId);\n if (!panel) return;\n this._unregister?.();\n this._unregister = this._overlays.register(panel, () =>\n this._trigger().close(),\n );\n });\n }\n\n /** @protected Releases focus ownership after close. */\n protected _unregisterOverlay(): void {\n this._menuOpen = false;\n this._unregister?.();\n this._unregister = undefined;\n }\n}\n\n/** @internal Defers public-toolbar context reads until Angular has assigned inputs. */\n@Injectable()\nclass MlvEditorToolbarContextProxy implements MlvEditorToolbarContext {\n /** @internal Owning public toolbar component. */\n private readonly _toolbar = inject(MlvEditorToolbar);\n\n /** Editor instance supplied through the public context input. */\n get editor(): Signal<Editor | null> {\n return this._toolbar.context().editor;\n }\n\n /** Disabled state combines the shell input and public context. */\n readonly disabled = computed(\n () => this._toolbar.disabled() || this._toolbar.context().disabled(),\n );\n\n /** Readonly state supplied through the public context input. */\n get readonly(): Signal<boolean> {\n return this._toolbar.context().readonly;\n }\n\n /** Focus state supplied by the public owner context. */\n get focused(): Signal<boolean> {\n return this._toolbar.context().focused;\n }\n\n /** Editable state supplied by the public owner context without shadowing. */\n get editable(): Signal<boolean> {\n return this._toolbar.context().editable;\n }\n\n /** Serialization format supplied through the public context input. */\n get format(): Signal<MlvEditorFormat> {\n return this._toolbar.context().format;\n }\n\n /** View zoom supplied through the public context input. */\n get zoom(): WritableSignal<number> {\n return this._toolbar.context().zoom;\n }\n\n /** Exact editor-owned upload capability supplied through the public context. */\n get imageUpload(): MlvEditorImageUploadControl | undefined {\n return this._toolbar.context().imageUpload;\n }\n\n /** Runs a public-context command. */\n run(command: (editor: Editor) => boolean): boolean {\n return this._toolbar.context().run(command);\n }\n\n /** Checks a public-context command. */\n can(command: (editor: Editor) => boolean): boolean {\n return this._toolbar.context().can(command);\n }\n\n /** Checks active state through the public context. */\n isActive(name: string, attributes?: Record<string, unknown>): boolean {\n return this._toolbar.context().isActive(name, attributes);\n }\n\n /** Reports a typed error through the public owner context. */\n reportError(error: MlvEditorError): void {\n this._toolbar.context().reportError(error);\n }\n}\n\n/** Public compatibility toolbar shell for standalone consumer use. */\n@Component({\n selector: 'mlv-editor-toolbar',\n host: {\n class: 'mlv-editor-toolbar',\n '[class.mlv-editor-toolbar--disabled]':\n 'disabled() || context().disabled()',\n },\n imports: [\n NgTemplateOutlet,\n MlvFade,\n MlvToolbar,\n MlvDivider,\n MlvEditorToolbarRoot,\n MlvEditorUndoRedo,\n MlvEditorZoom,\n MlvEditorHeading,\n MlvEditorList,\n MlvEditorInlineMarks,\n MlvEditorTextColor,\n MlvEditorHighlight,\n MlvEditorLink,\n MlvEditorImageUpload,\n MlvEditorTable,\n MlvEditorAlignment,\n MlvEditorBlockInsert,\n MlvEditorToolbarOverflow,\n ],\n template: `<div\n mlvEditorToolbarRoot\n #toolbarRoot=\"mlvEditorToolbarRoot\"\n [ariaLabel]=\"ariaLabel()\"\n [disabled]=\"disabled() || context().disabled()\"\n >\n <ng-content select=\"[mlvEditorToolbarStart]\" />\n @if (startTemplate(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template\"\n [ngTemplateOutletContext]=\"{ $implicit: context() }\"\n />\n }\n <div mlvFade class=\"mlv-editor-toolbar__scroll\">\n <mlv-toolbar>\n <mlv-editor-undo-redo />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n />\n <mlv-editor-zoom />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n />\n <mlv-editor-heading />\n <mlv-editor-list />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-inline-marks [hidden]=\"toolbarRoot.narrow()\" />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-text-color />\n <mlv-editor-highlight />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-alignment [hidden]=\"toolbarRoot.narrow()\" />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-link />\n <mlv-editor-table />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-block-insert [hidden]=\"toolbarRoot.narrow()\" />\n <mlv-divider\n class=\"mlv-editor-toolbar__separator\"\n orientation=\"vertical\"\n muted\n [hidden]=\"toolbarRoot.narrow()\"\n />\n <mlv-editor-image-upload />\n </mlv-toolbar>\n </div>\n <mlv-editor-toolbar-overflow />\n @if (endTemplate(); as template) {\n <ng-container\n [ngTemplateOutlet]=\"template\"\n [ngTemplateOutletContext]=\"{ $implicit: context() }\"\n />\n }\n <ng-content select=\"[mlvEditorToolbarEnd]\" /><ng-content />\n </div>`,\n styleUrl: './editor-toolbar.scss',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [\n MlvEditorOverlayRegistry,\n MlvEditorToolbarRevision,\n MlvEditorToolbarRovingRegistry,\n MlvEditorToolbarContextProxy,\n {\n provide: MLV_EDITOR_OVERLAY_REGISTRY,\n useExisting: MlvEditorOverlayRegistry,\n },\n {\n provide: MLV_EDITOR_TOOLBAR_CONTEXT,\n useExisting: MlvEditorToolbarContextProxy,\n },\n {\n provide: MLV_EDITOR_TOOLBAR_REVISION,\n useFactory: (state: MlvEditorToolbarRevision) => state.revision,\n deps: [MlvEditorToolbarRevision],\n },\n {\n provide: MLV_EDITOR_TOOLBAR_ROVING,\n useExisting: MlvEditorToolbarRovingRegistry,\n },\n ],\n})\nexport class MlvEditorToolbar {\n /** Accessible toolbar name. */\n readonly ariaLabel = input<string | undefined>(undefined);\n /** Whether all toolbar interactions are disabled. */\n readonly disabled = input<boolean, BooleanInput>(false, {\n transform: coerceBooleanProperty,\n });\n /** Optional content rendered before built-in groups. */\n readonly startTemplate = input<TemplateRef<{\n $implicit: MlvEditorToolbarContext;\n }> | null>(null);\n /** Optional content rendered after built-in groups. */\n readonly endTemplate = input<TemplateRef<{\n $implicit: MlvEditorToolbarContext;\n }> | null>(null);\n /** Context supplied to custom toolbar templates. */\n readonly context = input.required<MlvEditorToolbarContext>();\n\n /** @internal Invalidates built-in command state for the supplied standalone editor. */\n private readonly _revision = inject(MlvEditorToolbarRevision);\n\n constructor() {\n effect((onCleanup) => {\n const editor = this.context().editor();\n this._revision.revision.update((revision) => revision + 1);\n if (!editor) return;\n const invalidate = (): void =>\n this._revision.revision.update((revision) => revision + 1);\n editor.on('transaction', invalidate);\n editor.on('selectionUpdate', invalidate);\n onCleanup(() => {\n editor.off('transaction', invalidate);\n editor.off('selectionUpdate', invalidate);\n });\n });\n }\n}\n"]}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { ChangeDetectionStrategy, Component, computed, inject, ViewEncapsulation, } from '@angular/core';
|
|
2
|
-
import { LucideRedo2, LucideUndo2 } from '@lucide/angular';
|
|
3
|
-
import { MLV_EDITOR_I18N } from '@malva-ui/i18n';
|
|
4
|
-
import { MlvEditorCommandButton } from './editor-command-button';
|
|
5
|
-
import * as i0 from "@angular/core";
|
|
6
|
-
/** Undo and redo actions backed by Tiptap history commands. */
|
|
7
|
-
export class MlvEditorUndoRedo {
|
|
8
|
-
/** @private Optional localized editor copy. */
|
|
9
|
-
_i18n = inject(MLV_EDITOR_I18N, { optional: true });
|
|
10
|
-
/** @protected Resolved copy with SSR-safe English fallbacks. */
|
|
11
|
-
_copy = computed(() => ({
|
|
12
|
-
undo: this._i18n?.().undo ?? 'Undo',
|
|
13
|
-
redo: this._i18n?.().redo ?? 'Redo',
|
|
14
|
-
}), /* @ts-ignore */
|
|
15
|
-
...(ngDevMode ? [{ debugName: "_copy" }] : /* istanbul ignore next */ []));
|
|
16
|
-
/** @protected Tiptap availability query for undo. */
|
|
17
|
-
_canUndo = (editor) => editor.commands.undo !== undefined;
|
|
18
|
-
/** @protected Tiptap availability query for redo. */
|
|
19
|
-
_canRedo = (editor) => editor.commands.redo !== undefined;
|
|
20
|
-
/** @protected Current history availability for undo. */
|
|
21
|
-
_canExecuteUndo = (editor) => editor.can().undo();
|
|
22
|
-
/** @protected Current history availability for redo. */
|
|
23
|
-
_canExecuteRedo = (editor) => editor.can().redo();
|
|
24
|
-
/** @protected Selection-restoring undo command. */
|
|
25
|
-
_undo = (editor) => editor.chain().focus().undo().run();
|
|
26
|
-
/** @protected Selection-restoring redo command. */
|
|
27
|
-
_redo = (editor) => editor.chain().focus().redo().run();
|
|
28
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvEditorUndoRedo, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
29
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.7", type: MlvEditorUndoRedo, isStandalone: true, selector: "mlv-editor-undo-redo", host: { attributes: { "role": "group" }, classAttribute: "mlv-editor-undo-redo" }, ngImport: i0, template: `
|
|
30
|
-
<mlv-editor-command-button
|
|
31
|
-
[label]="_copy().undo"
|
|
32
|
-
[supports]="_canUndo"
|
|
33
|
-
[canCommand]="_canExecuteUndo"
|
|
34
|
-
[command]="_undo"
|
|
35
|
-
><svg lucideUndo2
|
|
36
|
-
/></mlv-editor-command-button>
|
|
37
|
-
<mlv-editor-command-button
|
|
38
|
-
[label]="_copy().redo"
|
|
39
|
-
[supports]="_canRedo"
|
|
40
|
-
[canCommand]="_canExecuteRedo"
|
|
41
|
-
[command]="_redo"
|
|
42
|
-
><svg lucideRedo2
|
|
43
|
-
/></mlv-editor-command-button>
|
|
44
|
-
`, isInline: true, dependencies: [{ kind: "component", type: MlvEditorCommandButton, selector: "mlv-editor-command-button", inputs: ["label", "supports", "command", "canCommand", "pressed"] }, { kind: "component", type: LucideRedo2, selector: "svg[lucideRedo2]" }, { kind: "component", type: LucideUndo2, selector: "svg[lucideUndo2]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
45
|
-
}
|
|
46
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvEditorUndoRedo, decorators: [{
|
|
47
|
-
type: Component,
|
|
48
|
-
args: [{
|
|
49
|
-
selector: 'mlv-editor-undo-redo',
|
|
50
|
-
imports: [MlvEditorCommandButton, LucideRedo2, LucideUndo2],
|
|
51
|
-
template: `
|
|
52
|
-
<mlv-editor-command-button
|
|
53
|
-
[label]="_copy().undo"
|
|
54
|
-
[supports]="_canUndo"
|
|
55
|
-
[canCommand]="_canExecuteUndo"
|
|
56
|
-
[command]="_undo"
|
|
57
|
-
><svg lucideUndo2
|
|
58
|
-
/></mlv-editor-command-button>
|
|
59
|
-
<mlv-editor-command-button
|
|
60
|
-
[label]="_copy().redo"
|
|
61
|
-
[supports]="_canRedo"
|
|
62
|
-
[canCommand]="_canExecuteRedo"
|
|
63
|
-
[command]="_redo"
|
|
64
|
-
><svg lucideRedo2
|
|
65
|
-
/></mlv-editor-command-button>
|
|
66
|
-
`,
|
|
67
|
-
encapsulation: ViewEncapsulation.None,
|
|
68
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
69
|
-
host: { class: 'mlv-editor-undo-redo', role: 'group' },
|
|
70
|
-
}]
|
|
71
|
-
}] });
|
|
72
|
-
//# sourceMappingURL=editor-undo-redo.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"editor-undo-redo.js","sourceRoot":"","sources":["../../../../../../libs/editor/src/lib/toolbar/editor-undo-redo.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,SAAS,EACT,QAAQ,EACR,MAAM,EACN,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;;AAEjE,+DAA+D;AAwB/D,MAAM,OAAO,iBAAiB;IAC5B,+CAA+C;IAC9B,KAAK,GAAG,MAAM,CAAC,eAAe,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IAErE,gEAAgE;IAC7C,KAAK,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;QACzC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,IAAI,MAAM;QACnC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,IAAI,MAAM;KACpC,CAAC;8EAAC,CAAC;IAEJ,qDAAqD;IAClC,QAAQ,GAAG,CAAC,MAAc,EAAW,EAAE,CACxD,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,CAAC;IACrC,qDAAqD;IAClC,QAAQ,GAAG,CAAC,MAAc,EAAW,EAAE,CACxD,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,CAAC;IACrC,wDAAwD;IACrC,eAAe,GAAG,CAAC,MAAc,EAAW,EAAE,CAC/D,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;IACtB,wDAAwD;IACrC,eAAe,GAAG,CAAC,MAAc,EAAW,EAAE,CAC/D,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;IACtB,mDAAmD;IAChC,KAAK,GAAG,CAAC,MAAc,EAAW,EAAE,CACrD,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC;IACtC,mDAAmD;IAChC,KAAK,GAAG,CAAC,MAAc,EAAW,EAAE,CACrD,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC;uGA3B3B,iBAAiB;2FAAjB,iBAAiB,mKApBlB;;;;;;;;;;;;;;;GAeT,4DAhBS,sBAAsB,yIAAE,WAAW,6DAAE,WAAW;;2FAqB/C,iBAAiB;kBAvB7B,SAAS;mBAAC;oBACT,QAAQ,EAAE,sBAAsB;oBAChC,OAAO,EAAE,CAAC,sBAAsB,EAAE,WAAW,EAAE,WAAW,CAAC;oBAC3D,QAAQ,EAAE;;;;;;;;;;;;;;;GAeT;oBACD,aAAa,EAAE,iBAAiB,CAAC,IAAI;oBACrC,eAAe,EAAE,uBAAuB,CAAC,MAAM;oBAC/C,IAAI,EAAE,EAAE,KAAK,EAAE,sBAAsB,EAAE,IAAI,EAAE,OAAO,EAAE;iBACvD","sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n inject,\n ViewEncapsulation,\n} from '@angular/core';\nimport type { Editor } from '@tiptap/core';\nimport { LucideRedo2, LucideUndo2 } from '@lucide/angular';\nimport { MLV_EDITOR_I18N } from '@malva-ui/i18n';\nimport { MlvEditorCommandButton } from './editor-command-button';\n\n/** Undo and redo actions backed by Tiptap history commands. */\n@Component({\n selector: 'mlv-editor-undo-redo',\n imports: [MlvEditorCommandButton, LucideRedo2, LucideUndo2],\n template: `\n <mlv-editor-command-button\n [label]=\"_copy().undo\"\n [supports]=\"_canUndo\"\n [canCommand]=\"_canExecuteUndo\"\n [command]=\"_undo\"\n ><svg lucideUndo2\n /></mlv-editor-command-button>\n <mlv-editor-command-button\n [label]=\"_copy().redo\"\n [supports]=\"_canRedo\"\n [canCommand]=\"_canExecuteRedo\"\n [command]=\"_redo\"\n ><svg lucideRedo2\n /></mlv-editor-command-button>\n `,\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: { class: 'mlv-editor-undo-redo', role: 'group' },\n})\nexport class MlvEditorUndoRedo {\n /** @private Optional localized editor copy. */\n private readonly _i18n = inject(MLV_EDITOR_I18N, { optional: true });\n\n /** @protected Resolved copy with SSR-safe English fallbacks. */\n protected readonly _copy = computed(() => ({\n undo: this._i18n?.().undo ?? 'Undo',\n redo: this._i18n?.().redo ?? 'Redo',\n }));\n\n /** @protected Tiptap availability query for undo. */\n protected readonly _canUndo = (editor: Editor): boolean =>\n editor.commands.undo !== undefined;\n /** @protected Tiptap availability query for redo. */\n protected readonly _canRedo = (editor: Editor): boolean =>\n editor.commands.redo !== undefined;\n /** @protected Current history availability for undo. */\n protected readonly _canExecuteUndo = (editor: Editor): boolean =>\n editor.can().undo();\n /** @protected Current history availability for redo. */\n protected readonly _canExecuteRedo = (editor: Editor): boolean =>\n editor.can().redo();\n /** @protected Selection-restoring undo command. */\n protected readonly _undo = (editor: Editor): boolean =>\n editor.chain().focus().undo().run();\n /** @protected Selection-restoring redo command. */\n protected readonly _redo = (editor: Editor): boolean =>\n editor.chain().focus().redo().run();\n}\n"]}
|
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
|
2
|
-
import { DOCUMENT, isPlatformBrowser } from '@angular/common';
|
|
3
|
-
import { ChangeDetectionStrategy, Component, computed, DestroyRef, ElementRef, effect, inject, input, model, PLATFORM_ID, signal, untracked, ViewEncapsulation, viewChild, } from '@angular/core';
|
|
4
|
-
import { LucideZoomIn, LucideZoomOut } from '@lucide/angular';
|
|
5
|
-
import { mlvNextId, MlvResizeObserverService } from '@malva-ui/cdk/utils';
|
|
6
|
-
import { MlvButton, MlvButtonIcon } from '@malva-ui/core/button';
|
|
7
|
-
import { MlvInput } from '@malva-ui/core/input';
|
|
8
|
-
import { MlvPopup, MlvPopupContent, MlvPopupTrigger, } from '@malva-ui/core/popup';
|
|
9
|
-
import { MLV_EDITOR_I18N } from '@malva-ui/i18n';
|
|
10
|
-
import { MlvTooltip } from '@malva-ui/core/tooltip';
|
|
11
|
-
import { MLV_EDITOR_OVERLAY_REGISTRY, MLV_EDITOR_TOOLBAR_CONTEXT, } from '../editor-toolbar-context';
|
|
12
|
-
import { MlvEditorToolbarWidget } from './editor-toolbar-widget';
|
|
13
|
-
import * as i0 from "@angular/core";
|
|
14
|
-
const DEFAULT_ZOOM = 100;
|
|
15
|
-
/** View-only editor zoom stepper and preset menu. */
|
|
16
|
-
export class MlvEditorZoom {
|
|
17
|
-
/** Current view-only zoom percentage. */
|
|
18
|
-
zoom = model(100, /* @ts-ignore */
|
|
19
|
-
...(ngDevMode ? [{ debugName: "zoom" }] : /* istanbul ignore next */ []));
|
|
20
|
-
/** Preset percentages displayed by the zoom menu. */
|
|
21
|
-
zoomLevels = input([
|
|
22
|
-
40, 50, 75, 90, 100, 125, 150, 175, 200,
|
|
23
|
-
], /* @ts-ignore */
|
|
24
|
-
...(ngDevMode ? [{ debugName: "zoomLevels" }] : /* istanbul ignore next */ []));
|
|
25
|
-
/** Smallest permitted zoom percentage. */
|
|
26
|
-
min = input(40, /* @ts-ignore */
|
|
27
|
-
...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
|
|
28
|
-
/** Largest permitted zoom percentage. */
|
|
29
|
-
max = input(200, /* @ts-ignore */
|
|
30
|
-
...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
31
|
-
/** Recalculates the largest safe zoom whenever the content viewport resizes. */
|
|
32
|
-
fitToContainer = input(false, { ...(ngDevMode ? { debugName: "fitToContainer" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
|
|
33
|
-
/** @protected Editor-scoped view and command state. */
|
|
34
|
-
_context = inject(MLV_EDITOR_TOOLBAR_CONTEXT);
|
|
35
|
-
/** @private Shared observer abstraction for the editor viewport. */
|
|
36
|
-
_resizeObserver = inject(MlvResizeObserverService);
|
|
37
|
-
/** @private Component host used to retain a stable focus-restore target. */
|
|
38
|
-
_host = inject(ElementRef);
|
|
39
|
-
/** @private Registry that keeps focus within the editor composite. */
|
|
40
|
-
_overlays = inject(MLV_EDITOR_OVERLAY_REGISTRY);
|
|
41
|
-
/** @private Document used only after a browser menu opens. */
|
|
42
|
-
_document = inject(DOCUMENT);
|
|
43
|
-
/** @private Component teardown scope. */
|
|
44
|
-
_destroyRef = inject(DestroyRef);
|
|
45
|
-
/** @private Prevents browser view access during server rendering. */
|
|
46
|
-
_isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
|
|
47
|
-
/** @private Optional reactive localized editor copy. */
|
|
48
|
-
_i18n = inject(MLV_EDITOR_I18N, { optional: true });
|
|
49
|
-
/** @protected Rendered mixed-control popup. */
|
|
50
|
-
_popup = viewChild.required('_popup', /* @ts-ignore */
|
|
51
|
-
...(ngDevMode ? [{ debugName: "_popup" }] : /* istanbul ignore next */ []));
|
|
52
|
-
/** @protected Trigger that owns the detached popup. */
|
|
53
|
-
_trigger = viewChild.required('_trigger', /* @ts-ignore */
|
|
54
|
-
...(ngDevMode ? [{ debugName: "_trigger" }] : /* istanbul ignore next */ []));
|
|
55
|
-
/** @protected Percentage field focused when the popup opens. */
|
|
56
|
-
_input = viewChild.required('_input', /* @ts-ignore */
|
|
57
|
-
...(ngDevMode ? [{ debugName: "_input" }] : /* istanbul ignore next */ []));
|
|
58
|
-
/** @protected Stable id used to resolve this component's detached panel. */
|
|
59
|
-
_panelId = mlvNextId('mlv-editor-zoom-panel');
|
|
60
|
-
/** @private Last synchronized model value. */
|
|
61
|
-
_lastZoom = DEFAULT_ZOOM;
|
|
62
|
-
/** @private Last synchronized editor-context value. */
|
|
63
|
-
_lastContextZoom = DEFAULT_ZOOM;
|
|
64
|
-
/** @private Distinguishes initial context adoption from later writes. */
|
|
65
|
-
_initialized = false;
|
|
66
|
-
/** @private Whether Angular assigned the public model, including an explicit default. */
|
|
67
|
-
_zoomWasSupplied = false;
|
|
68
|
-
/** @private Current detached-popup registration teardown. */
|
|
69
|
-
_unregister;
|
|
70
|
-
/** @private Guards a queued popup registration after close or destroy. */
|
|
71
|
-
_menuOpen = false;
|
|
72
|
-
/** @private Connected trigger retained while the popup is open. */
|
|
73
|
-
_restoreFocusTarget;
|
|
74
|
-
/** @protected Numeric field draft kept separate until commit. */
|
|
75
|
-
_draft = signal(String(DEFAULT_ZOOM), /* @ts-ignore */
|
|
76
|
-
...(ngDevMode ? [{ debugName: "_draft" }] : /* istanbul ignore next */ []));
|
|
77
|
-
/** @protected Normalized inclusive zoom bounds. */
|
|
78
|
-
_bounds = computed(() => {
|
|
79
|
-
const first = Number.isFinite(this.min())
|
|
80
|
-
? Math.max(1, this.min())
|
|
81
|
-
: DEFAULT_ZOOM;
|
|
82
|
-
const second = Number.isFinite(this.max())
|
|
83
|
-
? Math.max(1, this.max())
|
|
84
|
-
: DEFAULT_ZOOM;
|
|
85
|
-
return {
|
|
86
|
-
min: Math.min(first, second),
|
|
87
|
-
max: Math.max(first, second),
|
|
88
|
-
};
|
|
89
|
-
}, /* @ts-ignore */
|
|
90
|
-
...(ngDevMode ? [{ debugName: "_bounds" }] : /* istanbul ignore next */ []));
|
|
91
|
-
/** @protected Finite, in-range, sorted menu presets. */
|
|
92
|
-
_presetLevels = computed(() => {
|
|
93
|
-
const { min, max } = this._bounds();
|
|
94
|
-
return [...new Set(this.zoomLevels())]
|
|
95
|
-
.filter((level) => Number.isFinite(level) && level >= min && level <= max)
|
|
96
|
-
.sort((left, right) => left - right);
|
|
97
|
-
}, /* @ts-ignore */
|
|
98
|
-
...(ngDevMode ? [{ debugName: "_presetLevels" }] : /* istanbul ignore next */ []));
|
|
99
|
-
/** @protected Whether the complete editor composite is disabled. */
|
|
100
|
-
_disabled = computed(() => this._context.disabled(), /* @ts-ignore */
|
|
101
|
-
...(ngDevMode ? [{ debugName: "_disabled" }] : /* istanbul ignore next */ []));
|
|
102
|
-
/** @protected Reactive localized labels for every zoom surface. */
|
|
103
|
-
_copy = computed(() => {
|
|
104
|
-
const zoom = this._i18n?.().zoom ?? 'Zoom';
|
|
105
|
-
return {
|
|
106
|
-
zoom,
|
|
107
|
-
zoomOut: `${zoom} −`,
|
|
108
|
-
zoomIn: `${zoom} +`,
|
|
109
|
-
fitToContainer: this._i18n?.().fitToContainer ?? 'Fit to container',
|
|
110
|
-
};
|
|
111
|
-
}, /* @ts-ignore */
|
|
112
|
-
...(ngDevMode ? [{ debugName: "_copy" }] : /* istanbul ignore next */ []));
|
|
113
|
-
/** @protected Whether decrementing would exceed the lower bound. */
|
|
114
|
-
_zoomOutDisabled = computed(() => this._disabled() || this.zoom() <= this._bounds().min, /* @ts-ignore */
|
|
115
|
-
...(ngDevMode ? [{ debugName: "_zoomOutDisabled" }] : /* istanbul ignore next */ []));
|
|
116
|
-
/** @protected Whether incrementing would exceed the upper bound. */
|
|
117
|
-
_zoomInDisabled = computed(() => this._disabled() || this.zoom() >= this._bounds().max, /* @ts-ignore */
|
|
118
|
-
...(ngDevMode ? [{ debugName: "_zoomInDisabled" }] : /* istanbul ignore next */ []));
|
|
119
|
-
constructor() {
|
|
120
|
-
effect(() => this._synchronizeZoom());
|
|
121
|
-
effect(() => this._draft.set(String(this.zoom())));
|
|
122
|
-
effect((onCleanup) => {
|
|
123
|
-
const enabled = this.fitToContainer();
|
|
124
|
-
const editor = this._context.editor();
|
|
125
|
-
if (!enabled || !this._isBrowser || !editor)
|
|
126
|
-
return;
|
|
127
|
-
const viewport = editor.view.dom.closest('.mlv-editor__viewport');
|
|
128
|
-
if (!viewport)
|
|
129
|
-
return;
|
|
130
|
-
const subscription = this._resizeObserver
|
|
131
|
-
.observe(viewport)
|
|
132
|
-
.subscribe((entries) => {
|
|
133
|
-
const width = entries[entries.length - 1]?.contentRect.width;
|
|
134
|
-
if (width !== undefined)
|
|
135
|
-
this._fit(width);
|
|
136
|
-
});
|
|
137
|
-
this._fit(viewport.getBoundingClientRect().width);
|
|
138
|
-
onCleanup(() => subscription.unsubscribe());
|
|
139
|
-
});
|
|
140
|
-
this._destroyRef.onDestroy(() => this._releaseOverlay());
|
|
141
|
-
}
|
|
142
|
-
ngOnChanges(changes) {
|
|
143
|
-
if (changes['zoom'])
|
|
144
|
-
this._zoomWasSupplied = true;
|
|
145
|
-
}
|
|
146
|
-
/** @protected Selects the previous preset or the exact minimum. */
|
|
147
|
-
_zoomOut() {
|
|
148
|
-
if (this._disabled())
|
|
149
|
-
return;
|
|
150
|
-
const current = this.zoom();
|
|
151
|
-
const previous = this._steps().filter((level) => level < current);
|
|
152
|
-
const target = previous[previous.length - 1];
|
|
153
|
-
this._setZoom(target ?? this._bounds().min);
|
|
154
|
-
}
|
|
155
|
-
/** @protected Selects the next preset or the exact maximum. */
|
|
156
|
-
_zoomIn() {
|
|
157
|
-
if (this._disabled())
|
|
158
|
-
return;
|
|
159
|
-
const current = this.zoom();
|
|
160
|
-
const target = this._steps().find((level) => level > current);
|
|
161
|
-
this._setZoom(target ?? this._bounds().max);
|
|
162
|
-
}
|
|
163
|
-
/** @protected Applies a menu preset without dispatching an editor transaction. */
|
|
164
|
-
_select(level) {
|
|
165
|
-
if (this._disabled())
|
|
166
|
-
return;
|
|
167
|
-
this._setZoom(level);
|
|
168
|
-
this._trigger().close();
|
|
169
|
-
}
|
|
170
|
-
/** @protected Commits a finite numeric field value and restores the normalized display. */
|
|
171
|
-
_applyDraft(event) {
|
|
172
|
-
event?.preventDefault();
|
|
173
|
-
event?.stopPropagation();
|
|
174
|
-
if (this._disabled()) {
|
|
175
|
-
this._draft.set(String(this.zoom()));
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
const parsed = Number(this._draft());
|
|
179
|
-
if (Number.isFinite(parsed))
|
|
180
|
-
this._setZoom(parsed);
|
|
181
|
-
this._draft.set(String(this.zoom()));
|
|
182
|
-
}
|
|
183
|
-
/** @protected Fits against the viewport's latest synchronous width. */
|
|
184
|
-
_fitCurrentViewport() {
|
|
185
|
-
if (this._disabled())
|
|
186
|
-
return;
|
|
187
|
-
const viewport = this._context
|
|
188
|
-
.editor()
|
|
189
|
-
?.view.dom.closest('.mlv-editor__viewport');
|
|
190
|
-
if (viewport) {
|
|
191
|
-
this._fit(viewport.clientWidth || viewport.getBoundingClientRect().width);
|
|
192
|
-
this._trigger().close();
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
/** @protected Registers the detached dialog and moves focus to its field. */
|
|
196
|
-
_onPopupOpened() {
|
|
197
|
-
this._menuOpen = true;
|
|
198
|
-
this._restoreFocusTarget =
|
|
199
|
-
this._host.nativeElement.querySelector('button[aria-haspopup="dialog"]') ?? undefined;
|
|
200
|
-
queueMicrotask(() => {
|
|
201
|
-
if (!this._menuOpen)
|
|
202
|
-
return;
|
|
203
|
-
const content = this._document.getElementById(this._panelId);
|
|
204
|
-
const panel = content?.closest('.mlv-popup');
|
|
205
|
-
if (!panel)
|
|
206
|
-
return;
|
|
207
|
-
this._unregister?.();
|
|
208
|
-
this._unregister = this._overlays.register(panel, () => this._trigger().close());
|
|
209
|
-
this._input().focus();
|
|
210
|
-
this._input().select();
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
/** @protected Releases focus ownership and restores the visible trigger. */
|
|
214
|
-
_onPopupClosed() {
|
|
215
|
-
const trigger = this._restoreFocusTarget;
|
|
216
|
-
this._releaseOverlay();
|
|
217
|
-
if (!this._disabled() && trigger?.isConnected)
|
|
218
|
-
trigger.focus();
|
|
219
|
-
}
|
|
220
|
-
/** @private Removes detached popup focus ownership without moving focus. */
|
|
221
|
-
_releaseOverlay() {
|
|
222
|
-
this._menuOpen = false;
|
|
223
|
-
this._restoreFocusTarget = undefined;
|
|
224
|
-
this._unregister?.();
|
|
225
|
-
this._unregister = undefined;
|
|
226
|
-
}
|
|
227
|
-
/** @private Synchronizes the literal public model with the nearest toolbar context. */
|
|
228
|
-
_synchronizeZoom() {
|
|
229
|
-
const modelValue = this.zoom();
|
|
230
|
-
const contextValue = this._context.zoom();
|
|
231
|
-
const modelChanged = modelValue !== this._lastZoom;
|
|
232
|
-
const contextChanged = contextValue !== this._lastContextZoom;
|
|
233
|
-
let next;
|
|
234
|
-
if (!this._initialized) {
|
|
235
|
-
next =
|
|
236
|
-
this._zoomWasSupplied ||
|
|
237
|
-
modelValue !== DEFAULT_ZOOM ||
|
|
238
|
-
contextValue === DEFAULT_ZOOM
|
|
239
|
-
? this._clamp(modelValue)
|
|
240
|
-
: this._clamp(contextValue);
|
|
241
|
-
this._initialized = true;
|
|
242
|
-
}
|
|
243
|
-
else if (modelChanged || modelValue !== this._clamp(modelValue)) {
|
|
244
|
-
next = this._clamp(modelValue);
|
|
245
|
-
}
|
|
246
|
-
else if (contextChanged || contextValue !== this._clamp(contextValue)) {
|
|
247
|
-
next = this._clamp(contextValue);
|
|
248
|
-
}
|
|
249
|
-
else {
|
|
250
|
-
next = this._clamp(modelValue);
|
|
251
|
-
}
|
|
252
|
-
this._lastZoom = next;
|
|
253
|
-
this._lastContextZoom = next;
|
|
254
|
-
if (this.zoom() !== next)
|
|
255
|
-
this.zoom.set(next);
|
|
256
|
-
if (this._context.zoom() !== next)
|
|
257
|
-
this._context.zoom.set(next);
|
|
258
|
-
}
|
|
259
|
-
/** @private Ordered stepping levels, including exact configured bounds. */
|
|
260
|
-
_steps() {
|
|
261
|
-
const { min, max } = this._bounds();
|
|
262
|
-
return [...new Set([min, ...this._presetLevels(), max])].sort((left, right) => left - right);
|
|
263
|
-
}
|
|
264
|
-
/** @private Applies a clamped visual-only percentage to model and context. */
|
|
265
|
-
_setZoom(value) {
|
|
266
|
-
const next = this._clamp(value);
|
|
267
|
-
this._lastZoom = next;
|
|
268
|
-
this._lastContextZoom = next;
|
|
269
|
-
this.zoom.set(next);
|
|
270
|
-
this._context.zoom.set(next);
|
|
271
|
-
}
|
|
272
|
-
/** @private Calculates the largest integer zoom whose natural content fits. */
|
|
273
|
-
_fit(containerWidth) {
|
|
274
|
-
if (this._disabled())
|
|
275
|
-
return;
|
|
276
|
-
const viewport = this._context
|
|
277
|
-
.editor()
|
|
278
|
-
?.view.dom.closest('.mlv-editor__viewport');
|
|
279
|
-
const view = viewport?.querySelector('.mlv-editor__view');
|
|
280
|
-
if (!viewport || !view)
|
|
281
|
-
return;
|
|
282
|
-
const viewportWidths = [
|
|
283
|
-
containerWidth,
|
|
284
|
-
viewport.clientWidth,
|
|
285
|
-
viewport.getBoundingClientRect().width,
|
|
286
|
-
].filter((width) => Number.isFinite(width) && width > 0);
|
|
287
|
-
const availableWidth = Math.min(...viewportWidths);
|
|
288
|
-
const currentScale = untracked(this.zoom) / 100;
|
|
289
|
-
const transformedWidth = view.getBoundingClientRect().width;
|
|
290
|
-
const naturalWidth = Math.max(view.scrollWidth, currentScale > 0 ? transformedWidth / currentScale : 0);
|
|
291
|
-
if (!Number.isFinite(availableWidth) ||
|
|
292
|
-
!Number.isFinite(naturalWidth) ||
|
|
293
|
-
availableWidth <= 0 ||
|
|
294
|
-
naturalWidth <= 0) {
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
const { min, max } = this._bounds();
|
|
298
|
-
let next = Math.min(max, Math.max(min, Math.floor((availableWidth / naturalWidth) * 100)));
|
|
299
|
-
while (next > min && (naturalWidth * next) / 100 > availableWidth) {
|
|
300
|
-
next -= 1;
|
|
301
|
-
}
|
|
302
|
-
this._setZoom(next);
|
|
303
|
-
}
|
|
304
|
-
/** @private Clamps a finite percentage to the configured inclusive bounds. */
|
|
305
|
-
_clamp(value) {
|
|
306
|
-
const { min, max } = this._bounds();
|
|
307
|
-
const finite = Number.isFinite(value) ? value : DEFAULT_ZOOM;
|
|
308
|
-
return Math.min(Math.max(finite, min), max);
|
|
309
|
-
}
|
|
310
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvEditorZoom, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
311
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.7", type: MlvEditorZoom, isStandalone: true, selector: "mlv-editor-zoom", inputs: { zoom: { classPropertyName: "zoom", publicName: "zoom", isSignal: true, isRequired: false, transformFunction: null }, zoomLevels: { classPropertyName: "zoomLevels", publicName: "zoomLevels", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, fitToContainer: { classPropertyName: "fitToContainer", publicName: "fitToContainer", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zoom: "zoomChange" }, host: { classAttribute: "mlv-editor-zoom" }, viewQueries: [{ propertyName: "_popup", first: true, predicate: ["_popup"], descendants: true, isSignal: true }, { propertyName: "_trigger", first: true, predicate: ["_trigger"], descendants: true, isSignal: true }, { propertyName: "_input", first: true, predicate: ["_input"], descendants: true, isSignal: true }], usesOnChanges: true, ngImport: i0, template: "<button\n mlvButton\n mlvEditorToolbarWidget\n type=\"button\"\n shape=\"square\"\n mlvDensity=\"tight\"\n variant=\"transparent\"\n [disabled]=\"_zoomOutDisabled()\"\n [attr.aria-label]=\"_copy().zoomOut\"\n [mlvTooltip]=\"_copy().zoomOut\"\n (click)=\"_zoomOut()\"\n>\n <svg mlvButtonIcon lucideZoomOut aria-hidden=\"true\" />\n</button>\n\n<button\n #_trigger=\"mlvPopupTrigger\"\n mlvButton\n mlvEditorToolbarWidget\n type=\"button\"\n mlvDensity=\"tight\"\n variant=\"transparent\"\n [disabled]=\"_disabled()\"\n [mlvPopupTrigger]=\"_popup\"\n [ariaHasPopup]=\"'dialog'\"\n [attr.aria-label]=\"_copy().zoom\"\n [mlvTooltip]=\"_copy().zoom\"\n>\n {{ zoom() }}%\n</button>\n\n<button\n mlvButton\n mlvEditorToolbarWidget\n type=\"button\"\n shape=\"square\"\n mlvDensity=\"tight\"\n variant=\"transparent\"\n [disabled]=\"_zoomInDisabled()\"\n [attr.aria-label]=\"_copy().zoomIn\"\n [mlvTooltip]=\"_copy().zoomIn\"\n (click)=\"_zoomIn()\"\n>\n <svg mlvButtonIcon lucideZoomIn aria-hidden=\"true\" />\n</button>\n\n<mlv-popup\n #_popup\n panelRole=\"dialog\"\n [modal]=\"true\"\n [ariaLabel]=\"_copy().zoom\"\n (afterOpened)=\"_onPopupOpened()\"\n (afterClosed)=\"_onPopupClosed()\"\n>\n <ng-template mlvPopupContent>\n <div [id]=\"_panelId\" class=\"mlv-editor-zoom__panel\">\n <div class=\"mlv-editor-zoom__field\">\n <mlv-input\n #_input\n bare\n type=\"number\"\n inputMode=\"numeric\"\n [ariaLabel]=\"_copy().zoom\"\n [min]=\"_bounds().min\"\n [max]=\"_bounds().max\"\n [disabled]=\"_disabled()\"\n [value]=\"_draft()\"\n (valueChange)=\"_draft.set($event)\"\n (keydown.enter)=\"_applyDraft($event)\"\n (inputBlur)=\"_applyDraft()\"\n />\n </div>\n <div\n class=\"mlv-editor-zoom__presets\"\n role=\"group\"\n [attr.aria-label]=\"_copy().zoom\"\n >\n @for (level of _presetLevels(); track level) {\n <button\n mlvButton\n class=\"mlv-editor-zoom__preset\"\n type=\"button\"\n variant=\"secondary\"\n [disabled]=\"_disabled()\"\n [attr.aria-pressed]=\"zoom() === level\"\n (click)=\"_select(level)\"\n >\n {{ level }}%\n </button>\n } @if (fitToContainer()) {\n <button\n mlvButton\n class=\"mlv-editor-zoom__fit\"\n type=\"button\"\n variant=\"secondary\"\n [disabled]=\"_disabled()\"\n (click)=\"_fitCurrentViewport()\"\n >\n {{ _copy().fitToContainer }}\n </button>\n }\n </div>\n </div>\n </ng-template>\n</mlv-popup>\n", styles: [".mlv-editor-zoom{box-sizing:border-box;padding:0;margin:0;font-family:var(--mlv-typography-family-text);font-size:var(--mlv-typography-body-m-size)}.mlv-editor-zoom *{box-sizing:border-box}.mlv-editor-zoom{display:inline-flex;align-items:center;gap:var(--mlv-spacing-1);white-space:nowrap}.mlv-editor-zoom__panel{display:grid;gap:var(--mlv-spacing-2);padding:var(--mlv-padding-xs)}.mlv-editor-zoom__presets{display:flex;flex-wrap:wrap;gap:var(--mlv-spacing-1)}\n"], dependencies: [{ kind: "component", type: MlvButton, selector: "button[mlvButton], a[mlvButton]", inputs: ["variant", "shape", "disabled", "loading"] }, { kind: "directive", type: MlvButtonIcon, selector: "[mlvButtonIcon]" }, { kind: "directive", type: MlvTooltip, selector: "[mlvTooltip]", inputs: ["mlvTooltip", "tooltipPlacement", "tooltipTone", "tooltipDelay", "tooltipDisabled", "tooltipArrow"] }, { kind: "component", type: LucideZoomIn, selector: "svg[lucideZoomIn]" }, { kind: "component", type: LucideZoomOut, selector: "svg[lucideZoomOut]" }, { kind: "component", type: MlvInput, selector: "mlv-input", inputs: ["type", "placeholder", "autocomplete", "inputMode", "maxLength", "minLength", "pattern", "name", "autofocus", "min", "max", "step", "bare", "projectControl", "role", "ariaExpanded", "ariaHasPopup", "ariaAutocomplete", "ariaControls", "ariaActiveDescendant", "ariaDescribedBy", "value"], outputs: ["valueChange", "inputFocus", "inputBlur"] }, { kind: "component", type: MlvPopup, selector: "mlv-popup", inputs: ["position", "positions", "width", "height", "minWidth", "minHeight", "maxWidth", "maxHeight", "hasArrow", "hasShadow", "class", "mlvDensity", "flexibleDimensions", "scrollStrategy", "hasBackdrop", "restrictPosition", "panelRole", "modal", "ariaLabel", "dismissExcludeElements", "mobileMode", "mobileBreakpoint", "mobileTitle", "mobileCloseLabel", "opened"], outputs: ["openedChange", "afterOpened", "afterClosed"] }, { kind: "directive", type: MlvPopupContent, selector: "[mlvPopupContent]" }, { kind: "directive", type: MlvPopupTrigger, selector: "[mlvPopupTrigger]", inputs: ["mlvPopupTrigger", "triggerOn", "ariaHasPopup"], exportAs: ["mlvPopupTrigger"] }, { kind: "directive", type: MlvEditorToolbarWidget, selector: "[mlvEditorToolbarWidget]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
312
|
-
}
|
|
313
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.7", ngImport: i0, type: MlvEditorZoom, decorators: [{
|
|
314
|
-
type: Component,
|
|
315
|
-
args: [{ selector: 'mlv-editor-zoom', imports: [
|
|
316
|
-
MlvButton,
|
|
317
|
-
MlvButtonIcon,
|
|
318
|
-
MlvTooltip,
|
|
319
|
-
LucideZoomIn,
|
|
320
|
-
LucideZoomOut,
|
|
321
|
-
MlvInput,
|
|
322
|
-
MlvPopup,
|
|
323
|
-
MlvPopupContent,
|
|
324
|
-
MlvPopupTrigger,
|
|
325
|
-
MlvEditorToolbarWidget,
|
|
326
|
-
], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
327
|
-
class: 'mlv-editor-zoom',
|
|
328
|
-
}, template: "<button\n mlvButton\n mlvEditorToolbarWidget\n type=\"button\"\n shape=\"square\"\n mlvDensity=\"tight\"\n variant=\"transparent\"\n [disabled]=\"_zoomOutDisabled()\"\n [attr.aria-label]=\"_copy().zoomOut\"\n [mlvTooltip]=\"_copy().zoomOut\"\n (click)=\"_zoomOut()\"\n>\n <svg mlvButtonIcon lucideZoomOut aria-hidden=\"true\" />\n</button>\n\n<button\n #_trigger=\"mlvPopupTrigger\"\n mlvButton\n mlvEditorToolbarWidget\n type=\"button\"\n mlvDensity=\"tight\"\n variant=\"transparent\"\n [disabled]=\"_disabled()\"\n [mlvPopupTrigger]=\"_popup\"\n [ariaHasPopup]=\"'dialog'\"\n [attr.aria-label]=\"_copy().zoom\"\n [mlvTooltip]=\"_copy().zoom\"\n>\n {{ zoom() }}%\n</button>\n\n<button\n mlvButton\n mlvEditorToolbarWidget\n type=\"button\"\n shape=\"square\"\n mlvDensity=\"tight\"\n variant=\"transparent\"\n [disabled]=\"_zoomInDisabled()\"\n [attr.aria-label]=\"_copy().zoomIn\"\n [mlvTooltip]=\"_copy().zoomIn\"\n (click)=\"_zoomIn()\"\n>\n <svg mlvButtonIcon lucideZoomIn aria-hidden=\"true\" />\n</button>\n\n<mlv-popup\n #_popup\n panelRole=\"dialog\"\n [modal]=\"true\"\n [ariaLabel]=\"_copy().zoom\"\n (afterOpened)=\"_onPopupOpened()\"\n (afterClosed)=\"_onPopupClosed()\"\n>\n <ng-template mlvPopupContent>\n <div [id]=\"_panelId\" class=\"mlv-editor-zoom__panel\">\n <div class=\"mlv-editor-zoom__field\">\n <mlv-input\n #_input\n bare\n type=\"number\"\n inputMode=\"numeric\"\n [ariaLabel]=\"_copy().zoom\"\n [min]=\"_bounds().min\"\n [max]=\"_bounds().max\"\n [disabled]=\"_disabled()\"\n [value]=\"_draft()\"\n (valueChange)=\"_draft.set($event)\"\n (keydown.enter)=\"_applyDraft($event)\"\n (inputBlur)=\"_applyDraft()\"\n />\n </div>\n <div\n class=\"mlv-editor-zoom__presets\"\n role=\"group\"\n [attr.aria-label]=\"_copy().zoom\"\n >\n @for (level of _presetLevels(); track level) {\n <button\n mlvButton\n class=\"mlv-editor-zoom__preset\"\n type=\"button\"\n variant=\"secondary\"\n [disabled]=\"_disabled()\"\n [attr.aria-pressed]=\"zoom() === level\"\n (click)=\"_select(level)\"\n >\n {{ level }}%\n </button>\n } @if (fitToContainer()) {\n <button\n mlvButton\n class=\"mlv-editor-zoom__fit\"\n type=\"button\"\n variant=\"secondary\"\n [disabled]=\"_disabled()\"\n (click)=\"_fitCurrentViewport()\"\n >\n {{ _copy().fitToContainer }}\n </button>\n }\n </div>\n </div>\n </ng-template>\n</mlv-popup>\n", styles: [".mlv-editor-zoom{box-sizing:border-box;padding:0;margin:0;font-family:var(--mlv-typography-family-text);font-size:var(--mlv-typography-body-m-size)}.mlv-editor-zoom *{box-sizing:border-box}.mlv-editor-zoom{display:inline-flex;align-items:center;gap:var(--mlv-spacing-1);white-space:nowrap}.mlv-editor-zoom__panel{display:grid;gap:var(--mlv-spacing-2);padding:var(--mlv-padding-xs)}.mlv-editor-zoom__presets{display:flex;flex-wrap:wrap;gap:var(--mlv-spacing-1)}\n"] }]
|
|
329
|
-
}], ctorParameters: () => [], propDecorators: { zoom: [{ type: i0.Input, args: [{ isSignal: true, alias: "zoom", required: false }] }, { type: i0.Output, args: ["zoomChange"] }], zoomLevels: [{ type: i0.Input, args: [{ isSignal: true, alias: "zoomLevels", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], fitToContainer: [{ type: i0.Input, args: [{ isSignal: true, alias: "fitToContainer", required: false }] }], _popup: [{ type: i0.ViewChild, args: ['_popup', { isSignal: true }] }], _trigger: [{ type: i0.ViewChild, args: ['_trigger', { isSignal: true }] }], _input: [{ type: i0.ViewChild, args: ['_input', { isSignal: true }] }] } });
|
|
330
|
-
//# sourceMappingURL=editor-zoom.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"editor-zoom.js","sourceRoot":"","sources":["../../../../../../libs/editor/src/lib/toolbar/editor-zoom.ts","../../../../../../libs/editor/src/lib/toolbar/editor-zoom.html"],"names":[],"mappings":"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","sourcesContent":["import { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport type { BooleanInput } from '@angular/cdk/coercion';\nimport { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n ElementRef,\n effect,\n inject,\n input,\n model,\n PLATFORM_ID,\n signal,\n untracked,\n ViewEncapsulation,\n viewChild,\n} from '@angular/core';\nimport type { OnChanges, SimpleChanges } from '@angular/core';\nimport { LucideZoomIn, LucideZoomOut } from '@lucide/angular';\nimport { mlvNextId, MlvResizeObserverService } from '@malva-ui/cdk/utils';\nimport { MlvButton, MlvButtonIcon } from '@malva-ui/core/button';\nimport { MlvInput } from '@malva-ui/core/input';\nimport {\n MlvPopup,\n MlvPopupContent,\n MlvPopupTrigger,\n} from '@malva-ui/core/popup';\nimport { MLV_EDITOR_I18N } from '@malva-ui/i18n';\nimport { MlvTooltip } from '@malva-ui/core/tooltip';\nimport {\n MLV_EDITOR_OVERLAY_REGISTRY,\n MLV_EDITOR_TOOLBAR_CONTEXT,\n type MlvEditorOverlayRegistry,\n} from '../editor-toolbar-context';\nimport { MlvEditorToolbarWidget } from './editor-toolbar-widget';\n\nconst DEFAULT_ZOOM = 100;\n\n/** View-only editor zoom stepper and preset menu. */\n@Component({\n selector: 'mlv-editor-zoom',\n imports: [\n MlvButton,\n MlvButtonIcon,\n MlvTooltip,\n LucideZoomIn,\n LucideZoomOut,\n MlvInput,\n MlvPopup,\n MlvPopupContent,\n MlvPopupTrigger,\n MlvEditorToolbarWidget,\n ],\n templateUrl: './editor-zoom.html',\n styleUrl: './editor-zoom.scss',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n class: 'mlv-editor-zoom',\n },\n})\nexport class MlvEditorZoom implements OnChanges {\n /** Current view-only zoom percentage. */\n readonly zoom = model<number>(100);\n\n /** Preset percentages displayed by the zoom menu. */\n readonly zoomLevels = input<readonly number[]>([\n 40, 50, 75, 90, 100, 125, 150, 175, 200,\n ]);\n\n /** Smallest permitted zoom percentage. */\n readonly min = input(40);\n\n /** Largest permitted zoom percentage. */\n readonly max = input(200);\n\n /** Recalculates the largest safe zoom whenever the content viewport resizes. */\n readonly fitToContainer = input<boolean, BooleanInput>(false, {\n transform: coerceBooleanProperty,\n });\n\n /** @protected Editor-scoped view and command state. */\n protected readonly _context = inject(MLV_EDITOR_TOOLBAR_CONTEXT);\n\n /** @private Shared observer abstraction for the editor viewport. */\n private readonly _resizeObserver = inject(MlvResizeObserverService);\n\n /** @private Component host used to retain a stable focus-restore target. */\n private readonly _host = inject<ElementRef<HTMLElement>>(ElementRef);\n\n /** @private Registry that keeps focus within the editor composite. */\n private readonly _overlays = inject<MlvEditorOverlayRegistry>(\n MLV_EDITOR_OVERLAY_REGISTRY,\n );\n\n /** @private Document used only after a browser menu opens. */\n private readonly _document = inject(DOCUMENT);\n\n /** @private Component teardown scope. */\n private readonly _destroyRef = inject(DestroyRef);\n\n /** @private Prevents browser view access during server rendering. */\n private readonly _isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n /** @private Optional reactive localized editor copy. */\n private readonly _i18n = inject(MLV_EDITOR_I18N, { optional: true });\n\n /** @protected Rendered mixed-control popup. */\n protected readonly _popup = viewChild.required<MlvPopup>('_popup');\n\n /** @protected Trigger that owns the detached popup. */\n protected readonly _trigger = viewChild.required<MlvPopupTrigger>('_trigger');\n\n /** @protected Percentage field focused when the popup opens. */\n protected readonly _input = viewChild.required<MlvInput>('_input');\n\n /** @protected Stable id used to resolve this component's detached panel. */\n protected readonly _panelId = mlvNextId('mlv-editor-zoom-panel');\n\n /** @private Last synchronized model value. */\n private _lastZoom = DEFAULT_ZOOM;\n\n /** @private Last synchronized editor-context value. */\n private _lastContextZoom = DEFAULT_ZOOM;\n\n /** @private Distinguishes initial context adoption from later writes. */\n private _initialized = false;\n\n /** @private Whether Angular assigned the public model, including an explicit default. */\n private _zoomWasSupplied = false;\n\n /** @private Current detached-popup registration teardown. */\n private _unregister: (() => void) | undefined;\n\n /** @private Guards a queued popup registration after close or destroy. */\n private _menuOpen = false;\n\n /** @private Connected trigger retained while the popup is open. */\n private _restoreFocusTarget: HTMLButtonElement | undefined;\n\n /** @protected Numeric field draft kept separate until commit. */\n protected readonly _draft = signal(String(DEFAULT_ZOOM));\n\n /** @protected Normalized inclusive zoom bounds. */\n protected readonly _bounds = computed(() => {\n const first = Number.isFinite(this.min())\n ? Math.max(1, this.min())\n : DEFAULT_ZOOM;\n const second = Number.isFinite(this.max())\n ? Math.max(1, this.max())\n : DEFAULT_ZOOM;\n return {\n min: Math.min(first, second),\n max: Math.max(first, second),\n };\n });\n\n /** @protected Finite, in-range, sorted menu presets. */\n protected readonly _presetLevels = computed(() => {\n const { min, max } = this._bounds();\n return [...new Set(this.zoomLevels())]\n .filter((level) => Number.isFinite(level) && level >= min && level <= max)\n .sort((left, right) => left - right);\n });\n\n /** @protected Whether the complete editor composite is disabled. */\n protected readonly _disabled = computed(() => this._context.disabled());\n\n /** @protected Reactive localized labels for every zoom surface. */\n protected readonly _copy = computed(() => {\n const zoom = this._i18n?.().zoom ?? 'Zoom';\n return {\n zoom,\n zoomOut: `${zoom} −`,\n zoomIn: `${zoom} +`,\n fitToContainer: this._i18n?.().fitToContainer ?? 'Fit to container',\n };\n });\n\n /** @protected Whether decrementing would exceed the lower bound. */\n protected readonly _zoomOutDisabled = computed(\n () => this._disabled() || this.zoom() <= this._bounds().min,\n );\n\n /** @protected Whether incrementing would exceed the upper bound. */\n protected readonly _zoomInDisabled = computed(\n () => this._disabled() || this.zoom() >= this._bounds().max,\n );\n\n constructor() {\n effect(() => this._synchronizeZoom());\n effect(() => this._draft.set(String(this.zoom())));\n\n effect((onCleanup) => {\n const enabled = this.fitToContainer();\n const editor = this._context.editor();\n if (!enabled || !this._isBrowser || !editor) return;\n const viewport = editor.view.dom.closest<HTMLElement>(\n '.mlv-editor__viewport',\n );\n if (!viewport) return;\n const subscription = this._resizeObserver\n .observe(viewport)\n .subscribe((entries) => {\n const width = entries[entries.length - 1]?.contentRect.width;\n if (width !== undefined) this._fit(width);\n });\n this._fit(viewport.getBoundingClientRect().width);\n onCleanup(() => subscription.unsubscribe());\n });\n\n this._destroyRef.onDestroy(() => this._releaseOverlay());\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['zoom']) this._zoomWasSupplied = true;\n }\n\n /** @protected Selects the previous preset or the exact minimum. */\n protected _zoomOut(): void {\n if (this._disabled()) return;\n const current = this.zoom();\n const previous = this._steps().filter((level) => level < current);\n const target = previous[previous.length - 1];\n this._setZoom(target ?? this._bounds().min);\n }\n\n /** @protected Selects the next preset or the exact maximum. */\n protected _zoomIn(): void {\n if (this._disabled()) return;\n const current = this.zoom();\n const target = this._steps().find((level) => level > current);\n this._setZoom(target ?? this._bounds().max);\n }\n\n /** @protected Applies a menu preset without dispatching an editor transaction. */\n protected _select(level: number): void {\n if (this._disabled()) return;\n this._setZoom(level);\n this._trigger().close();\n }\n\n /** @protected Commits a finite numeric field value and restores the normalized display. */\n protected _applyDraft(event?: Event): void {\n event?.preventDefault();\n event?.stopPropagation();\n if (this._disabled()) {\n this._draft.set(String(this.zoom()));\n return;\n }\n const parsed = Number(this._draft());\n if (Number.isFinite(parsed)) this._setZoom(parsed);\n this._draft.set(String(this.zoom()));\n }\n\n /** @protected Fits against the viewport's latest synchronous width. */\n protected _fitCurrentViewport(): void {\n if (this._disabled()) return;\n const viewport = this._context\n .editor()\n ?.view.dom.closest<HTMLElement>('.mlv-editor__viewport');\n if (viewport) {\n this._fit(viewport.clientWidth || viewport.getBoundingClientRect().width);\n this._trigger().close();\n }\n }\n\n /** @protected Registers the detached dialog and moves focus to its field. */\n protected _onPopupOpened(): void {\n this._menuOpen = true;\n this._restoreFocusTarget =\n this._host.nativeElement.querySelector<HTMLButtonElement>(\n 'button[aria-haspopup=\"dialog\"]',\n ) ?? undefined;\n queueMicrotask(() => {\n if (!this._menuOpen) return;\n const content = this._document.getElementById(this._panelId);\n const panel = content?.closest<HTMLElement>('.mlv-popup');\n if (!panel) return;\n this._unregister?.();\n this._unregister = this._overlays.register(panel, () =>\n this._trigger().close(),\n );\n this._input().focus();\n this._input().select();\n });\n }\n\n /** @protected Releases focus ownership and restores the visible trigger. */\n protected _onPopupClosed(): void {\n const trigger = this._restoreFocusTarget;\n this._releaseOverlay();\n if (!this._disabled() && trigger?.isConnected) trigger.focus();\n }\n\n /** @private Removes detached popup focus ownership without moving focus. */\n private _releaseOverlay(): void {\n this._menuOpen = false;\n this._restoreFocusTarget = undefined;\n this._unregister?.();\n this._unregister = undefined;\n }\n\n /** @private Synchronizes the literal public model with the nearest toolbar context. */\n private _synchronizeZoom(): void {\n const modelValue = this.zoom();\n const contextValue = this._context.zoom();\n const modelChanged = modelValue !== this._lastZoom;\n const contextChanged = contextValue !== this._lastContextZoom;\n let next: number;\n\n if (!this._initialized) {\n next =\n this._zoomWasSupplied ||\n modelValue !== DEFAULT_ZOOM ||\n contextValue === DEFAULT_ZOOM\n ? this._clamp(modelValue)\n : this._clamp(contextValue);\n this._initialized = true;\n } else if (modelChanged || modelValue !== this._clamp(modelValue)) {\n next = this._clamp(modelValue);\n } else if (contextChanged || contextValue !== this._clamp(contextValue)) {\n next = this._clamp(contextValue);\n } else {\n next = this._clamp(modelValue);\n }\n\n this._lastZoom = next;\n this._lastContextZoom = next;\n if (this.zoom() !== next) this.zoom.set(next);\n if (this._context.zoom() !== next) this._context.zoom.set(next);\n }\n\n /** @private Ordered stepping levels, including exact configured bounds. */\n private _steps(): readonly number[] {\n const { min, max } = this._bounds();\n return [...new Set([min, ...this._presetLevels(), max])].sort(\n (left, right) => left - right,\n );\n }\n\n /** @private Applies a clamped visual-only percentage to model and context. */\n private _setZoom(value: number): void {\n const next = this._clamp(value);\n this._lastZoom = next;\n this._lastContextZoom = next;\n this.zoom.set(next);\n this._context.zoom.set(next);\n }\n\n /** @private Calculates the largest integer zoom whose natural content fits. */\n private _fit(containerWidth: number): void {\n if (this._disabled()) return;\n const viewport = this._context\n .editor()\n ?.view.dom.closest<HTMLElement>('.mlv-editor__viewport');\n const view = viewport?.querySelector<HTMLElement>('.mlv-editor__view');\n if (!viewport || !view) return;\n const viewportWidths = [\n containerWidth,\n viewport.clientWidth,\n viewport.getBoundingClientRect().width,\n ].filter((width) => Number.isFinite(width) && width > 0);\n const availableWidth = Math.min(...viewportWidths);\n const currentScale = untracked(this.zoom) / 100;\n const transformedWidth = view.getBoundingClientRect().width;\n const naturalWidth = Math.max(\n view.scrollWidth,\n currentScale > 0 ? transformedWidth / currentScale : 0,\n );\n if (\n !Number.isFinite(availableWidth) ||\n !Number.isFinite(naturalWidth) ||\n availableWidth <= 0 ||\n naturalWidth <= 0\n ) {\n return;\n }\n const { min, max } = this._bounds();\n let next = Math.min(\n max,\n Math.max(min, Math.floor((availableWidth / naturalWidth) * 100)),\n );\n while (next > min && (naturalWidth * next) / 100 > availableWidth) {\n next -= 1;\n }\n this._setZoom(next);\n }\n\n /** @private Clamps a finite percentage to the configured inclusive bounds. */\n private _clamp(value: number): number {\n const { min, max } = this._bounds();\n const finite = Number.isFinite(value) ? value : DEFAULT_ZOOM;\n return Math.min(Math.max(finite, min), max);\n }\n}\n","<button\n mlvButton\n mlvEditorToolbarWidget\n type=\"button\"\n shape=\"square\"\n mlvDensity=\"tight\"\n variant=\"transparent\"\n [disabled]=\"_zoomOutDisabled()\"\n [attr.aria-label]=\"_copy().zoomOut\"\n [mlvTooltip]=\"_copy().zoomOut\"\n (click)=\"_zoomOut()\"\n>\n <svg mlvButtonIcon lucideZoomOut aria-hidden=\"true\" />\n</button>\n\n<button\n #_trigger=\"mlvPopupTrigger\"\n mlvButton\n mlvEditorToolbarWidget\n type=\"button\"\n mlvDensity=\"tight\"\n variant=\"transparent\"\n [disabled]=\"_disabled()\"\n [mlvPopupTrigger]=\"_popup\"\n [ariaHasPopup]=\"'dialog'\"\n [attr.aria-label]=\"_copy().zoom\"\n [mlvTooltip]=\"_copy().zoom\"\n>\n {{ zoom() }}%\n</button>\n\n<button\n mlvButton\n mlvEditorToolbarWidget\n type=\"button\"\n shape=\"square\"\n mlvDensity=\"tight\"\n variant=\"transparent\"\n [disabled]=\"_zoomInDisabled()\"\n [attr.aria-label]=\"_copy().zoomIn\"\n [mlvTooltip]=\"_copy().zoomIn\"\n (click)=\"_zoomIn()\"\n>\n <svg mlvButtonIcon lucideZoomIn aria-hidden=\"true\" />\n</button>\n\n<mlv-popup\n #_popup\n panelRole=\"dialog\"\n [modal]=\"true\"\n [ariaLabel]=\"_copy().zoom\"\n (afterOpened)=\"_onPopupOpened()\"\n (afterClosed)=\"_onPopupClosed()\"\n>\n <ng-template mlvPopupContent>\n <div [id]=\"_panelId\" class=\"mlv-editor-zoom__panel\">\n <div class=\"mlv-editor-zoom__field\">\n <mlv-input\n #_input\n bare\n type=\"number\"\n inputMode=\"numeric\"\n [ariaLabel]=\"_copy().zoom\"\n [min]=\"_bounds().min\"\n [max]=\"_bounds().max\"\n [disabled]=\"_disabled()\"\n [value]=\"_draft()\"\n (valueChange)=\"_draft.set($event)\"\n (keydown.enter)=\"_applyDraft($event)\"\n (inputBlur)=\"_applyDraft()\"\n />\n </div>\n <div\n class=\"mlv-editor-zoom__presets\"\n role=\"group\"\n [attr.aria-label]=\"_copy().zoom\"\n >\n @for (level of _presetLevels(); track level) {\n <button\n mlvButton\n class=\"mlv-editor-zoom__preset\"\n type=\"button\"\n variant=\"secondary\"\n [disabled]=\"_disabled()\"\n [attr.aria-pressed]=\"zoom() === level\"\n (click)=\"_select(level)\"\n >\n {{ level }}%\n </button>\n } @if (fitToContainer()) {\n <button\n mlvButton\n class=\"mlv-editor-zoom__fit\"\n type=\"button\"\n variant=\"secondary\"\n [disabled]=\"_disabled()\"\n (click)=\"_fitCurrentViewport()\"\n >\n {{ _copy().fitToContainer }}\n </button>\n }\n </div>\n </div>\n </ng-template>\n</mlv-popup>\n"]}
|