@aster-editor/angular 0.0.0-stage → 0.4.1
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/LICENSE +21 -0
- package/README.md +395 -2
- package/fesm2022/aster-editor-angular.mjs +624 -0
- package/fesm2022/aster-editor-angular.mjs.map +1 -0
- package/package.json +55 -3
- package/types/aster-editor-angular.d.ts +310 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aster-editor-angular.mjs","names":[],"sources":["../../src/lib/provide-aster.ts","../../src/lib/tokens.ts","../../src/lib/aster-editor.component.ts"],"sourcesContent":["import { InjectionToken, makeEnvironmentProviders } from '@angular/core';\nimport type { EnvironmentProviders } from '@angular/core';\nimport type { AsterUiOptions } from '@aster-editor/ui';\n\n/**\n * Configuration globale des éditeurs d'une application (ou d'une route, si fournie\n * dans ses `providers`). Le composant la fusionne avec l'input `config`, qui prime,\n * puis avec les inputs dédiés (`toolbar`, `theme`, `locale`, `placeholder`, `readonly`).\n */\nexport const ASTER_CONFIG = new InjectionToken<Partial<AsterUiOptions>>('ASTER_CONFIG');\n\n/**\n * Déclare la configuration globale d'Aster dans `ApplicationConfig.providers` ou dans\n * les `providers` d'une route. Fusion superficielle : une clé donnée ici est remplacée\n * en bloc par la même clé passée dans l'input `config` d'un composant.\n *\n * ```ts\n * provideAster({ locale: 'en', theme: 'night', linkPolicy: { defaultTarget: '_blank' } })\n * ```\n */\nexport function provideAster(config: Partial<AsterUiOptions>): EnvironmentProviders {\n return makeEnvironmentProviders([{ provide: ASTER_CONFIG, useValue: config }]);\n}\n","import { InjectionToken } from '@angular/core';\nimport type { UploadHandler } from '@aster-editor/core';\n\n/**\n * Hook d'upload d'image fourni par l'application (service HTTP, stockage, CDN…).\n * Optionnel : s'il est présent et qu'aucun `upload` n'est passé par `provideAster`\n * ni par l'input `config`, le composant le branche sur `AsterOptions.upload`.\n * Sans handler, les images sont insérées en data URL base64.\n */\nexport const ASTER_UPLOAD_HANDLER = new InjectionToken<UploadHandler>('ASTER_UPLOAD_HANDLER');\n","import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n afterNextRender,\n computed,\n effect,\n forwardRef,\n inject,\n input,\n output,\n signal,\n untracked,\n viewChild,\n} from '@angular/core';\nimport type { ElementRef, Signal } from '@angular/core';\nimport { NG_VALUE_ACCESSOR } from '@angular/forms';\nimport type { ControlValueAccessor } from '@angular/forms';\nimport type {\n AsterDocument,\n AsterEditor,\n AsterLocale,\n AsterTheme,\n AsterVariable,\n GetHtmlOptions,\n PasteTransformer,\n ToolbarConfig,\n Unsubscribe,\n VariableResolver,\n VariableSource,\n VariableValues,\n} from '@aster-editor/core';\nimport { createAster } from '@aster-editor/ui';\nimport type { AsterInstance, AsterUiOptions } from '@aster-editor/ui';\nimport type { DocxExportOptions, DocxImportResult } from '@aster-editor/word';\nimport { ASTER_CONFIG } from './provide-aster';\nimport { ASTER_UPLOAD_HANDLER } from './tokens';\n\n/** Vue minimale des options de l'extension Tiptap `Placeholder`, pour la changer à chaud. */\ninterface PlaceholderExtensionOptions {\n placeholder?: unknown;\n}\n\ntype TiptapEditor = AsterEditor['tiptap'];\ntype ProseMirrorPlugin = Parameters<TiptapEditor['registerPlugin']>[0];\n\n/** Signature de `addProseMirrorPlugins` d'une extension Tiptap (hors nœud et marque). */\ntype ExtensionPluginFactory = (this: {\n name: string;\n options: PlaceholderExtensionOptions;\n storage: unknown;\n editor: TiptapEditor;\n type: null;\n parent: undefined;\n}) => ProseMirrorPlugin[];\n\n/** Pose l'attribut quand une valeur est fournie, le retire sinon. */\nfunction setOrRemoveAttribute(element: HTMLElement, name: string, value: string | undefined): void {\n if (value === undefined || value === '') {\n element.removeAttribute(name);\n } else {\n element.setAttribute(name, value);\n }\n}\n\n/** Égalité de deux listes de noms, pour ne pas notifier `variableNames` sans changement réel. */\nfunction sameNames(a: readonly string[], b: readonly string[]): boolean {\n return a.length === b.length && a.every((name, index) => name === b[index]);\n}\n\n/** État du magasin de variables à conserver au travers d'un remontage. */\ninterface VariableSnapshot {\n readonly declared: readonly AsterVariable[];\n readonly values: VariableValues;\n}\n\n/**\n * Composant Angular standalone autour de `createAster` (`@aster-editor/ui`).\n *\n * - `ControlValueAccessor` : utilisable avec `formControlName`, `[formControl]` et `ngModel`.\n * La valeur du formulaire est le HTML sémantique de `getHTML()`.\n * - Zoneless et `OnPush` : rien dans le template ne dépend de l'état, les sorties sont\n * des `output()` et l'éditeur est exposé en signal.\n * - SSR-safe : l'éditeur est monté dans `afterNextRender`, jamais dans le constructeur, et\n * le module Word n'est chargé qu'à partir du montage (donc jamais côté serveur).\n *\n * Configuration, par priorité croissante : `provideAster(config)` < input `config` <\n * inputs dédiés (`toolbar`, `theme`, `locale`, `placeholder`, `readonly`). Un input dédié\n * laissé à `undefined` n'écrase donc pas la valeur venue de la configuration.\n *\n * Changements à chaud : `theme`, `locale`, `readonly`, `placeholder`, `ariaLabel`,\n * `ariaLabelledBy`, `variables` et `variableValues` sont appliqués sur l'instance vivante.\n * `toolbar` remonte l'éditeur (le contenu, les déclarations et les valeurs de variables sont\n * conservés, l'historique d'annulation est perdu, `ready` est réémis avec la nouvelle\n * instance). Les autres clés de `config` (`extensions`, `commands`, `upload`…) ne sont lues\n * qu'au montage.\n *\n * Variables (champs de fusion) : les inputs `variables`, `variableValues`, `variableResolver`,\n * `allowUnknownVariables` et `variableSuggestion` se fusionnent dans `options.variables` et\n * `variableSuggestion` de `createAster`. `variableNames` expose les noms présents dans le\n * document, `variablesChanged` relaie `variablesChange`, `exportDocx` produit le `.docx` avec\n * les valeurs du magasin.\n */\n@Component({\n selector: 'aster-editor',\n changeDetection: ChangeDetectionStrategy.OnPush,\n template: '<div #host class=\"aster-editor__host\"></div>',\n styles: ':host { display: block; }',\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => AsterEditorComponent),\n multi: true,\n },\n ],\n})\nexport class AsterEditorComponent implements ControlValueAccessor {\n /** Preset, groupes déclaratifs, ou `false` pour aucune toolbar. Défaut effectif : `standard`. */\n readonly toolbar = input<ToolbarConfig | undefined>(undefined);\n /** Thème appliqué sur `.aster[data-theme]`. `light` et `night` sont fournis par `ui`. Défaut : `light`. */\n readonly theme = input<AsterTheme | undefined>(undefined);\n /** Locale de l'éditeur et de la toolbar. Défaut effectif : `fr`. */\n readonly locale = input<AsterLocale | undefined>(undefined);\n /** Texte affiché quand le document est vide. Sans valeur, la chaîne i18n `editor.placeholder`. */\n readonly placeholder = input<string | undefined>(undefined);\n /** Lecture seule. Le `disabled` d'un formulaire s'y ajoute (l'un ou l'autre suffit). Défaut : `false`. */\n readonly readonly = input<boolean | undefined>(undefined);\n /** Tout le reste des options (`extensions`, `commands`, `linkPolicy`, `upload`, `content`…). */\n readonly config = input<Partial<AsterUiOptions>>({});\n /**\n * Nettoyage automatique du HTML collé depuis Word et Google Docs via\n * `wordPasteTransformer()` de `@aster-editor/word`, chargé dynamiquement au montage.\n */\n readonly wordPaste = input<boolean>(true);\n /**\n * Nom accessible de la zone de saisie (`aria-label` sur le contenteditable). Un\n * contenteditable n'est pas associable à un `<label for>`, c'est le seul moyen de le nommer.\n */\n readonly ariaLabel = input<string | undefined>(undefined);\n /** `id` (ou liste d'ids) de l'élément qui sert de libellé (`aria-labelledby` sur le contenteditable). */\n readonly ariaLabelledBy = input<string | undefined>(undefined);\n /**\n * Variables déclarées (libellé, description, valeur), proposées dans le menu d'insertion\n * même si absentes du document. À chaud : `editor.variables.define(...)`, fusion par nom.\n */\n readonly variables = input<readonly AsterVariable[] | undefined>(undefined);\n /**\n * Valeurs par nom. À chaud : `editor.variables.setValues(...)`, fusion avec les valeurs\n * connues (une clé absente n'efface rien, `undefined` efface).\n */\n readonly variableValues = input<VariableValues | undefined>(undefined);\n /** Résolveur asynchrone appelé par `resolveVariables()` pour les variables sans valeur. Lu au montage. */\n readonly variableResolver = input<VariableResolver | undefined>(undefined);\n /** Autoriser l'insertion d'une variable non déclarée. Défaut effectif : `true`. Lu au montage. */\n readonly allowUnknownVariables = input<boolean | undefined>(undefined);\n /** Menu de suggestion déclenché par `{{` dans le contenu. Défaut effectif : `true`. Lu au montage. */\n readonly variableSuggestion = input<boolean | undefined>(undefined);\n\n /** L'éditeur est monté et prêt. Réémis après un remontage (changement de `toolbar`). */\n readonly ready = output<AsterEditor>();\n /** Le document a changé : HTML de `getHTML()`. Pas émis sur `writeValue`. */\n readonly changed = output<string>();\n /** Le contenteditable a pris le focus. */\n readonly focused = output<void>();\n /**\n * Le contenteditable a perdu le focus au profit d'un élément extérieur à l'éditeur. Un\n * blur vers la toolbar ou un de ses menus n'est pas remonté : l'utilisateur est toujours\n * « dans » l'éditeur. C'est aussi ce qui marque le contrôle de formulaire `touched`.\n */\n readonly blurred = output<void>();\n /** Les valeurs ou déclarations de variables ont changé (`setValues`, `define`, `resolve`, import). */\n readonly variablesChanged = output<VariableValues>();\n\n private readonly editorState = signal<AsterEditor | null>(null);\n /** Éditeur courant, `null` avant le montage et après la destruction. */\n readonly editor: Signal<AsterEditor | null> = this.editorState.asReadonly();\n\n private readonly variableNamesState = signal<readonly string[]>([], { equal: sameNames });\n /**\n * Noms des variables réellement présentes dans le document (`editor.variables.getNames()`),\n * relus sur `change` et `variablesChange`. Vide avant le montage et après la destruction.\n */\n readonly variableNames: Signal<readonly string[]> = this.variableNamesState.asReadonly();\n\n private readonly host = viewChild.required<ElementRef<HTMLDivElement>>('host');\n private readonly globalConfig = inject(ASTER_CONFIG, { optional: true });\n private readonly uploadHandler = inject(ASTER_UPLOAD_HANDLER, { optional: true });\n private readonly formDisabled = signal(false);\n\n /** `ASTER_CONFIG` < `config`, fusion superficielle. */\n private readonly mergedConfig = computed<Partial<AsterUiOptions>>(() => ({\n ...(this.globalConfig ?? {}),\n ...this.config(),\n }));\n private readonly resolvedToolbar = computed<ToolbarConfig>(\n () => this.toolbar() ?? this.mergedConfig().toolbar ?? 'standard',\n );\n private readonly resolvedTheme = computed<AsterTheme>(\n () => this.theme() ?? this.mergedConfig().theme ?? 'light',\n );\n private readonly resolvedLocale = computed<AsterLocale>(\n () => this.locale() ?? this.mergedConfig().locale ?? 'fr',\n );\n private readonly resolvedPlaceholder = computed<string | undefined>(\n () => this.placeholder() ?? this.mergedConfig().placeholder,\n );\n private readonly resolvedReadOnly = computed<boolean>(\n () => (this.readonly() ?? this.mergedConfig().readOnly ?? false) || this.formDisabled(),\n );\n /** `config.variables` < inputs dédiés, clé par clé ; un input `undefined` ne masque rien. */\n private readonly resolvedVariableSource = computed<VariableSource | undefined>(() => {\n const base = this.mergedConfig().variables;\n const source: VariableSource = {\n ...base,\n ...(this.variables() !== undefined ? { variables: this.variables() } : {}),\n ...(this.variableValues() !== undefined ? { values: this.variableValues() } : {}),\n ...(this.variableResolver() !== undefined ? { resolve: this.variableResolver() } : {}),\n ...(this.allowUnknownVariables() !== undefined\n ? { allowUnknown: this.allowUnknownVariables() }\n : {}),\n };\n return Object.keys(source).length > 0 ? source : undefined;\n });\n private readonly resolvedVariableSuggestion = computed<boolean | undefined>(\n () => this.variableSuggestion() ?? this.mergedConfig().variableSuggestion,\n );\n\n private instance: AsterInstance | null = null;\n private mountedToolbar: ToolbarConfig | null = null;\n private subscriptions: Unsubscribe[] = [];\n /** Valeur reçue par `writeValue` avant le montage, appliquée comme contenu initial. */\n private pendingValue: string | null = null;\n private wordTransformer: PasteTransformer | null = null;\n private wordLoading: Promise<void> | null = null;\n private onChange: ((html: string) => void) | null = null;\n private onTouched: (() => void) | null = null;\n\n /**\n * Transformateur synchrone branché au montage ; il délègue au vrai transformateur Word\n * une fois le module chargé. Garde `@aster-editor/word` optionnel et hors du bundle\n * initial tout en respectant le contrat synchrone de `PasteTransformer`.\n */\n private readonly lazyWordTransformer: PasteTransformer = (html, context) =>\n this.wordTransformer && untracked(() => this.wordPaste())\n ? this.wordTransformer(html, context)\n : html;\n\n constructor() {\n afterNextRender(() => this.mount());\n inject(DestroyRef).onDestroy(() => this.unmount());\n\n effect(() => {\n const theme = this.resolvedTheme();\n untracked(() => this.instance?.setTheme(theme));\n });\n effect(() => {\n const locale = this.resolvedLocale();\n untracked(() => {\n const editor = this.instance?.editor;\n if (editor && editor.i18n.getLocale() !== locale) {\n editor.i18n.setLocale(locale);\n }\n });\n });\n effect(() => {\n const readOnly = this.resolvedReadOnly();\n untracked(() => this.instance?.editor.setReadOnly(readOnly));\n });\n effect(() => {\n const placeholder = this.resolvedPlaceholder();\n untracked(() => {\n if (this.instance) {\n this.applyPlaceholder(this.instance.editor, placeholder);\n }\n });\n });\n effect(() => {\n const label = this.ariaLabel();\n const labelledBy = this.ariaLabelledBy();\n untracked(() => {\n if (this.instance) {\n this.applyAriaAttributes(this.instance.editor, label, labelledBy);\n }\n });\n });\n effect(() => {\n const toolbar = this.resolvedToolbar();\n untracked(() => {\n if (this.instance && this.mountedToolbar !== toolbar) {\n this.remount();\n }\n });\n });\n // Le chargement initial du module Word part de `mount()` (jamais côté serveur) ; cet\n // effet ne couvre que le passage `false → true` d'un éditeur déjà monté.\n effect(() => {\n if (this.wordPaste()) {\n untracked(() => {\n if (this.instance) {\n this.loadWordPaste();\n }\n });\n }\n });\n // Au montage, déclarations et valeurs passent par `options.variables` ; ces deux effets\n // ne couvrent que les changements d'input sur un éditeur déjà monté.\n effect(() => {\n const declared = this.variables();\n untracked(() => {\n if (declared && this.instance) {\n this.instance.editor.variables.define(declared);\n }\n });\n });\n effect(() => {\n const values = this.variableValues();\n untracked(() => {\n if (values && this.instance) {\n this.instance.editor.variables.setValues(values);\n }\n });\n });\n }\n\n // --- API publique --------------------------------------------------------\n\n /**\n * Importe un `.docx` via `@aster-editor/word` (chargé à la demande, mammoth reste dans\n * un chunk séparé), remplace le contenu de l'éditeur en émettant `change` pour que le\n * formulaire voie la nouvelle valeur, et rend le résultat avec ses avertissements.\n * Le hook d'upload de l'éditeur est réutilisé pour les images embarquées. Si le\n * composant est détruit ou remonté pendant l'import, le résultat est rendu mais aucun\n * contenu n'est écrit : l'instance vivante est relue après chaque `await`.\n */\n async importDocx(file: File): Promise<DocxImportResult> {\n this.requireEditor('importDocx');\n const upload = untracked(() => this.resolvedOptions().upload);\n const { importDocx } = await import('@aster-editor/word');\n const result = await importDocx(file, upload ? { upload } : {});\n const editor = this.instance?.editor;\n if (editor && !editor.isDestroyed()) {\n editor.setHTML(result.html, true);\n this.declareImportedVariables(editor, result.variables);\n }\n return result;\n }\n\n /**\n * Convertit le document en `.docx` via `exportDocx` de `@aster-editor/word` (chargé à la\n * demande, la lib `docx` reste dans son chunk). Les valeurs du magasin de variables sont\n * transmises quand `options.variables.values` n'est pas fourni : `mode: 'resolve'` substitue\n * donc ce que l'utilisateur a saisi, `'fields'` produit des champs de fusion Word avec ces\n * valeurs comme résultat. Rend le `Blob`, à passer à `downloadDocx` ou à un upload.\n */\n async exportDocx(options: DocxExportOptions = {}): Promise<Blob> {\n const editor = this.requireEditor('exportDocx');\n const { exportDocx } = await import('@aster-editor/word');\n const variables = {\n ...options.variables,\n values: options.variables?.values ?? editor.variables.getValues(),\n };\n return exportDocx(editor.getHTML(), { ...options, variables });\n }\n\n /**\n * HTML du document, `{ variables: 'resolve' }` substitue les valeurs connues. Avant le\n * montage, rend la valeur reçue par `writeValue` (puces conservées) ou une chaîne vide.\n */\n getHTML(options?: GetHtmlOptions): string {\n return this.instance?.editor.getHTML(options) ?? this.pendingValue ?? '';\n }\n\n /**\n * Appelle le résolveur (`variableResolver` ou `config.variables.resolve`) pour les\n * variables présentes sans valeur, applique les valeurs obtenues et les rend toutes.\n */\n resolveVariables(): Promise<VariableValues> {\n return this.requireEditor('resolveVariables').variables.resolve();\n }\n\n // --- ControlValueAccessor ------------------------------------------------\n\n /**\n * Applique la valeur du formulaire sans émettre `change` ni entrer dans l'historique ;\n * mémorisée si l'éditeur n'est pas monté. Une valeur identique au HTML courant est\n * ignorée pour ne pas déplacer la sélection (les reactive forms réécrivent la valeur à\n * chaque `setValue`, y compris quand elle n'a pas changé).\n */\n writeValue(value: string | null | undefined): void {\n const html = value ?? '';\n const editor = this.instance?.editor;\n if (!editor) {\n this.pendingValue = html;\n return;\n }\n if (editor.getHTML() === html) {\n return;\n }\n editor.setHTML(html, false);\n }\n\n /** Enregistre le rappel appelé avec le HTML à chaque modification du document par l'utilisateur. */\n registerOnChange(fn: (html: string) => void): void {\n this.onChange = fn;\n }\n\n /** Enregistre le rappel appelé quand l'éditeur perd le focus vers l'extérieur (`touched`). */\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n /** `disabled` du formulaire → lecture seule, cumulé avec l'input `readonly`. */\n setDisabledState(isDisabled: boolean): void {\n this.formDisabled.set(isDisabled);\n this.instance?.editor.setReadOnly(untracked(() => this.resolvedReadOnly()));\n }\n\n // --- Cycle de vie --------------------------------------------------------\n\n /**\n * Monte l'éditeur. `content` force le contenu initial (remontage) et, dans ce cas,\n * `autofocus` est neutralisé : le focus est restauré explicitement par `remount()`.\n */\n private mount(content?: string, variables?: VariableSnapshot): void {\n if (this.instance) {\n return;\n }\n const options = untracked(() => this.resolvedOptions(content, variables));\n const instance = createAster(this.host().nativeElement, options);\n const editor = instance.editor;\n this.instance = instance;\n this.mountedToolbar = options.toolbar ?? 'standard';\n this.pendingValue = null;\n this.subscriptions = [\n editor.on('ready', ({ editor: ready }) => this.ready.emit(ready)),\n editor.on('change', ({ editor: changed }) => {\n const html = changed.getHTML();\n this.onChange?.(html);\n this.changed.emit(html);\n this.refreshVariableNames(changed);\n }),\n editor.on('variablesChange', ({ editor: source, values }) => {\n this.refreshVariableNames(source);\n this.variablesChanged.emit(values);\n }),\n editor.on('focus', () => this.focused.emit()),\n editor.on('blur', ({ event }) => {\n // Un blur vers la toolbar, un menu ou un dialogue de l'éditeur n'est pas une sortie.\n const related = event.relatedTarget;\n if (related instanceof Node && instance.element.contains(related)) {\n return;\n }\n this.onTouched?.();\n this.blurred.emit();\n }),\n ];\n untracked(() => this.applyAriaAttributes(editor, this.ariaLabel(), this.ariaLabelledBy()));\n if (untracked(() => this.wordPaste())) {\n this.loadWordPaste();\n }\n this.refreshVariableNames(editor);\n this.editorState.set(editor);\n }\n\n private unmount(): void {\n for (const unsubscribe of this.subscriptions) {\n unsubscribe();\n }\n this.subscriptions = [];\n this.instance?.destroy();\n this.instance = null;\n this.mountedToolbar = null;\n this.editorState.set(null);\n this.variableNamesState.set([]);\n }\n\n /**\n * Remonte l'éditeur en conservant le contenu, le focus, les déclarations et les valeurs\n * de variables ; l'historique est perdu.\n */\n private remount(): void {\n const current = this.instance;\n if (!current) {\n return;\n }\n const html = current.editor.getHTML();\n const focused = current.editor.isFocused();\n const variables: VariableSnapshot = {\n declared: current.editor.variables.list(),\n values: current.editor.variables.getValues(),\n };\n this.unmount();\n this.mount(html, variables);\n if (focused) {\n this.instance?.editor.focus('end');\n }\n }\n\n /**\n * Fusionne `ASTER_CONFIG` < `config` < inputs dédiés. Le transformateur Word est placé\n * en tête pour que les transformateurs de l'intégrateur reçoivent du HTML déjà nettoyé.\n * Avec `content` (remontage), `autofocus` est désactivé pour ne pas reprendre le focus et\n * `variables` réinjecte l'état du magasin précédent par-dessus la configuration.\n */\n private resolvedOptions(content?: string, variables?: VariableSnapshot): AsterUiOptions {\n const merged = this.mergedConfig();\n const initial: string | AsterDocument | undefined =\n content ?? this.pendingValue ?? merged.content;\n const source = this.resolvedVariableSource();\n const variableSource: VariableSource | undefined = variables\n ? {\n ...source,\n variables: [...(source?.variables ?? []), ...variables.declared],\n values: { ...source?.values, ...variables.values },\n }\n : source;\n return {\n ...merged,\n content: initial,\n autofocus: content === undefined ? merged.autofocus : false,\n toolbar: this.resolvedToolbar(),\n theme: this.resolvedTheme(),\n locale: this.resolvedLocale(),\n placeholder: this.resolvedPlaceholder(),\n readOnly: this.resolvedReadOnly(),\n pasteTransformers: [this.lazyWordTransformer, ...(merged.pasteTransformers ?? [])],\n upload: merged.upload ?? this.uploadHandler ?? undefined,\n variables: variableSource,\n variableSuggestion: this.resolvedVariableSuggestion(),\n };\n }\n\n /** Éditeur monté, sinon erreur explicite nommant la méthode appelée trop tôt. */\n private requireEditor(method: string): AsterEditor {\n const editor = this.instance?.editor;\n if (!editor) {\n throw new Error(`[aster-editor/angular] ${method}: editor is not mounted yet`);\n }\n return editor;\n }\n\n /** Relit `getNames()` ; le signal n'est notifié que si la liste change réellement. */\n private refreshVariableNames(editor: AsterEditor): void {\n this.variableNamesState.set(editor.variables.getNames());\n }\n\n /**\n * Après un import : déclare les variables trouvées dans le `.docx` (libellé et valeur des\n * contrôles de contenu compris), puis réapplique l'input `variableValues` pour les noms que\n * Word a lui-même valorisés, l'application restant la source de vérité des valeurs.\n */\n private declareImportedVariables(editor: AsterEditor, found: readonly AsterVariable[]): void {\n if (found.length === 0) {\n return;\n }\n editor.variables.define(found);\n const known = untracked(() => this.variableValues());\n if (!known) {\n return;\n }\n const overrides: Record<string, string> = {};\n for (const variable of found) {\n const value = known[variable.name];\n if (variable.value !== undefined && value !== undefined && value !== variable.value) {\n overrides[variable.name] = value;\n }\n }\n if (Object.keys(overrides).length > 0) {\n editor.variables.setValues(overrides);\n }\n }\n\n private loadWordPaste(): void {\n if (this.wordTransformer || this.wordLoading) {\n return;\n }\n this.wordLoading = import('@aster-editor/word')\n .then((word) => {\n this.wordTransformer = word.wordPasteTransformer();\n })\n .catch((error: unknown) => {\n this.wordLoading = null;\n console.warn(\n '[aster-editor/angular] @aster-editor/word unavailable, paste kept raw',\n error,\n );\n });\n }\n\n /** Nom accessible du contenteditable : `aria-label` et/ou `aria-labelledby`, retirés si vides. */\n private applyAriaAttributes(\n editor: AsterEditor,\n label: string | undefined,\n labelledBy: string | undefined,\n ): void {\n setOrRemoveAttribute(editor.contentElement, 'aria-label', label);\n setOrRemoveAttribute(editor.contentElement, 'aria-labelledby', labelledBy);\n }\n\n /**\n * Change le placeholder à chaud. L'extension `Placeholder` lit ses options au moment où\n * son plugin ProseMirror est créé (et `extension.options` est une copie à chaque accès),\n * donc on refabrique le plugin via `addProseMirrorPlugins` avec un `placeholder` surchargé\n * et on le substitue à l'ancien par `unregisterPlugin`/`registerPlugin`, API publiques de\n * Tiptap. Le repli sur la chaîne i18n `editor.placeholder` est conservé.\n */\n private applyPlaceholder(editor: AsterEditor, placeholder: string | undefined): void {\n const tiptap = editor.tiptap;\n const extension = tiptap.extensionManager.extensions.find(\n (candidate) => candidate.name === 'placeholder',\n );\n if (extension?.type !== 'extension') {\n return;\n }\n const factory = extension.config.addProseMirrorPlugins as ExtensionPluginFactory | undefined;\n if (!factory) {\n return;\n }\n const options: PlaceholderExtensionOptions = {\n ...extension.options,\n placeholder: (): string => placeholder ?? editor.i18n.t('editor.placeholder'),\n };\n const plugins = factory.call({\n name: extension.name,\n options,\n storage: extension.storage,\n editor: tiptap,\n type: null,\n parent: undefined,\n });\n for (const plugin of plugins) {\n tiptap.unregisterPlugin(plugin.spec.key ?? extension.name);\n tiptap.registerPlugin(plugin);\n }\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,58 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aster-editor/angular",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"description": "Composant Angular standalone pour Aster Editor : reactive forms, signals, zoneless",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Joris Tremoulet",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"aster-editor",
|
|
9
|
+
"angular",
|
|
10
|
+
"control-value-accessor",
|
|
11
|
+
"signals",
|
|
12
|
+
"editor"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/jtremoulet/aster-editor/tree/main/packages/angular#readme",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/jtremoulet/aster-editor.git",
|
|
18
|
+
"directory": "packages/angular"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/jtremoulet/aster-editor/issues"
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=20.0.0"
|
|
28
|
+
},
|
|
29
|
+
"peerDependencies": {
|
|
30
|
+
"@angular/common": ">=20.0.0",
|
|
31
|
+
"@angular/core": ">=20.0.0",
|
|
32
|
+
"@angular/forms": ">=20.0.0",
|
|
33
|
+
"@aster-editor/core": "^0.4.1",
|
|
34
|
+
"@aster-editor/ui": "^0.4.1",
|
|
35
|
+
"@aster-editor/word": "^0.4.1"
|
|
36
|
+
},
|
|
37
|
+
"peerDependenciesMeta": {
|
|
38
|
+
"@aster-editor/word": {
|
|
39
|
+
"optional": true
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"tslib": "^2.3.0"
|
|
44
|
+
},
|
|
45
|
+
"sideEffects": false,
|
|
46
|
+
"module": "fesm2022/aster-editor-angular.mjs",
|
|
47
|
+
"typings": "types/aster-editor-angular.d.ts",
|
|
48
|
+
"exports": {
|
|
49
|
+
"./package.json": {
|
|
50
|
+
"default": "./package.json"
|
|
51
|
+
},
|
|
52
|
+
".": {
|
|
53
|
+
"types": "./types/aster-editor-angular.d.ts",
|
|
54
|
+
"default": "./fesm2022/aster-editor-angular.mjs"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"type": "module"
|
|
6
58
|
}
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { EnvironmentProviders, InjectionToken, Signal } from "@angular/core";
|
|
3
|
+
import { ControlValueAccessor } from "@angular/forms";
|
|
4
|
+
import { AsterCounts, AsterDocument, AsterEditor, AsterEditor as AsterEditor$1, AsterLocale, AsterLocale as AsterLocale$1, AsterTheme, AsterTheme as AsterTheme$1, AsterVariable, AsterVariable as AsterVariable$1, GetHtmlOptions, GetHtmlOptions as GetHtmlOptions$1, LinkPolicy, PasteTransformer, ToolbarConfig, ToolbarConfig as ToolbarConfig$1, ToolbarPreset, UploadHandler, UploadHandler as UploadHandler$1, VariableRenderMode, VariableResolver, VariableResolver as VariableResolver$1, VariableSource, VariableValues, VariableValues as VariableValues$1 } from "@aster-editor/core";
|
|
5
|
+
import { AsterUiOptions, AsterUiOptions as AsterUiOptions$1 } from "@aster-editor/ui";
|
|
6
|
+
import { DocxExportOptions, DocxExportOptions as DocxExportOptions$1, DocxExportVariableOptions, DocxExportWarning, DocxImportResult, DocxImportResult as DocxImportResult$1, DocxImportWarning, DocxVariableMode } from "@aster-editor/word";
|
|
7
|
+
/**
|
|
8
|
+
* Composant Angular standalone autour de `createAster` (`@aster-editor/ui`).
|
|
9
|
+
*
|
|
10
|
+
* - `ControlValueAccessor` : utilisable avec `formControlName`, `[formControl]` et `ngModel`.
|
|
11
|
+
* La valeur du formulaire est le HTML sémantique de `getHTML()`.
|
|
12
|
+
* - Zoneless et `OnPush` : rien dans le template ne dépend de l'état, les sorties sont
|
|
13
|
+
* des `output()` et l'éditeur est exposé en signal.
|
|
14
|
+
* - SSR-safe : l'éditeur est monté dans `afterNextRender`, jamais dans le constructeur, et
|
|
15
|
+
* le module Word n'est chargé qu'à partir du montage (donc jamais côté serveur).
|
|
16
|
+
*
|
|
17
|
+
* Configuration, par priorité croissante : `provideAster(config)` < input `config` <
|
|
18
|
+
* inputs dédiés (`toolbar`, `theme`, `locale`, `placeholder`, `readonly`). Un input dédié
|
|
19
|
+
* laissé à `undefined` n'écrase donc pas la valeur venue de la configuration.
|
|
20
|
+
*
|
|
21
|
+
* Changements à chaud : `theme`, `locale`, `readonly`, `placeholder`, `ariaLabel`,
|
|
22
|
+
* `ariaLabelledBy`, `variables` et `variableValues` sont appliqués sur l'instance vivante.
|
|
23
|
+
* `toolbar` remonte l'éditeur (le contenu, les déclarations et les valeurs de variables sont
|
|
24
|
+
* conservés, l'historique d'annulation est perdu, `ready` est réémis avec la nouvelle
|
|
25
|
+
* instance). Les autres clés de `config` (`extensions`, `commands`, `upload`…) ne sont lues
|
|
26
|
+
* qu'au montage.
|
|
27
|
+
*
|
|
28
|
+
* Variables (champs de fusion) : les inputs `variables`, `variableValues`, `variableResolver`,
|
|
29
|
+
* `allowUnknownVariables` et `variableSuggestion` se fusionnent dans `options.variables` et
|
|
30
|
+
* `variableSuggestion` de `createAster`. `variableNames` expose les noms présents dans le
|
|
31
|
+
* document, `variablesChanged` relaie `variablesChange`, `exportDocx` produit le `.docx` avec
|
|
32
|
+
* les valeurs du magasin.
|
|
33
|
+
*/
|
|
34
|
+
export declare class AsterEditorComponent implements ControlValueAccessor {
|
|
35
|
+
/** Preset, groupes déclaratifs, ou `false` pour aucune toolbar. Défaut effectif : `standard`. */
|
|
36
|
+
readonly toolbar: import("@angular/core").InputSignal<ToolbarConfig$1 | undefined>;
|
|
37
|
+
/** Thème appliqué sur `.aster[data-theme]`. `light` et `night` sont fournis par `ui`. Défaut : `light`. */
|
|
38
|
+
readonly theme: import("@angular/core").InputSignal<AsterTheme$1 | undefined>;
|
|
39
|
+
/** Locale de l'éditeur et de la toolbar. Défaut effectif : `fr`. */
|
|
40
|
+
readonly locale: import("@angular/core").InputSignal<AsterLocale$1 | undefined>;
|
|
41
|
+
/** Texte affiché quand le document est vide. Sans valeur, la chaîne i18n `editor.placeholder`. */
|
|
42
|
+
readonly placeholder: import("@angular/core").InputSignal<string | undefined>;
|
|
43
|
+
/** Lecture seule. Le `disabled` d'un formulaire s'y ajoute (l'un ou l'autre suffit). Défaut : `false`. */
|
|
44
|
+
readonly readonly: import("@angular/core").InputSignal<boolean | undefined>;
|
|
45
|
+
/** Tout le reste des options (`extensions`, `commands`, `linkPolicy`, `upload`, `content`…). */
|
|
46
|
+
readonly config: import("@angular/core").InputSignal<Partial<AsterUiOptions$1>>;
|
|
47
|
+
/**
|
|
48
|
+
* Nettoyage automatique du HTML collé depuis Word et Google Docs via
|
|
49
|
+
* `wordPasteTransformer()` de `@aster-editor/word`, chargé dynamiquement au montage.
|
|
50
|
+
*/
|
|
51
|
+
readonly wordPaste: import("@angular/core").InputSignal<boolean>;
|
|
52
|
+
/**
|
|
53
|
+
* Nom accessible de la zone de saisie (`aria-label` sur le contenteditable). Un
|
|
54
|
+
* contenteditable n'est pas associable à un `<label for>`, c'est le seul moyen de le nommer.
|
|
55
|
+
*/
|
|
56
|
+
readonly ariaLabel: import("@angular/core").InputSignal<string | undefined>;
|
|
57
|
+
/** `id` (ou liste d'ids) de l'élément qui sert de libellé (`aria-labelledby` sur le contenteditable). */
|
|
58
|
+
readonly ariaLabelledBy: import("@angular/core").InputSignal<string | undefined>;
|
|
59
|
+
/**
|
|
60
|
+
* Variables déclarées (libellé, description, valeur), proposées dans le menu d'insertion
|
|
61
|
+
* même si absentes du document. À chaud : `editor.variables.define(...)`, fusion par nom.
|
|
62
|
+
*/
|
|
63
|
+
readonly variables: import("@angular/core").InputSignal<readonly AsterVariable$1[] | undefined>;
|
|
64
|
+
/**
|
|
65
|
+
* Valeurs par nom. À chaud : `editor.variables.setValues(...)`, fusion avec les valeurs
|
|
66
|
+
* connues (une clé absente n'efface rien, `undefined` efface).
|
|
67
|
+
*/
|
|
68
|
+
readonly variableValues: import("@angular/core").InputSignal<Readonly<Record<string, string>> | undefined>;
|
|
69
|
+
/** Résolveur asynchrone appelé par `resolveVariables()` pour les variables sans valeur. Lu au montage. */
|
|
70
|
+
readonly variableResolver: import("@angular/core").InputSignal<VariableResolver$1 | undefined>;
|
|
71
|
+
/** Autoriser l'insertion d'une variable non déclarée. Défaut effectif : `true`. Lu au montage. */
|
|
72
|
+
readonly allowUnknownVariables: import("@angular/core").InputSignal<boolean | undefined>;
|
|
73
|
+
/** Menu de suggestion déclenché par `{{` dans le contenu. Défaut effectif : `true`. Lu au montage. */
|
|
74
|
+
readonly variableSuggestion: import("@angular/core").InputSignal<boolean | undefined>;
|
|
75
|
+
/** L'éditeur est monté et prêt. Réémis après un remontage (changement de `toolbar`). */
|
|
76
|
+
readonly ready: import("@angular/core").OutputEmitterRef<AsterEditor$1>;
|
|
77
|
+
/** Le document a changé : HTML de `getHTML()`. Pas émis sur `writeValue`. */
|
|
78
|
+
readonly changed: import("@angular/core").OutputEmitterRef<string>;
|
|
79
|
+
/** Le contenteditable a pris le focus. */
|
|
80
|
+
readonly focused: import("@angular/core").OutputEmitterRef<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Le contenteditable a perdu le focus au profit d'un élément extérieur à l'éditeur. Un
|
|
83
|
+
* blur vers la toolbar ou un de ses menus n'est pas remonté : l'utilisateur est toujours
|
|
84
|
+
* « dans » l'éditeur. C'est aussi ce qui marque le contrôle de formulaire `touched`.
|
|
85
|
+
*/
|
|
86
|
+
readonly blurred: import("@angular/core").OutputEmitterRef<void>;
|
|
87
|
+
/** Les valeurs ou déclarations de variables ont changé (`setValues`, `define`, `resolve`, import). */
|
|
88
|
+
readonly variablesChanged: import("@angular/core").OutputEmitterRef<Readonly<Record<string, string>>>;
|
|
89
|
+
private readonly editorState;
|
|
90
|
+
/** Éditeur courant, `null` avant le montage et après la destruction. */
|
|
91
|
+
readonly editor: Signal<AsterEditor$1 | null>;
|
|
92
|
+
private readonly variableNamesState;
|
|
93
|
+
/**
|
|
94
|
+
* Noms des variables réellement présentes dans le document (`editor.variables.getNames()`),
|
|
95
|
+
* relus sur `change` et `variablesChange`. Vide avant le montage et après la destruction.
|
|
96
|
+
*/
|
|
97
|
+
readonly variableNames: Signal<readonly string[]>;
|
|
98
|
+
private readonly host;
|
|
99
|
+
private readonly globalConfig;
|
|
100
|
+
private readonly uploadHandler;
|
|
101
|
+
private readonly formDisabled;
|
|
102
|
+
/** `ASTER_CONFIG` < `config`, fusion superficielle. */
|
|
103
|
+
private readonly mergedConfig;
|
|
104
|
+
private readonly resolvedToolbar;
|
|
105
|
+
private readonly resolvedTheme;
|
|
106
|
+
private readonly resolvedLocale;
|
|
107
|
+
private readonly resolvedPlaceholder;
|
|
108
|
+
private readonly resolvedReadOnly;
|
|
109
|
+
/** `config.variables` < inputs dédiés, clé par clé ; un input `undefined` ne masque rien. */
|
|
110
|
+
private readonly resolvedVariableSource;
|
|
111
|
+
private readonly resolvedVariableSuggestion;
|
|
112
|
+
private instance;
|
|
113
|
+
private mountedToolbar;
|
|
114
|
+
private subscriptions;
|
|
115
|
+
/** Valeur reçue par `writeValue` avant le montage, appliquée comme contenu initial. */
|
|
116
|
+
private pendingValue;
|
|
117
|
+
private wordTransformer;
|
|
118
|
+
private wordLoading;
|
|
119
|
+
private onChange;
|
|
120
|
+
private onTouched;
|
|
121
|
+
/**
|
|
122
|
+
* Transformateur synchrone branché au montage ; il délègue au vrai transformateur Word
|
|
123
|
+
* une fois le module chargé. Garde `@aster-editor/word` optionnel et hors du bundle
|
|
124
|
+
* initial tout en respectant le contrat synchrone de `PasteTransformer`.
|
|
125
|
+
*/
|
|
126
|
+
private readonly lazyWordTransformer;
|
|
127
|
+
constructor();
|
|
128
|
+
/**
|
|
129
|
+
* Importe un `.docx` via `@aster-editor/word` (chargé à la demande, mammoth reste dans
|
|
130
|
+
* un chunk séparé), remplace le contenu de l'éditeur en émettant `change` pour que le
|
|
131
|
+
* formulaire voie la nouvelle valeur, et rend le résultat avec ses avertissements.
|
|
132
|
+
* Le hook d'upload de l'éditeur est réutilisé pour les images embarquées. Si le
|
|
133
|
+
* composant est détruit ou remonté pendant l'import, le résultat est rendu mais aucun
|
|
134
|
+
* contenu n'est écrit : l'instance vivante est relue après chaque `await`.
|
|
135
|
+
*/
|
|
136
|
+
importDocx(file: File): Promise<DocxImportResult$1>;
|
|
137
|
+
/**
|
|
138
|
+
* Convertit le document en `.docx` via `exportDocx` de `@aster-editor/word` (chargé à la
|
|
139
|
+
* demande, la lib `docx` reste dans son chunk). Les valeurs du magasin de variables sont
|
|
140
|
+
* transmises quand `options.variables.values` n'est pas fourni : `mode: 'resolve'` substitue
|
|
141
|
+
* donc ce que l'utilisateur a saisi, `'fields'` produit des champs de fusion Word avec ces
|
|
142
|
+
* valeurs comme résultat. Rend le `Blob`, à passer à `downloadDocx` ou à un upload.
|
|
143
|
+
*/
|
|
144
|
+
exportDocx(options?: DocxExportOptions$1): Promise<Blob>;
|
|
145
|
+
/**
|
|
146
|
+
* HTML du document, `{ variables: 'resolve' }` substitue les valeurs connues. Avant le
|
|
147
|
+
* montage, rend la valeur reçue par `writeValue` (puces conservées) ou une chaîne vide.
|
|
148
|
+
*/
|
|
149
|
+
getHTML(options?: GetHtmlOptions$1): string;
|
|
150
|
+
/**
|
|
151
|
+
* Appelle le résolveur (`variableResolver` ou `config.variables.resolve`) pour les
|
|
152
|
+
* variables présentes sans valeur, applique les valeurs obtenues et les rend toutes.
|
|
153
|
+
*/
|
|
154
|
+
resolveVariables(): Promise<VariableValues$1>;
|
|
155
|
+
/**
|
|
156
|
+
* Applique la valeur du formulaire sans émettre `change` ni entrer dans l'historique ;
|
|
157
|
+
* mémorisée si l'éditeur n'est pas monté. Une valeur identique au HTML courant est
|
|
158
|
+
* ignorée pour ne pas déplacer la sélection (les reactive forms réécrivent la valeur à
|
|
159
|
+
* chaque `setValue`, y compris quand elle n'a pas changé).
|
|
160
|
+
*/
|
|
161
|
+
writeValue(value: string | null | undefined): void;
|
|
162
|
+
/** Enregistre le rappel appelé avec le HTML à chaque modification du document par l'utilisateur. */
|
|
163
|
+
registerOnChange(fn: (html: string) => void): void;
|
|
164
|
+
/** Enregistre le rappel appelé quand l'éditeur perd le focus vers l'extérieur (`touched`). */
|
|
165
|
+
registerOnTouched(fn: () => void): void;
|
|
166
|
+
/** `disabled` du formulaire → lecture seule, cumulé avec l'input `readonly`. */
|
|
167
|
+
setDisabledState(isDisabled: boolean): void;
|
|
168
|
+
/**
|
|
169
|
+
* Monte l'éditeur. `content` force le contenu initial (remontage) et, dans ce cas,
|
|
170
|
+
* `autofocus` est neutralisé : le focus est restauré explicitement par `remount()`.
|
|
171
|
+
*/
|
|
172
|
+
private mount;
|
|
173
|
+
private unmount;
|
|
174
|
+
/**
|
|
175
|
+
* Remonte l'éditeur en conservant le contenu, le focus, les déclarations et les valeurs
|
|
176
|
+
* de variables ; l'historique est perdu.
|
|
177
|
+
*/
|
|
178
|
+
private remount;
|
|
179
|
+
/**
|
|
180
|
+
* Fusionne `ASTER_CONFIG` < `config` < inputs dédiés. Le transformateur Word est placé
|
|
181
|
+
* en tête pour que les transformateurs de l'intégrateur reçoivent du HTML déjà nettoyé.
|
|
182
|
+
* Avec `content` (remontage), `autofocus` est désactivé pour ne pas reprendre le focus et
|
|
183
|
+
* `variables` réinjecte l'état du magasin précédent par-dessus la configuration.
|
|
184
|
+
*/
|
|
185
|
+
private resolvedOptions;
|
|
186
|
+
/** Éditeur monté, sinon erreur explicite nommant la méthode appelée trop tôt. */
|
|
187
|
+
private requireEditor;
|
|
188
|
+
/** Relit `getNames()` ; le signal n'est notifié que si la liste change réellement. */
|
|
189
|
+
private refreshVariableNames;
|
|
190
|
+
/**
|
|
191
|
+
* Après un import : déclare les variables trouvées dans le `.docx` (libellé et valeur des
|
|
192
|
+
* contrôles de contenu compris), puis réapplique l'input `variableValues` pour les noms que
|
|
193
|
+
* Word a lui-même valorisés, l'application restant la source de vérité des valeurs.
|
|
194
|
+
*/
|
|
195
|
+
private declareImportedVariables;
|
|
196
|
+
private loadWordPaste;
|
|
197
|
+
/** Nom accessible du contenteditable : `aria-label` et/ou `aria-labelledby`, retirés si vides. */
|
|
198
|
+
private applyAriaAttributes;
|
|
199
|
+
/**
|
|
200
|
+
* Change le placeholder à chaud. L'extension `Placeholder` lit ses options au moment où
|
|
201
|
+
* son plugin ProseMirror est créé (et `extension.options` est une copie à chaque accès),
|
|
202
|
+
* donc on refabrique le plugin via `addProseMirrorPlugins` avec un `placeholder` surchargé
|
|
203
|
+
* et on le substitue à l'ancien par `unregisterPlugin`/`registerPlugin`, API publiques de
|
|
204
|
+
* Tiptap. Le repli sur la chaîne i18n `editor.placeholder` est conservé.
|
|
205
|
+
*/
|
|
206
|
+
private applyPlaceholder;
|
|
207
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AsterEditorComponent, never>;
|
|
208
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<AsterEditorComponent, "aster-editor", never, {
|
|
209
|
+
"toolbar": {
|
|
210
|
+
"alias": "toolbar";
|
|
211
|
+
"required": false;
|
|
212
|
+
"isSignal": true;
|
|
213
|
+
};
|
|
214
|
+
"theme": {
|
|
215
|
+
"alias": "theme";
|
|
216
|
+
"required": false;
|
|
217
|
+
"isSignal": true;
|
|
218
|
+
};
|
|
219
|
+
"locale": {
|
|
220
|
+
"alias": "locale";
|
|
221
|
+
"required": false;
|
|
222
|
+
"isSignal": true;
|
|
223
|
+
};
|
|
224
|
+
"placeholder": {
|
|
225
|
+
"alias": "placeholder";
|
|
226
|
+
"required": false;
|
|
227
|
+
"isSignal": true;
|
|
228
|
+
};
|
|
229
|
+
"readonly": {
|
|
230
|
+
"alias": "readonly";
|
|
231
|
+
"required": false;
|
|
232
|
+
"isSignal": true;
|
|
233
|
+
};
|
|
234
|
+
"config": {
|
|
235
|
+
"alias": "config";
|
|
236
|
+
"required": false;
|
|
237
|
+
"isSignal": true;
|
|
238
|
+
};
|
|
239
|
+
"wordPaste": {
|
|
240
|
+
"alias": "wordPaste";
|
|
241
|
+
"required": false;
|
|
242
|
+
"isSignal": true;
|
|
243
|
+
};
|
|
244
|
+
"ariaLabel": {
|
|
245
|
+
"alias": "ariaLabel";
|
|
246
|
+
"required": false;
|
|
247
|
+
"isSignal": true;
|
|
248
|
+
};
|
|
249
|
+
"ariaLabelledBy": {
|
|
250
|
+
"alias": "ariaLabelledBy";
|
|
251
|
+
"required": false;
|
|
252
|
+
"isSignal": true;
|
|
253
|
+
};
|
|
254
|
+
"variables": {
|
|
255
|
+
"alias": "variables";
|
|
256
|
+
"required": false;
|
|
257
|
+
"isSignal": true;
|
|
258
|
+
};
|
|
259
|
+
"variableValues": {
|
|
260
|
+
"alias": "variableValues";
|
|
261
|
+
"required": false;
|
|
262
|
+
"isSignal": true;
|
|
263
|
+
};
|
|
264
|
+
"variableResolver": {
|
|
265
|
+
"alias": "variableResolver";
|
|
266
|
+
"required": false;
|
|
267
|
+
"isSignal": true;
|
|
268
|
+
};
|
|
269
|
+
"allowUnknownVariables": {
|
|
270
|
+
"alias": "allowUnknownVariables";
|
|
271
|
+
"required": false;
|
|
272
|
+
"isSignal": true;
|
|
273
|
+
};
|
|
274
|
+
"variableSuggestion": {
|
|
275
|
+
"alias": "variableSuggestion";
|
|
276
|
+
"required": false;
|
|
277
|
+
"isSignal": true;
|
|
278
|
+
};
|
|
279
|
+
}, {
|
|
280
|
+
"ready": "ready";
|
|
281
|
+
"changed": "changed";
|
|
282
|
+
"focused": "focused";
|
|
283
|
+
"blurred": "blurred";
|
|
284
|
+
"variablesChanged": "variablesChanged";
|
|
285
|
+
}, never, never, true, never>;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Configuration globale des éditeurs d'une application (ou d'une route, si fournie
|
|
289
|
+
* dans ses `providers`). Le composant la fusionne avec l'input `config`, qui prime,
|
|
290
|
+
* puis avec les inputs dédiés (`toolbar`, `theme`, `locale`, `placeholder`, `readonly`).
|
|
291
|
+
*/
|
|
292
|
+
export declare const ASTER_CONFIG: InjectionToken<Partial<AsterUiOptions$1>>;
|
|
293
|
+
/**
|
|
294
|
+
* Déclare la configuration globale d'Aster dans `ApplicationConfig.providers` ou dans
|
|
295
|
+
* les `providers` d'une route. Fusion superficielle : une clé donnée ici est remplacée
|
|
296
|
+
* en bloc par la même clé passée dans l'input `config` d'un composant.
|
|
297
|
+
*
|
|
298
|
+
* ```ts
|
|
299
|
+
* provideAster({ locale: 'en', theme: 'night', linkPolicy: { defaultTarget: '_blank' } })
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
export declare function provideAster(config: Partial<AsterUiOptions$1>): EnvironmentProviders;
|
|
303
|
+
/**
|
|
304
|
+
* Hook d'upload d'image fourni par l'application (service HTTP, stockage, CDN…).
|
|
305
|
+
* Optionnel : s'il est présent et qu'aucun `upload` n'est passé par `provideAster`
|
|
306
|
+
* ni par l'input `config`, le composant le branche sur `AsterOptions.upload`.
|
|
307
|
+
* Sans handler, les images sont insérées en data URL base64.
|
|
308
|
+
*/
|
|
309
|
+
export declare const ASTER_UPLOAD_HANDLER: InjectionToken<UploadHandler$1>;
|
|
310
|
+
export type { AsterCounts, AsterDocument, AsterEditor, AsterLocale, AsterTheme, AsterUiOptions, AsterVariable, DocxExportOptions, DocxExportVariableOptions, DocxExportWarning, DocxImportResult, DocxImportWarning, DocxVariableMode, GetHtmlOptions, LinkPolicy, PasteTransformer, ToolbarConfig, ToolbarPreset, UploadHandler, VariableRenderMode, VariableResolver, VariableSource, VariableValues };
|