UNPKG

3.76 kBTypeScriptView Raw
1import BaseComponent, { Args } from '../addon/-private/component';
2export interface Bounds {
3 firstNode: Node;
4 lastNode: Node;
5}
6export default class Component<S = unknown> extends BaseComponent<S> {
7 args: Readonly<Args<S>>;
8 /**
9 * Development-mode only name of the component, useful for debugging.
10 */
11 readonly debugName: string;
12 /**
13 * Called when the component has been inserted into the DOM.
14 * Override this function to do any set up that requires an element in the document body.
15 */
16 didInsertElement(): void;
17 /**
18 * Called when the component has updated and rerendered itself.
19 * Called only during a rerender, not during an initial render.
20 */
21 didUpdate(): void;
22 /**
23 * Contains the first and last DOM nodes of a component's rendered template.
24 * These nodes can be used to traverse all of the DOM nodes that belong to a
25 * particular component.
26 *
27 * Note that a component's first and last nodes *can* change over time, if the
28 * beginning or ending of the template is dynamic. You should always access
29 * `bounds` directly at the time a node is needed to ensure you are acting on
30 * up-to-date nodes.
31 *
32 * ### Examples
33 *
34 * For components with a single root element, `this.bounds.firstNode` and
35 * `this.bounds.lastNode` are the same.
36 *
37 * ```hbs
38 * <div class="user-profile">
39 * <Avatar @user={{user}} />
40 * </div>
41 * ```
42 *
43 * ```ts
44 * export default class extends Component {
45 * didInsertElement() {
46 * let { firstNode, lastNode } = this.bounds;
47 * console.log(firstNode === lastNode); // true
48 * console.log(firstNode.className); // "user-profile"
49 * }
50 * }
51 * ```
52 *
53 * For components with multiple root nodes, `this.bounds.firstNode` refers to
54 * the first node in the template and `this.bounds.lastNode` refers to the
55 * last:
56 *
57 * ```hbs
58 * Welcome to Glimmer.js!
59 * <span>Let's build some components!</span>
60 * <img src="logo.png">
61 * ```
62 *
63 * ```ts
64 * export default class extends Component {
65 * didInsertElement() {
66 * let { firstNode, lastNode } = this.bounds;
67 *
68 * // Walk all of the DOM siblings from the
69 * // firstNode to the lastNode and push their
70 * // nodeName into an array.
71 * let node = firstNode;
72 * let names = [firstNode.nodeName];
73 * do {
74 * node = node.nextSibling;
75 * names.push(node.nodeName);
76 * } while (node !== lastNode);
77 *
78 * console.log(names);
79 * // ["#text", "SPAN", "IMG"]
80 * }
81 * }
82 * ```
83 *
84 * The bounds can change if the template has dynamic content at the beginning
85 * or the end:
86 *
87 * ```hbs
88 * {{#if user.isAdmin}}
89 * <span class="warning">Admin</span>
90 * {{else}}
91 * Normal User
92 * {{/if}}
93 * ```
94 *
95 * In this example, the `firstNode` will change between a `span` element and a
96 * `TextNode` as the `user.isAdmin` property changes.
97 */
98 bounds: Bounds;
99 /**
100 * The element corresponding to the main element of the component's template.
101 * The main element is the element in the template that has `...attributes` set on it:
102 *
103 * ```hbs
104 * <h1>Modal</h1>
105 * <div class="contents" ...attributes>
106 * {{yield}}
107 * </div>
108 * ```
109 *
110 * In this example, `this.element` would be the `div` with the class `contents`.
111 *
112 * You should not try to access this property until after the component's `didInsertElement()`
113 * lifecycle hook is called.
114 */
115 readonly element: HTMLElement;
116}