@rivet-health/design-system 40.8.0 → 40.9.0

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.
@@ -1,8 +1,9 @@
1
- import { ChangeDetectionStrategy, Component, EventEmitter, HostBinding, HostListener, Input, Output, ViewChild, } from '@angular/core';
1
+ import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, HostBinding, HostListener, Input, Output, ViewChild, } from '@angular/core';
2
2
  import * as i0 from "@angular/core";
3
3
  import * as i1 from "@angular/common";
4
4
  import * as i2 from "../../input/button/button.component";
5
- import * as i3 from "../../format/truncate/truncate.component";
5
+ import * as i3 from "../../input/text-field/text-field.component";
6
+ import * as i4 from "../../format/truncate/truncate.component";
6
7
  /**
7
8
  * A borderless heading with a click-to-edit title and an optional
8
9
  * click-to-edit description, plus a projected slot for actions.
@@ -21,12 +22,10 @@ import * as i3 from "../../format/truncate/truncate.component";
21
22
  * "commit" framing over "change" is deliberate: consumers that persist on
22
23
  * commit (analytics, PATCH) treat the gesture itself as the event; those
23
24
  * that only care about diffs can compare `next === current` in the handler.
24
- * There is no cancel path.
25
25
  *
26
- * Outside-click commits (rather than cancels) to match the established DS
27
- * interaction pattern in `riv-date` and `riv-select`. If a future consumer
28
- * needs an abandon path, the soft first step is Escape-to-cancel rather
29
- * than changing outside-click's meaning.
26
+ * Escape cancels: reverts the draft back to the current value and drops out
27
+ * of edit mode WITHOUT emitting a change. Outside-click still commits (to
28
+ * match `riv-date` / `riv-select`); Escape is the deliberate abandon path.
30
29
  *
31
30
  * Value handling follows the same convention as `riv-text-field`: `[title]`
32
31
  * and `[description]` are treated as suggestions, not authoritative state.
@@ -35,6 +34,12 @@ import * as i3 from "../../format/truncate/truncate.component";
35
34
  * a different value. That lets the component demo out of the box (e.g. in
36
35
  * Storybook) without requiring a round trip through the parent.
37
36
  *
37
+ * Programmatic entry into edit mode is available via `startEditingTitle()`
38
+ * and `startEditingDescription()` — obtain a reference with
39
+ * `@ViewChild(EditableHeadingComponent)`. Use these for secondary entry
40
+ * points like a kebab-menu "Rename" item, or to auto-open rename after
41
+ * creating a new entity.
42
+ *
38
43
  * The component owns no border, background, or card chrome — consumers who
39
44
  * want a bordered container should wrap it.
40
45
  *
@@ -71,6 +76,15 @@ export class EditableHeadingComponent {
71
76
  get description() {
72
77
  return this._description;
73
78
  }
79
+ set disabled(v) {
80
+ this._disabled = v;
81
+ if (v && this.mode !== 'view')
82
+ this.cancel();
83
+ this.cdr.markForCheck();
84
+ }
85
+ get disabled() {
86
+ return this._disabled;
87
+ }
74
88
  constructor(cdr, host) {
75
89
  this.cdr = cdr;
76
90
  this.host = host;
@@ -79,6 +93,13 @@ export class EditableHeadingComponent {
79
93
  this._description = '';
80
94
  this.titleMaxLength = 100;
81
95
  this.descriptionMaxLength = 300;
96
+ /**
97
+ * When true, the title and description are not clickable and cannot be
98
+ * edited. Any in-progress edit is dropped without emitting. Imperative
99
+ * `startEditing*` calls no-op. Useful for consumers that need to gate
100
+ * editing on a permission or a broader "actions disabled" state.
101
+ */
102
+ this._disabled = false;
82
103
  this.titleChange = new EventEmitter();
83
104
  this.descriptionChange = new EventEmitter();
84
105
  this.mode = 'view';
@@ -88,15 +109,38 @@ export class EditableHeadingComponent {
88
109
  get isEditing() {
89
110
  return this.mode !== 'view';
90
111
  }
112
+ /**
113
+ * Enter title-edit mode programmatically. Same behavior as clicking the
114
+ * title — populates the edit buffer from the current value, focuses the
115
+ * input with the caret at the end, and hides the actions slot. No-op if
116
+ * already in an editing mode or when the component is disabled.
117
+ *
118
+ * Intended for consumers that offer a secondary entry point to renaming
119
+ * (e.g. a kebab menu item), or that want to auto-open rename after
120
+ * creating a new entity. Bind via `@ViewChild(EditableHeadingComponent)`.
121
+ */
91
122
  startEditingTitle() {
123
+ if (this.disabled || this.mode !== 'view')
124
+ return;
92
125
  this.draftTitle = this.title;
93
126
  this.mode = 'editingTitle';
127
+ // `markForCheck` so consumers can call this from outside Angular's zone
128
+ // (e.g. an async callback) without having to trigger CD themselves.
129
+ this.cdr.markForCheck();
94
130
  // Defer focus until Angular has rendered the input into the DOM.
95
131
  setTimeout(() => this.focusEnd(this.titleInputRef), 0);
96
132
  }
133
+ /**
134
+ * Enter description-edit mode programmatically. Same behavior as clicking
135
+ * the description (or the "+ Add description" button). No-op if already
136
+ * in an editing mode or when the component is disabled.
137
+ */
97
138
  startEditingDescription() {
139
+ if (this.disabled || this.mode !== 'view')
140
+ return;
98
141
  this.draftDescription = this.description;
99
142
  this.mode = 'editingDescription';
143
+ this.cdr.markForCheck();
100
144
  setTimeout(() => this.focusEnd(this.descriptionInputRef), 0);
101
145
  }
102
146
  commitTitle() {
@@ -122,6 +166,18 @@ export class EditableHeadingComponent {
122
166
  this.mode = 'view';
123
167
  this.descriptionChange.emit(value);
124
168
  }
169
+ /**
170
+ * Abandon the current edit and return to view mode. No change is emitted.
171
+ * Wired to the Escape key on both edit inputs; also called internally
172
+ * when `disabled` flips to true mid-edit.
173
+ */
174
+ cancel() {
175
+ if (this.mode === 'view')
176
+ return;
177
+ this.draftTitle = this._title;
178
+ this.draftDescription = this._description;
179
+ this.mode = 'view';
180
+ }
125
181
  // Listens on `mousedown` (not `click`) so the check runs before Angular
126
182
  // re-renders the trigger element out of the DOM — otherwise
127
183
  // `host.contains(target)` returns false for a click that landed on the
@@ -139,23 +195,24 @@ export class EditableHeadingComponent {
139
195
  this.commitDescription();
140
196
  }
141
197
  }
142
- // Focus with caret at end (rather than selecting all) so the user can
143
- // continue typing where the previous value left off.
198
+ // Position caret at end (rather than selecting all) so the user can continue
199
+ // typing where the previous value left off. `riv-text-field` handles the
200
+ // focus itself via `[autoFocus]`; we just fix up the selection range on the
201
+ // descendant `<input>`.
144
202
  focusEnd(ref) {
145
- const el = ref?.nativeElement;
146
- if (!el)
203
+ const input = ref?.nativeElement.querySelector('input');
204
+ if (!input)
147
205
  return;
148
- el.focus();
149
- const len = el.value.length;
150
- el.setSelectionRange(len, len);
206
+ const len = input.value.length;
207
+ input.setSelectionRange(len, len);
151
208
  this.cdr.markForCheck();
152
209
  }
153
210
  }
154
211
  EditableHeadingComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: EditableHeadingComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
