@h-k-dev/angular-email-editor 0.0.0-placeholder.0 → 0.0.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.
Files changed (51) hide show
  1. package/README.md +127 -3
  2. package/fesm2022/h-k-dev-angular-email-editor-actions.mjs +179 -0
  3. package/fesm2022/h-k-dev-angular-email-editor-actions.mjs.map +1 -0
  4. package/fesm2022/h-k-dev-angular-email-editor-address-chip.mjs +285 -0
  5. package/fesm2022/h-k-dev-angular-email-editor-address-chip.mjs.map +1 -0
  6. package/fesm2022/h-k-dev-angular-email-editor-address-input.mjs +686 -0
  7. package/fesm2022/h-k-dev-angular-email-editor-address-input.mjs.map +1 -0
  8. package/fesm2022/h-k-dev-angular-email-editor-address.mjs +489 -0
  9. package/fesm2022/h-k-dev-angular-email-editor-address.mjs.map +1 -0
  10. package/fesm2022/h-k-dev-angular-email-editor-anchor.mjs +64 -0
  11. package/fesm2022/h-k-dev-angular-email-editor-anchor.mjs.map +1 -0
  12. package/fesm2022/h-k-dev-angular-email-editor-attachment-chip.mjs +387 -0
  13. package/fesm2022/h-k-dev-angular-email-editor-attachment-chip.mjs.map +1 -0
  14. package/fesm2022/h-k-dev-angular-email-editor-attachment-chips.mjs +80 -0
  15. package/fesm2022/h-k-dev-angular-email-editor-attachment-chips.mjs.map +1 -0
  16. package/fesm2022/h-k-dev-angular-email-editor-chat-input.mjs +346 -0
  17. package/fesm2022/h-k-dev-angular-email-editor-chat-input.mjs.map +1 -0
  18. package/fesm2022/h-k-dev-angular-email-editor-focus.mjs +68 -0
  19. package/fesm2022/h-k-dev-angular-email-editor-focus.mjs.map +1 -0
  20. package/fesm2022/h-k-dev-angular-email-editor-image.mjs +132 -0
  21. package/fesm2022/h-k-dev-angular-email-editor-image.mjs.map +1 -0
  22. package/fesm2022/h-k-dev-angular-email-editor-material.mjs +124 -0
  23. package/fesm2022/h-k-dev-angular-email-editor-material.mjs.map +1 -0
  24. package/fesm2022/h-k-dev-angular-email-editor-metrics.mjs +243 -0
  25. package/fesm2022/h-k-dev-angular-email-editor-metrics.mjs.map +1 -0
  26. package/fesm2022/h-k-dev-angular-email-editor-palette.mjs +87 -0
  27. package/fesm2022/h-k-dev-angular-email-editor-palette.mjs.map +1 -0
  28. package/fesm2022/h-k-dev-angular-email-editor-proposal.mjs +307 -0
  29. package/fesm2022/h-k-dev-angular-email-editor-proposal.mjs.map +1 -0
  30. package/fesm2022/h-k-dev-angular-email-editor-suggestion-menu.mjs +392 -0
  31. package/fesm2022/h-k-dev-angular-email-editor-suggestion-menu.mjs.map +1 -0
  32. package/fesm2022/h-k-dev-angular-email-editor.mjs +18818 -0
  33. package/fesm2022/h-k-dev-angular-email-editor.mjs.map +1 -0
  34. package/package.json +130 -6
  35. package/styles/_scroll.scss +101 -0
  36. package/types/h-k-dev-angular-email-editor-actions.d.ts +147 -0
  37. package/types/h-k-dev-angular-email-editor-address-chip.d.ts +193 -0
  38. package/types/h-k-dev-angular-email-editor-address-input.d.ts +328 -0
  39. package/types/h-k-dev-angular-email-editor-address.d.ts +125 -0
  40. package/types/h-k-dev-angular-email-editor-anchor.d.ts +44 -0
  41. package/types/h-k-dev-angular-email-editor-attachment-chip.d.ts +271 -0
  42. package/types/h-k-dev-angular-email-editor-attachment-chips.d.ts +48 -0
  43. package/types/h-k-dev-angular-email-editor-chat-input.d.ts +101 -0
  44. package/types/h-k-dev-angular-email-editor-focus.d.ts +40 -0
  45. package/types/h-k-dev-angular-email-editor-image.d.ts +66 -0
  46. package/types/h-k-dev-angular-email-editor-material.d.ts +65 -0
  47. package/types/h-k-dev-angular-email-editor-metrics.d.ts +110 -0
  48. package/types/h-k-dev-angular-email-editor-palette.d.ts +51 -0
  49. package/types/h-k-dev-angular-email-editor-proposal.d.ts +170 -0
  50. package/types/h-k-dev-angular-email-editor-suggestion-menu.d.ts +177 -0
  51. package/types/h-k-dev-angular-email-editor.d.ts +3959 -0
