@h-k-dev/angular-email-editor 0.0.5 → 0.0.6
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/fesm2022/h-k-dev-angular-email-editor-actions.mjs +20 -9
- package/fesm2022/h-k-dev-angular-email-editor-actions.mjs.map +1 -1
- package/fesm2022/h-k-dev-angular-email-editor-address-input.mjs +5 -6
- package/fesm2022/h-k-dev-angular-email-editor-address-input.mjs.map +1 -1
- package/fesm2022/h-k-dev-angular-email-editor-suggestion-menu.mjs +6 -6
- package/fesm2022/h-k-dev-angular-email-editor-suggestion-menu.mjs.map +1 -1
- package/fesm2022/h-k-dev-angular-email-editor.mjs +68 -7
- package/fesm2022/h-k-dev-angular-email-editor.mjs.map +1 -1
- package/package.json +1 -1
- package/types/h-k-dev-angular-email-editor-actions.d.ts +16 -7
- package/types/h-k-dev-angular-email-editor-address-input.d.ts +2 -1
- package/types/h-k-dev-angular-email-editor-suggestion-menu.d.ts +6 -6
- package/types/h-k-dev-angular-email-editor.d.ts +81 -14
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"h-k-dev-angular-email-editor-suggestion-menu.mjs","sources":["../../../projects/angular-email-editor/suggestion-menu/suggestion-menu.slots.ts","../../../projects/angular-email-editor/suggestion-menu/suggestion-menu.ts","../../../projects/angular-email-editor/suggestion-menu/suggestion-menu.html","../../../projects/angular-email-editor/suggestion-menu/suggestion-menu-item.ts","../../../projects/angular-email-editor/suggestion-menu/suggestion-menu-section.ts","../../../projects/angular-email-editor/suggestion-menu/public-api.ts","../../../projects/angular-email-editor/suggestion-menu/h-k-dev-angular-email-editor-suggestion-menu.ts"],"sourcesContent":["import { Directive, TemplateRef, inject } from '@angular/core';\nimport { SuggestionGroup } from '@h-k-dev/angular-email-editor';\n\n/**\n * A suggestion menu's header slot, shown on level 2 above the group's\n * children. The default is a back button and the group's title; a host\n * that wants its own — a Material icon button, the group's icon, a\n * breadcrumb — hands the menu a template:\n *\n * <div email-suggestion-menu [state]=\"state()\">\n * <ng-template emailSuggestionMenuHeader let-group let-back=\"back\" let-label=\"backLabel\">\n * <button mat-icon-button tabindex=\"-1\" [attr.aria-label]=\"label\" (click)=\"back()\">\n * <mat-icon>arrow_back</mat-icon>\n * </button>\n * {{ group.title }}\n * </ng-template>\n * …\n * </div>\n *\n * The template renders inside the menu's own `header` box.\n */\n\n/** What the header template is given. */\nexport interface SuggestionMenuHeaderContext {\n /** The group whose children are listed — its title already translated. */\n readonly $implicit: SuggestionGroup;\n /** Back to level 1 with an empty query. */\n readonly back: () => void;\n /** The back control's accessible name, as the menu was given it. */\n readonly backLabel: string;\n}\n\n/** Marks the `ng-template` the menu renders as its level-2 header. */\n@Directive({ selector: 'ng-template[emailSuggestionMenuHeader]' })\nexport class SuggestionMenuHeader {\n readonly template = inject<TemplateRef<SuggestionMenuHeaderContext>>(TemplateRef);\n\n static ngTemplateContextGuard(\n _directive: SuggestionMenuHeader,\n context: unknown,\n ): context is SuggestionMenuHeaderContext {\n return true;\n }\n}\n","import {\n Component,\n DestroyRef,\n ElementRef,\n inject,\n\n // Signals\n afterRenderEffect,\n computed,\n contentChild,\n debounced,\n input,\n linkedSignal,\n viewChild,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { SuggestionItem, SuggestionMenuState, measureMenuPlacement } from '@h-k-dev/angular-email-editor';\nimport { SuggestionMenuHeader, SuggestionMenuHeaderContext } from './suggestion-menu.slots';\n\n/**\n * A suggestion menu's floating box — the element `createSuggestionMenu` is\n * given, rendered from the state it reports. The extension does the work\n * (finding the trigger, filtering, paging, the keys, placing the box,\n * applying); this gives the state its roles and ids, so the editor's\n * `aria-controls` and `aria-activedescendant` land on real elements, keeps\n * the next page coming as the list scrolls, and says what is going on.\n *\n * **The pair.** The menu is the container; the host renders one\n * `[email-suggestion-menu-item]` per item into it and decides what a row\n * shows (an icon, the title, a detail). Rows are options of the menu's\n * listbox and never take focus: the caret stays in the editor, which is the\n * combobox. One pair serves every trigger — `/`, `{{`, `||` — at once: they\n * never open together, so a menu of several triggers is still one element\n * and one state, which says whose list it is (`trigger`, `label`).\n *\n * <div email-suggestion-menu #menu [state]=\"state()\">\n * @for (item of state()?.items; track item.id) {\n * <div email-suggestion-menu-item [item]=\"item\">{{ item.title }}</div>\n * }\n * </div>\n *\n * createSuggestionMenu({ element: menu, onChange: (s) => state.set(s), triggers: [\n * { trigger: '/', label: 'Insert block', items: extensionSuggestions },\n * { trigger: '{{', label: 'Tokens', source: fetchMergeTags },\n * ] })\n *\n * **Two levels.** Inside a group the menu shows a header above the list — a\n * back button and the group's title by default, or the host's\n * `ng-template[emailSuggestionMenuHeader]` — names the listbox after the\n * group, and says \"No results\" rather than closing when nothing matches.\n *\n * **Said twice, differently.** What is going on shows as a line under the\n * list, at once. A screen reader hears it from a separate live region that\n * waits for the typing to settle (`announceDelay`) and also counts the\n * results — the highlighted option's id does not change when the list is\n * filtered under it, so nothing else would say the list is a new one.\n *\n * Every word it says is an input, English by default.\n */\n@Component({\n selector: '[email-suggestion-menu]',\n imports: [NgTemplateOutlet],\n templateUrl: './suggestion-menu.html',\n styleUrl: './suggestion-menu.scss',\n host: {\n '[attr.data-level]': 'state()?.level ?? 1',\n },\n})\nexport class SuggestionMenu {\n /** The extension's latest state — undefined before the editor mounts. */\n readonly state = input<SuggestionMenuState>();\n\n /** Names the listbox on level 1 when the open trigger has no `label` of\n its own — a menu of several triggers names each list there (\"Insert\n block\", \"Personalization tokens\"); level 2 is named by its group. */\n readonly label = input('Suggestions');\n /** The level-2 back button's accessible name. */\n readonly backLabel = input('Back');\n /** Said while a source is still searching. */\n readonly loadingLabel = input('Searching…');\n /** Said on level 2 when nothing matches. */\n readonly emptyLabel = input('No results');\n /** Said while a further page is on its way. */\n readonly loadingMoreLabel = input('Loading more…');\n /** Said when the source's answer failed. */\n readonly errorLabel = input('Couldn’t load suggestions');\n /** Announced once a list is in: how many rows it has. */\n readonly resultsLabel = input<(count: number) => string>((count) =>\n count === 1 ? '1 result' : `${count} results`,\n );\n /** Milliseconds the announcement waits for the typing to settle, so a\n screen reader hears the list that stayed, not one per letter. Going\n quiet (the menu closes) never waits. 0 announces at once. */\n readonly announceDelay = input(400);\n /** Gap between the trigger's line and the menu, in px. */\n readonly offset = input(4);\n\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n\n /** The state's list. The extension reports a new state for every arrow\n press but the same list until it changes — so what hangs off the list\n (the index below, every row's position) sits an arrow press out. */\n readonly #items = computed(() => this.state()?.items);\n\n /** Each item's position in the list, looked up once per list — rows ask\n by identity, so a list of n rows costs n lookups, not n². */\n readonly #indices = computed(\n () => new Map(this.#items()?.map((item, index) => [item, index]) ?? []),\n );\n\n /** The keyboard-highlighted row's index; -1 before there is a state. */\n readonly activeIndex = computed(() => this.state()?.activeIndex ?? -1);\n\n /** The extension's id for the option at an index — the same function for\n the menu's whole life. */\n readonly optionId = computed(() => this.state()?.optionId);\n\n /** Where `item` sits in the current list; -1 when it is not in it. */\n indexOf(item: SuggestionItem): number {\n return this.#indices().get(item) ?? -1;\n }\n\n protected readonly header = contentChild(SuggestionMenuHeader);\n protected readonly listbox = viewChild.required<ElementRef<HTMLElement>>('listbox');\n protected readonly end = viewChild.required<ElementRef<HTMLElement>>('end');\n\n /** The group being searched, on level 2. */\n protected readonly parent = computed(() => this.state()?.parent ?? null);\n\n protected readonly listLabel = computed(\n () => this.parent()?.title ?? this.state()?.label ?? this.label(),\n );\n\n /** The header template's context, while there is a group to head. */\n protected readonly headerContext = computed((): SuggestionMenuHeaderContext | null => {\n const group = this.parent();\n return group && { $implicit: group, back: this.back, backLabel: this.backLabel() };\n });\n\n /** The line under the list: failed, searching, loading more, nothing\n found, or nothing. Not \"searching\" over stale rows — dimmed, they say\n it themselves, and a line that came and went with every keystroke\n would resize the box (and have it placed again) twice per letter. */\n protected readonly status = computed(() => {\n const state = this.state();\n if (!state?.open) return '';\n if (state.error !== null) return this.errorLabel();\n if (state.loading) return state.stale ? '' : this.loadingLabel();\n if (state.loadingMore) return this.loadingMoreLabel();\n if (state.level === 2 && !state.items.length) return this.emptyLabel();\n return '';\n });\n\n /** What a screen reader should hear next: the status line, or how many\n rows the list has now. While the rows on screen answer the previous\n query there is no news yet — what was said last stands. */\n readonly #announcement = linkedSignal<\n { state: SuggestionMenuState | undefined; status: string; results: (count: number) => string },\n string\n >({\n source: () => ({ state: this.state(), status: this.status(), results: this.resultsLabel() }),\n computation: ({ state, status, results }, previous) => {\n if (!state?.open) return '';\n if (status) return status;\n if (state.loading) return previous?.value ?? '';\n return results(state.items.length);\n },\n });\n\n /** The announcement, once the typing has settled. */\n protected readonly announced = debounced(this.#announcement, (text) => {\n const delay = this.announceDelay();\n return text && delay > 0\n ? new Promise<void>((resolve) => setTimeout(resolve, delay))\n : undefined;\n });\n\n /** A page can be asked for right now: more exist and nothing is out. */\n readonly #canLoadMore = computed(() => {\n const state = this.state();\n return !!state?.open && state.hasMore && !state.loading && !state.loadingMore;\n });\n\n /** What the box's place depends on: where the session starts, and what\n decides its size (rows, header, status line, query). An arrow press\n changes none of it, so it measures nothing. */\n readonly #layout = computed(\n () => {\n const state = this.state();\n if (!state?.open || !state.range) return null;\n return {\n from: state.range.from,\n rows: state.items.length,\n level: state.level,\n query: state.query,\n status: this.status(),\n clientRect: state.clientRect,\n offset: this.offset(),\n };\n },\n {\n equal: (a, b) =>\n a === b ||\n (!!a &&\n !!b &&\n a.from === b.from &&\n a.rows === b.rows &&\n a.level === b.level &&\n a.query === b.query &&\n a.status === b.status &&\n a.offset === b.offset),\n },\n );\n\n /** What moves the highlight: the row it is on, and the list it is in — a\n level, a query. Null while closed. */\n readonly #highlight = computed(() => {\n const state = this.state();\n return state?.open ? `${state.level}:${state.query}:${state.activeIndex}` : null;\n });\n\n /** Watches the list's end marker: its coming within two rows of the\n listbox's bottom edge asks for the next page. An observer, not a scroll\n listener — it speaks only when the marker crosses in, so scrolling\n costs nothing. Made on first use: its root is the rendered listbox. */\n #endObserver: IntersectionObserver | undefined;\n\n constructor() {\n inject(DestroyRef).onDestroy(() => this.#endObserver?.disconnect());\n\n // Watched only while a page can be loaded. Observing afresh reports the\n // marker's current state, so a page too short to fill the box (the\n // marker still in view once it lands) asks for the next one straight\n // away, and a list that scrolls waits for the scroll.\n afterRenderEffect({\n read: () => {\n if (typeof IntersectionObserver === 'undefined') return;\n const canLoad = this.#canLoadMore();\n // Any new list re-arms the watch, not only a longer one: a source\n // that answers at once never passes through `loading`, and its next\n // list can have as many rows as the last.\n this.#items();\n const end = this.end().nativeElement;\n this.#endObserver ??= new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) this.state()?.loadMore();\n },\n { root: this.listbox().nativeElement, rootMargin: '0px 0px 64px 0px' },\n );\n this.#endObserver.unobserve(end);\n if (canLoad) this.#endObserver.observe(end);\n },\n });\n\n // Placing the box: after its rows are rendered, measured in one phase and\n // written in the next — the plugin never touches the element, so no read\n // follows a write inside a keystroke. Shown only once it is in place.\n //\n // A box that fits on neither side of the line is shrunk to the side with\n // more room. The cap goes on the listbox, not the box: the box keeps its\n // own max-height (the --email-suggestion-menu-max-height token) to be\n // read, and its height without the cap is its rendered height plus what\n // the capped list hides — a box measured at its last cap would choose its\n // side by the old room and flip back and forth.\n afterRenderEffect({\n earlyRead: () => {\n const layout = this.#layout();\n const anchor = layout?.clientRect();\n if (!layout || !anchor) return null;\n const list = this.listbox().nativeElement;\n const rendered = this.#host.offsetHeight;\n const cap = parseFloat(getComputedStyle(this.#host).maxHeight);\n const full = rendered + list.scrollHeight - list.clientHeight;\n const height = cap >= 0 ? Math.min(full, cap) : full;\n const place = measureMenuPlacement(anchor, this.#host, layout.offset, height);\n return place && { ...place, chrome: rendered - list.offsetHeight };\n },\n write: (placement) => {\n const place = placement();\n const style = this.#host.style;\n const visibility = place ? 'visible' : 'hidden';\n if (place) {\n const left = `${place.left}px`;\n const top = `${place.top}px`;\n const listHeight =\n place.maxHeight === null ? '' : `${Math.max(place.maxHeight - place.chrome, 0)}px`;\n const list = this.listbox().nativeElement.style;\n if (style.left !== left) style.left = left;\n if (style.top !== top) style.top = top;\n if (list.maxHeight !== listHeight) list.maxHeight = listHeight;\n }\n if (style.visibility !== visibility) style.visibility = visibility;\n },\n });\n\n // The highlighted row stays visible as the arrows walk past the fold —\n // one watch for the whole list, not one per row: measured in one phase,\n // scrolled in the next, the listbox only. A new query is a new list\n // (back at its top row); a page landing under a list scrolled by hand is\n // not, and must not pull it back.\n afterRenderEffect({\n earlyRead: () => {\n if (this.#highlight() === null) return null;\n const list = this.listbox().nativeElement;\n const row = list.querySelector<HTMLElement>('[data-active]');\n if (!row) return null;\n const { offsetTop: top, offsetHeight: height } = row;\n const { scrollTop, clientHeight } = list;\n if (top < scrollTop) return { list, scrollTop: top };\n if (top + height > scrollTop + clientHeight) {\n return { list, scrollTop: top + height - clientHeight };\n }\n return null;\n },\n write: (scroll) => {\n const target = scroll();\n if (target) target.list.scrollTop = target.scrollTop;\n },\n });\n\n // A level starts at its top: entering a group or leaving one does not\n // keep the other list's scroll position.\n afterRenderEffect({\n write: () => {\n this.parent();\n this.listbox().nativeElement.scrollTop = 0;\n },\n });\n }\n\n protected readonly back = (): void => this.state()?.back();\n}\n","@if (parent(); as group) {\n <div data-slot=\"header\">\n @if (header(); as slot) {\n <ng-container *ngTemplateOutlet=\"slot.template; context: headerContext()\" />\n } @else {\n <!-- The pointer's way back; the keyboard's is Backspace in the editor,\n which keeps the focus — so this never joins the tab order. -->\n <button\n type=\"button\"\n data-slot=\"back\"\n tabindex=\"-1\"\n [attr.aria-label]=\"backLabel()\"\n (click)=\"back()\"\n >\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M15.41 7.41 14 6l-6 6 6 6 1.41-1.41L10.83 12z\" />\n </svg>\n </button>\n <span data-slot=\"title\">{{ group.title }}</span>\n }\n </div>\n}\n\n<div\n #listbox\n role=\"listbox\"\n data-slot=\"listbox\"\n [attr.id]=\"state()?.listboxId\"\n [attr.aria-label]=\"listLabel()\"\n [attr.aria-busy]=\"state()?.loading || state()?.loadingMore || null\"\n [attr.data-stale]=\"state()?.stale || null\"\n>\n <ng-content />\n <!-- The end of the list, watched for the next page (never an option). -->\n <div #end data-slot=\"end\" role=\"none\" aria-hidden=\"true\"></div>\n</div>\n\n<!-- What is going on, for the eye: at once, collapsed while there is nothing\n to say. -->\n<div\n data-slot=\"status\"\n aria-hidden=\"true\"\n [attr.data-empty]=\"!status() || null\"\n [textContent]=\"status()\"\n></div>\n\n<!-- …and for a screen reader: settled, and with the result count. Always in\n the accessibility tree — visible while the box around it is hidden — so\n the first words of an opening menu are heard too. -->\n<div role=\"status\" data-slot=\"announcer\">{{ announced.value() }}</div>\n","import { Component, computed, inject, input } from '@angular/core';\nimport { SuggestionItem } from '@h-k-dev/angular-email-editor';\nimport { SuggestionMenu } from './suggestion-menu';\n\n/**\n * One row of a suggestion menu: an option of its listbox, standing for one of\n * the state's items. The host fills the row; the row takes its id (the one\n * the editor's `aria-activedescendant` names), reflects the highlight as\n * `aria-selected` and `data-active` — which is what the menu keeps scrolled\n * into view — and applies its item on click: a group opens, a command runs.\n *\n * Never focusable, never a button: the caret stays in the editor, and the\n * extension keeps a press on the menu from taking it away.\n */\n@Component({\n selector: '[email-suggestion-menu-item]',\n template: '<ng-content />',\n styleUrl: './suggestion-menu-item.scss',\n host: {\n role: 'option',\n '[attr.id]': 'id()',\n '[attr.aria-selected]': 'active()',\n '[attr.data-active]': 'active() || null',\n '[attr.data-group]': '!!item().children || null',\n '(click)': 'select()',\n },\n})\nexport class SuggestionMenuItem {\n /** The item this row stands for — one of the menu state's `items`. */\n readonly item = input.required<SuggestionItem>();\n\n readonly #menu = inject(SuggestionMenu);\n\n readonly #index = computed(() => this.#menu.indexOf(this.item()));\n\n /** The keyboard highlight is on this row. */\n readonly active = computed(() => {\n const index = this.#index();\n return index >= 0 && index === this.#menu.activeIndex();\n });\n\n protected readonly id = computed(() => {\n const optionId = this.#menu.optionId();\n const index = this.#index();\n return optionId && index >= 0 ? optionId(index) : null;\n });\n\n protected select(): void {\n this.#menu.state()?.select(this.item());\n }\n}\n","import { Component } from '@angular/core';\n\n/**\n * A heading in a suggestion menu's list: the words of a section\n * (`SuggestionItem.section`, worded by the state's `sectionTitle`), shown\n * where the section changes from one row to the next. Never an option: it\n * takes no highlight, no click, and no place in the count — presentation,\n * the way a chat's slash menu heads its groups.\n *\n * @for (item of state.items; track item.id) {\n * @if (item.section && item.section !== state.items[$index - 1]?.section) {\n * <div email-suggestion-menu-section>{{ state.sectionTitle(item.section) }}</div>\n * }\n * <div email-suggestion-menu-item [item]=\"item\">…</div>\n * }\n */\n@Component({\n selector: '[email-suggestion-menu-section]',\n template: '<ng-content />',\n styleUrl: './suggestion-menu-section.scss',\n host: { role: 'presentation' },\n})\nexport class SuggestionMenuSection {}\n","/*\n * Public API Surface of @h-k-dev/angular-email-editor/suggestion-menu\n */\n\nexport * from './suggestion-menu';\nexport * from './suggestion-menu-item';\nexport * from './suggestion-menu.slots';\nexport * from './suggestion-menu-section';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"h-k-dev-angular-email-editor-suggestion-menu.mjs","sources":["../../../projects/angular-email-editor/suggestion-menu/suggestion-menu.slots.ts","../../../projects/angular-email-editor/suggestion-menu/suggestion-menu.ts","../../../projects/angular-email-editor/suggestion-menu/suggestion-menu.html","../../../projects/angular-email-editor/suggestion-menu/suggestion-menu-item.ts","../../../projects/angular-email-editor/suggestion-menu/suggestion-menu-section.ts","../../../projects/angular-email-editor/suggestion-menu/public-api.ts","../../../projects/angular-email-editor/suggestion-menu/h-k-dev-angular-email-editor-suggestion-menu.ts"],"sourcesContent":["import { Directive, TemplateRef, inject } from '@angular/core';\nimport { SuggestionGroup } from '@h-k-dev/angular-email-editor';\n\n/**\n * A suggestion menu's header slot, shown on level 2 above the group's\n * children. The default is a back button and the group's title; a host\n * that wants its own — a Material icon button, the group's icon, a\n * breadcrumb — hands the menu a template:\n *\n * <div email-suggestion-menu [state]=\"state()\">\n * <ng-template emailSuggestionMenuHeader let-group let-back=\"back\" let-label=\"backLabel\">\n * <button mat-icon-button tabindex=\"-1\" [attr.aria-label]=\"label\" (click)=\"back()\">\n * <mat-icon>arrow_back</mat-icon>\n * </button>\n * {{ group.title }}\n * </ng-template>\n * …\n * </div>\n *\n * The template renders inside the menu's own `header` box.\n */\n\n/** What the header template is given. */\nexport interface SuggestionMenuHeaderContext {\n /** The group whose children are listed — its title already translated. */\n readonly $implicit: SuggestionGroup;\n /** Back to level 1 with an empty query. */\n readonly back: () => void;\n /** The back control's accessible name, as the menu was given it. */\n readonly backLabel: string;\n}\n\n/** Marks the `ng-template` the menu renders as its level-2 header. */\n@Directive({ selector: 'ng-template[emailSuggestionMenuHeader]' })\nexport class SuggestionMenuHeader {\n readonly template = inject<TemplateRef<SuggestionMenuHeaderContext>>(TemplateRef);\n\n static ngTemplateContextGuard(\n _directive: SuggestionMenuHeader,\n context: unknown,\n ): context is SuggestionMenuHeaderContext {\n return true;\n }\n}\n","import {\n Component,\n DestroyRef,\n ElementRef,\n inject,\n\n // Signals\n afterRenderEffect,\n computed,\n contentChild,\n debounced,\n input,\n linkedSignal,\n viewChild,\n} from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport { SuggestionItem, SuggestionMenuState, measureMenuPlacement } from '@h-k-dev/angular-email-editor';\nimport { SuggestionMenuHeader, SuggestionMenuHeaderContext } from './suggestion-menu.slots';\n\n/**\n * A suggestion menu's floating box — the element `createSuggestionMenu` is\n * given, rendered from the state it reports. The extension does the work\n * (finding the trigger, filtering, paging, the keys, placing the box,\n * applying); this gives the state its roles and ids, so the editor's\n * `aria-controls` and `aria-activedescendant` land on real elements, keeps\n * the next page coming as the list scrolls, and says what is going on.\n *\n * **The pair.** The menu is the container; the host renders one\n * `[email-suggestion-menu-item]` per item into it and decides what a row\n * shows (an icon, the title, a detail). Rows are options of the menu's\n * listbox and never take focus: the caret stays in the editor, which is the\n * combobox. One pair serves every trigger — `/`, `{{`, `||` — at once: they\n * never open together, so a menu of several triggers is still one element\n * and one state, which says whose list it is (`trigger`, `label`).\n *\n * <div email-suggestion-menu #menu [state]=\"state()\">\n * @for (item of state()?.items; track item.id) {\n * <div email-suggestion-menu-item [item]=\"item\">{{ item.title }}</div>\n * }\n * </div>\n *\n * createSuggestionMenu({ element: menu, onChange: (s) => state.set(s), triggers: [\n * { trigger: '/', label: 'Insert block', items: extensionSuggestions },\n * { trigger: '{{', label: 'Tokens', source: fetchMergeTags },\n * ] })\n *\n * **Two levels.** Inside a group the menu shows a header above the list — a\n * back button and the group's title by default, or the host's\n * `ng-template[emailSuggestionMenuHeader]` — names the listbox after the\n * group, and says \"No results\" rather than closing when nothing matches.\n *\n * **Said twice, differently.** What is going on shows as a line under the\n * list, at once. A screen reader hears it from a separate live region that\n * waits for the typing to settle (`announceDelay`) and also counts the\n * results — the highlighted option's id does not change when the list is\n * filtered under it, so nothing else would say the list is a new one.\n *\n * Every word it says is an input, English by default.\n */\n@Component({\n selector: '[email-suggestion-menu]',\n imports: [NgTemplateOutlet],\n templateUrl: './suggestion-menu.html',\n styleUrl: './suggestion-menu.scss',\n host: {\n '[attr.data-level]': 'state()?.level ?? 1',\n },\n})\nexport class SuggestionMenu {\n /** The extension's latest state — undefined before the editor mounts. */\n readonly state = input<SuggestionMenuState>();\n\n /** Names the listbox on level 1 when the open trigger has no `label` of\n its own — a menu of several triggers names each list there (\"Insert\n block\", \"Personalization tokens\"); level 2 is named by its group. */\n readonly label = input('Suggestions');\n /** The level-2 back button's accessible name. */\n readonly backLabel = input('Back');\n /** Said while a source is still searching. */\n readonly loadingLabel = input('Searching…');\n /** Said on level 2 when nothing matches. */\n readonly emptyLabel = input('No results');\n /** Said while a further page is on its way. */\n readonly loadingMoreLabel = input('Loading more…');\n /** Said when the source's answer failed. */\n readonly errorLabel = input('Couldn’t load suggestions');\n /** Announced once a list is in: how many rows it has. */\n readonly resultsLabel = input<(count: number) => string>((count) =>\n count === 1 ? '1 result' : `${count} results`,\n );\n /** Milliseconds the announcement waits for the typing to settle, so a\n screen reader hears the list that stayed, not one per letter. Going\n quiet (the menu closes) never waits. 0 announces at once. */\n readonly announceDelay = input(400);\n /** Gap between the trigger's line and the menu, in px. */\n readonly offset = input(4);\n\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n\n /** The state's list. The extension reports a new state for every arrow\n press but the same list until it changes — so what hangs off the list\n (the index below, every row's position) sits an arrow press out. */\n readonly #items = computed(() => this.state()?.items);\n\n /** Each item's position in the list, looked up once per list — rows ask\n by identity, so a list of n rows costs n lookups, not n². */\n readonly #indices = computed(\n () => new Map<SuggestionItem, number>(this.#items()?.map((item, index) => [item, index]) ?? []),\n );\n\n /** The keyboard-highlighted row's index; -1 before there is a state. */\n readonly activeIndex = computed(() => this.state()?.activeIndex ?? -1);\n\n /** The extension's id for the option at an index — the same function for\n the menu's whole life. */\n readonly optionId = computed(() => this.state()?.optionId);\n\n /** Where `item` sits in the current list; -1 when it is not in it. */\n indexOf(item: SuggestionItem): number {\n return this.#indices().get(item) ?? -1;\n }\n\n protected readonly header = contentChild(SuggestionMenuHeader);\n protected readonly listbox = viewChild.required<ElementRef<HTMLElement>>('listbox');\n protected readonly end = viewChild.required<ElementRef<HTMLElement>>('end');\n\n /** The group being searched, on level 2. */\n protected readonly parent = computed(() => this.state()?.parent ?? null);\n\n protected readonly listLabel = computed(\n () => this.parent()?.title ?? this.state()?.label ?? this.label(),\n );\n\n /** The header template's context, while there is a group to head. */\n protected readonly headerContext = computed((): SuggestionMenuHeaderContext | null => {\n const group = this.parent();\n return group && { $implicit: group, back: this.back, backLabel: this.backLabel() };\n });\n\n /** The line under the list: failed, searching, loading more, nothing\n found, or nothing. Not \"searching\" over stale rows — dimmed, they say\n it themselves, and a line that came and went with every keystroke\n would resize the box (and have it placed again) twice per letter. */\n protected readonly status = computed(() => {\n const state = this.state();\n if (!state?.open) return '';\n if (state.error !== null) return this.errorLabel();\n if (state.loading) return state.stale ? '' : this.loadingLabel();\n if (state.loadingMore) return this.loadingMoreLabel();\n if (state.level === 2 && !state.items.length) return this.emptyLabel();\n return '';\n });\n\n /** What a screen reader should hear next: the status line, or how many\n rows the list has now. While the rows on screen answer the previous\n query there is no news yet — what was said last stands. */\n readonly #announcement = linkedSignal<\n { state: SuggestionMenuState | undefined; status: string; results: (count: number) => string },\n string\n >({\n source: () => ({ state: this.state(), status: this.status(), results: this.resultsLabel() }),\n computation: ({ state, status, results }, previous) => {\n if (!state?.open) return '';\n if (status) return status;\n if (state.loading) return previous?.value ?? '';\n return results(state.items.length);\n },\n });\n\n /** The announcement, once the typing has settled. */\n protected readonly announced = debounced(this.#announcement, (text) => {\n const delay = this.announceDelay();\n return text && delay > 0\n ? new Promise<void>((resolve) => setTimeout(resolve, delay))\n : undefined;\n });\n\n /** A page can be asked for right now: more exist and nothing is out. */\n readonly #canLoadMore = computed(() => {\n const state = this.state();\n return !!state?.open && state.hasMore && !state.loading && !state.loadingMore;\n });\n\n /** What the box's place depends on: where the session starts, and what\n decides its size (rows, header, status line, query). An arrow press\n changes none of it, so it measures nothing. */\n readonly #layout = computed(\n () => {\n const state = this.state();\n if (!state?.open || !state.range) return null;\n return {\n from: state.range.from,\n rows: state.items.length,\n level: state.level,\n query: state.query,\n status: this.status(),\n clientRect: state.clientRect,\n offset: this.offset(),\n };\n },\n {\n equal: (a, b) =>\n a === b ||\n (!!a &&\n !!b &&\n a.from === b.from &&\n a.rows === b.rows &&\n a.level === b.level &&\n a.query === b.query &&\n a.status === b.status &&\n a.offset === b.offset),\n },\n );\n\n /** What moves the highlight: the row it is on, and the list it is in — a\n level, a query. Null while closed. */\n readonly #highlight = computed(() => {\n const state = this.state();\n return state?.open ? `${state.level}:${state.query}:${state.activeIndex}` : null;\n });\n\n /** Watches the list's end marker: its coming within two rows of the\n listbox's bottom edge asks for the next page. An observer, not a scroll\n listener — it speaks only when the marker crosses in, so scrolling\n costs nothing. Made on first use: its root is the rendered listbox. */\n #endObserver: IntersectionObserver | undefined;\n\n constructor() {\n inject(DestroyRef).onDestroy(() => this.#endObserver?.disconnect());\n\n // Watched only while a page can be loaded. Observing afresh reports the\n // marker's current state, so a page too short to fill the box (the\n // marker still in view once it lands) asks for the next one straight\n // away, and a list that scrolls waits for the scroll.\n afterRenderEffect({\n read: () => {\n if (typeof IntersectionObserver === 'undefined') return;\n const canLoad = this.#canLoadMore();\n // Any new list re-arms the watch, not only a longer one: a source\n // that answers at once never passes through `loading`, and its next\n // list can have as many rows as the last.\n this.#items();\n const end = this.end().nativeElement;\n this.#endObserver ??= new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) this.state()?.loadMore();\n },\n { root: this.listbox().nativeElement, rootMargin: '0px 0px 64px 0px' },\n );\n this.#endObserver.unobserve(end);\n if (canLoad) this.#endObserver.observe(end);\n },\n });\n\n // Placing the box: after its rows are rendered, measured in one phase and\n // written in the next — the plugin never touches the element, so no read\n // follows a write inside a keystroke. Shown only once it is in place.\n //\n // A box that fits on neither side of the line is shrunk to the side with\n // more room. The cap goes on the listbox, not the box: the box keeps its\n // own max-height (the --email-suggestion-menu-max-height token) to be\n // read, and its height without the cap is its rendered height plus what\n // the capped list hides — a box measured at its last cap would choose its\n // side by the old room and flip back and forth.\n afterRenderEffect({\n earlyRead: () => {\n const layout = this.#layout();\n const anchor = layout?.clientRect();\n if (!layout || !anchor) return null;\n const list = this.listbox().nativeElement;\n const rendered = this.#host.offsetHeight;\n const cap = parseFloat(getComputedStyle(this.#host).maxHeight);\n const full = rendered + list.scrollHeight - list.clientHeight;\n const height = cap >= 0 ? Math.min(full, cap) : full;\n const place = measureMenuPlacement(anchor, this.#host, layout.offset, height);\n return place && { ...place, chrome: rendered - list.offsetHeight };\n },\n write: (placement) => {\n const place = placement();\n const style = this.#host.style;\n const visibility = place ? 'visible' : 'hidden';\n if (place) {\n const left = `${place.left}px`;\n const top = `${place.top}px`;\n const listHeight =\n place.maxHeight === null ? '' : `${Math.max(place.maxHeight - place.chrome, 0)}px`;\n const list = this.listbox().nativeElement.style;\n if (style.left !== left) style.left = left;\n if (style.top !== top) style.top = top;\n if (list.maxHeight !== listHeight) list.maxHeight = listHeight;\n }\n if (style.visibility !== visibility) style.visibility = visibility;\n },\n });\n\n // The highlighted row stays visible as the arrows walk past the fold —\n // one watch for the whole list, not one per row: measured in one phase,\n // scrolled in the next, the listbox only. A new query is a new list\n // (back at its top row); a page landing under a list scrolled by hand is\n // not, and must not pull it back.\n afterRenderEffect({\n earlyRead: () => {\n if (this.#highlight() === null) return null;\n const list = this.listbox().nativeElement;\n const row = list.querySelector<HTMLElement>('[data-active]');\n if (!row) return null;\n const { offsetTop: top, offsetHeight: height } = row;\n const { scrollTop, clientHeight } = list;\n if (top < scrollTop) return { list, scrollTop: top };\n if (top + height > scrollTop + clientHeight) {\n return { list, scrollTop: top + height - clientHeight };\n }\n return null;\n },\n write: (scroll) => {\n const target = scroll();\n if (target) target.list.scrollTop = target.scrollTop;\n },\n });\n\n // A level starts at its top: entering a group or leaving one does not\n // keep the other list's scroll position.\n afterRenderEffect({\n write: () => {\n this.parent();\n this.listbox().nativeElement.scrollTop = 0;\n },\n });\n }\n\n protected readonly back = (): void => this.state()?.back();\n}\n","@if (parent(); as group) {\n <div data-slot=\"header\">\n @if (header(); as slot) {\n <ng-container *ngTemplateOutlet=\"slot.template; context: headerContext()\" />\n } @else {\n <!-- The pointer's way back; the keyboard's is Backspace in the editor,\n which keeps the focus — so this never joins the tab order. -->\n <button\n type=\"button\"\n data-slot=\"back\"\n tabindex=\"-1\"\n [attr.aria-label]=\"backLabel()\"\n (click)=\"back()\"\n >\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M15.41 7.41 14 6l-6 6 6 6 1.41-1.41L10.83 12z\" />\n </svg>\n </button>\n <span data-slot=\"title\">{{ group.title }}</span>\n }\n </div>\n}\n\n<div\n #listbox\n role=\"listbox\"\n data-slot=\"listbox\"\n [attr.id]=\"state()?.listboxId\"\n [attr.aria-label]=\"listLabel()\"\n [attr.aria-busy]=\"state()?.loading || state()?.loadingMore || null\"\n [attr.data-stale]=\"state()?.stale || null\"\n>\n <ng-content />\n <!-- The end of the list, watched for the next page (never an option). -->\n <div #end data-slot=\"end\" role=\"none\" aria-hidden=\"true\"></div>\n</div>\n\n<!-- What is going on, for the eye: at once, collapsed while there is nothing\n to say. -->\n<div\n data-slot=\"status\"\n aria-hidden=\"true\"\n [attr.data-empty]=\"!status() || null\"\n [textContent]=\"status()\"\n></div>\n\n<!-- …and for a screen reader: settled, and with the result count. Always in\n the accessibility tree — visible while the box around it is hidden — so\n the first words of an opening menu are heard too. -->\n<div role=\"status\" data-slot=\"announcer\">{{ announced.value() }}</div>\n","import { Component, computed, inject, input } from '@angular/core';\nimport { SuggestionItem } from '@h-k-dev/angular-email-editor';\nimport { SuggestionMenu } from './suggestion-menu';\n\n/**\n * One row of a suggestion menu: an option of its listbox, standing for one of\n * the state's items. The host fills the row; the row takes its id (the one\n * the editor's `aria-activedescendant` names), reflects the highlight as\n * `aria-selected` and `data-active` — which is what the menu keeps scrolled\n * into view — and applies its item on click: a group opens, a command runs.\n *\n * Never focusable, never a button: the caret stays in the editor, and the\n * extension keeps a press on the menu from taking it away.\n */\n@Component({\n selector: '[email-suggestion-menu-item]',\n template: '<ng-content />',\n styleUrl: './suggestion-menu-item.scss',\n host: {\n role: 'option',\n '[attr.id]': 'id()',\n '[attr.aria-selected]': 'active()',\n '[attr.data-active]': 'active() || null',\n '[attr.data-group]': '!!item().children || null',\n '(click)': 'select()',\n },\n})\nexport class SuggestionMenuItem {\n /** The item this row stands for — one of the menu state's `items`. */\n readonly item = input.required<SuggestionItem>();\n\n readonly #menu = inject(SuggestionMenu);\n\n readonly #index = computed(() => this.#menu.indexOf(this.item()));\n\n /** The keyboard highlight is on this row. */\n readonly active = computed(() => {\n const index = this.#index();\n return index >= 0 && index === this.#menu.activeIndex();\n });\n\n protected readonly id = computed(() => {\n const optionId = this.#menu.optionId();\n const index = this.#index();\n return optionId && index >= 0 ? optionId(index) : null;\n });\n\n protected select(): void {\n this.#menu.state()?.select(this.item());\n }\n}\n","import { Component } from '@angular/core';\n\n/**\n * A heading in a suggestion menu's list: the words of a section\n * (`SuggestionItem.section`), shown where the section changes from one row\n * to the next — the state says where, and in which words, as each item's\n * `heading`. Never an option: it takes no highlight, no click, and no place\n * in the count — presentation, the way a chat's slash menu heads its groups.\n *\n * @for (item of state.items; track item.id) {\n * @if (item.heading; as heading) {\n * <div email-suggestion-menu-section>{{ heading }}</div>\n * }\n * <div email-suggestion-menu-item [item]=\"item\">…</div>\n * }\n */\n@Component({\n selector: '[email-suggestion-menu-section]',\n template: '<ng-content />',\n styleUrl: './suggestion-menu-section.scss',\n host: { role: 'presentation' },\n})\nexport class SuggestionMenuSection {}\n","/*\n * Public API Surface of @h-k-dev/angular-email-editor/suggestion-menu\n */\n\nexport * from './suggestion-menu';\nexport * from './suggestion-menu-item';\nexport * from './suggestion-menu.slots';\nexport * from './suggestion-menu-section';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -16116,8 +16116,12 @@ const commandWord = (text) => text.trim().toLowerCase().split(/\s+/).join('-');
|
|
|
16116
16116
|
/** A group is entered by its (translated) title, its id, or any keyword —
|
|
16117
16117
|
the original title among them once translated. */
|
|
16118
16118
|
const groupWords = (group) => [group.id, group.title, ...(group.keywords ?? [])].map(commandWord);
|
|
16119
|
+
/** A map's own entry for an id — never what every object inherits: an id
|
|
16120
|
+
such as `constructor` or `toString` finds nothing in a map that does
|
|
16121
|
+
not name it. */
|
|
16122
|
+
const own = (map, id) => map && Object.hasOwn(map, id) ? map[id] : undefined;
|
|
16119
16123
|
function localize(item, i18n) {
|
|
16120
|
-
const label = typeof i18n === 'function' ? i18n(item.id) : i18n
|
|
16124
|
+
const label = typeof i18n === 'function' ? i18n(item.id) : own(i18n, item.id);
|
|
16121
16125
|
if (!label)
|
|
16122
16126
|
return item;
|
|
16123
16127
|
const keywords = [...(item.keywords ?? []), ...(label.keywords ?? [])];
|
|
@@ -16272,9 +16276,24 @@ function createSuggestionMenuPlugin(ctx, options, host) {
|
|
|
16272
16276
|
const optionId = (index) => `${listboxId}-option-${index}`;
|
|
16273
16277
|
const sectionTitle = (id) => {
|
|
16274
16278
|
const { sections } = options;
|
|
16275
|
-
const words = typeof sections === 'function' ? sections(id) : sections
|
|
16276
|
-
return words ?? suggestionSectionTitles
|
|
16279
|
+
const words = typeof sections === 'function' ? sections(id) : own(sections, id);
|
|
16280
|
+
return words ?? own(suggestionSectionTitles, id) ?? id;
|
|
16277
16281
|
};
|
|
16282
|
+
/** Each listed item with the heading it opens. A row is kept while its
|
|
16283
|
+
heading holds, so its identity survives a keystroke or an arrow press —
|
|
16284
|
+
a renderer's row is not handed a new item for nothing. */
|
|
16285
|
+
const rows = new WeakMap();
|
|
16286
|
+
const listed = () => filtered.map((item, index) => {
|
|
16287
|
+
const { section } = item;
|
|
16288
|
+
const opens = !!section && section !== filtered[index - 1]?.section;
|
|
16289
|
+
const heading = opens ? sectionTitle(section) : null;
|
|
16290
|
+
const kept = rows.get(item);
|
|
16291
|
+
if (kept && kept.heading === heading)
|
|
16292
|
+
return kept;
|
|
16293
|
+
const row = { ...item, heading };
|
|
16294
|
+
rows.set(item, row);
|
|
16295
|
+
return row;
|
|
16296
|
+
});
|
|
16278
16297
|
/**
|
|
16279
16298
|
* An active session is derived from the document, not from keystrokes: a
|
|
16280
16299
|
* cursor sitting right after `<trigger><query>` is a session.
|
|
@@ -16371,8 +16390,20 @@ function createSuggestionMenuPlugin(ctx, options, host) {
|
|
|
16371
16390
|
nextCursor = null;
|
|
16372
16391
|
advanceOnLoad = false;
|
|
16373
16392
|
};
|
|
16393
|
+
/** Static matches, then the source's rows — each id once. The id is what a
|
|
16394
|
+
renderer tracks a row by and what `optionId` names it after, so a row
|
|
16395
|
+
under an id already listed adds nothing: a page that repeats a row of
|
|
16396
|
+
the last (skip paging over rows that moved between requests), a source
|
|
16397
|
+
row under a static row's id. The first to list an id keeps it. */
|
|
16374
16398
|
const mergeItems = () => {
|
|
16375
|
-
|
|
16399
|
+
const ids = new Set();
|
|
16400
|
+
filtered = [];
|
|
16401
|
+
for (const item of [...staticMatches, ...dynamicItems]) {
|
|
16402
|
+
if (ids.has(item.id))
|
|
16403
|
+
continue;
|
|
16404
|
+
ids.add(item.id);
|
|
16405
|
+
filtered.push(item);
|
|
16406
|
+
}
|
|
16376
16407
|
if (activeIndex >= filtered.length)
|
|
16377
16408
|
activeIndex = Math.max(0, filtered.length - 1);
|
|
16378
16409
|
};
|
|
@@ -16576,7 +16607,7 @@ function createSuggestionMenuPlugin(ctx, options, host) {
|
|
|
16576
16607
|
level: scope.parent ? 2 : 1,
|
|
16577
16608
|
parent: scope.parent,
|
|
16578
16609
|
query: scope.query,
|
|
16579
|
-
items:
|
|
16610
|
+
items: listed(),
|
|
16580
16611
|
activeIndex,
|
|
16581
16612
|
loading,
|
|
16582
16613
|
stale,
|
|
@@ -16587,7 +16618,6 @@ function createSuggestionMenuPlugin(ctx, options, host) {
|
|
|
16587
16618
|
clientRect,
|
|
16588
16619
|
listboxId,
|
|
16589
16620
|
optionId,
|
|
16590
|
-
sectionTitle,
|
|
16591
16621
|
select,
|
|
16592
16622
|
back,
|
|
16593
16623
|
loadMore,
|
|
@@ -16834,6 +16864,37 @@ function createSuggestionMenuPlugin(ctx, options, host) {
|
|
|
16834
16864
|
});
|
|
16835
16865
|
}
|
|
16836
16866
|
|
|
16867
|
+
/**
|
|
16868
|
+
* A {@link SuggestionSource} for a backend that pages by offset — the
|
|
16869
|
+
* paging written once: a query and a page become a filter (`with`), the
|
|
16870
|
+
* filter becomes rows (`from`), each row a suggestion (`map`). The cursor
|
|
16871
|
+
* is the next page's offset; a short page ends the list.
|
|
16872
|
+
*
|
|
16873
|
+
* createSuggestionMenu({
|
|
16874
|
+
* trigger: '{{',
|
|
16875
|
+
* source: pagedSource({
|
|
16876
|
+
* from: { find: (filter, signal) => api.mergeTags(filter, signal) },
|
|
16877
|
+
* with: (query, { skip, limit }) => ({ where: { path: { ilike: `%${query}%` } }, skip, limit }),
|
|
16878
|
+
* map: (row) => ({ id: row.path, title: row.label, command: insertMergeTag(row.path) }),
|
|
16879
|
+
* }),
|
|
16880
|
+
* …
|
|
16881
|
+
* });
|
|
16882
|
+
*
|
|
16883
|
+
* Anything else — a cursor of the backend's own, a merged answer of two
|
|
16884
|
+
* calls — is a {@link SuggestionSource} written by hand.
|
|
16885
|
+
*/
|
|
16886
|
+
function pagedSource(options) {
|
|
16887
|
+
const { from, map, pageSize = 20 } = options;
|
|
16888
|
+
return async ({ query, cursor, signal }) => {
|
|
16889
|
+
const skip = cursor ? Number(cursor) : 0;
|
|
16890
|
+
const rows = await from.find(options.with(query, { skip, limit: pageSize }), signal);
|
|
16891
|
+
return {
|
|
16892
|
+
items: rows.map(map),
|
|
16893
|
+
nextCursor: rows.length < pageSize ? null : String(skip + pageSize),
|
|
16894
|
+
};
|
|
16895
|
+
};
|
|
16896
|
+
}
|
|
16897
|
+
|
|
16837
16898
|
const key$1 = new PluginKey('contentStream');
|
|
16838
16899
|
/** What a transaction of a stream says about where the stream is now —
|
|
16839
16900
|
for another plugin (a proposal's) to follow the range as precisely as
|
|
@@ -19023,5 +19084,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImpor
|
|
|
19023
19084
|
* Generated bundle index. Do not edit.
|
|
19024
19085
|
*/
|
|
19025
19086
|
|
|
19026
|
-
export { AUTHORED_ATTR, AUTHORED_SPEC_KEY, AUTHORED_STYLE_DEFAULTS_KEY, AuthoredEnter, BLOCKQUOTE_STYLE, BLOCK_MENU_FOCUS_KEY, BUTTON_FILL, BUTTON_STYLE, BaseKeymap, Blockquote, Bold, BulletList, Button, CARET_ROOM, CLIENT_LABELS, COLUMN_STARTING_LINES, COMMENT_TAG, CONTENT_ATTRS, CSS_SUPPORT, ClearFormatting, CodeLine, CodeLineIndent, Column, ColumnResize, Columns, ColumnsResize, DOCUMENT_CLASS, DOCUMENT_TAGS, DUAL_BACKGROUND_MIN_RATIO, DUAL_CONTRAST_DARK, DUAL_CONTRAST_LIGHT, DUAL_CONTRAST_MIN_RATIO, Divider, Document$1 as Document, DocumentStyles, EMAIL_ATTRIBUTES, EMAIL_CSS_PROPERTIES, EMAIL_SAFE_STYLE_PROPERTIES, EMAIL_SAFE_TAGS, EMAIL_TAGS, EMAIL_TAG_ATTRIBUTES, EmailParagraph, FILE_CHOOSER_POINTER_WAIT, FILL_TEXT_COLOR, FILL_TEXT_COLOR_LIGHT, FILL_TEXT_COLOR_RGB, FOLD_WIDTH, FORMAT_WIDTH, GMAIL_CLIP_BYTES, GUIDES_ACTIVE_CLASS, GUIDES_PEEK_CLASS, GUIDES_PEEK_DELAY_MS, Gapcursor, HEADING_SIZES, HardBreak, Heading, History, HtmlComment, HtmlCommentInline, HtmlElement, HtmlInline, HtmlLanguage, HtmlRaw, HtmlTextElement, HtmlVoid, HtmlVoidBlock, IMPORT_VIEWPORT_WIDTH, INDENT_MAX, INDENT_STEP, INLINE_TAGS, INLINE_VOID_TAGS, IN_SELECTION_CLASS, Image, InlineAtomSelection, InlineImageStore, InlineImages, Italic, LIST_STYLE, LayoutGuides, Link, ListItem, MAX_COLUMNS, MAX_IMAGE_WIDTH, MAX_MERGE_TAG_LENGTH, MAX_UNBROKEN_RUN, MIN_COLUMN_CAP, MIN_COLUMN_PCT, MIN_FONT_SIZE, MIN_IMAGE_WIDTH, MIN_TABLE_PCT, MJML_WORLDLY_HTML, MergeTag, NoTextDrag, OrderedList, PARSE_SCOPE_KEY, PLACEHOLDER_WIDTH, Paragraph, PasteHygiene, QuotedHistory, REFUSED_TAGS, RENDERING_CLIENTS, SECTION_CONTENT_MAX, SECTION_INSET, SECTION_PADDING, STACK_CLASS, STACK_RULE, Section, SplitKeepingMarks, TABLE_BLOCK_SPACING, TABLE_BORDER_COLOR, TABLE_CELL_PADDING, TABLE_SECTION_TAGS, TYPING_REST, Table, TableCell, TableRow, Text, TextStyle, UNSET_BUTTON_HREF, Underline, VOID_TAGS, acceptProposal, addColumn, addColumnAtEnd, addRowAtEnd, analyzeAngularExpression, angularDialect, angularRequiredFields, appendColumn, applyAuthoredAttributes, applyEmailVocabulary, attributeString, authoredAttribute, authoredMarkupOf, authoredViewAttributes, bareButtons, buttonStyle, canonicalHead, canonicalMergeTagInner, canonicalRender, caretCellPos, caretInsideMergeTag, claimedImageFiles, clearCells, clientList, columnCaps, columnWidths, completionContextAt, containerStyle, contrastRatio, correctStoredMistakes, createAngularExpressions, createBlockMenu, createBubbleMenu, createButtonEdit, createContentProposal, createContentStream, createDOMParser, createEditor, createHtmlAutocomplete, createHtmlLanguage, createImageDrag, createInlineImages, createMergeTagResolution, createOffsetMapper, createQuotedHistory, createSchema, createSendIntent, createSourceMarks, createSuggestionMenu, createTableHandles, declarationProperty, declaredBackground, decodeDataUrl, defaultBubbleShouldShow, defineExtension, defineMark, defineNode, deleteColumns, deleteFullySelected, discardProposal, distributePadding, docText, dropDeadOfficeClasses, dropHidden, dropMediaQueries, dropZeroSizedWhitespace, duplicateColumn, duplicateRow, editQuotedHistory, effectiveWidths, emailBackgroundPalette, emailDocument, emailExtensions, emailPlainText, emailSizeBudget, emailTextPalette, embedsAsLinks, entitySpans, escapeAttribute$2 as escapeAttribute, escapeText$1 as escapeText, expressionDialect, expressionDialectKey, extensionActions, extensionSuggestions, fillTextColor, filledPlaceholderAttrs, filterEmailStyle, findColumnContext, findColumnsContext, findCssIssues, findListDepth, findSectionContext, findTableContext, fitImageWidth, foldHTML, formatHTML, formatPct, forwardDocument, forwardQuote, hasBlockChildren$1 as hasBlockChildren, hasDocumentEnvelope, headingStyle, holdsBlock, holdsColumn, hrefProblem, htmlSourceExtensions, imageDropTarget, importLoss, importedDocument, inheritTextStyles, inheritedMarkup, inlineBootstrapTableBorders, inlineImageCids, inlineImageRegistry, inlineImagesKey, inlineStyles, insertHTML, insertMergeTag, isActionEnabled, isBlock$1 as isBlock, isBlockLevel, isBlockish, isBooleanAttribute, isEmailAttribute, isEmailCssProperty, isEmailTag, isFillTextColor, isInlineAtom, isMarkActive, isMergeTagExpression, isMergeTagPath, isNodeActive, isPadded, isProposing, isQuotedHistoryFolded, isSafeColor, isSafeFontFamily, isSafeFontSize, isSafeUrl$1 as isSafeUrl, isSectionImageUrl, isStreaming, italicStarInputRegex, italicStarPasteRegex, italicUnderscoreInputRegex, italicUnderscorePasteRegex, keepGmailRules, layoutBlockAt, linkClickPlugin, linkPastePlugin, linkRangeAt, lintHTML, lowerInlinesAroundBlocks, markAttrsOf, markStackingColumns, marksAcrossBreak, materializeComments, measureMenuPlacement, mediaMatches, mergeTagAt, mergeTagExpressions, mergeTagFields, mergeTagRanges, mergeTagResolutionPending, moveColumn, moveRow, normalizeCommentText, normalizeCss, normalizeHref, normalizeMergeTagText, noteOwnWidths, openFileChooser, openTag$1 as openTag, openTags, outlookColumns, paddingOf, parseAngularExpression, parseDocument, parseFontFamily, parseFontSize, parseHTML, parsePadding, parseRules, parseTextTransform, passesDualBackground, passesDualContrast, preserveExtensions, preservedAttributes, promoteInlineImages, promoteMergeTags, proposalRange, proposeContent, quotedHistory, readEnvelope, readImageFile, realizeComments, relativeLuminance, removeColumn, removeLastColumn, removeQuotedHistory, renderForClient, renderedPath, repairLinkSchemes, repairTables, replaceHTML, replyDocument, replyEnvelope, replyQuote, reviseProposal, rewriteInlineImageSources, richTextExtensions, ruleForScope, ruleScope, sanitizePastedHTML, scanHTML, scanMergeTags, scopeOf$1 as scopeOf, scopedDocumentCss, selectColumn, selectRow, selectedButton, selectedImage, selectedImageAlt, selectedMarkAtom, selectionInsideMergeTag, serializeDocument, serializeToHTML, setCellBackground, setColumnBackground, setColumnBoundary, setColumnsBoundary, setQuotedHistory, setSectionBackground, setSectionImage, setTableBox, setTableWidth, soleInlineAtom, splitDeclarations$2 as splitDeclarations, splitListItemKeepMarks, starInputRegex, starPasteRegex, stopProposal, streamContent, streamedRange, streamingRange, suggestionSectionTitles, tableStyle, textOffsetAt, textRegions, toEmailSafeColor, toInboundMessage, toggleList, trimInlineBoxes, underscoreInputRegex, underscorePasteRegex, unwrapLayoutTables, unwrapOfficeParagraphMarks, verbatimElement, videoPage, watchMenuScroll, withAttribute, withAuthoredMarkup, withQuoted, withQuotedHistory, withStyleDeclaration, withoutAttribute, withoutStyleDeclaration };
|
|
19087
|
+
export { AUTHORED_ATTR, AUTHORED_SPEC_KEY, AUTHORED_STYLE_DEFAULTS_KEY, AuthoredEnter, BLOCKQUOTE_STYLE, BLOCK_MENU_FOCUS_KEY, BUTTON_FILL, BUTTON_STYLE, BaseKeymap, Blockquote, Bold, BulletList, Button, CARET_ROOM, CLIENT_LABELS, COLUMN_STARTING_LINES, COMMENT_TAG, CONTENT_ATTRS, CSS_SUPPORT, ClearFormatting, CodeLine, CodeLineIndent, Column, ColumnResize, Columns, ColumnsResize, DOCUMENT_CLASS, DOCUMENT_TAGS, DUAL_BACKGROUND_MIN_RATIO, DUAL_CONTRAST_DARK, DUAL_CONTRAST_LIGHT, DUAL_CONTRAST_MIN_RATIO, Divider, Document$1 as Document, DocumentStyles, EMAIL_ATTRIBUTES, EMAIL_CSS_PROPERTIES, EMAIL_SAFE_STYLE_PROPERTIES, EMAIL_SAFE_TAGS, EMAIL_TAGS, EMAIL_TAG_ATTRIBUTES, EmailParagraph, FILE_CHOOSER_POINTER_WAIT, FILL_TEXT_COLOR, FILL_TEXT_COLOR_LIGHT, FILL_TEXT_COLOR_RGB, FOLD_WIDTH, FORMAT_WIDTH, GMAIL_CLIP_BYTES, GUIDES_ACTIVE_CLASS, GUIDES_PEEK_CLASS, GUIDES_PEEK_DELAY_MS, Gapcursor, HEADING_SIZES, HardBreak, Heading, History, HtmlComment, HtmlCommentInline, HtmlElement, HtmlInline, HtmlLanguage, HtmlRaw, HtmlTextElement, HtmlVoid, HtmlVoidBlock, IMPORT_VIEWPORT_WIDTH, INDENT_MAX, INDENT_STEP, INLINE_TAGS, INLINE_VOID_TAGS, IN_SELECTION_CLASS, Image, InlineAtomSelection, InlineImageStore, InlineImages, Italic, LIST_STYLE, LayoutGuides, Link, ListItem, MAX_COLUMNS, MAX_IMAGE_WIDTH, MAX_MERGE_TAG_LENGTH, MAX_UNBROKEN_RUN, MIN_COLUMN_CAP, MIN_COLUMN_PCT, MIN_FONT_SIZE, MIN_IMAGE_WIDTH, MIN_TABLE_PCT, MJML_WORLDLY_HTML, MergeTag, NoTextDrag, OrderedList, PARSE_SCOPE_KEY, PLACEHOLDER_WIDTH, Paragraph, PasteHygiene, QuotedHistory, REFUSED_TAGS, RENDERING_CLIENTS, SECTION_CONTENT_MAX, SECTION_INSET, SECTION_PADDING, STACK_CLASS, STACK_RULE, Section, SplitKeepingMarks, TABLE_BLOCK_SPACING, TABLE_BORDER_COLOR, TABLE_CELL_PADDING, TABLE_SECTION_TAGS, TYPING_REST, Table, TableCell, TableRow, Text, TextStyle, UNSET_BUTTON_HREF, Underline, VOID_TAGS, acceptProposal, addColumn, addColumnAtEnd, addRowAtEnd, analyzeAngularExpression, angularDialect, angularRequiredFields, appendColumn, applyAuthoredAttributes, applyEmailVocabulary, attributeString, authoredAttribute, authoredMarkupOf, authoredViewAttributes, bareButtons, buttonStyle, canonicalHead, canonicalMergeTagInner, canonicalRender, caretCellPos, caretInsideMergeTag, claimedImageFiles, clearCells, clientList, columnCaps, columnWidths, completionContextAt, containerStyle, contrastRatio, correctStoredMistakes, createAngularExpressions, createBlockMenu, createBubbleMenu, createButtonEdit, createContentProposal, createContentStream, createDOMParser, createEditor, createHtmlAutocomplete, createHtmlLanguage, createImageDrag, createInlineImages, createMergeTagResolution, createOffsetMapper, createQuotedHistory, createSchema, createSendIntent, createSourceMarks, createSuggestionMenu, createTableHandles, declarationProperty, declaredBackground, decodeDataUrl, defaultBubbleShouldShow, defineExtension, defineMark, defineNode, deleteColumns, deleteFullySelected, discardProposal, distributePadding, docText, dropDeadOfficeClasses, dropHidden, dropMediaQueries, dropZeroSizedWhitespace, duplicateColumn, duplicateRow, editQuotedHistory, effectiveWidths, emailBackgroundPalette, emailDocument, emailExtensions, emailPlainText, emailSizeBudget, emailTextPalette, embedsAsLinks, entitySpans, escapeAttribute$2 as escapeAttribute, escapeText$1 as escapeText, expressionDialect, expressionDialectKey, extensionActions, extensionSuggestions, fillTextColor, filledPlaceholderAttrs, filterEmailStyle, findColumnContext, findColumnsContext, findCssIssues, findListDepth, findSectionContext, findTableContext, fitImageWidth, foldHTML, formatHTML, formatPct, forwardDocument, forwardQuote, hasBlockChildren$1 as hasBlockChildren, hasDocumentEnvelope, headingStyle, holdsBlock, holdsColumn, hrefProblem, htmlSourceExtensions, imageDropTarget, importLoss, importedDocument, inheritTextStyles, inheritedMarkup, inlineBootstrapTableBorders, inlineImageCids, inlineImageRegistry, inlineImagesKey, inlineStyles, insertHTML, insertMergeTag, isActionEnabled, isBlock$1 as isBlock, isBlockLevel, isBlockish, isBooleanAttribute, isEmailAttribute, isEmailCssProperty, isEmailTag, isFillTextColor, isInlineAtom, isMarkActive, isMergeTagExpression, isMergeTagPath, isNodeActive, isPadded, isProposing, isQuotedHistoryFolded, isSafeColor, isSafeFontFamily, isSafeFontSize, isSafeUrl$1 as isSafeUrl, isSectionImageUrl, isStreaming, italicStarInputRegex, italicStarPasteRegex, italicUnderscoreInputRegex, italicUnderscorePasteRegex, keepGmailRules, layoutBlockAt, linkClickPlugin, linkPastePlugin, linkRangeAt, lintHTML, lowerInlinesAroundBlocks, markAttrsOf, markStackingColumns, marksAcrossBreak, materializeComments, measureMenuPlacement, mediaMatches, mergeTagAt, mergeTagExpressions, mergeTagFields, mergeTagRanges, mergeTagResolutionPending, moveColumn, moveRow, normalizeCommentText, normalizeCss, normalizeHref, normalizeMergeTagText, noteOwnWidths, openFileChooser, openTag$1 as openTag, openTags, outlookColumns, paddingOf, pagedSource, parseAngularExpression, parseDocument, parseFontFamily, parseFontSize, parseHTML, parsePadding, parseRules, parseTextTransform, passesDualBackground, passesDualContrast, preserveExtensions, preservedAttributes, promoteInlineImages, promoteMergeTags, proposalRange, proposeContent, quotedHistory, readEnvelope, readImageFile, realizeComments, relativeLuminance, removeColumn, removeLastColumn, removeQuotedHistory, renderForClient, renderedPath, repairLinkSchemes, repairTables, replaceHTML, replyDocument, replyEnvelope, replyQuote, reviseProposal, rewriteInlineImageSources, richTextExtensions, ruleForScope, ruleScope, sanitizePastedHTML, scanHTML, scanMergeTags, scopeOf$1 as scopeOf, scopedDocumentCss, selectColumn, selectRow, selectedButton, selectedImage, selectedImageAlt, selectedMarkAtom, selectionInsideMergeTag, serializeDocument, serializeToHTML, setCellBackground, setColumnBackground, setColumnBoundary, setColumnsBoundary, setQuotedHistory, setSectionBackground, setSectionImage, setTableBox, setTableWidth, soleInlineAtom, splitDeclarations$2 as splitDeclarations, splitListItemKeepMarks, starInputRegex, starPasteRegex, stopProposal, streamContent, streamedRange, streamingRange, suggestionSectionTitles, tableStyle, textOffsetAt, textRegions, toEmailSafeColor, toInboundMessage, toggleList, trimInlineBoxes, underscoreInputRegex, underscorePasteRegex, unwrapLayoutTables, unwrapOfficeParagraphMarks, verbatimElement, videoPage, watchMenuScroll, withAttribute, withAuthoredMarkup, withQuoted, withQuotedHistory, withStyleDeclaration, withoutAttribute, withoutStyleDeclaration };
|
|
19027
19088
|
//# sourceMappingURL=h-k-dev-angular-email-editor.mjs.map
|