155
- EditableHeadingComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: EditableHeadingComponent, selector: "riv-editable-heading", inputs: { title: "title", description: "description", titleMaxLength: "titleMaxLength", descriptionMaxLength: "descriptionMaxLength" }, outputs: { titleChange: "titleChange", descriptionChange: "descriptionChange" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event.target)" }, properties: { "class.editing": "this.isEditing" } }, viewQueries: [{ propertyName: "titleInputRef", first: true, predicate: ["titleInput"], descendants: true }, { propertyName: "descriptionInputRef", first: true, predicate: ["descriptionInput"], descendants: true }], ngImport: i0, template: "<div class=\"leading\">\n <ng-container [ngSwitch]=\"mode\">\n <!-- View mode -->\n <ng-container *ngSwitchDefault>\n <button\n type=\"button\"\n class=\"title\"\n [class.has-description]=\"description\"\n rivTruncate\n aria-label=\"Rename\"\n (click)=\"startEditingTitle()\"\n >\n {{ title || 'Untitled' }}\n </button>\n\n <div class=\"divider\"></div>\n\n <button\n *ngIf=\"description; else addDescription\"\n type=\"button\"\n class=\"description\"\n rivTruncate\n aria-label=\"Edit description\"\n (click)=\"startEditingDescription()\"\n >\n {{ description }}\n </button>\n\n <ng-template #addDescription>\n <div class=\"add-description-wrap\">\n <button\n rivButton\n [variant]=\"'ghost'\"\n [size]=\"'xsmall'\"\n [icon]=\"'Plus'\"\n [iconPosition]=\"'first'\"\n type=\"button\"\n (click)=\"startEditingDescription()\"\n >\n Add description\n </button>\n </div>\n </ng-template>\n </ng-container>\n\n <!-- Editing title -->\n <ng-container *ngSwitchCase=\"'editingTitle'\">\n <input\n #titleInput\n class=\"title-input\"\n type=\"text\"\n aria-label=\"Title\"\n [value]=\"draftTitle\"\n [attr.maxlength]=\"titleMaxLength\"\n (input)=\"draftTitle = titleInput.value\"\n (keydown.enter)=\"commitTitle()\"\n />\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n [disabled]=\"!draftTitle\"\n (click)=\"commitTitle()\"\n aria-label=\"Save title\"\n ></button>\n </ng-container>\n\n <!-- Editing description -->\n <ng-container *ngSwitchCase=\"'editingDescription'\">\n <input\n #descriptionInput\n class=\"description-input\"\n type=\"text\"\n aria-label=\"Description\"\n [value]=\"draftDescription\"\n [attr.maxlength]=\"descriptionMaxLength\"\n placeholder=\"Add a description\"\n (input)=\"draftDescription = descriptionInput.value\"\n (keydown.enter)=\"commitDescription()\"\n />\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n (click)=\"commitDescription()\"\n aria-label=\"Save description\"\n ></button>\n </ng-container>\n </ng-container>\n</div>\n\n<div class=\"actions\" *ngIf=\"!isEditing\">\n <ng-content select=\"[actions]\"></ng-content>\n</div>\n", styles: [":host{display:flex;align-items:stretch;gap:var(--size-large);min-height:calc(var(--base-grid-size) * 8);font:var(--body-medium)}.leading{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:var(--size-small)}.title,.description{padding:0;border:none;background:none;text-align:left;cursor:pointer;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.title{font:var(--stat-xsmall);line-height:calc(var(--base-grid-size) * 4.5);color:var(--type-light-high-contrast);max-width:100%}.title.has-description{width:-moz-fit-content;width:fit-content;max-width:50%;flex-shrink:0}.description{font:var(--input-small);line-height:calc(var(--base-grid-size) * 3.5);color:var(--type-light-low-contrast);flex:1 1 auto}.divider{align-self:stretch;border-right:var(--border-width) solid var(--border-light);margin:0 var(--base-grid-size) 0 0;flex-shrink:0}.add-description-wrap{flex-shrink:0}.title-input,.description-input{border:var(--border-width) solid var(--border-light);border-radius:var(--border-radius-small);padding:var(--size-small) var(--size-medium);color:var(--type-light-high-contrast);outline:none;min-width:0}.title-input{font:var(--stat-xsmall);flex:1 1 auto}.description-input{font:var(--input-small);flex:1 1 auto}.title-input:focus,.description-input:focus{border-color:var(--purp-60)}.commit{flex-shrink:0}.actions{display:flex;align-items:center;gap:var(--size-small);flex-shrink:0}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "component", type: i2.ButtonComponent, selector: "[rivButton]", inputs: ["locked", "disabled", "loading", "full", "size", "variant", "icon", "iconPosition", "current"] }, { kind: "component", type: i3.TruncateComponent, selector: "[rivTruncate]", inputs: ["maxTooltipWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
212
+ EditableHeadingComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: EditableHeadingComponent, selector: "riv-editable-heading", inputs: { title: "title", description: "description", titleMaxLength: "titleMaxLength", descriptionMaxLength: "descriptionMaxLength", disabled: "disabled" }, outputs: { titleChange: "titleChange", descriptionChange: "descriptionChange" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event.target)" }, properties: { "class.editing": "this.isEditing" } }, viewQueries: [{ propertyName: "titleInputRef", first: true, predicate: ["titleInput"], descendants: true, read: ElementRef }, { propertyName: "descriptionInputRef", first: true, predicate: ["descriptionInput"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div class=\"leading\">\n <ng-container [ngSwitch]=\"mode\">\n <!-- View mode -->\n <ng-container *ngSwitchDefault>\n <button\n type=\"button\"\n class=\"title\"\n [class.has-description]=\"description\"\n [disabled]=\"disabled\"\n rivTruncate\n aria-label=\"Rename\"\n (click)=\"startEditingTitle()\"\n >\n {{ title || 'Untitled' }}\n </button>\n\n <div class=\"divider\"></div>\n\n <button\n *ngIf=\"description; else addDescription\"\n type=\"button\"\n class=\"description\"\n [disabled]=\"disabled\"\n rivTruncate\n aria-label=\"Edit description\"\n (click)=\"startEditingDescription()\"\n >\n {{ description }}\n </button>\n\n <ng-template #addDescription>\n <div class=\"add-description-wrap\" *ngIf=\"!disabled\">\n <button\n rivButton\n [variant]=\"'ghost'\"\n [size]=\"'xsmall'\"\n [icon]=\"'Plus'\"\n [iconPosition]=\"'first'\"\n type=\"button\"\n (click)=\"startEditingDescription()\"\n >\n Add description\n </button>\n </div>\n </ng-template>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'editingTitle'\">\n <riv-text-field\n #titleInput\n class=\"title-input\"\n [value]=\"draftTitle\"\n [maxLength]=\"titleMaxLength\"\n [autoFocus]=\"true\"\n (valueChange)=\"draftTitle = $event\"\n (keydown.enter)=\"commitTitle()\"\n (keydown.escape)=\"cancel()\"\n ></riv-text-field>\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n [disabled]=\"!draftTitle\"\n (click)=\"commitTitle()\"\n aria-label=\"Save title\"\n ></button>\n </ng-container>\n\n <!-- Editing description -->\n <ng-container *ngSwitchCase=\"'editingDescription'\">\n <riv-text-field\n #descriptionInput\n class=\"description-input\"\n placeholder=\"Add a description\"\n [value]=\"draftDescription\"\n [maxLength]=\"descriptionMaxLength\"\n [autoFocus]=\"true\"\n (valueChange)=\"draftDescription = $event\"\n (keydown.enter)=\"commitDescription()\"\n (keydown.escape)=\"cancel()\"\n ></riv-text-field>\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n (click)=\"commitDescription()\"\n aria-label=\"Save description\"\n ></button>\n </ng-container>\n </ng-container>\n</div>\n\n<div class=\"actions\" *ngIf=\"!isEditing\">\n <ng-content select=\"[actions]\"></ng-content>\n</div>\n", styles: [":host{display:flex;align-items:stretch;gap:var(--size-large);min-height:calc(var(--base-grid-size) * 8);font:var(--body-medium)}.leading{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:var(--size-small)}.title,.description{padding:0;border:none;background:none;text-align:left;cursor:pointer;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.title:disabled,.description:disabled{cursor:default}.title{font:var(--stat-xsmall);line-height:calc(var(--base-grid-size) * 4.5);color:var(--type-light-high-contrast);max-width:100%}.title.has-description{width:-moz-fit-content;width:fit-content;max-width:50%;flex-shrink:0}.description{font:var(--input-small);line-height:calc(var(--base-grid-size) * 3.5);color:var(--type-light-low-contrast);flex:1 1 auto}.divider{align-self:stretch;border-right:var(--border-width) solid var(--border-light);margin:0 var(--base-grid-size) 0 0;flex-shrink:0}.add-description-wrap{flex-shrink:0}.title-input,.description-input{flex:1 1 auto;min-width:0}.commit{flex-shrink:0}.actions{display:flex;align-items:center;gap:var(--size-small);flex-shrink:0}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "component", type: i2.ButtonComponent, selector: "[rivButton]", inputs: ["locked", "disabled", "loading", "full", "size", "variant", "icon", "iconPosition", "current"] }, { kind: "component", type: i3.TextFieldComponent, selector: "riv-text-field", inputs: ["disabled", "readonly", "placeholder", "casing", "type", "size", "autoFocus", "name", "minLength", "maxLength", "value"], outputs: ["valueChange", "blur"] }, { kind: "component", type: i4.TruncateComponent, selector: "[rivTruncate]", inputs: ["maxTooltipWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
156
213
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: EditableHeadingComponent, decorators: [{
157
214
  type: Component,
158
- args: [{ selector: 'riv-editable-heading', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"leading\">\n <ng-container [ngSwitch]=\"mode\">\n <!-- View mode -->\n <ng-container *ngSwitchDefault>\n <button\n type=\"button\"\n class=\"title\"\n [class.has-description]=\"description\"\n rivTruncate\n aria-label=\"Rename\"\n (click)=\"startEditingTitle()\"\n >\n {{ title || 'Untitled' }}\n </button>\n\n <div class=\"divider\"></div>\n\n <button\n *ngIf=\"description; else addDescription\"\n type=\"button\"\n class=\"description\"\n rivTruncate\n aria-label=\"Edit description\"\n (click)=\"startEditingDescription()\"\n >\n {{ description }}\n </button>\n\n <ng-template #addDescription>\n <div class=\"add-description-wrap\">\n <button\n rivButton\n [variant]=\"'ghost'\"\n [size]=\"'xsmall'\"\n [icon]=\"'Plus'\"\n [iconPosition]=\"'first'\"\n type=\"button\"\n (click)=\"startEditingDescription()\"\n >\n Add description\n </button>\n </div>\n </ng-template>\n </ng-container>\n\n <!-- Editing title -->\n <ng-container *ngSwitchCase=\"'editingTitle'\">\n <input\n #titleInput\n class=\"title-input\"\n type=\"text\"\n aria-label=\"Title\"\n [value]=\"draftTitle\"\n [attr.maxlength]=\"titleMaxLength\"\n (input)=\"draftTitle = titleInput.value\"\n (keydown.enter)=\"commitTitle()\"\n />\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n [disabled]=\"!draftTitle\"\n (click)=\"commitTitle()\"\n aria-label=\"Save title\"\n ></button>\n </ng-container>\n\n <!-- Editing description -->\n <ng-container *ngSwitchCase=\"'editingDescription'\">\n <input\n #descriptionInput\n class=\"description-input\"\n type=\"text\"\n aria-label=\"Description\"\n [value]=\"draftDescription\"\n [attr.maxlength]=\"descriptionMaxLength\"\n placeholder=\"Add a description\"\n (input)=\"draftDescription = descriptionInput.value\"\n (keydown.enter)=\"commitDescription()\"\n />\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n (click)=\"commitDescription()\"\n aria-label=\"Save description\"\n ></button>\n </ng-container>\n </ng-container>\n</div>\n\n<div class=\"actions\" *ngIf=\"!isEditing\">\n <ng-content select=\"[actions]\"></ng-content>\n</div>\n", styles: [":host{display:flex;align-items:stretch;gap:var(--size-large);min-height:calc(var(--base-grid-size) * 8);font:var(--body-medium)}.leading{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:var(--size-small)}.title,.description{padding:0;border:none;background:none;text-align:left;cursor:pointer;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.title{font:var(--stat-xsmall);line-height:calc(var(--base-grid-size) * 4.5);color:var(--type-light-high-contrast);max-width:100%}.title.has-description{width:-moz-fit-content;width:fit-content;max-width:50%;flex-shrink:0}.description{font:var(--input-small);line-height:calc(var(--base-grid-size) * 3.5);color:var(--type-light-low-contrast);flex:1 1 auto}.divider{align-self:stretch;border-right:var(--border-width) solid var(--border-light);margin:0 var(--base-grid-size) 0 0;flex-shrink:0}.add-description-wrap{flex-shrink:0}.title-input,.description-input{border:var(--border-width) solid var(--border-light);border-radius:var(--border-radius-small);padding:var(--size-small) var(--size-medium);color:var(--type-light-high-contrast);outline:none;min-width:0}.title-input{font:var(--stat-xsmall);flex:1 1 auto}.description-input{font:var(--input-small);flex:1 1 auto}.title-input:focus,.description-input:focus{border-color:var(--purp-60)}.commit{flex-shrink:0}.actions{display:flex;align-items:center;gap:var(--size-small);flex-shrink:0}\n"] }]
215
+ args: [{ selector: 'riv-editable-heading', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"leading\">\n <ng-container [ngSwitch]=\"mode\">\n <!-- View mode -->\n <ng-container *ngSwitchDefault>\n <button\n type=\"button\"\n class=\"title\"\n [class.has-description]=\"description\"\n [disabled]=\"disabled\"\n rivTruncate\n aria-label=\"Rename\"\n (click)=\"startEditingTitle()\"\n >\n {{ title || 'Untitled' }}\n </button>\n\n <div class=\"divider\"></div>\n\n <button\n *ngIf=\"description; else addDescription\"\n type=\"button\"\n class=\"description\"\n [disabled]=\"disabled\"\n rivTruncate\n aria-label=\"Edit description\"\n (click)=\"startEditingDescription()\"\n >\n {{ description }}\n </button>\n\n <ng-template #addDescription>\n <div class=\"add-description-wrap\" *ngIf=\"!disabled\">\n <button\n rivButton\n [variant]=\"'ghost'\"\n [size]=\"'xsmall'\"\n [icon]=\"'Plus'\"\n [iconPosition]=\"'first'\"\n type=\"button\"\n (click)=\"startEditingDescription()\"\n >\n Add description\n </button>\n </div>\n </ng-template>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'editingTitle'\">\n <riv-text-field\n #titleInput\n class=\"title-input\"\n [value]=\"draftTitle\"\n [maxLength]=\"titleMaxLength\"\n [autoFocus]=\"true\"\n (valueChange)=\"draftTitle = $event\"\n (keydown.enter)=\"commitTitle()\"\n (keydown.escape)=\"cancel()\"\n ></riv-text-field>\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n [disabled]=\"!draftTitle\"\n (click)=\"commitTitle()\"\n aria-label=\"Save title\"\n ></button>\n </ng-container>\n\n <!-- Editing description -->\n <ng-container *ngSwitchCase=\"'editingDescription'\">\n <riv-text-field\n #descriptionInput\n class=\"description-input\"\n placeholder=\"Add a description\"\n [value]=\"draftDescription\"\n [maxLength]=\"descriptionMaxLength\"\n [autoFocus]=\"true\"\n (valueChange)=\"draftDescription = $event\"\n (keydown.enter)=\"commitDescription()\"\n (keydown.escape)=\"cancel()\"\n ></riv-text-field>\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n (click)=\"commitDescription()\"\n aria-label=\"Save description\"\n ></button>\n </ng-container>\n </ng-container>\n</div>\n\n<div class=\"actions\" *ngIf=\"!isEditing\">\n <ng-content select=\"[actions]\"></ng-content>\n</div>\n", styles: [":host{display:flex;align-items:stretch;gap:var(--size-large);min-height:calc(var(--base-grid-size) * 8);font:var(--body-medium)}.leading{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:var(--size-small)}.title,.description{padding:0;border:none;background:none;text-align:left;cursor:pointer;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.title:disabled,.description:disabled{cursor:default}.title{font:var(--stat-xsmall);line-height:calc(var(--base-grid-size) * 4.5);color:var(--type-light-high-contrast);max-width:100%}.title.has-description{width:-moz-fit-content;width:fit-content;max-width:50%;flex-shrink:0}.description{font:var(--input-small);line-height:calc(var(--base-grid-size) * 3.5);color:var(--type-light-low-contrast);flex:1 1 auto}.divider{align-self:stretch;border-right:var(--border-width) solid var(--border-light);margin:0 var(--base-grid-size) 0 0;flex-shrink:0}.add-description-wrap{flex-shrink:0}.title-input,.description-input{flex:1 1 auto;min-width:0}.commit{flex-shrink:0}.actions{display:flex;align-items:center;gap:var(--size-small);flex-shrink:0}\n"] }]
159
216
  }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { title: [{
160
217
  type: Input
161
218
  }], description: [{
@@ -164,16 +221,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
164
221
  type: Input
165
222
  }], descriptionMaxLength: [{
166
223
  type: Input
224
+ }], disabled: [{
225
+ type: Input
167
226
  }], titleChange: [{
168
227
  type: Output
169
228
  }], descriptionChange: [{
170
229
  type: Output
171
230
  }], titleInputRef: [{
172
231
  type: ViewChild,
173
- args: ['titleInput']
232
+ args: ['titleInput', { read: ElementRef }]
174
233
  }], descriptionInputRef: [{
175
234
  type: ViewChild,
176
- args: ['descriptionInput']
235
+ args: ['descriptionInput', { read: ElementRef }]
177
236
  }], isEditing: [{
178
237
  type: HostBinding,
179
238
  args: ['class.editing']
@@ -181,4 +240,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
181
240
  type: HostListener,
182
241
  args: ['document:mousedown', ['$event.target']]
183
242
  }] } });
184
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWRpdGFibGUtaGVhZGluZy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9yaXYvc3JjL2xpYi9uYXZpZ2F0aW9uL2VkaXRhYmxlLWhlYWRpbmcvZWRpdGFibGUtaGVhZGluZy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9yaXYvc3JjL2xpYi9uYXZpZ2F0aW9uL2VkaXRhYmxlLWhlYWRpbmcvZWRpdGFibGUtaGVhZGluZy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBRXZCLFNBQVMsRUFFVCxZQUFZLEVBQ1osV0FBVyxFQUNYLFlBQVksRUFDWixLQUFLLEVBQ0wsTUFBTSxFQUNOLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQzs7Ozs7QUFFdkI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvREc7QUFPSCxNQUFNLE9BQU8sd0JBQXdCO0lBR25DLElBQ0ksS0FBSyxDQUFDLENBQVM7UUFDakIsSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLE1BQU07WUFBRSxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBQ0QsSUFBSSxLQUFLO1FBQ1AsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3JCLENBQUM7SUFHRCxJQUNJLFdBQVcsQ0FBQyxDQUFTO1FBQ3ZCLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxZQUFZO1lBQUUsSUFBSSxDQUFDLFlBQVksR0FBRyxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUNELElBQUksV0FBVztRQUNiLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQztJQUMzQixDQUFDO0lBd0JELFlBQ21CLEdBQXNCLEVBQ3RCLElBQTZCO1FBRDdCLFFBQUcsR0FBSCxHQUFHLENBQW1CO1FBQ3RCLFNBQUks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RSxxREFBcUQ7SUFDN0MsUUFBUSxDQUFDLEdBQWtDO1FBQ2pELE1BQU0sRUFBRSxHQUFHLEdBQUcsRUFBRSxhQUFhLENBQUM7UUFDOUIsSUFBSSxDQUFDLEVBQUU7WUFBRSxPQUFPO1FBQ2hCLEVBQUUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNYLE1BQU0sR0FBRyxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBQzVCLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDL0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUMxQixDQUFDOztzSEFqSFUsd0JBQXdCOzBHQUF4Qix3QkFBd0Isb25CQ3hFckMsNHJGQWtHQTs0RkQxQmEsd0JBQXdCO2tCQU5wQyxTQUFTOytCQUNFLHNCQUFzQixtQkFHZix1QkFBdUIsQ0FBQyxNQUFNO2lJQU0zQyxLQUFLO3NCQURSLEtBQUs7Z0JBVUYsV0FBVztzQkFEZCxLQUFLO2dCQVNOLGNBQWM7c0JBRGIsS0FBSztnQkFJTixvQkFBb0I7c0JBRG5CLEtBQUs7Z0JBSU4sV0FBVztzQkFEVixNQUFNO2dCQUlQLGlCQUFpQjtzQkFEaEIsTUFBTTtnQkFJQyxhQUFhO3NCQURwQixTQUFTO3VCQUFDLFlBQVk7Z0JBSWYsbUJBQW1CO3NCQUQxQixTQUFTO3VCQUFDLGtCQUFrQjtnQkFhekIsU0FBUztzQkFEWixXQUFXO3VCQUFDLGVBQWU7Z0JBK0NsQixtQkFBbUI7c0JBRDVCLFlBQVk7dUJBQUMsb0JBQW9CLEVBQUUsQ0FBQyxlQUFlLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBIb3N0QmluZGluZyxcbiAgSG9zdExpc3RlbmVyLFxuICBJbnB1dCxcbiAgT3V0cHV0LFxuICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG4vKipcbiAqIEEgYm9yZGVybGVzcyBoZWFkaW5nIHdpdGggYSBjbGljay10by1lZGl0IHRpdGxlIGFuZCBhbiBvcHRpb25hbFxuICogY2xpY2stdG8tZWRpdCBkZXNjcmlwdGlvbiwgcGx1cyBhIHByb2plY3RlZCBzbG90IGZvciBhY3Rpb25zLlxuICpcbiAqIExheW91dDogYFt0aXRsZV0gfCBbZGVzY3JpcHRpb25dICBbYWN0aW9uc11gXG4gKlxuICogLSBDbGljayB0aGUgdGl0bGUgdG8gcmVuYW1lOyBjbGljayB0aGUgZGVzY3JpcHRpb24gKG9yIHRoZSBnaG9zdFxuICogICBcIisgQWRkIGRlc2NyaXB0aW9uXCIgYnV0dG9uIHdoZW4gZW1wdHkpIHRvIGVkaXQgaXQuXG4gKiAtIE9ubHkgb25lIG9mIHRpdGxlIG9yIGRlc2NyaXB0aW9uIGNhbiBiZSBlZGl0ZWQgYXQgYSB0aW1lLlxuICogLSBXaGlsZSBlaXRoZXIgaXMgYmVpbmcgZWRpdGVkLCB0aGUgYFthY3Rpb25zXWAgc2xvdCBpcyBoaWRkZW4gc29cbiAqICAgcHJvamVjdGVkIGNvbnRyb2xzIGRvbid0IGNvbXBldGUgd2l0aCB0aGUgZWRpdCBhZmZvcmRhbmNlLlxuICpcbiAqIENvbW1pdCBzZW1hbnRpY3M6IGB0aXRsZUNoYW5nZWAgLyBgZGVzY3JpcHRpb25DaGFuZ2VgIGZpcmUgd2hlbiB0aGUgdXNlclxuICogY29tbWl0cyDigJQgRW50ZXIsIG91dHNpZGUgY2xpY2ssIG9yIHRoZSBDaGVjayBidXR0b24g4oCUIG5vdCBvbiBldmVyeVxuICoga2V5c3Ryb2tlLCBhbmQgYWx3YXlzIG9uIGNvbW1pdCAoZXZlbiB3aGVuIHRoZSB2YWx1ZSBpcyB1bmNoYW5nZWQpLiBUaGVcbiAqIFwiY29tbWl0XCIgZnJhbWluZyBvdmVyIFwiY2hhbmdlXCIgaXMgZGVsaWJlcmF0ZTogY29uc3VtZXJzIHRoYXQgcGVyc2lzdCBvblxuICogY29tbWl0IChhbmFseXRpY3MsIFBBVENIKSB0cmVhdCB0aGUgZ2VzdHVyZSBpdHNlbGYgYXMgdGhlIGV2ZW50OyB0aG9zZVxuICogdGhhdCBvbmx5IGNhcmUgYWJvdXQgZGlmZnMgY2FuIGNvbXBhcmUgYG5leHQgPT09IGN1cnJlbnRgIGluIHRoZSBoYW5kbGVyLlxuICogVGhlcmUgaXMgbm8gY2FuY2VsIHBhdGguXG4gKlxuICogT3V0c2lkZS1jbGljayBjb21taXRzIChyYXRoZXIgdGhhbiBjYW5jZWxzKSB0byBtYXRjaCB0aGUgZXN0YWJsaXNoZWQgRFNcbiAqIGludGVyYWN0aW9uIHBhdHRlcm4gaW4gYHJpdi1kYXRlYCBhbmQgYHJpdi1zZWxlY3RgLiBJZiBhIGZ1dHVyZSBjb25zdW1lclxuICogbmVlZHMgYW4gYWJhbmRvbiBwYXRoLCB0aGUgc29mdCBmaXJzdCBzdGVwIGlzIEVzY2FwZS10by1jYW5jZWwgcmF0aGVyXG4gKiB0aGFuIGNoYW5naW5nIG91dHNpZGUtY2xpY2sncyBtZWFuaW5nLlxuICpcbiAqIFZhbHVlIGhhbmRsaW5nIGZvbGxvd3MgdGhlIHNhbWUgY29udmVudGlvbiBhcyBgcml2LXRleHQtZmllbGRgOiBgW3RpdGxlXWBcbiAqIGFuZCBgW2Rlc2NyaXB0aW9uXWAgYXJlIHRyZWF0ZWQgYXMgc3VnZ2VzdGlvbnMsIG5vdCBhdXRob3JpdGF0aXZlIHN0YXRlLlxuICogT24gY29tbWl0LCB0aGUgY29tcG9uZW50IGtlZXBzIGRpc3BsYXlpbmcgdGhlIHVzZXIncyBjb21taXR0ZWQgdmFsdWUsXG4gKiBhbmQgb25seSBvdmVyd3JpdGVzIGl0cyBpbnRlcm5hbCBzdGF0ZSB3aGVuIHRoZSBwYXJlbnQgZXhwbGljaXRseSBzZW5kc1xuICogYSBkaWZmZXJlbnQgdmFsdWUuIFRoYXQgbGV0cyB0aGUgY29tcG9uZW50IGRlbW8gb3V0IG9mIHRoZSBib3ggKGUuZy4gaW5cbiAqIFN0b3J5Ym9vaykgd2l0aG91dCByZXF1aXJpbmcgYSByb3VuZCB0cmlwIHRocm91Z2ggdGhlIHBhcmVudC5cbiAqXG4gKiBUaGUgY29tcG9uZW50IG93bnMgbm8gYm9yZGVyLCBiYWNrZ3JvdW5kLCBvciBjYXJkIGNocm9tZSDigJQgY29uc3VtZXJzIHdob1xuICogd2FudCBhIGJvcmRlcmVkIGNvbnRhaW5lciBzaG91bGQgd3JhcCBpdC5cbiAqXG4gKiBgYGBodG1sXG4gKiA8cml2LWVkaXRhYmxlLWhlYWRpbmdcbiAqICAgW3RpdGxlXT1cInJlcG9ydC50aXRsZVwiXG4gKiAgIFtkZXNjcmlwdGlvbl09XCJyZXBvcnQuZGVzY3JpcHRpb25cIlxuICogICAodGl0bGVDaGFuZ2UpPVwib25UaXRsZUNvbW1pdCgkZXZlbnQpXCJcbiAqICAgKGRlc2NyaXB0aW9uQ2hhbmdlKT1cIm9uRGVzY3JpcHRpb25Db21taXQoJGV2ZW50KVwiXG4gKiA+XG4gKiAgIDxyaXYtbWVudSBhY3Rpb25zPlxuICogICAgIDxuZy10ZW1wbGF0ZSAjdHJpZ2dlcj5cbiAqICAgICAgIDxidXR0b24gcml2QnV0dG9uIFtpY29uXT1cIidNb3JlVmVydGljYWwnXCIgW3ZhcmlhbnRdPVwiJ2dob3N0J1wiPjwvYnV0dG9uPlxuICogICAgIDwvbmctdGVtcGxhdGU+XG4gKiAgICAgPGJ1dHRvbiByaXYtbWVudS1pdGVtPlJlbmFtZTwvYnV0dG9uPlxuICogICAgIDxidXR0b24gcml2LW1lbnUtaXRlbT5EdXBsaWNhdGU8L2J1dHRvbj5cbiAqICAgPC9yaXYtbWVudT5cbiAqICAgPGJ1dHRvbiByaXZCdXR0b24gYWN0aW9ucyBbdmFyaWFudF09XCIncHJpbWFyeSdcIj5TYXZlPC9idXR0b24+XG4gKiA8L3Jpdi1lZGl0YWJsZS1oZWFkaW5nPlxuICogYGBgXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3Jpdi1lZGl0YWJsZS1oZWFkaW5nJyxcbiAgdGVtcGxhdGVVcmw6ICcuL2VkaXRhYmxlLWhlYWRpbmcuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9lZGl0YWJsZS1oZWFkaW5nLmNvbXBvbmVudC5jc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIEVkaXRhYmxlSGVhZGluZ0NvbXBvbmVudCB7XG4gIC8vIFNlZSB0aGUgXCJWYWx1ZSBoYW5kbGluZ1wiIHNlY3Rpb24gb2YgdGhlIGNsYXNzLWxldmVsIGRvYy5cbiAgcHJvdGVjdGVkIF90aXRsZTogc3RyaW5nID0gJyc7XG4gIEBJbnB1dCgpXG4gIHNldCB0aXRsZSh2OiBzdHJpbmcpIHtcbiAgICBpZiAodiAhPT0gdGhpcy5fdGl0bGUpIHRoaXMuX3RpdGxlID0gdjtcbiAgfVxuICBnZXQgdGl0bGUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fdGl0bGU7XG4gIH1cblxuICBwcm90ZWN0ZWQgX2Rlc2NyaXB0aW9uOiBzdHJpbmcgPSAnJztcbiAgQElucHV0KClcbiAgc2V0IGRlc2NyaXB0aW9uKHY6IHN0cmluZykge1xuICAgIGlmICh2ICE9PSB0aGlzLl9kZXNjcmlwdGlvbikgdGhpcy5fZGVzY3JpcHRpb24gPSB2O1xuICB9XG4gIGdldCBkZXNjcmlwdGlvbigpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl9kZXNjcmlwdGlvbjtcbiAgfVxuXG4gIEBJbnB1dCgpXG4gIHRpdGxlTWF4TGVuZ3RoOiBudW1iZXIgPSAxMDA7XG5cbiAgQElucHV0KClcbiAgZGVzY3JpcHRpb25NYXhMZW5ndGg6IG51bWJlciA9IDMwMDtcblxuICBAT3V0cHV0KClcbiAgdGl0bGVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcblxuICBAT3V0cHV0KClcbiAgZGVzY3JpcHRpb25DaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcblxuICBAVmlld0NoaWxkKCd0aXRsZUlucHV0JylcbiAgcHJpdmF0ZSB0aXRsZUlucHV0UmVmPzogRWxlbWVudFJlZjxIVE1MSW5wdXRFbGVtZW50PjtcblxuICBAVmlld0NoaWxkKCdkZXNjcmlwdGlvbklucHV0JylcbiAgcHJpdmF0ZSBkZXNjcmlwdGlvbklucHV0UmVmPzogRWxlbWVudFJlZjxIVE1MSW5wdXRFbGVtZW50PjtcblxuICBwcm90ZWN0ZWQgbW9kZTogJ3ZpZXcnIHwgJ2VkaXRpbmdUaXRsZScgfCAnZWRpdGluZ0Rlc2NyaXB0aW9uJyA9ICd2aWV3JztcbiAgcHJvdGVjdGVkIGRyYWZ0VGl0bGU6IHN0cmluZyA9ICcnO1xuICBwcm90ZWN0ZWQgZHJhZnREZXNjcmlwdGlvbjogc3RyaW5nID0gJyc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBjZHI6IENoYW5nZURldGVjdG9yUmVmLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgaG9zdDogRWxlbWVudFJlZjxIVE1MRWxlbWVudD4sXG4gICkge31cblxuICBASG9zdEJpbmRpbmcoJ2NsYXNzLmVkaXRpbmcnKVxuICBnZXQgaXNFZGl0aW5nKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm1vZGUgIT09ICd2aWV3JztcbiAgfVxuXG4gIHByb3RlY3RlZCBzdGFydEVkaXRpbmdUaXRsZSgpOiB2b2lkIHtcbiAgICB0aGlzLmRyYWZ0VGl0bGUgPSB0aGlzLnRpdGxlO1xuICAgIHRoaXMubW9kZSA9ICdlZGl0aW5nVGl0bGUnO1xuICAgIC8vIERlZmVyIGZvY3VzIHVudGlsIEFuZ3VsYXIgaGFzIHJlbmRlcmVkIHRoZSBpbnB1dCBpbnRvIHRoZSBET00uXG4gICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLmZvY3VzRW5kKHRoaXMudGl0bGVJbnB1dFJlZiksIDApO1xuICB9XG5cbiAgcHJvdGVjdGVkIHN0YXJ0RWRpdGluZ0Rlc2NyaXB0aW9uKCk6IHZvaWQge1xuICAgIHRoaXMuZHJhZnREZXNjcmlwdGlvbiA9IHRoaXMuZGVzY3JpcHRpb247XG4gICAgdGhpcy5tb2RlID0gJ2VkaXRpbmdEZXNjcmlwdGlvbic7XG4gICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLmZvY3VzRW5kKHRoaXMuZGVzY3JpcHRpb25JbnB1dFJlZiksIDApO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNvbW1pdFRpdGxlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLm1vZGUgIT09ICdlZGl0aW5nVGl0bGUnKSByZXR1cm47XG4gICAgLy8gVGl0bGUgY2Fubm90IGJlIGNvbW1pdHRlZCBlbXB0eS4gVGhlIENoZWNrIGJ1dHRvbiBpcyBkaXNhYmxlZCBpbiB0aGF0XG4gICAgLy8gc3RhdGU7IGZvciBFbnRlciBhbmQgb3V0c2lkZS1jbGljayB3ZSByZXZlcnQgdG8gdGhlIGN1cnJlbnQgdGl0bGUgc29cbiAgICAvLyB0aGUgdXNlciBpcyBuZXZlciBzdHVjayBpbiBlZGl0IG1vZGUgd2l0aCBhIHJlamVjdGVkIHZhbHVlLlxuICAgIGlmICghdGhpcy5kcmFmdFRpdGxlKSB7XG4gICAgICB0aGlzLm1vZGUgPSAndmlldyc7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHZhbHVlID0gdGhpcy5kcmFmdFRpdGxlO1xuICAgIHRoaXMuX3RpdGxlID0gdmFsdWU7XG4gICAgdGhpcy5tb2RlID0gJ3ZpZXcnO1xuICAgIHRoaXMudGl0bGVDaGFuZ2UuZW1pdCh2YWx1ZSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgY29tbWl0RGVzY3JpcHRpb24oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMubW9kZSAhPT0gJ2VkaXRpbmdEZXNjcmlwdGlvbicpIHJldHVybjtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuZHJhZnREZXNjcmlwdGlvbjtcbiAgICB0aGlzLl9kZXNjcmlwdGlvbiA9IHZhbHVlO1xuICAgIHRoaXMubW9kZSA9ICd2aWV3JztcbiAgICB0aGlzLmRlc2NyaXB0aW9uQ2hhbmdlLmVtaXQodmFsdWUpO1xuICB9XG5cbiAgLy8gTGlzdGVucyBvbiBgbW91c2Vkb3duYCAobm90IGBjbGlja2ApIHNvIHRoZSBjaGVjayBydW5zIGJlZm9yZSBBbmd1bGFyXG4gIC8vIHJlLXJlbmRlcnMgdGhlIHRyaWdnZXIgZWxlbWVudCBvdXQgb2YgdGhlIERPTSDigJQgb3RoZXJ3aXNlXG4gIC8vIGBob3N0LmNvbnRhaW5zKHRhcmdldClgIHJldHVybnMgZmFsc2UgZm9yIGEgY2xpY2sgdGhhdCBsYW5kZWQgb24gdGhlXG4gIC8vIG5vdy1yZW1vdmVkIGAudGl0bGVgIC8gYC5kZXNjcmlwdGlvbmAgZWxlbWVudC4gU2FtZSBwYXR0ZXJuIGFzXG4gIC8vIGByaXYtZGF0ZWAuXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50Om1vdXNlZG93bicsIFsnJGV2ZW50LnRhcmdldCddKVxuICBwcm90ZWN0ZWQgb25Eb2N1bWVudE1vdXNlRG93bih0YXJnZXQ6IEV2ZW50VGFyZ2V0IHwgbnVsbCk6IHZvaWQge1xuICAgIGlmICh0aGlzLm1vZGUgPT09ICd2aWV3JyB8fCAhKHRhcmdldCBpbnN0YW5jZW9mIEVsZW1lbnQpKSByZXR1cm47XG4gICAgaWYgKHRoaXMuaG9zdC5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKHRhcmdldCkpIHJldHVybjtcbiAgICBpZiAodGhpcy5tb2RlID09PSAnZWRpdGluZ1RpdGxlJykge1xuICAgICAgdGhpcy5jb21taXRUaXRsZSgpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5tb2RlID09PSAnZWRpdGluZ0Rlc2NyaXB0aW9uJykge1xuICAgICAgdGhpcy5jb21taXREZXNjcmlwdGlvbigpO1xuICAgIH1cbiAgfVxuXG4gIC8vIEZvY3VzIHdpdGggY2FyZXQgYXQgZW5kIChyYXRoZXIgdGhhbiBzZWxlY3RpbmcgYWxsKSBzbyB0aGUgdXNlciBjYW5cbiAgLy8gY29udGludWUgdHlwaW5nIHdoZXJlIHRoZSBwcmV2aW91cyB2YWx1ZSBsZWZ0IG9mZi5cbiAgcHJpdmF0ZSBmb2N1c0VuZChyZWY/OiBFbGVtZW50UmVmPEhUTUxJbnB1dEVsZW1lbnQ+KTogdm9pZCB7XG4gICAgY29uc3QgZWwgPSByZWY/Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgaWYgKCFlbCkgcmV0dXJuO1xuICAgIGVsLmZvY3VzKCk7XG4gICAgY29uc3QgbGVuID0gZWwudmFsdWUubGVuZ3RoO1xuICAgIGVsLnNldFNlbGVjdGlvblJhbmdlKGxlbiwgbGVuKTtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxufVxuIiwiPGRpdiBjbGFzcz1cImxlYWRpbmdcIj5cbiAgPG5nLWNvbnRhaW5lciBbbmdTd2l0Y2hdPVwibW9kZVwiPlxuICAgIDwhLS0gVmlldyBtb2RlIC0tPlxuICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoRGVmYXVsdD5cbiAgICAgIDxidXR0b25cbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIGNsYXNzPVwidGl0bGVcIlxuICAgICAgICBbY2xhc3MuaGFzLWRlc2NyaXB0aW9uXT1cImRlc2NyaXB0aW9uXCJcbiAgICAgICAgcml2VHJ1bmNhdGVcbiAgICAgICAgYXJpYS1sYWJlbD1cIlJlbmFtZVwiXG4gICAgICAgIChjbGljayk9XCJzdGFydEVkaXRpbmdUaXRsZSgpXCJcbiAgICAgID5cbiAgICAgICAge3sgdGl0bGUgfHwgJ1VudGl0bGVkJyB9fVxuICAgICAgPC9idXR0b24+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJkaXZpZGVyXCI+PC9kaXY+XG5cbiAgICAgIDxidXR0b25cbiAgICAgICAgKm5nSWY9XCJkZXNjcmlwdGlvbjsgZWxzZSBhZGREZXNjcmlwdGlvblwiXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cImRlc2NyaXB0aW9uXCJcbiAgICAgICAgcml2VHJ1bmNhdGVcbiAgICAgICAgYXJpYS1sYWJlbD1cIkVkaXQgZGVzY3JpcHRpb25cIlxuICAgICAgICAoY2xpY2spPVwic3RhcnRFZGl0aW5nRGVzY3JpcHRpb24oKVwiXG4gICAgICA+XG4gICAgICAgIHt7IGRlc2NyaXB0aW9uIH19XG4gICAgICA8L2J1dHRvbj5cblxuICAgICAgPG5nLXRlbXBsYXRlICNhZGREZXNjcmlwdGlvbj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImFkZC1kZXNjcmlwdGlvbi13cmFwXCI+XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgcml2QnV0dG9uXG4gICAgICAgICAgICBbdmFyaWFudF09XCInZ2hvc3QnXCJcbiAgICAgICAgICAgIFtzaXplXT1cIid4c21hbGwnXCJcbiAgICAgICAgICAgIFtpY29uXT1cIidQbHVzJ1wiXG4gICAgICAgICAgICBbaWNvblBvc2l0aW9uXT1cIidmaXJzdCdcIlxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAoY2xpY2spPVwic3RhcnRFZGl0aW5nRGVzY3JpcHRpb24oKVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgQWRkIGRlc2NyaXB0aW9uXG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgIDwhLS0gRWRpdGluZyB0aXRsZSAtLT5cbiAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaENhc2U9XCInZWRpdGluZ1RpdGxlJ1wiPlxuICAgICAgPGlucHV0XG4gICAgICAgICN0aXRsZUlucHV0XG4gICAgICAgIGNsYXNzPVwidGl0bGUtaW5wdXRcIlxuICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgIGFyaWEtbGFiZWw9XCJUaXRsZVwiXG4gICAgICAgIFt2YWx1ZV09XCJkcmFmdFRpdGxlXCJcbiAgICAgICAgW2F0dHIubWF4bGVuZ3RoXT1cInRpdGxlTWF4TGVuZ3RoXCJcbiAgICAgICAgKGlucHV0KT1cImRyYWZ0VGl0bGUgPSB0aXRsZUlucHV0LnZhbHVlXCJcbiAgICAgICAgKGtleWRvd24uZW50ZXIpPVwiY29tbWl0VGl0bGUoKVwiXG4gICAgICAvPlxuICAgICAgPGJ1dHRvblxuICAgICAgICByaXZCdXR0b25cbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIGNsYXNzPVwiY29tbWl0XCJcbiAgICAgICAgW3ZhcmlhbnRdPVwiJ3ByaW1hcnknXCJcbiAgICAgICAgW2ljb25dPVwiJ0NoZWNrJ1wiXG4gICAgICAgIFtkaXNhYmxlZF09XCIhZHJhZnRUaXRsZVwiXG4gICAgICAgIChjbGljayk9XCJjb21taXRUaXRsZSgpXCJcbiAgICAgICAgYXJpYS1sYWJlbD1cIlNhdmUgdGl0bGVcIlxuICAgICAgPjwvYnV0dG9uPlxuICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgPCEtLSBFZGl0aW5nIGRlc2NyaXB0aW9uIC0tPlxuICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidlZGl0aW5nRGVzY3JpcHRpb24nXCI+XG4gICAgICA8aW5wdXRcbiAgICAgICAgI2Rlc2NyaXB0aW9uSW5wdXRcbiAgICAgICAgY2xhc3M9XCJkZXNjcmlwdGlvbi1pbnB1dFwiXG4gICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgYXJpYS1sYWJlbD1cIkRlc2NyaXB0aW9uXCJcbiAgICAgICAgW3ZhbHVlXT1cImRyYWZ0RGVzY3JpcHRpb25cIlxuICAgICAgICBbYXR0ci5tYXhsZW5ndGhdPVwiZGVzY3JpcHRpb25NYXhMZW5ndGhcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIkFkZCBhIGRlc2NyaXB0aW9uXCJcbiAgICAgICAgKGlucHV0KT1cImRyYWZ0RGVzY3JpcHRpb24gPSBkZXNjcmlwdGlvbklucHV0LnZhbHVlXCJcbiAgICAgICAgKGtleWRvd24uZW50ZXIpPVwiY29tbWl0RGVzY3JpcHRpb24oKVwiXG4gICAgICAvPlxuICAgICAgPGJ1dHRvblxuICAgICAgICByaXZCdXR0b25cbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIGNsYXNzPVwiY29tbWl0XCJcbiAgICAgICAgW3ZhcmlhbnRdPVwiJ3ByaW1hcnknXCJcbiAgICAgICAgW2ljb25dPVwiJ0NoZWNrJ1wiXG4gICAgICAgIChjbGljayk9XCJjb21taXREZXNjcmlwdGlvbigpXCJcbiAgICAgICAgYXJpYS1sYWJlbD1cIlNhdmUgZGVzY3JpcHRpb25cIlxuICAgICAgPjwvYnV0dG9uPlxuICAgIDwvbmctY29udGFpbmVyPlxuICA8L25nLWNvbnRhaW5lcj5cbjwvZGl2PlxuXG48ZGl2IGNsYXNzPVwiYWN0aW9uc1wiICpuZ0lmPVwiIWlzRWRpdGluZ1wiPlxuICA8bmctY29udGVudCBzZWxlY3Q9XCJbYWN0aW9uc11cIj48L25nLWNvbnRlbnQ+XG48L2Rpdj5cbiJdfQ==
243
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWRpdGFibGUtaGVhZGluZy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9yaXYvc3JjL2xpYi9uYXZpZ2F0aW9uL2VkaXRhYmxlLWhlYWRpbmcvZWRpdGFibGUtaGVhZGluZy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9yaXYvc3JjL2xpYi9uYXZpZ2F0aW9uL2VkaXRhYmxlLWhlYWRpbmcvZWRpdGFibGUtaGVhZGluZy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBRXZCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLFdBQVcsRUFDWCxZQUFZLEVBQ1osS0FBSyxFQUNMLE1BQU0sRUFDTixTQUFTLEdBQ1YsTUFBTSxlQUFlLENBQUM7Ozs7OztBQUV2Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F3REc7QUFPSCxNQUFNLE9BQU8sd0JBQXdCO0lBR25DLElBQ0ksS0FBSyxDQUFDLENBQVM7UUFDakIsSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLE1BQU07WUFBRSxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBQ0QsSUFBSSxLQUFLO1FBQ1AsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3JCLENBQUM7SUFHRCxJQUNJLFdBQVcsQ0FBQyxDQUFTO1FBQ3ZCLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxZQUFZO1lBQUUsSUFBSSxDQUFDLFlBQVksR0FBRyxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUNELElBQUksV0FBVztRQUNiLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQztJQUMzQixDQUFDO0lBZUQsSUFDSSxRQUFRLENBQUMsQ0FBVTtRQUNyQixJQUFJLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQztRQUNuQixJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLE1BQU07WUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDN0MsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBQ0QsSUFBSSxRQUFRO1FBQ1YsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQ3hCLENBQUM7SUFvQkQsWUFDbUIsR0FBc0IsRUFDdEIsSUFBNkI7UUFEN0IsUUFBRyxHQUFILEdBQUcsQ0FBbUI7UUFDdEIsU0FBSSxHQUFKLElBQUksQ0FBeUI7UUE5RGhELDJEQUEyRDtRQUNqRCxXQUFNLEdBQVcsRUFBRSxDQUFDO1FBU3BCLGlCQUFZLEdBQVcsRUFBRSxDQUFDO1FBVXBDLG1CQUFjLEdBQVcsR0FBRyxDQUFDO1FBRzdCLHlCQUFvQixHQUFXLEdBQUcsQ0FBQztRQUVuQzs7Ozs7V0FLRztRQUNPLGNBQVMsR0FBWSxLQUFLLENBQUM7UUFZckMsZ0JBQVcsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO1FBR3pDLHNCQUFpQixHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFVckMsU0FBSSxHQUFtRCxNQUFNLENBQUM7UUFDOUQsZUFBVSxHQUFXLEVBQUUsQ0FBQztRQUN4QixxQkFBZ0IsR0FBVyxFQUFFLENBQUM7SUFLckMsQ0FBQztJQUVKLElBQ0ksU0FBUztRQUNYLE9BQU8sSUFBSSxDQUFDLElBQUksS0FBSyxNQUFNLENBQUM7SUFDOUIsQ0FBQztJQUVEOzs7Ozs7Ozs7T0FTRztJQUNILGlCQUFpQjtRQUNmLElBQUksSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLE1BQU07WUFBRSxPQUFPO1FBQ2xELElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUM3QixJQUFJLENBQUMsSUFBSSxHQUFHLGNBQWMsQ0FBQztRQUMzQix3RUFBd0U7UUFDeEUsb0VBQW9FO1FBQ3BFLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDeEIsaUVBQWlFO1FBQ2pFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILHVCQUF1QjtRQUNyQixJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxNQUFNO1lBQUUsT0FBTztRQUNsRCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUN6QyxJQUFJLENBQUMsSUFBSSxHQUFHLG9CQUFvQixDQUFDO1FBQ2pDLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDeEIsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDL0QsQ0FBQztJQUVTLFdBQVc7UUFDbkIsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLGNBQWM7WUFBRSxPQUFPO1FBQ3pDLHdFQUF3RTtRQUN4RSx1RUFBdUU7UUFDdkUsOERBQThEO1FBQzlELElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ3BCLElBQUksQ0FBQyxJQUFJLEdBQUcsTUFBTSxDQUFDO1lBQ25CLE9BQU87U0FDUjtRQUNELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7UUFDOUIsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7UUFDcEIsSUFBSSxDQUFDLElBQUksR0FBRyxNQUFNLENBQUM7UUFDbkIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVTLGlCQUFpQjtRQUN6QixJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssb0JBQW9CO1lBQUUsT0FBTztRQUMvQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUM7UUFDcEMsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDMUIsSUFBSSxDQUFDLElBQUksR0FBRyxNQUFNLENBQUM7UUFDbkIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNyQyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNPLE1BQU07UUFDZCxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssTUFBTTtZQUFFLE9BQU87UUFDakMsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1FBQzlCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO1FBQzFDLElBQUksQ0FBQyxJQUFJLEdBQUcsTUFBTSxDQUFDO0lBQ3JCLENBQUM7SUFFRCx3RUFBd0U7SUFDeEUsNERBQTREO0lBQzVELHVFQUF1RTtJQUN2RSxpRUFBaUU7SUFDakUsY0FBYztJQUVKLG1CQUFtQixDQUFDLE1BQTBCO1FBQ3RELElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxNQUFNLElBQUksQ0FBQyxDQUFDLE1BQU0sWUFBWSxPQUFPLENBQUM7WUFBRSxPQUFPO1FBQ2pFLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQztZQUFFLE9BQU87UUFDckQsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLGNBQWMsRUFBRTtZQUNoQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7U0FDcEI7YUFBTSxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssb0JBQW9CLEVBQUU7WUFDN0MsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7U0FDMUI7SUFDSCxDQUFDO0lBRUQsNkVBQTZFO0lBQzdFLHlFQUF5RTtJQUN6RSw0RUFBNEU7SUFDNUUsd0JBQXdCO0lBQ2hCLFFBQVEsQ0FBQyxHQUE2QjtRQUM1QyxNQUFNLEtBQUssR0FBRyxHQUFHLEVBQUUsYUFBYSxDQUFDLGFBQWEsQ0FBbUIsT0FBTyxDQUFDLENBQUM7UUFDMUUsSUFBSSxDQUFDLEtBQUs7WUFBRSxPQUFPO1FBQ25CLE1BQU0sR0FBRyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBQy9CLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDbEMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUMxQixDQUFDOztzSEF0S1Usd0JBQXdCOzBHQUF4Qix3QkFBd0IsMmdCQW1ERixVQUFVLGtIQUdKLFVBQVUsNkJDbEluRCwweUZBbUdBOzRGRHZCYSx3QkFBd0I7a0JBTnBDLFNBQVM7K0JBQ0Usc0JBQXNCLG1CQUdmLHVCQUF1QixDQUFDLE1BQU07aUlBTTNDLEtBQUs7c0JBRFIsS0FBSztnQkFVRixXQUFXO3NCQURkLEtBQUs7Z0JBU04sY0FBYztzQkFEYixLQUFLO2dCQUlOLG9CQUFvQjtzQkFEbkIsS0FBSztnQkFXRixRQUFRO3NCQURYLEtBQUs7Z0JBV04sV0FBVztzQkFEVixNQUFNO2dCQUlQLGlCQUFpQjtzQkFEaEIsTUFBTTtnQkFNQyxhQUFhO3NCQURwQixTQUFTO3VCQUFDLFlBQVksRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7Z0JBSXJDLG1CQUFtQjtzQkFEMUIsU0FBUzt1QkFBQyxrQkFBa0IsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7Z0JBYS9DLFNBQVM7c0JBRFosV0FBVzt1QkFBQyxlQUFlO2dCQWdGbEIsbUJBQW1CO3NCQUQ1QixZQUFZO3VCQUFDLG9CQUFvQixFQUFFLENBQUMsZUFBZSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSG9zdEJpbmRpbmcsXG4gIEhvc3RMaXN0ZW5lcixcbiAgSW5wdXQsXG4gIE91dHB1dCxcbiAgVmlld0NoaWxkLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuLyoqXG4gKiBBIGJvcmRlcmxlc3MgaGVhZGluZyB3aXRoIGEgY2xpY2stdG8tZWRpdCB0aXRsZSBhbmQgYW4gb3B0aW9uYWxcbiAqIGNsaWNrLXRvLWVkaXQgZGVzY3JpcHRpb24sIHBsdXMgYSBwcm9qZWN0ZWQgc2xvdCBmb3IgYWN0aW9ucy5cbiAqXG4gKiBMYXlvdXQ6IGBbdGl0bGVdIHwgW2Rlc2NyaXB0aW9uXSAgW2FjdGlvbnNdYFxuICpcbiAqIC0gQ2xpY2sgdGhlIHRpdGxlIHRvIHJlbmFtZTsgY2xpY2sgdGhlIGRlc2NyaXB0aW9uIChvciB0aGUgZ2hvc3RcbiAqICAgXCIrIEFkZCBkZXNjcmlwdGlvblwiIGJ1dHRvbiB3aGVuIGVtcHR5KSB0byBlZGl0IGl0LlxuICogLSBPbmx5IG9uZSBvZiB0aXRsZSBvciBkZXNjcmlwdGlvbiBjYW4gYmUgZWRpdGVkIGF0IGEgdGltZS5cbiAqIC0gV2hpbGUgZWl0aGVyIGlzIGJlaW5nIGVkaXRlZCwgdGhlIGBbYWN0aW9uc11gIHNsb3QgaXMgaGlkZGVuIHNvXG4gKiAgIHByb2plY3RlZCBjb250cm9scyBkb24ndCBjb21wZXRlIHdpdGggdGhlIGVkaXQgYWZmb3JkYW5jZS5cbiAqXG4gKiBDb21taXQgc2VtYW50aWNzOiBgdGl0bGVDaGFuZ2VgIC8gYGRlc2NyaXB0aW9uQ2hhbmdlYCBmaXJlIHdoZW4gdGhlIHVzZXJcbiAqIGNvbW1pdHMg4oCUIEVudGVyLCBvdXRzaWRlIGNsaWNrLCBvciB0aGUgQ2hlY2sgYnV0dG9uIOKAlCBub3Qgb24gZXZlcnlcbiAqIGtleXN0cm9rZSwgYW5kIGFsd2F5cyBvbiBjb21taXQgKGV2ZW4gd2hlbiB0aGUgdmFsdWUgaXMgdW5jaGFuZ2VkKS4gVGhlXG4gKiBcImNvbW1pdFwiIGZyYW1pbmcgb3ZlciBcImNoYW5nZVwiIGlzIGRlbGliZXJhdGU6IGNvbnN1bWVycyB0aGF0IHBlcnNpc3Qgb25cbiAqIGNvbW1pdCAoYW5hbHl0aWNzLCBQQVRDSCkgdHJlYXQgdGhlIGdlc3R1cmUgaXRzZWxmIGFzIHRoZSBldmVudDsgdGhvc2VcbiAqIHRoYXQgb25seSBjYXJlIGFib3V0IGRpZmZzIGNhbiBjb21wYXJlIGBuZXh0ID09PSBjdXJyZW50YCBpbiB0aGUgaGFuZGxlci5cbiAqXG4gKiBFc2NhcGUgY2FuY2VsczogcmV2ZXJ0cyB0aGUgZHJhZnQgYmFjayB0byB0aGUgY3VycmVudCB2YWx1ZSBhbmQgZHJvcHMgb3V0XG4gKiBvZiBlZGl0IG1vZGUgV0lUSE9VVCBlbWl0dGluZyBhIGNoYW5nZS4gT3V0c2lkZS1jbGljayBzdGlsbCBjb21taXRzICh0b1xuICogbWF0Y2ggYHJpdi1kYXRlYCAvIGByaXYtc2VsZWN0YCk7IEVzY2FwZSBpcyB0aGUgZGVsaWJlcmF0ZSBhYmFuZG9uIHBhdGguXG4gKlxuICogVmFsdWUgaGFuZGxpbmcgZm9sbG93cyB0aGUgc2FtZSBjb252ZW50aW9uIGFzIGByaXYtdGV4dC1maWVsZGA6IGBbdGl0bGVdYFxuICogYW5kIGBbZGVzY3JpcHRpb25dYCBhcmUgdHJlYXRlZCBhcyBzdWdnZXN0aW9ucywgbm90IGF1dGhvcml0YXRpdmUgc3RhdGUuXG4gKiBPbiBjb21taXQsIHRoZSBjb21wb25lbnQga2VlcHMgZGlzcGxheWluZyB0aGUgdXNlcidzIGNvbW1pdHRlZCB2YWx1ZSxcbiAqIGFuZCBvbmx5IG92ZXJ3cml0ZXMgaXRzIGludGVybmFsIHN0YXRlIHdoZW4gdGhlIHBhcmVudCBleHBsaWNpdGx5IHNlbmRzXG4gKiBhIGRpZmZlcmVudCB2YWx1ZS4gVGhhdCBsZXRzIHRoZSBjb21wb25lbnQgZGVtbyBvdXQgb2YgdGhlIGJveCAoZS5nLiBpblxuICogU3Rvcnlib29rKSB3aXRob3V0IHJlcXVpcmluZyBhIHJvdW5kIHRyaXAgdGhyb3VnaCB0aGUgcGFyZW50LlxuICpcbiAqIFByb2dyYW1tYXRpYyBlbnRyeSBpbnRvIGVkaXQgbW9kZSBpcyBhdmFpbGFibGUgdmlhIGBzdGFydEVkaXRpbmdUaXRsZSgpYFxuICogYW5kIGBzdGFydEVkaXRpbmdEZXNjcmlwdGlvbigpYCDigJQgb2J0YWluIGEgcmVmZXJlbmNlIHdpdGhcbiAqIGBAVmlld0NoaWxkKEVkaXRhYmxlSGVhZGluZ0NvbXBvbmVudClgLiBVc2UgdGhlc2UgZm9yIHNlY29uZGFyeSBlbnRyeVxuICogcG9pbnRzIGxpa2UgYSBrZWJhYi1tZW51IFwiUmVuYW1lXCIgaXRlbSwgb3IgdG8gYXV0by1vcGVuIHJlbmFtZSBhZnRlclxuICogY3JlYXRpbmcgYSBuZXcgZW50aXR5LlxuICpcbiAqIFRoZSBjb21wb25lbnQgb3ducyBubyBib3JkZXIsIGJhY2tncm91bmQsIG9yIGNhcmQgY2hyb21lIOKAlCBjb25zdW1lcnMgd2hvXG4gKiB3YW50IGEgYm9yZGVyZWQgY29udGFpbmVyIHNob3VsZCB3cmFwIGl0LlxuICpcbiAqIGBgYGh0bWxcbiAqIDxyaXYtZWRpdGFibGUtaGVhZGluZ1xuICogICBbdGl0bGVdPVwicmVwb3J0LnRpdGxlXCJcbiAqICAgW2Rlc2NyaXB0aW9uXT1cInJlcG9ydC5kZXNjcmlwdGlvblwiXG4gKiAgICh0aXRsZUNoYW5nZSk9XCJvblRpdGxlQ29tbWl0KCRldmVudClcIlxuICogICAoZGVzY3JpcHRpb25DaGFuZ2UpPVwib25EZXNjcmlwdGlvbkNvbW1pdCgkZXZlbnQpXCJcbiAqID5cbiAqICAgPHJpdi1tZW51IGFjdGlvbnM+XG4gKiAgICAgPG5nLXRlbXBsYXRlICN0cmlnZ2VyPlxuICogICAgICAgPGJ1dHRvbiByaXZCdXR0b24gW2ljb25dPVwiJ01vcmVWZXJ0aWNhbCdcIiBbdmFyaWFudF09XCInZ2hvc3QnXCI+PC9idXR0b24+XG4gKiAgICAgPC9uZy10ZW1wbGF0ZT5cbiAqICAgICA8YnV0dG9uIHJpdi1tZW51LWl0ZW0+UmVuYW1lPC9idXR0b24+XG4gKiAgICAgPGJ1dHRvbiByaXYtbWVudS1pdGVtPkR1cGxpY2F0ZTwvYnV0dG9uPlxuICogICA8L3Jpdi1tZW51PlxuICogICA8YnV0dG9uIHJpdkJ1dHRvbiBhY3Rpb25zIFt2YXJpYW50XT1cIidwcmltYXJ5J1wiPlNhdmU8L2J1dHRvbj5cbiAqIDwvcml2LWVkaXRhYmxlLWhlYWRpbmc+XG4gKiBgYGBcbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAncml2LWVkaXRhYmxlLWhlYWRpbmcnLFxuICB0ZW1wbGF0ZVVybDogJy4vZWRpdGFibGUtaGVhZGluZy5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2VkaXRhYmxlLWhlYWRpbmcuY29tcG9uZW50LmNzcyddLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgRWRpdGFibGVIZWFkaW5nQ29tcG9uZW50IHtcbiAgLy8gU2VlIHRoZSBcIlZhbHVlIGhhbmRsaW5nXCIgc2VjdGlvbiBvZiB0aGUgY2xhc3MtbGV2ZWwgZG9jLlxuICBwcm90ZWN0ZWQgX3RpdGxlOiBzdHJpbmcgPSAnJztcbiAgQElucHV0KClcbiAgc2V0IHRpdGxlKHY6IHN0cmluZykge1xuICAgIGlmICh2ICE9PSB0aGlzLl90aXRsZSkgdGhpcy5fdGl0bGUgPSB2O1xuICB9XG4gIGdldCB0aXRsZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl90aXRsZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBfZGVzY3JpcHRpb246IHN0cmluZyA9ICcnO1xuICBASW5wdXQoKVxuICBzZXQgZGVzY3JpcHRpb24odjogc3RyaW5nKSB7XG4gICAgaWYgKHYgIT09IHRoaXMuX2Rlc2NyaXB0aW9uKSB0aGlzLl9kZXNjcmlwdGlvbiA9IHY7XG4gIH1cbiAgZ2V0IGRlc2NyaXB0aW9uKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX2Rlc2NyaXB0aW9uO1xuICB9XG5cbiAgQElucHV0KClcbiAgdGl0bGVNYXhMZW5ndGg6IG51bWJlciA9IDEwMDtcblxuICBASW5wdXQoKVxuICBkZXNjcmlwdGlvbk1heExlbmd0aDogbnVtYmVyID0gMzAwO1xuXG4gIC8qKlxuICAgKiBXaGVuIHRydWUsIHRoZSB0aXRsZSBhbmQgZGVzY3JpcHRpb24gYXJlIG5vdCBjbGlja2FibGUgYW5kIGNhbm5vdCBiZVxuICAgKiBlZGl0ZWQuIEFueSBpbi1wcm9ncmVzcyBlZGl0IGlzIGRyb3BwZWQgd2l0aG91dCBlbWl0dGluZy4gSW1wZXJhdGl2ZVxuICAgKiBgc3RhcnRFZGl0aW5nKmAgY2FsbHMgbm8tb3AuIFVzZWZ1bCBmb3IgY29uc3VtZXJzIHRoYXQgbmVlZCB0byBnYXRlXG4gICAqIGVkaXRpbmcgb24gYSBwZXJtaXNzaW9uIG9yIGEgYnJvYWRlciBcImFjdGlvbnMgZGlzYWJsZWRcIiBzdGF0ZS5cbiAgICovXG4gIHByb3RlY3RlZCBfZGlzYWJsZWQ6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KClcbiAgc2V0IGRpc2FibGVkKHY6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9kaXNhYmxlZCA9IHY7XG4gICAgaWYgKHYgJiYgdGhpcy5tb2RlICE9PSAndmlldycpIHRoaXMuY2FuY2VsKCk7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cbiAgZ2V0IGRpc2FibGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9kaXNhYmxlZDtcbiAgfVxuXG4gIEBPdXRwdXQoKVxuICB0aXRsZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gIEBPdXRwdXQoKVxuICBkZXNjcmlwdGlvbkNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gIC8vIGByZWFkOiBFbGVtZW50UmVmYCBnZXRzIHRoZSBob3N0IGVsZW1lbnQgb2YgdGhlIGA8cml2LXRleHQtZmllbGQ+YCwgZnJvbVxuICAvLyB3aGljaCB3ZSBjYW4gcmVhY2ggdGhlIGFjdHVhbCBgPGlucHV0PmAgZm9yIGNhcmV0LWF0LWVuZCBwb3NpdGlvbmluZy5cbiAgQFZpZXdDaGlsZCgndGl0bGVJbnB1dCcsIHsgcmVhZDogRWxlbWVudFJlZiB9KVxuICBwcml2YXRlIHRpdGxlSW5wdXRSZWY/OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PjtcblxuICBAVmlld0NoaWxkKCdkZXNjcmlwdGlvbklucHV0JywgeyByZWFkOiBFbGVtZW50UmVmIH0pXG4gIHByaXZhdGUgZGVzY3JpcHRpb25JbnB1dFJlZj86IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+O1xuXG4gIHByb3RlY3RlZCBtb2RlOiAndmlldycgfCAnZWRpdGluZ1RpdGxlJyB8ICdlZGl0aW5nRGVzY3JpcHRpb24nID0gJ3ZpZXcnO1xuICBwcm90ZWN0ZWQgZHJhZnRUaXRsZTogc3RyaW5nID0gJyc7XG4gIHByb3RlY3RlZCBkcmFmdERlc2NyaXB0aW9uOiBzdHJpbmcgPSAnJztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGNkcjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgcHJpdmF0ZSByZWFkb25seSBob3N0OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PixcbiAgKSB7fVxuXG4gIEBIb3N0QmluZGluZygnY2xhc3MuZWRpdGluZycpXG4gIGdldCBpc0VkaXRpbmcoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubW9kZSAhPT0gJ3ZpZXcnO1xuICB9XG5cbiAgLyoqXG4gICAqIEVudGVyIHRpdGxlLWVkaXQgbW9kZSBwcm9ncmFtbWF0aWNhbGx5LiBTYW1lIGJlaGF2aW9yIGFzIGNsaWNraW5nIHRoZVxuICAgKiB0aXRsZSDigJQgcG9wdWxhdGVzIHRoZSBlZGl0IGJ1ZmZlciBmcm9tIHRoZSBjdXJyZW50IHZhbHVlLCBmb2N1c2VzIHRoZVxuICAgKiBpbnB1dCB3aXRoIHRoZSBjYXJldCBhdCB0aGUgZW5kLCBhbmQgaGlkZXMgdGhlIGFjdGlvbnMgc2xvdC4gTm8tb3AgaWZcbiAgICogYWxyZWFkeSBpbiBhbiBlZGl0aW5nIG1vZGUgb3Igd2hlbiB0aGUgY29tcG9uZW50IGlzIGRpc2FibGVkLlxuICAgKlxuICAgKiBJbnRlbmRlZCBmb3IgY29uc3VtZXJzIHRoYXQgb2ZmZXIgYSBzZWNvbmRhcnkgZW50cnkgcG9pbnQgdG8gcmVuYW1pbmdcbiAgICogKGUuZy4gYSBrZWJhYiBtZW51IGl0ZW0pLCBvciB0aGF0IHdhbnQgdG8gYXV0by1vcGVuIHJlbmFtZSBhZnRlclxuICAgKiBjcmVhdGluZyBhIG5ldyBlbnRpdHkuIEJpbmQgdmlhIGBAVmlld0NoaWxkKEVkaXRhYmxlSGVhZGluZ0NvbXBvbmVudClgLlxuICAgKi9cbiAgc3RhcnRFZGl0aW5nVGl0bGUoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQgfHwgdGhpcy5tb2RlICE9PSAndmlldycpIHJldHVybjtcbiAgICB0aGlzLmRyYWZ0VGl0bGUgPSB0aGlzLnRpdGxlO1xuICAgIHRoaXMubW9kZSA9ICdlZGl0aW5nVGl0bGUnO1xuICAgIC8vIGBtYXJrRm9yQ2hlY2tgIHNvIGNvbnN1bWVycyBjYW4gY2FsbCB0aGlzIGZyb20gb3V0c2lkZSBBbmd1bGFyJ3Mgem9uZVxuICAgIC8vIChlLmcuIGFuIGFzeW5jIGNhbGxiYWNrKSB3aXRob3V0IGhhdmluZyB0byB0cmlnZ2VyIENEIHRoZW1zZWx2ZXMuXG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgLy8gRGVmZXIgZm9jdXMgdW50aWwgQW5ndWxhciBoYXMgcmVuZGVyZWQgdGhlIGlucHV0IGludG8gdGhlIERPTS5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMuZm9jdXNFbmQodGhpcy50aXRsZUlucHV0UmVmKSwgMCk7XG4gIH1cblxuICAvKipcbiAgICogRW50ZXIgZGVzY3JpcHRpb24tZWRpdCBtb2RlIHByb2dyYW1tYXRpY2FsbHkuIFNhbWUgYmVoYXZpb3IgYXMgY2xpY2tpbmdcbiAgICogdGhlIGRlc2NyaXB0aW9uIChvciB0aGUgXCIrIEFkZCBkZXNjcmlwdGlvblwiIGJ1dHRvbikuIE5vLW9wIGlmIGFscmVhZHlcbiAgICogaW4gYW4gZWRpdGluZyBtb2RlIG9yIHdoZW4gdGhlIGNvbXBvbmVudCBpcyBkaXNhYmxlZC5cbiAgICovXG4gIHN0YXJ0RWRpdGluZ0Rlc2NyaXB0aW9uKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmRpc2FibGVkIHx8IHRoaXMubW9kZSAhPT0gJ3ZpZXcnKSByZXR1cm47XG4gICAgdGhpcy5kcmFmdERlc2NyaXB0aW9uID0gdGhpcy5kZXNjcmlwdGlvbjtcbiAgICB0aGlzLm1vZGUgPSAnZWRpdGluZ0Rlc2NyaXB0aW9uJztcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHRoaXMuZm9jdXNFbmQodGhpcy5kZXNjcmlwdGlvbklucHV0UmVmKSwgMCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgY29tbWl0VGl0bGUoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMubW9kZSAhPT0gJ2VkaXRpbmdUaXRsZScpIHJldHVybjtcbiAgICAvLyBUaXRsZSBjYW5ub3QgYmUgY29tbWl0dGVkIGVtcHR5LiBUaGUgQ2hlY2sgYnV0dG9uIGlzIGRpc2FibGVkIGluIHRoYXRcbiAgICAvLyBzdGF0ZTsgZm9yIEVudGVyIGFuZCBvdXRzaWRlLWNsaWNrIHdlIHJldmVydCB0byB0aGUgY3VycmVudCB0aXRsZSBzb1xuICAgIC8vIHRoZSB1c2VyIGlzIG5ldmVyIHN0dWNrIGluIGVkaXQgbW9kZSB3aXRoIGEgcmVqZWN0ZWQgdmFsdWUuXG4gICAgaWYgKCF0aGlzLmRyYWZ0VGl0bGUpIHtcbiAgICAgIHRoaXMubW9kZSA9ICd2aWV3JztcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgdmFsdWUgPSB0aGlzLmRyYWZ0VGl0bGU7XG4gICAgdGhpcy5fdGl0bGUgPSB2YWx1ZTtcbiAgICB0aGlzLm1vZGUgPSAndmlldyc7XG4gICAgdGhpcy50aXRsZUNoYW5nZS5lbWl0KHZhbHVlKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBjb21taXREZXNjcmlwdGlvbigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5tb2RlICE9PSAnZWRpdGluZ0Rlc2NyaXB0aW9uJykgcmV0dXJuO1xuICAgIGNvbnN0IHZhbHVlID0gdGhpcy5kcmFmdERlc2NyaXB0aW9uO1xuICAgIHRoaXMuX2Rlc2NyaXB0aW9uID0gdmFsdWU7XG4gICAgdGhpcy5tb2RlID0gJ3ZpZXcnO1xuICAgIHRoaXMuZGVzY3JpcHRpb25DaGFuZ2UuZW1pdCh2YWx1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQWJhbmRvbiB0aGUgY3VycmVudCBlZGl0IGFuZCByZXR1cm4gdG8gdmlldyBtb2RlLiBObyBjaGFuZ2UgaXMgZW1pdHRlZC5cbiAgICogV2lyZWQgdG8gdGhlIEVzY2FwZSBrZXkgb24gYm90aCBlZGl0IGlucHV0czsgYWxzbyBjYWxsZWQgaW50ZXJuYWxseVxuICAgKiB3aGVuIGBkaXNhYmxlZGAgZmxpcHMgdG8gdHJ1ZSBtaWQtZWRpdC5cbiAgICovXG4gIHByb3RlY3RlZCBjYW5jZWwoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMubW9kZSA9PT0gJ3ZpZXcnKSByZXR1cm47XG4gICAgdGhpcy5kcmFmdFRpdGxlID0gdGhpcy5fdGl0bGU7XG4gICAgdGhpcy5kcmFmdERlc2NyaXB0aW9uID0gdGhpcy5fZGVzY3JpcHRpb247XG4gICAgdGhpcy5tb2RlID0gJ3ZpZXcnO1xuICB9XG5cbiAgLy8gTGlzdGVucyBvbiBgbW91c2Vkb3duYCAobm90IGBjbGlja2ApIHNvIHRoZSBjaGVjayBydW5zIGJlZm9yZSBBbmd1bGFyXG4gIC8vIHJlLXJlbmRlcnMgdGhlIHRyaWdnZXIgZWxlbWVudCBvdXQgb2YgdGhlIERPTSDigJQgb3RoZXJ3aXNlXG4gIC8vIGBob3N0LmNvbnRhaW5zKHRhcmdldClgIHJldHVybnMgZmFsc2UgZm9yIGEgY2xpY2sgdGhhdCBsYW5kZWQgb24gdGhlXG4gIC8vIG5vdy1yZW1vdmVkIGAudGl0bGVgIC8gYC5kZXNjcmlwdGlvbmAgZWxlbWVudC4gU2FtZSBwYXR0ZXJuIGFzXG4gIC8vIGByaXYtZGF0ZWAuXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50Om1vdXNlZG93bicsIFsnJGV2ZW50LnRhcmdldCddKVxuICBwcm90ZWN0ZWQgb25Eb2N1bWVudE1vdXNlRG93bih0YXJnZXQ6IEV2ZW50VGFyZ2V0IHwgbnVsbCk6IHZvaWQge1xuICAgIGlmICh0aGlzLm1vZGUgPT09ICd2aWV3JyB8fCAhKHRhcmdldCBpbnN0YW5jZW9mIEVsZW1lbnQpKSByZXR1cm47XG4gICAgaWYgKHRoaXMuaG9zdC5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKHRhcmdldCkpIHJldHVybjtcbiAgICBpZiAodGhpcy5tb2RlID09PSAnZWRpdGluZ1RpdGxlJykge1xuICAgICAgdGhpcy5jb21taXRUaXRsZSgpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5tb2RlID09PSAnZWRpdGluZ0Rlc2NyaXB0aW9uJykge1xuICAgICAgdGhpcy5jb21taXREZXNjcmlwdGlvbigpO1xuICAgIH1cbiAgfVxuXG4gIC8vIFBvc2l0aW9uIGNhcmV0IGF0IGVuZCAocmF0aGVyIHRoYW4gc2VsZWN0aW5nIGFsbCkgc28gdGhlIHVzZXIgY2FuIGNvbnRpbnVlXG4gIC8vIHR5cGluZyB3aGVyZSB0aGUgcHJldmlvdXMgdmFsdWUgbGVmdCBvZmYuIGByaXYtdGV4dC1maWVsZGAgaGFuZGxlcyB0aGVcbiAgLy8gZm9jdXMgaXRzZWxmIHZpYSBgW2F1dG9Gb2N1c11gOyB3ZSBqdXN0IGZpeCB1cCB0aGUgc2VsZWN0aW9uIHJhbmdlIG9uIHRoZVxuICAvLyBkZXNjZW5kYW50IGA8aW5wdXQ+YC5cbiAgcHJpdmF0ZSBmb2N1c0VuZChyZWY/OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50Pik6IHZvaWQge1xuICAgIGNvbnN0IGlucHV0ID0gcmVmPy5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTElucHV0RWxlbWVudD4oJ2lucHV0Jyk7XG4gICAgaWYgKCFpbnB1dCkgcmV0dXJuO1xuICAgIGNvbnN0IGxlbiA9IGlucHV0LnZhbHVlLmxlbmd0aDtcbiAgICBpbnB1dC5zZXRTZWxlY3Rpb25SYW5nZShsZW4sIGxlbik7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJsZWFkaW5nXCI+XG4gIDxuZy1jb250YWluZXIgW25nU3dpdGNoXT1cIm1vZGVcIj5cbiAgICA8IS0tIFZpZXcgbW9kZSAtLT5cbiAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaERlZmF1bHQ+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cInRpdGxlXCJcbiAgICAgICAgW2NsYXNzLmhhcy1kZXNjcmlwdGlvbl09XCJkZXNjcmlwdGlvblwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgIHJpdlRydW5jYXRlXG4gICAgICAgIGFyaWEtbGFiZWw9XCJSZW5hbWVcIlxuICAgICAgICAoY2xpY2spPVwic3RhcnRFZGl0aW5nVGl0bGUoKVwiXG4gICAgICA+XG4gICAgICAgIHt7IHRpdGxlIHx8ICdVbnRpdGxlZCcgfX1cbiAgICAgIDwvYnV0dG9uPlxuXG4gICAgICA8ZGl2IGNsYXNzPVwiZGl2aWRlclwiPjwvZGl2PlxuXG4gICAgICA8YnV0dG9uXG4gICAgICAgICpuZ0lmPVwiZGVzY3JpcHRpb247IGVsc2UgYWRkRGVzY3JpcHRpb25cIlxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgY2xhc3M9XCJkZXNjcmlwdGlvblwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgIHJpdlRydW5jYXRlXG4gICAgICAgIGFyaWEtbGFiZWw9XCJFZGl0IGRlc2NyaXB0aW9uXCJcbiAgICAgICAgKGNsaWNrKT1cInN0YXJ0RWRpdGluZ0Rlc2NyaXB0aW9uKClcIlxuICAgICAgPlxuICAgICAgICB7eyBkZXNjcmlwdGlvbiB9fVxuICAgICAgPC9idXR0b24+XG5cbiAgICAgIDxuZy10ZW1wbGF0ZSAjYWRkRGVzY3JpcHRpb24+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJhZGQtZGVzY3JpcHRpb24td3JhcFwiICpuZ0lmPVwiIWRpc2FibGVkXCI+XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgcml2QnV0dG9uXG4gICAgICAgICAgICBbdmFyaWFudF09XCInZ2hvc3QnXCJcbiAgICAgICAgICAgIFtzaXplXT1cIid4c21hbGwnXCJcbiAgICAgICAgICAgIFtpY29uXT1cIidQbHVzJ1wiXG4gICAgICAgICAgICBbaWNvblBvc2l0aW9uXT1cIidmaXJzdCdcIlxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAoY2xpY2spPVwic3RhcnRFZGl0aW5nRGVzY3JpcHRpb24oKVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgQWRkIGRlc2NyaXB0aW9uXG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidlZGl0aW5nVGl0bGUnXCI+XG4gICAgICA8cml2LXRleHQtZmllbGRcbiAgICAgICAgI3RpdGxlSW5wdXRcbiAgICAgICAgY2xhc3M9XCJ0aXRsZS1pbnB1dFwiXG4gICAgICAgIFt2YWx1ZV09XCJkcmFmdFRpdGxlXCJcbiAgICAgICAgW21heExlbmd0aF09XCJ0aXRsZU1heExlbmd0aFwiXG4gICAgICAgIFthdXRvRm9jdXNdPVwidHJ1ZVwiXG4gICAgICAgICh2YWx1ZUNoYW5nZSk9XCJkcmFmdFRpdGxlID0gJGV2ZW50XCJcbiAgICAgICAgKGtleWRvd24uZW50ZXIpPVwiY29tbWl0VGl0bGUoKVwiXG4gICAgICAgIChrZXlkb3duLmVzY2FwZSk9XCJjYW5jZWwoKVwiXG4gICAgICA+PC9yaXYtdGV4dC1maWVsZD5cbiAgICAgIDxidXR0b25cbiAgICAgICAgcml2QnV0dG9uXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cImNvbW1pdFwiXG4gICAgICAgIFt2YXJpYW50XT1cIidwcmltYXJ5J1wiXG4gICAgICAgIFtpY29uXT1cIidDaGVjaydcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiIWRyYWZ0VGl0bGVcIlxuICAgICAgICAoY2xpY2spPVwiY29tbWl0VGl0bGUoKVwiXG4gICAgICAgIGFyaWEtbGFiZWw9XCJTYXZlIHRpdGxlXCJcbiAgICAgID48L2J1dHRvbj5cbiAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgIDwhLS0gRWRpdGluZyBkZXNjcmlwdGlvbiAtLT5cbiAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaENhc2U9XCInZWRpdGluZ0Rlc2NyaXB0aW9uJ1wiPlxuICAgICAgPHJpdi10ZXh0LWZpZWxkXG4gICAgICAgICNkZXNjcmlwdGlvbklucHV0XG4gICAgICAgIGNsYXNzPVwiZGVzY3JpcHRpb24taW5wdXRcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIkFkZCBhIGRlc2NyaXB0aW9uXCJcbiAgICAgICAgW3ZhbHVlXT1cImRyYWZ0RGVzY3JpcHRpb25cIlxuICAgICAgICBbbWF4TGVuZ3RoXT1cImRlc2NyaXB0aW9uTWF4TGVuZ3RoXCJcbiAgICAgICAgW2F1dG9Gb2N1c109XCJ0cnVlXCJcbiAgICAgICAgKHZhbHVlQ2hhbmdlKT1cImRyYWZ0RGVzY3JpcHRpb24gPSAkZXZlbnRcIlxuICAgICAgICAoa2V5ZG93bi5lbnRlcik9XCJjb21taXREZXNjcmlwdGlvbigpXCJcbiAgICAgICAgKGtleWRvd24uZXNjYXBlKT1cImNhbmNlbCgpXCJcbiAgICAgID48L3Jpdi10ZXh0LWZpZWxkPlxuICAgICAgPGJ1dHRvblxuICAgICAgICByaXZCdXR0b25cbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIGNsYXNzPVwiY29tbWl0XCJcbiAgICAgICAgW3ZhcmlhbnRdPVwiJ3ByaW1hcnknXCJcbiAgICAgICAgW2ljb25dPVwiJ0NoZWNrJ1wiXG4gICAgICAgIChjbGljayk9XCJjb21taXREZXNjcmlwdGlvbigpXCJcbiAgICAgICAgYXJpYS1sYWJlbD1cIlNhdmUgZGVzY3JpcHRpb25cIlxuICAgICAgPjwvYnV0dG9uPlxuICAgIDwvbmctY29udGFpbmVyPlxuICA8L25nLWNvbnRhaW5lcj5cbjwvZGl2PlxuXG48ZGl2IGNsYXNzPVwiYWN0aW9uc1wiICpuZ0lmPVwiIWlzRWRpdGluZ1wiPlxuICA8bmctY29udGVudCBzZWxlY3Q9XCJbYWN0aW9uc11cIj48L25nLWNvbnRlbnQ+XG48L2Rpdj5cbiJdfQ==
@@ -5395,12 +5395,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
5395
5395
  * "commit" framing over "change" is deliberate: consumers that persist on
5396
5396
  * commit (analytics, PATCH) treat the gesture itself as the event; those
5397
5397
  * that only care about diffs can compare `next === current` in the handler.
5398
- * There is no cancel path.
5399
5398
  *
5400
- * Outside-click commits (rather than cancels) to match the established DS
5401
- * interaction pattern in `riv-date` and `riv-select`. If a future consumer
5402
- * needs an abandon path, the soft first step is Escape-to-cancel rather
5403
- * than changing outside-click's meaning.
5399
+ * Escape cancels: reverts the draft back to the current value and drops out
5400
+ * of edit mode WITHOUT emitting a change. Outside-click still commits (to
5401
+ * match `riv-date` / `riv-select`); Escape is the deliberate abandon path.
5404
5402
  *
5405
5403
  * Value handling follows the same convention as `riv-text-field`: `[title]`
5406
5404
  * and `[description]` are treated as suggestions, not authoritative state.
@@ -5409,6 +5407,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
5409
5407
  * a different value. That lets the component demo out of the box (e.g. in
5410
5408
  * Storybook) without requiring a round trip through the parent.
5411
5409
  *
5410
+ * Programmatic entry into edit mode is available via `startEditingTitle()`
5411
+ * and `startEditingDescription()` — obtain a reference with
5412
+ * `@ViewChild(EditableHeadingComponent)`. Use these for secondary entry
5413
+ * points like a kebab-menu "Rename" item, or to auto-open rename after
5414
+ * creating a new entity.
5415
+ *
5412
5416
  * The component owns no border, background, or card chrome — consumers who
5413
5417
  * want a bordered container should wrap it.
5414
5418
  *
@@ -5445,6 +5449,15 @@ class EditableHeadingComponent {
5445
5449
  get description() {
5446
5450
  return this._description;
5447
5451
  }
5452
+ set disabled(v) {
5453
+ this._disabled = v;
5454
+ if (v && this.mode !== 'view')
5455
+ this.cancel();
5456
+ this.cdr.markForCheck();
5457
+ }
5458
+ get disabled() {
5459
+ return this._disabled;
5460
+ }
5448
5461
  constructor(cdr, host) {
5449
5462
  this.cdr = cdr;
5450
5463
  this.host = host;
@@ -5453,6 +5466,13 @@ class EditableHeadingComponent {
5453
5466
  this._description = '';
5454
5467
  this.titleMaxLength = 100;
5455
5468
  this.descriptionMaxLength = 300;
5469
+ /**
5470
+ * When true, the title and description are not clickable and cannot be
5471
+ * edited. Any in-progress edit is dropped without emitting. Imperative
5472
+ * `startEditing*` calls no-op. Useful for consumers that need to gate
5473
+ * editing on a permission or a broader "actions disabled" state.
5474
+ */
5475
+ this._disabled = false;
5456
5476
  this.titleChange = new EventEmitter();
5457
5477
  this.descriptionChange = new EventEmitter();
5458
5478
  this.mode = 'view';
@@ -5462,15 +5482,38 @@ class EditableHeadingComponent {
5462
5482
  get isEditing() {
5463
5483
  return this.mode !== 'view';
5464
5484
  }
5485
+ /**
5486
+ * Enter title-edit mode programmatically. Same behavior as clicking the
5487
+ * title — populates the edit buffer from the current value, focuses the
5488
+ * input with the caret at the end, and hides the actions slot. No-op if
5489
+ * already in an editing mode or when the component is disabled.
5490
+ *
5491
+ * Intended for consumers that offer a secondary entry point to renaming
5492
+ * (e.g. a kebab menu item), or that want to auto-open rename after
5493
+ * creating a new entity. Bind via `@ViewChild(EditableHeadingComponent)`.
5494
+ */
5465
5495
  startEditingTitle() {
5496
+ if (this.disabled || this.mode !== 'view')
5497
+ return;
5466
5498
  this.draftTitle = this.title;
5467
5499
  this.mode = 'editingTitle';
5500
+ // `markForCheck` so consumers can call this from outside Angular's zone
5501
+ // (e.g. an async callback) without having to trigger CD themselves.
5502
+ this.cdr.markForCheck();
5468
5503
  // Defer focus until Angular has rendered the input into the DOM.
5469
5504
  setTimeout(() => this.focusEnd(this.titleInputRef), 0);
5470
5505
  }
5506
+ /**
5507
+ * Enter description-edit mode programmatically. Same behavior as clicking
5508
+ * the description (or the "+ Add description" button). No-op if already
5509
+ * in an editing mode or when the component is disabled.
5510
+ */
5471
5511
  startEditingDescription() {
5512
+ if (this.disabled || this.mode !== 'view')
5513
+ return;
5472
5514
  this.draftDescription = this.description;
5473
5515
  this.mode = 'editingDescription';
5516
+ this.cdr.markForCheck();
5474
5517
  setTimeout(() => this.focusEnd(this.descriptionInputRef), 0);
5475
5518
  }
5476
5519
  commitTitle() {
@@ -5496,6 +5539,18 @@ class EditableHeadingComponent {
5496
5539
  this.mode = 'view';
5497
5540
  this.descriptionChange.emit(value);
5498
5541
  }
5542
+ /**
5543
+ * Abandon the current edit and return to view mode. No change is emitted.
5544
+ * Wired to the Escape key on both edit inputs; also called internally
5545
+ * when `disabled` flips to true mid-edit.
5546
+ */
5547
+ cancel() {
5548
+ if (this.mode === 'view')
5549
+ return;
5550
+ this.draftTitle = this._title;
5551
+ this.draftDescription = this._description;
5552
+ this.mode = 'view';
5553
+ }
5499
5554
  // Listens on `mousedown` (not `click`) so the check runs before Angular
5500
5555
  // re-renders the trigger element out of the DOM — otherwise
5501
5556
  // `host.contains(target)` returns false for a click that landed on the
@@ -5513,23 +5568,24 @@ class EditableHeadingComponent {
5513
5568
  this.commitDescription();
5514
5569
  }
5515
5570
  }
5516
- // Focus with caret at end (rather than selecting all) so the user can
5517
- // continue typing where the previous value left off.
5571
+ // Position caret at end (rather than selecting all) so the user can continue
5572
+ // typing where the previous value left off. `riv-text-field` handles the
5573
+ // focus itself via `[autoFocus]`; we just fix up the selection range on the
5574
+ // descendant `<input>`.
5518
5575
  focusEnd(ref) {
5519
- const el = ref === null || ref === void 0 ? void 0 : ref.nativeElement;
5520
- if (!el)
5576
+ const input = ref === null || ref === void 0 ? void 0 : ref.nativeElement.querySelector('input');
5577
+ if (!input)
5521
5578
  return;
5522
- el.focus();
5523
- const len = el.value.length;
5524
- el.setSelectionRange(len, len);
5579
+ const len = input.value.length;
5580
+ input.setSelectionRange(len, len);
5525
5581
  this.cdr.markForCheck();
5526
5582
  }
5527
5583
  }
5528
5584
  EditableHeadingComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: EditableHeadingComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
5529
- EditableHeadingComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: EditableHeadingComponent, selector: "riv-editable-heading", inputs: { title: "title", description: "description", titleMaxLength: "titleMaxLength", descriptionMaxLength: "descriptionMaxLength" }, outputs: { titleChange: "titleChange", descriptionChange: "descriptionChange" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event.target)" }, properties: { "class.editing": "this.isEditing" } }, viewQueries: [{ propertyName: "titleInputRef", first: true, predicate: ["titleInput"], descendants: true }, { propertyName: "descriptionInputRef", first: true, predicate: ["descriptionInput"], descendants: true }], ngImport: i0, template: "<div class=\"leading\">\n <ng-container [ngSwitch]=\"mode\">\n <!-- View mode -->\n <ng-container *ngSwitchDefault>\n <button\n type=\"button\"\n class=\"title\"\n [class.has-description]=\"description\"\n rivTruncate\n aria-label=\"Rename\"\n (click)=\"startEditingTitle()\"\n >\n {{ title || 'Untitled' }}\n </button>\n\n <div class=\"divider\"></div>\n\n <button\n *ngIf=\"description; else addDescription\"\n type=\"button\"\n class=\"description\"\n rivTruncate\n aria-label=\"Edit description\"\n (click)=\"startEditingDescription()\"\n >\n {{ description }}\n </button>\n\n <ng-template #addDescription>\n <div class=\"add-description-wrap\">\n <button\n rivButton\n [variant]=\"'ghost'\"\n [size]=\"'xsmall'\"\n [icon]=\"'Plus'\"\n [iconPosition]=\"'first'\"\n type=\"button\"\n (click)=\"startEditingDescription()\"\n >\n Add description\n </button>\n </div>\n </ng-template>\n </ng-container>\n\n <!-- Editing title -->\n <ng-container *ngSwitchCase=\"'editingTitle'\">\n <input\n #titleInput\n class=\"title-input\"\n type=\"text\"\n aria-label=\"Title\"\n [value]=\"draftTitle\"\n [attr.maxlength]=\"titleMaxLength\"\n (input)=\"draftTitle = titleInput.value\"\n (keydown.enter)=\"commitTitle()\"\n />\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n [disabled]=\"!draftTitle\"\n (click)=\"commitTitle()\"\n aria-label=\"Save title\"\n ></button>\n </ng-container>\n\n <!-- Editing description -->\n <ng-container *ngSwitchCase=\"'editingDescription'\">\n <input\n #descriptionInput\n class=\"description-input\"\n type=\"text\"\n aria-label=\"Description\"\n [value]=\"draftDescription\"\n [attr.maxlength]=\"descriptionMaxLength\"\n placeholder=\"Add a description\"\n (input)=\"draftDescription = descriptionInput.value\"\n (keydown.enter)=\"commitDescription()\"\n />\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n (click)=\"commitDescription()\"\n aria-label=\"Save description\"\n ></button>\n </ng-container>\n </ng-container>\n</div>\n\n<div class=\"actions\" *ngIf=\"!isEditing\">\n <ng-content select=\"[actions]\"></ng-content>\n</div>\n", styles: [":host{display:flex;align-items:stretch;gap:var(--size-large);min-height:calc(var(--base-grid-size) * 8);font:var(--body-medium)}.leading{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:var(--size-small)}.title,.description{padding:0;border:none;background:none;text-align:left;cursor:pointer;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.title{font:var(--stat-xsmall);line-height:calc(var(--base-grid-size) * 4.5);color:var(--type-light-high-contrast);max-width:100%}.title.has-description{width:-moz-fit-content;width:fit-content;max-width:50%;flex-shrink:0}.description{font:var(--input-small);line-height:calc(var(--base-grid-size) * 3.5);color:var(--type-light-low-contrast);flex:1 1 auto}.divider{align-self:stretch;border-right:var(--border-width) solid var(--border-light);margin:0 var(--base-grid-size) 0 0;flex-shrink:0}.add-description-wrap{flex-shrink:0}.title-input,.description-input{border:var(--border-width) solid var(--border-light);border-radius:var(--border-radius-small);padding:var(--size-small) var(--size-medium);color:var(--type-light-high-contrast);outline:none;min-width:0}.title-input{font:var(--stat-xsmall);flex:1 1 auto}.description-input{font:var(--input-small);flex:1 1 auto}.title-input:focus,.description-input:focus{border-color:var(--purp-60)}.commit{flex-shrink:0}.actions{display:flex;align-items:center;gap:var(--size-small);flex-shrink:0}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "component", type: ButtonComponent, selector: "[rivButton]", inputs: ["locked", "disabled", "loading", "full", "size", "variant", "icon", "iconPosition", "current"] }, { kind: "component", type: TruncateComponent, selector: "[rivTruncate]", inputs: ["maxTooltipWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5585
+ EditableHeadingComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: EditableHeadingComponent, selector: "riv-editable-heading", inputs: { title: "title", description: "description", titleMaxLength: "titleMaxLength", descriptionMaxLength: "descriptionMaxLength", disabled: "disabled" }, outputs: { titleChange: "titleChange", descriptionChange: "descriptionChange" }, host: { listeners: { "document:mousedown": "onDocumentMouseDown($event.target)" }, properties: { "class.editing": "this.isEditing" } }, viewQueries: [{ propertyName: "titleInputRef", first: true, predicate: ["titleInput"], descendants: true, read: ElementRef }, { propertyName: "descriptionInputRef", first: true, predicate: ["descriptionInput"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div class=\"leading\">\n <ng-container [ngSwitch]=\"mode\">\n <!-- View mode -->\n <ng-container *ngSwitchDefault>\n <button\n type=\"button\"\n class=\"title\"\n [class.has-description]=\"description\"\n [disabled]=\"disabled\"\n rivTruncate\n aria-label=\"Rename\"\n (click)=\"startEditingTitle()\"\n >\n {{ title || 'Untitled' }}\n </button>\n\n <div class=\"divider\"></div>\n\n <button\n *ngIf=\"description; else addDescription\"\n type=\"button\"\n class=\"description\"\n [disabled]=\"disabled\"\n rivTruncate\n aria-label=\"Edit description\"\n (click)=\"startEditingDescription()\"\n >\n {{ description }}\n </button>\n\n <ng-template #addDescription>\n <div class=\"add-description-wrap\" *ngIf=\"!disabled\">\n <button\n rivButton\n [variant]=\"'ghost'\"\n [size]=\"'xsmall'\"\n [icon]=\"'Plus'\"\n [iconPosition]=\"'first'\"\n type=\"button\"\n (click)=\"startEditingDescription()\"\n >\n Add description\n </button>\n </div>\n </ng-template>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'editingTitle'\">\n <riv-text-field\n #titleInput\n class=\"title-input\"\n [value]=\"draftTitle\"\n [maxLength]=\"titleMaxLength\"\n [autoFocus]=\"true\"\n (valueChange)=\"draftTitle = $event\"\n (keydown.enter)=\"commitTitle()\"\n (keydown.escape)=\"cancel()\"\n ></riv-text-field>\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n [disabled]=\"!draftTitle\"\n (click)=\"commitTitle()\"\n aria-label=\"Save title\"\n ></button>\n </ng-container>\n\n <!-- Editing description -->\n <ng-container *ngSwitchCase=\"'editingDescription'\">\n <riv-text-field\n #descriptionInput\n class=\"description-input\"\n placeholder=\"Add a description\"\n [value]=\"draftDescription\"\n [maxLength]=\"descriptionMaxLength\"\n [autoFocus]=\"true\"\n (valueChange)=\"draftDescription = $event\"\n (keydown.enter)=\"commitDescription()\"\n (keydown.escape)=\"cancel()\"\n ></riv-text-field>\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n (click)=\"commitDescription()\"\n aria-label=\"Save description\"\n ></button>\n </ng-container>\n </ng-container>\n</div>\n\n<div class=\"actions\" *ngIf=\"!isEditing\">\n <ng-content select=\"[actions]\"></ng-content>\n</div>\n", styles: [":host{display:flex;align-items:stretch;gap:var(--size-large);min-height:calc(var(--base-grid-size) * 8);font:var(--body-medium)}.leading{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:var(--size-small)}.title,.description{padding:0;border:none;background:none;text-align:left;cursor:pointer;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.title:disabled,.description:disabled{cursor:default}.title{font:var(--stat-xsmall);line-height:calc(var(--base-grid-size) * 4.5);color:var(--type-light-high-contrast);max-width:100%}.title.has-description{width:-moz-fit-content;width:fit-content;max-width:50%;flex-shrink:0}.description{font:var(--input-small);line-height:calc(var(--base-grid-size) * 3.5);color:var(--type-light-low-contrast);flex:1 1 auto}.divider{align-self:stretch;border-right:var(--border-width) solid var(--border-light);margin:0 var(--base-grid-size) 0 0;flex-shrink:0}.add-description-wrap{flex-shrink:0}.title-input,.description-input{flex:1 1 auto;min-width:0}.commit{flex-shrink:0}.actions{display:flex;align-items:center;gap:var(--size-small);flex-shrink:0}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i1.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "component", type: ButtonComponent, selector: "[rivButton]", inputs: ["locked", "disabled", "loading", "full", "size", "variant", "icon", "iconPosition", "current"] }, { kind: "component", type: TextFieldComponent, selector: "riv-text-field", inputs: ["disabled", "readonly", "placeholder", "casing", "type", "size", "autoFocus", "name", "minLength", "maxLength", "value"], outputs: ["valueChange", "blur"] }, { kind: "component", type: TruncateComponent, selector: "[rivTruncate]", inputs: ["maxTooltipWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5530
5586
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: EditableHeadingComponent, decorators: [{
5531
5587
  type: Component,
5532
- args: [{ selector: 'riv-editable-heading', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"leading\">\n <ng-container [ngSwitch]=\"mode\">\n <!-- View mode -->\n <ng-container *ngSwitchDefault>\n <button\n type=\"button\"\n class=\"title\"\n [class.has-description]=\"description\"\n rivTruncate\n aria-label=\"Rename\"\n (click)=\"startEditingTitle()\"\n >\n {{ title || 'Untitled' }}\n </button>\n\n <div class=\"divider\"></div>\n\n <button\n *ngIf=\"description; else addDescription\"\n type=\"button\"\n class=\"description\"\n rivTruncate\n aria-label=\"Edit description\"\n (click)=\"startEditingDescription()\"\n >\n {{ description }}\n </button>\n\n <ng-template #addDescription>\n <div class=\"add-description-wrap\">\n <button\n rivButton\n [variant]=\"'ghost'\"\n [size]=\"'xsmall'\"\n [icon]=\"'Plus'\"\n [iconPosition]=\"'first'\"\n type=\"button\"\n (click)=\"startEditingDescription()\"\n >\n Add description\n </button>\n </div>\n </ng-template>\n </ng-container>\n\n <!-- Editing title -->\n <ng-container *ngSwitchCase=\"'editingTitle'\">\n <input\n #titleInput\n class=\"title-input\"\n type=\"text\"\n aria-label=\"Title\"\n [value]=\"draftTitle\"\n [attr.maxlength]=\"titleMaxLength\"\n (input)=\"draftTitle = titleInput.value\"\n (keydown.enter)=\"commitTitle()\"\n />\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n [disabled]=\"!draftTitle\"\n (click)=\"commitTitle()\"\n aria-label=\"Save title\"\n ></button>\n </ng-container>\n\n <!-- Editing description -->\n <ng-container *ngSwitchCase=\"'editingDescription'\">\n <input\n #descriptionInput\n class=\"description-input\"\n type=\"text\"\n aria-label=\"Description\"\n [value]=\"draftDescription\"\n [attr.maxlength]=\"descriptionMaxLength\"\n placeholder=\"Add a description\"\n (input)=\"draftDescription = descriptionInput.value\"\n (keydown.enter)=\"commitDescription()\"\n />\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n (click)=\"commitDescription()\"\n aria-label=\"Save description\"\n ></button>\n </ng-container>\n </ng-container>\n</div>\n\n<div class=\"actions\" *ngIf=\"!isEditing\">\n <ng-content select=\"[actions]\"></ng-content>\n</div>\n", styles: [":host{display:flex;align-items:stretch;gap:var(--size-large);min-height:calc(var(--base-grid-size) * 8);font:var(--body-medium)}.leading{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:var(--size-small)}.title,.description{padding:0;border:none;background:none;text-align:left;cursor:pointer;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.title{font:var(--stat-xsmall);line-height:calc(var(--base-grid-size) * 4.5);color:var(--type-light-high-contrast);max-width:100%}.title.has-description{width:-moz-fit-content;width:fit-content;max-width:50%;flex-shrink:0}.description{font:var(--input-small);line-height:calc(var(--base-grid-size) * 3.5);color:var(--type-light-low-contrast);flex:1 1 auto}.divider{align-self:stretch;border-right:var(--border-width) solid var(--border-light);margin:0 var(--base-grid-size) 0 0;flex-shrink:0}.add-description-wrap{flex-shrink:0}.title-input,.description-input{border:var(--border-width) solid var(--border-light);border-radius:var(--border-radius-small);padding:var(--size-small) var(--size-medium);color:var(--type-light-high-contrast);outline:none;min-width:0}.title-input{font:var(--stat-xsmall);flex:1 1 auto}.description-input{font:var(--input-small);flex:1 1 auto}.title-input:focus,.description-input:focus{border-color:var(--purp-60)}.commit{flex-shrink:0}.actions{display:flex;align-items:center;gap:var(--size-small);flex-shrink:0}\n"] }]
5588
+ args: [{ selector: 'riv-editable-heading', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"leading\">\n <ng-container [ngSwitch]=\"mode\">\n <!-- View mode -->\n <ng-container *ngSwitchDefault>\n <button\n type=\"button\"\n class=\"title\"\n [class.has-description]=\"description\"\n [disabled]=\"disabled\"\n rivTruncate\n aria-label=\"Rename\"\n (click)=\"startEditingTitle()\"\n >\n {{ title || 'Untitled' }}\n </button>\n\n <div class=\"divider\"></div>\n\n <button\n *ngIf=\"description; else addDescription\"\n type=\"button\"\n class=\"description\"\n [disabled]=\"disabled\"\n rivTruncate\n aria-label=\"Edit description\"\n (click)=\"startEditingDescription()\"\n >\n {{ description }}\n </button>\n\n <ng-template #addDescription>\n <div class=\"add-description-wrap\" *ngIf=\"!disabled\">\n <button\n rivButton\n [variant]=\"'ghost'\"\n [size]=\"'xsmall'\"\n [icon]=\"'Plus'\"\n [iconPosition]=\"'first'\"\n type=\"button\"\n (click)=\"startEditingDescription()\"\n >\n Add description\n </button>\n </div>\n </ng-template>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'editingTitle'\">\n <riv-text-field\n #titleInput\n class=\"title-input\"\n [value]=\"draftTitle\"\n [maxLength]=\"titleMaxLength\"\n [autoFocus]=\"true\"\n (valueChange)=\"draftTitle = $event\"\n (keydown.enter)=\"commitTitle()\"\n (keydown.escape)=\"cancel()\"\n ></riv-text-field>\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n [disabled]=\"!draftTitle\"\n (click)=\"commitTitle()\"\n aria-label=\"Save title\"\n ></button>\n </ng-container>\n\n <!-- Editing description -->\n <ng-container *ngSwitchCase=\"'editingDescription'\">\n <riv-text-field\n #descriptionInput\n class=\"description-input\"\n placeholder=\"Add a description\"\n [value]=\"draftDescription\"\n [maxLength]=\"descriptionMaxLength\"\n [autoFocus]=\"true\"\n (valueChange)=\"draftDescription = $event\"\n (keydown.enter)=\"commitDescription()\"\n (keydown.escape)=\"cancel()\"\n ></riv-text-field>\n <button\n rivButton\n type=\"button\"\n class=\"commit\"\n [variant]=\"'primary'\"\n [icon]=\"'Check'\"\n (click)=\"commitDescription()\"\n aria-label=\"Save description\"\n ></button>\n </ng-container>\n </ng-container>\n</div>\n\n<div class=\"actions\" *ngIf=\"!isEditing\">\n <ng-content select=\"[actions]\"></ng-content>\n</div>\n", styles: [":host{display:flex;align-items:stretch;gap:var(--size-large);min-height:calc(var(--base-grid-size) * 8);font:var(--body-medium)}.leading{flex:1 1 auto;min-width:0;display:flex;align-items:center;gap:var(--size-small)}.title,.description{padding:0;border:none;background:none;text-align:left;cursor:pointer;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.title:disabled,.description:disabled{cursor:default}.title{font:var(--stat-xsmall);line-height:calc(var(--base-grid-size) * 4.5);color:var(--type-light-high-contrast);max-width:100%}.title.has-description{width:-moz-fit-content;width:fit-content;max-width:50%;flex-shrink:0}.description{font:var(--input-small);line-height:calc(var(--base-grid-size) * 3.5);color:var(--type-light-low-contrast);flex:1 1 auto}.divider{align-self:stretch;border-right:var(--border-width) solid var(--border-light);margin:0 var(--base-grid-size) 0 0;flex-shrink:0}.add-description-wrap{flex-shrink:0}.title-input,.description-input{flex:1 1 auto;min-width:0}.commit{flex-shrink:0}.actions{display:flex;align-items:center;gap:var(--size-small);flex-shrink:0}\n"] }]
5533
5589
  }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { title: [{
5534
5590
  type: Input
5535
5591
  }], description: [{
@@ -5538,16 +5594,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImpo
5538
5594
  type: Input
5539
5595
  }], descriptionMaxLength: [{
5540
5596
  type: Input
5597
+ }], disabled: [{
5598
+ type: Input
5541
5599
  }], titleChange: [{
5542
5600
  type: Output
5543
5601
  }], descriptionChange: [{
5544
5602
  type: Output
5545
5603
  }], titleInputRef: [{
5546
5604
  type: ViewChild,
5547
- args: ['titleInput']
5605
+ args: ['titleInput', { read: ElementRef }]
5548
5606
  }], descriptionInputRef: [{
5549
5607
  type: ViewChild,
5550
- args: ['descriptionInput']
5608
+ args: ['descriptionInput', { read: ElementRef }]
5551
5609
  }], isEditing: [{
5552
5610
  type: HostBinding,
5553
5611
  args: ['class.editing']