package/package.json CHANGED
@@ -1,12 +1,136 @@
1
1
  {
2
2
  "name": "@h-k-dev/angular-email-editor",
3
- "version": "0.0.0-placeholder.0",
4
- "description": "Angular email editor (ProseMirror) — name reserved; the first release follows.",
3
+ "version": "0.0.1",
4
+ "description": "An email editor for Angular on ProseMirror — a visual composer and an HTML source editor over one schema that is the vocabulary of email HTML.",
5
5
  "license": "MIT",
6
+ "author": "h-k-dev",
6
7
  "repository": {
7
8
  "type": "git",
8
- "url": "git+https://github.com/h-k-dev/angular-email-editor.git"
9
+ "url": "git+https://github.com/h-k-dev/angular-email-editor.git",
10
+ "directory": "projects/angular-email-editor"
9
11
  },
10
- "homepage": "https://github.com/h-k-dev/angular-email-editor#readme",
11
- "files": ["README.md"]
12
- }
12
+ "homepage": "https://h-k-dev.github.io/angular-email-editor/",
13
+ "bugs": "https://github.com/h-k-dev/angular-email-editor/issues",
14
+ "keywords": [
15
+ "angular",
16
+ "email",
17
+ "email-editor",
18
+ "prosemirror",
19
+ "wysiwyg",
20
+ "html-email",
21
+ "rich-text",
22
+ "signals"
23
+ ],
24
+ "peerDependencies": {
25
+ "@angular/common": "^22.0.0",
26
+ "@angular/core": "^22.0.0",
27
+ "@angular/forms": "^22.0.0",
28
+ "@angular/material": "^22.0.0",
29
+ "@chenglou/pretext": "^1.0.0",
30
+ "prosemirror-commands": "^1.7.1",
31
+ "prosemirror-gapcursor": "^1.4.1",
32
+ "prosemirror-history": "^1.5.0",
33
+ "prosemirror-inputrules": "^1.5.1",
34
+ "prosemirror-keymap": "^1.2.3",
35
+ "prosemirror-model": "^1.25.9",
36
+ "prosemirror-schema-list": "^1.5.1",
37
+ "prosemirror-state": "^1.4.4",
38
+ "prosemirror-tables": "^1.8.5",
39
+ "prosemirror-transform": "^1.12.0",
40
+ "prosemirror-view": "^1.41.9",
41
+ "rxjs": "^7.4.0"
42
+ },
43
+ "peerDependenciesMeta": {
44
+ "@angular/forms": {
45
+ "optional": true
46
+ },
47
+ "@angular/material": {
48
+ "optional": true
49
+ },
50
+ "@chenglou/pretext": {
51
+ "optional": true
52
+ },
53
+ "rxjs": {
54
+ "optional": true
55
+ }
56
+ },
57
+ "dependencies": {
58
+ "tslib": "^2.3.0"
59
+ },
60
+ "exports": {
61
+ "./styles/*": {
62
+ "sass": "./styles/_*.scss"
63
+ },
64
+ "./package.json": {
65
+ "default": "./package.json"
66
+ },
67
+ ".": {
68
+ "types": "./types/h-k-dev-angular-email-editor.d.ts",
69
+ "default": "./fesm2022/h-k-dev-angular-email-editor.mjs"
70
+ },
71
+ "./actions": {
72
+ "types": "./types/h-k-dev-angular-email-editor-actions.d.ts",
73
+ "default": "./fesm2022/h-k-dev-angular-email-editor-actions.mjs"
74
+ },
75
+ "./address": {
76
+ "types": "./types/h-k-dev-angular-email-editor-address.d.ts",
77
+ "default": "./fesm2022/h-k-dev-angular-email-editor-address.mjs"
78
+ },
79
+ "./address-chip": {
80
+ "types": "./types/h-k-dev-angular-email-editor-address-chip.d.ts",
81
+ "default": "./fesm2022/h-k-dev-angular-email-editor-address-chip.mjs"
82
+ },
83
+ "./address-input": {
84
+ "types": "./types/h-k-dev-angular-email-editor-address-input.d.ts",
85
+ "default": "./fesm2022/h-k-dev-angular-email-editor-address-input.mjs"
86
+ },
87
+ "./anchor": {
88
+ "types": "./types/h-k-dev-angular-email-editor-anchor.d.ts",
89
+ "default": "./fesm2022/h-k-dev-angular-email-editor-anchor.mjs"
90
+ },
91
+ "./attachment-chip": {
92
+ "types": "./types/h-k-dev-angular-email-editor-attachment-chip.d.ts",
93
+ "default": "./fesm2022/h-k-dev-angular-email-editor-attachment-chip.mjs"
94
+ },
95
+ "./attachment-chips": {
96
+ "types": "./types/h-k-dev-angular-email-editor-attachment-chips.d.ts",
97
+ "default": "./fesm2022/h-k-dev-angular-email-editor-attachment-chips.mjs"
98
+ },
99
+ "./chat-input": {
100
+ "types": "./types/h-k-dev-angular-email-editor-chat-input.d.ts",
101
+ "default": "./fesm2022/h-k-dev-angular-email-editor-chat-input.mjs"
102
+ },
103
+ "./focus": {
104
+ "types": "./types/h-k-dev-angular-email-editor-focus.d.ts",
105
+ "default": "./fesm2022/h-k-dev-angular-email-editor-focus.mjs"
106
+ },
107
+ "./image": {
108
+ "types": "./types/h-k-dev-angular-email-editor-image.d.ts",
109
+ "default": "./fesm2022/h-k-dev-angular-email-editor-image.mjs"
110
+ },
111
+ "./material": {
112
+ "types": "./types/h-k-dev-angular-email-editor-material.d.ts",
113
+ "default": "./fesm2022/h-k-dev-angular-email-editor-material.mjs"
114
+ },
115
+ "./metrics": {
116
+ "types": "./types/h-k-dev-angular-email-editor-metrics.d.ts",
117
+ "default": "./fesm2022/h-k-dev-angular-email-editor-metrics.mjs"
118
+ },
119
+ "./palette": {
120
+ "types": "./types/h-k-dev-angular-email-editor-palette.d.ts",
121
+ "default": "./fesm2022/h-k-dev-angular-email-editor-palette.mjs"
122
+ },
123
+ "./proposal": {
124
+ "types": "./types/h-k-dev-angular-email-editor-proposal.d.ts",
125
+ "default": "./fesm2022/h-k-dev-angular-email-editor-proposal.mjs"
126
+ },
127
+ "./suggestion-menu": {
128
+ "types": "./types/h-k-dev-angular-email-editor-suggestion-menu.d.ts",
129
+ "default": "./fesm2022/h-k-dev-angular-email-editor-suggestion-menu.mjs"
130
+ }
131
+ },
132
+ "sideEffects": false,
133
+ "module": "fesm2022/h-k-dev-angular-email-editor.mjs",
134
+ "typings": "types/h-k-dev-angular-email-editor.d.ts",
135
+ "type": "module"
136
+ }
@@ -0,0 +1,101 @@
1
+ // The library's scrollbar, for anything that scrolls — after iusta-core's
2
+ // `.iusta-scroll`, on our own tokens. A thin, round thumb on no track, out
3
+ // of sight until the pointer is over the scroller or the focus is in it
4
+ // (always there where nothing hovers: a touch screen); a stable gutter, so
5
+ // the thumb coming and going never moves the content; sideways overscroll
6
+ // kept in the scroller, so a pane scrolled to its edge never swipes the
7
+ // page back a page.
8
+ //
9
+ // @use '@h-k-dev/angular-email-editor/styles/scroll';
10
+ //
11
+ // .pane {
12
+ // overflow-y: auto;
13
+ // @include scroll.scroll;
14
+ // }
15
+ //
16
+ // A mixin, not a class: nothing reaches a stylesheet that does not include
17
+ // it. Tokens — `--email-scroll-*` first, then Material's system token of the
18
+ // same meaning, then a fallback:
19
+ //
20
+ // - `--email-scroll-size` — the thumb's thickness and the gutter's (6px).
21
+ // - `--email-scroll-thumb` — the thumb at rest (the outline variant at 50%).
22
+ // - `--email-scroll-thumb-hover` — under the pointer (at 75%).
23
+ // - `--email-scroll-track` — the track (transparent).
24
+ //
25
+ // **Smooth scrolling is opt-in** (`$smooth: true`, and then only without
26
+ // reduced motion). Most of what scrolls here is driven by a caret or by keys —
27
+ // an editor following its caret, a menu following its active row — and a
28
+ // smooth scroll there animates every one of those nudges: arrowing past the
29
+ // edge reads as lag, a held key queues animations behind the cursor. iusta
30
+ // turned it on everywhere and turns it off one scroller at a time; here it
31
+ // is the other way round. Only a scroller a person drags or jumps through
32
+ // by link wants it.
33
+ //
34
+ // Webkit and Blink draw the thumb from `::-webkit-scrollbar`; Firefox, which
35
+ // has no pseudo-elements for it, gets the standard `scrollbar-width` and
36
+ // `scrollbar-color` — kept to Firefox, because in Chrome either one switches
37
+ // the pseudo-elements, and so the thickness and the round thumb, off.
38
+
39
+ $_outline-variant: var(--mat-sys-outline-variant, light-dark(#c4c7c5, #444746));
40
+
41
+ @mixin scroll($smooth: false) {
42
+ --_email-scroll-size: var(--email-scroll-size, 6px);
43
+ --_email-scroll-thumb: var(
44
+ --email-scroll-thumb,
45
+ color-mix(in srgb, #{$_outline-variant} 50%, transparent)
46
+ );
47
+ --_email-scroll-thumb-hover: var(
48
+ --email-scroll-thumb-hover,
49
+ color-mix(in srgb, #{$_outline-variant} 75%, transparent)
50
+ );
51
+ // The thumb's colour now: none until the scroller is in use. Declared on
52
+ // every scroller, so a nested one starts out of sight however its outer
53
+ // one stands.
54
+ --_email-scroll-current: transparent;
55
+
56
+ scrollbar-gutter: stable;
57
+ overscroll-behavior-x: contain;
58
+
59
+ @supports (-moz-appearance: none) {
60
+ scrollbar-width: thin;
61
+ scrollbar-color: var(--_email-scroll-current) var(--email-scroll-track, transparent);
62
+ }
63
+
64
+ &::-webkit-scrollbar {
65
+ width: var(--_email-scroll-size);
66
+ height: var(--_email-scroll-size);
67
+ }
68
+
69
+ &::-webkit-scrollbar-track {
70
+ background: var(--email-scroll-track, transparent);
71
+ }
72
+
73
+ &::-webkit-scrollbar-corner {
74
+ background: transparent;
75
+ }
76
+
77
+ &::-webkit-scrollbar-thumb {
78
+ background-color: var(--_email-scroll-current);
79
+ border-radius: 1e3px;
80
+ }
81
+
82
+ &:hover,
83
+ &:focus-within {
84
+ --_email-scroll-current: var(--_email-scroll-thumb);
85
+
86
+ &::-webkit-scrollbar-thumb:hover {
87
+ background-color: var(--_email-scroll-thumb-hover);
88
+ }
89
+ }
90
+
91
+ // Nothing hovers on a touch screen: the thumb is simply there.
92
+ @media (hover: none) {
93
+ --_email-scroll-current: var(--_email-scroll-thumb);
94
+ }
95
+
96
+ @if $smooth {
97
+ @media (prefers-reduced-motion: no-preference) {
98
+ scroll-behavior: smooth;
99
+ }
100
+ }
101
+ }
@@ -0,0 +1,147 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { Signal, Injector } from '@angular/core';
3
+ import { EditorState } from 'prosemirror-state';
4
+ import { EditorAction, Editor } from '@h-k-dev/angular-email-editor';
5
+
6
+ /**
7
+ * An editor's state as a signal: the text, the selection, the stored marks —
8
+ * whatever changed, the signal has the new one. It follows the editor it is
9
+ * given, so handing it "the source pane in code view, the email editor
10
+ * otherwise" is one `computed`; `undefined` while there is none.
11
+ *
12
+ * It listens through `editor.subscribe`, so the editor can already exist:
13
+ * nothing has to be in the kit before the editor is made.
14
+ *
15
+ * Call in an injection context, or hand it an injector.
16
+ */
17
+ declare function editorState(editor: () => Editor | undefined, options?: {
18
+ injector?: Injector;
19
+ }): Signal<EditorState | undefined>;
20
+ /**
21
+ * An action of the host's own: something that opens its UI — a link dialog,
22
+ * a colour or table picker — rather than running a command. It has a `run`,
23
+ * not a `command`, on purpose: a command is *asked* whether it would apply
24
+ * (called without a dispatch), and a function that opens a dialog must never
25
+ * be called to ask.
26
+ *
27
+ * Two ways in, by what it is:
28
+ * - `host` — an action of its own, there for every editor: "Link", which
29
+ * no extension can offer because it needs the host's dialog;
30
+ * - `override` — the host's `run` *over* an action the kit declares, by its
31
+ * id: a toolbar's "Insert table" that opens a size picker instead of
32
+ * inserting one. It exists only where the kit's action does (so not in a
33
+ * code view), and what it leaves out — when it is on, whether it can run —
34
+ * is still the extension's answer.
35
+ */
36
+ interface HostAction {
37
+ id: string;
38
+ /** What triggering it does. Focus is the host's from here on: the caret
39
+ is not sent back to the editor after it. */
40
+ run: () => void;
41
+ /** On at the selection — makes it a toggle. */
42
+ isActive?: (state: EditorState) => boolean;
43
+ /** Can run right now. Absent: the extension action's answer when it
44
+ stands over one, else yes. */
45
+ isEnabled?: (state: EditorState) => boolean;
46
+ }
47
+ /** An action bound to a live editor: what a button needs. */
48
+ interface BoundAction {
49
+ /** The action as its extension declared it — id, title, icon, keywords;
50
+ `undefined` for a {@link HostAction} that stands alone. */
51
+ readonly action: EditorAction | undefined;
52
+ readonly id: string;
53
+ /** It is the host's `run`: what happens after — where focus goes — is the
54
+ host's too. */
55
+ readonly external: boolean;
56
+ /** On at the selection. Always false for an action with no "on". */
57
+ readonly pressed: Signal<boolean>;
58
+ /** Whether it is a toggle at all — whether `pressed` means anything. */
59
+ readonly toggles: boolean;
60
+ /** Cannot run right now. */
61
+ readonly disabled: Signal<boolean>;
62
+ /** Runs it on the editor; false when it did not apply. */
63
+ run(): boolean;
64
+ /** Puts the caret back in the editor it acts on. */
65
+ focus(): void;
66
+ }
67
+ /** The actions of the editor being watched. */
68
+ interface EditorActions {
69
+ /** The action of that id — `undefined` while there is no editor, and when
70
+ the editor's kit has no such action: a button for it has nothing to do.
71
+ Reactive: it follows the editor. */
72
+ get(id: string): BoundAction | undefined;
73
+ /** Every action of the current editor, in kit order. */
74
+ readonly all: Signal<readonly BoundAction[]>;
75
+ /** The watched editor's state. */
76
+ readonly state: Signal<EditorState | undefined>;
77
+ }
78
+ /**
79
+ * The actions of an editor, bound and live — for a toolbar, a bubble menu,
80
+ * a menu:
81
+ *
82
+ * readonly actions = injectActions(() => this.editor());
83
+ *
84
+ * <button [emailAction]="actions.get('bold')">…</button>
85
+ *
86
+ * `editor` is read reactively: when it changes — a composer switching to its
87
+ * code view — the actions are the new editor's. Its kit decides what exists:
88
+ * the source pane offers the marks, so there a list button has no action
89
+ * and shows disabled, with no routing written anywhere.
90
+ *
91
+ * `host` and `override` bring in the host's own — see {@link HostAction} — so
92
+ * that one list serves a surface whose buttons are not all the editor's.
93
+ *
94
+ * Call in an injection context, or hand it an injector.
95
+ */
96
+ declare function injectActions(editor: () => Editor | undefined, options?: {
97
+ host?: readonly HostAction[];
98
+ override?: Readonly<Record<string, Omit<HostAction, 'id'>>>;
99
+ injector?: Injector;
100
+ }): EditorActions;
101
+
102
+ /**
103
+ * Makes the host's own control the trigger of an editor action: a click runs
104
+ * it, and the control says what the action's state is.
105
+ *
106
+ * <button mat-icon-button [emailAction]="actions.get('bold')" #bold="emailAction"
107
+ * [disabled]="bold.disabled()">
108
+ * <mat-icon>format_bold</mat-icon>
109
+ * </button>
110
+ *
111
+ * Behaviour only, and ARIA only where the host's widget has not spoken:
112
+ * - `aria-pressed` for a toggle, and `aria-disabled` when it cannot run —
113
+ * both off with `[emailActionAria]="false"` for a widget that writes its own
114
+ * (a Material button toggle);
115
+ * - never the native `disabled`, a class or a style: how disabled *looks* is
116
+ * the host's, bound from `disabled()` as above. A control that is only
117
+ * `aria-disabled` stays reachable by keyboard, which is what a toolbar wants;
118
+ * - a click on a disabled trigger runs nothing.
119
+ *
120
+ * After running, the caret goes back to the editor the action ran on — a
121
+ * no-op for a pointer press under `emailKeepFocus`, the way back for a key
122
+ * press in a toolbar. `[emailActionFocus]="false"` leaves focus on the
123
+ * control, as the ARIA toolbar pattern has it. A host's own action (a link
124
+ * dialog, a picker) never has focus taken from what it opened.
125
+ */
126
+ declare class ActionTrigger {
127
+ /** The action to trigger — `actions.get(id)`. `undefined` (no editor yet,
128
+ or a kit without it) is a trigger with nothing to do: disabled. */
129
+ readonly action: _angular_core.InputSignal<BoundAction | undefined>;
130
+ /** Whether this directive writes `aria-pressed` and `aria-disabled`. */
131
+ readonly aria: _angular_core.InputSignalWithTransform<boolean, unknown>;
132
+ /** Whether the caret returns to the editor after the action ran. */
133
+ readonly returnFocus: _angular_core.InputSignalWithTransform<boolean, unknown>;
134
+ /** On at the selection. */
135
+ readonly pressed: _angular_core.Signal<boolean>;
136
+ /** Cannot run right now — or has no action at all. */
137
+ readonly disabled: _angular_core.Signal<boolean>;
138
+ protected readonly ariaPressed: _angular_core.Signal<boolean | null>;
139
+ protected readonly ariaDisabled: _angular_core.Signal<true | null>;
140
+ /** Runs the action, as a click does. False when it did not apply. */
141
+ run(): boolean;
142
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ActionTrigger, never>;
143
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ActionTrigger, "[emailAction]", ["emailAction"], { "action": { "alias": "emailAction"; "required": true; "isSignal": true; }; "aria": { "alias": "emailActionAria"; "required": false; "isSignal": true; }; "returnFocus": { "alias": "emailActionFocus"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
144
+ }
145
+
146
+ export { ActionTrigger, editorState, injectActions };
147
+ export type { BoundAction, EditorActions, HostAction };
@@ -0,0 +1,193 @@
1
+ import * as _h_k_dev_angular_email_editor_address from '@h-k-dev/angular-email-editor/address';
2
+ import { Mailbox } from '@h-k-dev/angular-email-editor/address';
3
+ import * as _angular_core from '@angular/core';
4
+ import { TemplateRef } from '@angular/core';
5
+
6
+ /**
7
+ * The chip's template slot. A host that wants its own remove control — a
8
+ * Material icon button, a text link, a different glyph — hands the chip a
9
+ * template, and the chip renders it in the box at its end where the default
10
+ * button sits. The template gets everything the default button uses, so it
11
+ * can be just as accessible.
12
+ *
13
+ * <div email-address-input [formField]="envelope.to">
14
+ * <button
15
+ * *emailAddressChipRemove="let remove = remove; let label = label; let disabled = disabled"
16
+ * type="button"
17
+ * [attr.aria-label]="label"
18
+ * [disabled]="disabled"
19
+ * (click)="remove()"
20
+ * >
21
+ * <mat-icon inline>close</mat-icon>
22
+ * </button>
23
+ * </div>
24
+ *
25
+ * On an address input it applies to every chip the input renders; on a chip
26
+ * of the host's own it applies to that chip.
27
+ */
28
+ /** What the remove template is given. */
29
+ interface AddressChipRemoveContext {
30
+ /** The mailbox in header form, as the chip holds it. */
31
+ readonly $implicit: string;
32
+ readonly mailbox: Mailbox;
33
+ /** Whether the address is well-formed. */
34
+ readonly valid: boolean;
35
+ /** Whether the address is a placeholder a template fills in later. */
36
+ readonly pending: boolean;
37
+ /** The remove control is out of play — the chip is `aria-disabled`. */
38
+ readonly disabled: boolean;
39
+ /** Whether the control belongs in the tab order. False in a list that
40
+ reaches its chips with the arrow keys instead; give it tabindex -1. */
41
+ readonly tabbable: boolean;
42
+ /** The control's accessible name — "Remove ada@example.com". */
43
+ readonly label: string;
44
+ /** Asks the host to drop the address; does nothing while disabled. */
45
+ readonly remove: () => void;
46
+ }
47
+ /**
48
+ * The chip's remove slot: mark an `ng-template` with it (or use the `*`
49
+ * shorthand on the element itself) and the chip renders it in place of the
50
+ * default button, in its `trailing` box. Not rendered at all when the chip
51
+ * is not `removable`.
52
+ */
53
+ declare class AddressChipRemove {
54
+ readonly template: TemplateRef<AddressChipRemoveContext>;
55
+ static ngTemplateContextGuard(_directive: AddressChipRemove, context: unknown): context is AddressChipRemoveContext;
56
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AddressChipRemove, never>;
57
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<AddressChipRemove, "ng-template[emailAddressChipRemove]", never, {}, {}, never, never, true, never>;
58
+ }
59
+
60
+ /**
61
+ * One address as a chip, the way Gmail draws it: the display name when the
62
+ * mailbox has one, the address otherwise, and the whole header form in the
63
+ * title. An address that is not one is flagged, not refused — the user
64
+ * sees the typo, the host decides what to do about it.
65
+ *
66
+ * **Parts are `data-slot`s** — `name`, `note`, `trailing`, `remove` — and
67
+ * that is how it is styled from outside: theme it through the `--email-*` tokens, and reach
68
+ * a part for a structural override with two attributes
69
+ * (`[email-address-chip] [data-slot='name'][data-slot]`).
70
+ *
71
+ * **State on the host.** `data-invalid` marks a malformed address (a list
72
+ * item may not carry `aria-invalid`; the flag is spoken through the `note`
73
+ * slot instead). `data-pending` marks a placeholder a template fills in
74
+ * later (`{{contact.email}}`) — no mistake, so never flagged as one; the
75
+ * note says what it is. `aria-disabled` takes the remove button out of play, and
76
+ * `aria-current` marks the chip a list's keys act on; each is an input under
77
+ * its ARIA name, reflected back, and a styling hook too.
78
+ *
79
+ * **The remove control is a template slot.** The chip draws its own ×
80
+ * button by default; an `ng-template[emailAddressChipRemove]` in the chip's
81
+ * content — or handed down as `removeTemplate` by the address input —
82
+ * replaces it, rendered in the `trailing` box with the address, the
83
+ * accessible name, the disabled state and a `remove()` to call.
84
+ *
85
+ * **Hold to copy.** A press held on the chip for the length of a phone's
86
+ * touch-and-hold — 500ms, `holdDelay` — copies the address, in header form,
87
+ * to the clipboard, mouse or touch alike; a release or a drag before that
88
+ * does not, and the browser's own context menu stays away. The chip shows
89
+ * and says "Copied" for a moment (`data-copied`, a live `status` slot) and
90
+ * emits `copied`.
91
+ *
92
+ * **It asks, it does not do.** The chip holds no list: `removed` is a
93
+ * request the host answers by dropping the address. The address input
94
+ * renders these for its value; a host can render them on its own for a
95
+ * read-only header (a sent copy, a preview).
96
+ *
97
+ * Meant for an `<li>`. No Material, no icon font, no headless library.
98
+ */
99
+ declare class AddressChip {
100
+ #private;
101
+ /** The mailbox in header form: `Ada <ada@example.com>` or `ada@example.com`. */
102
+ readonly address: _angular_core.InputSignal<string>;
103
+ /** Set false for a read-only list: the chip stays, the remove button goes. */
104
+ readonly removable: _angular_core.InputSignalWithTransform<boolean, unknown>;
105
+ /** Draw the address as text in a line, not as a chip: no surface, no
106
+ room after the address, and the remove control out of the flow and out
107
+ of sight — still focusable, so the keyboard reaches it and a list can
108
+ turn back into chips when it does. The address input sets it while it
109
+ is not focused. Reflected as `data-inline`. */
110
+ readonly inline: _angular_core.InputSignalWithTransform<boolean, unknown>;
111
+ /** The list's highlight is on this chip: the one the arrow keys reached,
112
+ or a click picked, while the caret stays in the list's input. An input
113
+ under its ARIA name, like `aria-disabled`, reflected back as
114
+ `aria-current="true"` — the list names the same chip in its input's
115
+ `aria-activedescendant` — and drawn as a focus ring. */
116
+ readonly ariaCurrent: _angular_core.InputSignalWithTransform<boolean, unknown>;
117
+ /** Whether the remove button is in the tab order. A list that reaches
118
+ its chips with the arrow keys sets false: Tab goes straight to its
119
+ input, and the button stays clickable and focusable by script. */
120
+ readonly removeTabbable: _angular_core.InputSignalWithTransform<boolean, unknown>;
121
+ /** Prefix for the remove button's accessible name — "Remove ada@example.com". */
122
+ readonly removeLabel: _angular_core.InputSignal<string>;
123
+ /** What the flag on a malformed address says, for the title and for
124
+ assistive tech. */
125
+ readonly invalidLabel: _angular_core.InputSignal<string>;
126
+ /** What the note on a placeholder says, for the title and for assistive
127
+ tech. */
128
+ readonly pendingLabel: _angular_core.InputSignal<string>;
129
+ /** The remove button is out of play — e.g. while the message sends. */
130
+ readonly ariaDisabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
131
+ /** The remove button was pressed. The host drops the address; the chip
132
+ goes when the host's list no longer has it. */
133
+ readonly removed: _angular_core.OutputEmitterRef<void>;
134
+ /** How long a press must be held to copy the address, in milliseconds:
135
+ the length of a phone's touch-and-hold, 500ms, so the gesture is the
136
+ one a thumb already knows. 0 turns the hold off. */
137
+ readonly holdDelay: _angular_core.InputSignalWithTransform<number, unknown>;
138
+ /** What the chip says, for a moment, once a hold has copied the address
139
+ — "Copied", followed by the address. */
140
+ readonly copiedLabel: _angular_core.InputSignal<string>;
141
+ /** A hold copied the address to the clipboard, in header form. */
142
+ readonly copied: _angular_core.OutputEmitterRef<string>;
143
+ /** The address was just copied: shown for a moment, and said. Reflected
144
+ as `data-copied`. */
145
+ protected readonly justCopied: _angular_core.WritableSignal<boolean>;
146
+ constructor();
147
+ /** A press begins a hold — a primary pointer, mouse or touch alike, on
148
+ the chip itself and not its remove control. */
149
+ protected onPointerdown(event: PointerEvent): void;
150
+ /** A hold that moves is a drag or a scroll, not a hold. */
151
+ protected onPointermove(event: PointerEvent): void;
152
+ /** Released, cancelled or gone before the time: no copy. */
153
+ protected cancelHold(): void;
154
+ /** The hold is the chip's, not the browser's: no context menu on it, on
155
+ a phone or under a right button. */
156
+ protected onContextmenu(event: Event): void;
157
+ /** Writes the address to the clipboard: the async API first, and when
158
+ it refuses — an unfocused document, a context without it — the old
159
+ copy command on a selection made for the purpose. */
160
+ /** Copies the address, in header form, to the clipboard — what a hold
161
+ does, and what a host's own control may ask for — and shows and says
162
+ so. The async API first; when it refuses (an unfocused document, a
163
+ context without it), the old copy command on a selection made for the
164
+ purpose. Resolves to whether the copy went. */
165
+ copy(): Promise<boolean>;
166
+ /** A remove template handed down by a list that renders the chip — the
167
+ address input passes its own `emailAddressChipRemove` slot here. One
168
+ in the chip's own content wins. */
169
+ readonly removeTemplate: _angular_core.InputSignal<TemplateRef<AddressChipRemoveContext> | null>;
170
+ protected readonly removeSlot: _angular_core.Signal<AddressChipRemove | undefined>;
171
+ /** The template the trailing box renders, or null for the default button. */
172
+ protected readonly removeOutlet: _angular_core.Signal<TemplateRef<AddressChipRemoveContext> | null>;
173
+ protected readonly mailbox: _angular_core.Signal<_h_k_dev_angular_email_editor_address.Mailbox>;
174
+ /** Whether the address part is well-formed. Public so a list can count. */
175
+ readonly valid: _angular_core.Signal<boolean>;
176
+ /** Whether the address is a placeholder a template fills in later —
177
+ neither valid nor invalid yet. */
178
+ readonly pending: _angular_core.Signal<boolean>;
179
+ /** The remove control's accessible name — "Remove ada@example.com". */
180
+ protected readonly removeName: _angular_core.Signal<string>;
181
+ protected readonly removeContext: _angular_core.Signal<AddressChipRemoveContext>;
182
+ /** Asks to be removed, unless the control is out of play. One function
183
+ for the chip's life, so a template holding it never sees it change. */
184
+ protected readonly remove: () => void;
185
+ /** The note the chip carries, if any — said, and shown in the title. */
186
+ protected readonly note: _angular_core.Signal<string | null>;
187
+ protected readonly title: _angular_core.Signal<string>;
188
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AddressChip, never>;
189
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AddressChip, "[email-address-chip]", never, { "address": { "alias": "address"; "required": true; "isSignal": true; }; "removable": { "alias": "removable"; "required": false; "isSignal": true; }; "inline": { "alias": "inline"; "required": false; "isSignal": true; }; "ariaCurrent": { "alias": "aria-current"; "required": false; "isSignal": true; }; "removeTabbable": { "alias": "removeTabbable"; "required": false; "isSignal": true; }; "removeLabel": { "alias": "removeLabel"; "required": false; "isSignal": true; }; "invalidLabel": { "alias": "invalidLabel"; "required": false; "isSignal": true; }; "pendingLabel": { "alias": "pendingLabel"; "required": false; "isSignal": true; }; "ariaDisabled": { "alias": "aria-disabled"; "required": false; "isSignal": true; }; "holdDelay": { "alias": "holdDelay"; "required": false; "isSignal": true; }; "copiedLabel": { "alias": "copiedLabel"; "required": false; "isSignal": true; }; "removeTemplate": { "alias": "removeTemplate"; "required": false; "isSignal": true; }; }, { "removed": "removed"; "copied": "copied"; }, ["removeSlot"], never, true, never>;
190
+ }
191
+
192
+ export { AddressChip, AddressChipRemove };
193
+ export type { AddressChipRemoveContext };