Merge "UI: Replace iron-autogrow-textarea with gr-autogrow-textarea"
diff --git a/.gitignore b/.gitignore
index bc489bc..e04444d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,6 +39,7 @@
/polygerrit-ui/coverage/
/polygerrit-ui/app/plugins/*
/polygerrit-ui/screenshots/Chrome/failed/
+/polygerrit-ui/screenshots/Chromium/failed/
!/plugins/.eslintignore
!/plugins/.eslintrc.js
!/plugins/.prettierrc.js
diff --git a/polygerrit-ui/app/api/embed.ts b/polygerrit-ui/app/api/embed.ts
index d6425be..37e68e3 100644
--- a/polygerrit-ui/app/api/embed.ts
+++ b/polygerrit-ui/app/api/embed.ts
@@ -68,3 +68,11 @@
hint?: string;
setRangeText: (replacement: string, start: number, end: number) => void;
}
+
+/** <gr-autogrow-textarea> interface that external users can rely on */
+export declare interface GrAutogrowTextarea extends HTMLElement {
+ value?: string;
+ nativeElement?: HTMLElement;
+ placeholder?: string;
+ setRangeText: (replacement: string, start: number, end: number) => void;
+}
diff --git a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts
index 210b17c..99908c2 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts
+++ b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog.ts
@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
import '@polymer/iron-input/iron-input';
-import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
+import '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
import '../../../styles/gr-form-styles';
import '../../../styles/shared-styles';
import '../../shared/gr-autocomplete/gr-autocomplete';
@@ -32,6 +32,7 @@
import {throwingErrorCallback} from '../../shared/gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper';
import {formStyles} from '../../../styles/form-styles';
import {branchName} from '../../../utils/patch-set-util';
+import {GrAutogrowTextarea} from '../../../api/embed';
const SUGGESTIONS_LIMIT = 15;
@@ -101,7 +102,7 @@
css`
input:not([type='checkbox']),
gr-autocomplete,
- iron-autogrow-textarea {
+ gr-autogrow-textarea {
width: 100%;
}
.value {
@@ -177,19 +178,20 @@
<section id="description">
<span class="title">Description</span>
<span class="value">
- <iron-autogrow-textarea
+ <gr-autogrow-textarea
id="messageInput"
class="message"
autocomplete="on"
- rows="4"
- maxRows="15"
- .bindValue=${this.subject}
+ .rows=${'4'}
+ .maxRows=${'15'}
+ .value=${this.subject}
placeholder="Insert the description of the change."
- @bind-value-changed=${(e: BindValueChangeEvent) => {
- this.subject = e.detail.value ?? '';
+ @input=${(e: InputEvent) => {
+ const value = (e.target as GrAutogrowTextarea).value ?? '';
+ this.subject = value;
}}
>
- </iron-autogrow-textarea>
+ </gr-autogrow-textarea>
</span>
</section>
<section class=${this.privateChangesEnabled ? 'hide' : ''}>
diff --git a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.ts b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.ts
index 2bcde2c..1ef6426 100644
--- a/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.ts
+++ b/polygerrit-ui/app/elements/admin/gr-create-change-dialog/gr-create-change-dialog_test.ts
@@ -79,16 +79,13 @@
<section id="description">
<span class="title"> Description </span>
<span class="value">
- <iron-autogrow-textarea
- aria-disabled="false"
+ <gr-autogrow-textarea
autocomplete="on"
class="message"
id="messageInput"
- maxrows="15"
placeholder="Insert the description of the change."
- rows="4"
>
- </iron-autogrow-textarea>
+ </gr-autogrow-textarea>
</span>
</section>
<section>
diff --git a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.ts b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.ts
index 3095d54..bc44e5a 100644
--- a/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.ts
+++ b/polygerrit-ui/app/elements/admin/gr-repo/gr-repo_test.ts
@@ -152,7 +152,7 @@
function getFormFields() {
const selects = Array.from(queryAll(element, 'select'));
- const textareas = Array.from(queryAll(element, 'iron-autogrow-textarea'));
+ const textareas = Array.from(queryAll(element, 'gr-autogrow-textarea'));
const inputs = Array.from(queryAll(element, 'input'));
return inputs.concat(textareas).concat(selects);
}
diff --git a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.ts b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.ts
index 483d2c1c..acad82f 100644
--- a/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.ts
+++ b/polygerrit-ui/app/elements/admin/gr-rule-editor/gr-rule-editor.ts
@@ -3,7 +3,7 @@
* Copyright 2017 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
-import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
+import '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
import '../../shared/gr-button/gr-button';
import '../../shared/gr-select/gr-select';
import {encodeURL, getBaseUrl} from '../../../utils/url-util';
@@ -18,6 +18,7 @@
import {EditablePermissionRuleInfo} from '../gr-repo-access/gr-repo-access-interfaces';
import {PermissionAction} from '../../../constants/constants';
import {formStyles} from '../../../styles/form-styles';
+import {GrAutogrowTextarea} from '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
const PRIORITY_OPTIONS = [PermissionAction.BATCH, PermissionAction.INTERACTIVE];
@@ -174,7 +175,7 @@
.groupPath {
color: var(--deemphasized-text-color);
}
- iron-autogrow-textarea {
+ gr-autogrow-textarea {
width: 14em;
}
`,
@@ -288,28 +289,46 @@
if (!this.hasRange) return;
return html`
- <iron-autogrow-textarea
+ <gr-autogrow-textarea
id="minInput"
class="min"
autocomplete="on"
placeholder="Min value"
- .bindValue=${this.rule?.value?.min}
+ .value=${this.rule?.value?.min}
?disabled=${!this.editing}
- @bind-value-changed=${(e: BindValueChangeEvent) => {
- this.handleMinBindValueChanged(e);
+ @input=${(e: InputEvent) => {
+ const value = (e.target as GrAutogrowTextarea).value ?? '';
+ if (
+ !this.rule?.value ||
+ value === undefined ||
+ this.rule.value.min === Number(value)
+ )
+ return;
+ this.rule.value.min = Number(value);
+
+ this.handleValueChange();
}}
- ></iron-autogrow-textarea>
- <iron-autogrow-textarea
+ ></gr-autogrow-textarea>
+ <gr-autogrow-textarea
id="maxInput"
class="max"
autocomplete="on"
placeholder="Max value"
- .bindValue=${this.rule?.value?.max}
+ .value=${this.rule?.value?.max}
?disabled=${!this.editing}
- @bind-value-changed=${(e: BindValueChangeEvent) => {
- this.handleMaxBindValueChanged(e);
+ @input=${(e: InputEvent) => {
+ const value = (e.target as GrAutogrowTextarea).value ?? '';
+ if (
+ !this.rule?.value ||
+ value === undefined ||
+ this.rule.value.max === Number(value)
+ )
+ return;
+ this.rule.value.max = Number(value);
+
+ this.handleValueChange();
}}
- ></iron-autogrow-textarea>
+ ></gr-autogrow-textarea>
`;
}
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.ts
index 36641d6..4c36c5f 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog.ts
@@ -3,19 +3,18 @@
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
-import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
+import '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
import '../../shared/gr-dialog/gr-dialog';
-import {IronAutogrowTextareaElement} from '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
import {Key, Modifier} from '../../../utils/dom-util';
import {sharedStyles} from '../../../styles/shared-styles';
import {css, html, LitElement} from 'lit';
import {customElement, property, query} from 'lit/decorators.js';
import {assertIsDefined} from '../../../utils/common-util';
-import {BindValueChangeEvent} from '../../../types/events';
import {ShortcutController} from '../../lit/shortcut-controller';
import {ChangeActionDialog} from '../../../types/common';
import {fireNoBubble} from '../../../utils/event-util';
import {formStyles} from '../../../styles/form-styles';
+import {GrAutogrowTextarea} from '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
declare global {
interface HTMLElementTagNameMap {
@@ -40,7 +39,7 @@
* @event cancel
*/
- @query('#messageInput') private messageInput?: IronAutogrowTextareaElement;
+ @query('#messageInput') private messageInput?: GrAutogrowTextarea;
@property({type: String})
message = '';
@@ -82,7 +81,7 @@
display: block;
width: 100%;
}
- iron-autogrow-textarea {
+ gr-autogrow-textarea {
font-family: var(--monospace-font-family);
font-size: var(--font-size-mono);
line-height: var(--line-height-mono);
@@ -106,16 +105,14 @@
<div class="header" slot="header">Abandon Change</div>
<div class="main" slot="main">
<label for="messageInput">Abandon Message</label>
- <iron-autogrow-textarea
+ <gr-autogrow-textarea
id="messageInput"
class="message"
autocomplete="on"
placeholder="<Insert reasoning here>"
- .bindValue=${this.message}
- @bind-value-changed=${(e: BindValueChangeEvent) => {
- this.handleBindValueChanged(e);
- }}
- ></iron-autogrow-textarea>
+ .value=${this.message}
+ @input=${this.handleInputChanged}
+ ></gr-autogrow-textarea>
</div>
</gr-dialog>
`;
@@ -123,7 +120,7 @@
resetFocus() {
assertIsDefined(this.messageInput, 'messageInput');
- this.messageInput.textarea.focus();
+ this.messageInput.focus();
}
// private but used in test
@@ -145,7 +142,8 @@
fireNoBubble(this, 'cancel', {});
}
- private handleBindValueChanged(e: BindValueChangeEvent) {
- this.message = e.detail.value ?? '';
+ private handleInputChanged(e: InputEvent) {
+ const value = (e.target as GrAutogrowTextarea).value ?? '';
+ this.message = value;
}
}
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.ts b/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.ts
index 3842f7a..ee2d541 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-abandon-dialog/gr-confirm-abandon-dialog_test.ts
@@ -28,14 +28,13 @@
<div class="header" slot="header">Abandon Change</div>
<div class="main" slot="main">
<label for="messageInput"> Abandon Message </label>
- <iron-autogrow-textarea
- aria-disabled="false"
+ <gr-autogrow-textarea
autocomplete="on"
class="message"
id="messageInput"
placeholder="<Insert reasoning here>"
>
- </iron-autogrow-textarea>
+ </gr-autogrow-textarea>
</div>
</gr-dialog>
`
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
index b15a4e4..d74ac52 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
@@ -3,7 +3,7 @@
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
-import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
+import '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
import '@polymer/iron-input/iron-input';
import '../../../styles/shared-styles';
import '../../shared/gr-autocomplete/gr-autocomplete';
@@ -48,6 +48,7 @@
import {formStyles} from '../../../styles/form-styles';
import {branchName} from '../../../utils/patch-set-util';
import {changeModelToken} from '../../../models/change/change-model';
+import {GrAutogrowTextarea} from '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
const SUGGESTIONS_LIMIT = 15;
const CHANGE_SUBJECT_LIMIT = 50;
@@ -209,7 +210,7 @@
display: block;
width: 100%;
}
- iron-autogrow-textarea {
+ gr-autogrow-textarea {
font-family: var(--monospace-font-family);
font-size: var(--font-size-mono);
line-height: var(--line-height-mono);
@@ -354,16 +355,18 @@
/>
</iron-input>
<label for="messageInput"> Cherry Pick Commit Message </label>
- <iron-autogrow-textarea
+ <gr-autogrow-textarea
id="messageInput"
class="message"
autocomplete="on"
- rows="4"
+ .rows=${4}
.maxRows=${15}
- .bindValue=${this.message}
- @bind-value-changed=${(e: BindValueChangeEvent) =>
- (this.message = e.detail.value ?? '')}
- ></iron-autogrow-textarea>
+ .value=${this.message}
+ @input=${(e: InputEvent) => {
+ const value = (e.target as GrAutogrowTextarea).value ?? '';
+ this.message = value;
+ }}
+ ></gr-autogrow-textarea>
${when(
this.canShowEmailDropdown(),
() => html`<div id="cherryPickEmailDropdown">Cherry Pick Committer Email
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.ts b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.ts
index 7f20c61..5ae607a 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.ts
@@ -136,14 +136,12 @@
/>
</iron-input>
<label for="messageInput"> Cherry Pick Commit Message </label>
- <iron-autogrow-textarea
- aria-disabled="false"
+ <gr-autogrow-textarea
autocomplete="on"
class="message"
id="messageInput"
- rows="4"
>
- </iron-autogrow-textarea>
+ </gr-autogrow-textarea>
<gr-endpoint-slot name="bottom"></gr-endpoint-slot>
</gr-endpoint-decorator>
</div>
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts
index a9bb86e..206fa46 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog.ts
@@ -10,7 +10,7 @@
import {getAppContext} from '../../../services/app-context';
import '../../shared/gr-autocomplete/gr-autocomplete';
import '../../shared/gr-dialog/gr-dialog';
-import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
+import '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
import {Key, Modifier} from '../../../utils/dom-util';
import {ValueChangedEvent} from '../../../types/events';
import {ShortcutController} from '../../lit/shortcut-controller';
@@ -18,6 +18,7 @@
import {fireNoBubble} from '../../../utils/event-util';
import {formStyles} from '../../../styles/form-styles';
import {branchName} from '../../../utils/patch-set-util';
+import {GrAutogrowTextarea} from '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
const SUGGESTIONS_LIMIT = 15;
@@ -130,14 +131,18 @@
>
</gr-autocomplete>
<label for="messageInput"> Move Change Message </label>
- <iron-autogrow-textarea
+ <gr-autogrow-textarea
id="messageInput"
class="message"
autocomplete="on"
.rows=${4}
.maxRows=${15}
- .bindValue=${this.message}
- ></iron-autogrow-textarea>
+ .value=${this.message}
+ @input=${(e: InputEvent) => {
+ const value = (e.target as GrAutogrowTextarea).value ?? '';
+ this.message = value;
+ }}
+ ></gr-autogrow-textarea>
</div>
</gr-dialog>
`;
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.ts b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.ts
index 42d8654..3fe2e0b 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-move-dialog/gr-confirm-move-dialog_test.ts
@@ -49,12 +49,11 @@
<gr-autocomplete id="branchInput" placeholder="Destination branch">
</gr-autocomplete>
<label for="messageInput"> Move Change Message </label>
- <iron-autogrow-textarea
- aria-disabled="false"
+ <gr-autogrow-textarea
id="messageInput"
class="message"
autocomplete="on"
- ></iron-autogrow-textarea>
+ ></gr-autogrow-textarea>
</div>
</gr-dialog>
`
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.ts
index d038140..2854905 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog.ts
@@ -6,7 +6,7 @@
import '../../shared/gr-dialog/gr-dialog';
import '../../plugins/gr-endpoint-decorator/gr-endpoint-decorator';
import '../gr-validation-options/gr-validation-options';
-import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
+import '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
import {css, html, LitElement, nothing} from 'lit';
import {customElement, query, state} from 'lit/decorators.js';
import {
@@ -17,7 +17,6 @@
} from '../../../types/common';
import {fire, fireAlert} from '../../../utils/event-util';
import {sharedStyles} from '../../../styles/shared-styles';
-import {BindValueChangeEvent} from '../../../types/events';
import {resolve} from '../../../models/dependency';
import {pluginLoaderToken} from '../../shared/gr-js-api-interface/gr-plugin-loader';
import {createSearchUrl} from '../../../models/views/search';
@@ -25,6 +24,7 @@
import {formStyles} from '../../../styles/form-styles';
import {GrValidationOptions} from '../gr-validation-options/gr-validation-options';
import {parseCommitMessageString} from '../../../utils/commit-message-formatter-util';
+import {GrAutogrowTextarea} from '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
const ERR_COMMIT_NOT_FOUND = 'Unable to find the commit hash of this change.';
const SPECIFY_REASON_STRING = '<MUST SPECIFY REASON HERE>';
@@ -106,7 +106,7 @@
.label {
margin-left: var(--spacing-m);
}
- iron-autogrow-textarea {
+ gr-autogrow-textarea {
font-family: var(--monospace-font-family);
font-size: var(--font-size-mono);
line-height: var(--line-height-mono);
@@ -168,14 +168,17 @@
: nothing}
<gr-endpoint-decorator name="confirm-revert-change">
<label for="messageInput"> Revert Commit Message </label>
- <iron-autogrow-textarea
+ <gr-autogrow-textarea
id="messageInput"
class="message"
.autocomplete=${'on'}
.maxRows=${15}
- .bindValue=${this.message}
- @bind-value-changed=${this.handleBindValueChanged}
- ></iron-autogrow-textarea>
+ .value=${this.message}
+ @input=${(e: InputEvent) => {
+ const value = (e.target as GrAutogrowTextarea).value ?? '';
+ this.message = value;
+ }}
+ ></gr-autogrow-textarea>
</gr-endpoint-decorator>
<gr-validation-options
.validationOptions=${this.validationOptions}
@@ -316,10 +319,6 @@
this.showRevertSubmission = true;
}
- private handleBindValueChanged(e: BindValueChangeEvent) {
- this.message = e.detail.value ?? '';
- }
-
private handleRevertSingleChangeClicked() {
this.showErrorMessage = false;
if (this.message)
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.ts b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.ts
index 0daa30e..cd75f2c 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.ts
@@ -32,11 +32,10 @@
</div>
<gr-endpoint-decorator name="confirm-revert-change">
<label for="messageInput"> Revert Commit Message </label>
- <iron-autogrow-textarea
+ <gr-autogrow-textarea
id="messageInput"
class="message"
- aria-disabled="false"
- ></iron-autogrow-textarea>
+ ></gr-autogrow-textarea>
</gr-endpoint-decorator>
<gr-validation-options></gr-validation-options>
</div>
diff --git a/polygerrit-ui/app/elements/gr-css-mixins.ts b/polygerrit-ui/app/elements/gr-css-mixins.ts
index 0a00819..a4b01c2 100644
--- a/polygerrit-ui/app/elements/gr-css-mixins.ts
+++ b/polygerrit-ui/app/elements/gr-css-mixins.ts
@@ -63,10 +63,6 @@
--paper-listbox: {
padding: 0;
};
- --iron-autogrow-textarea: {
- box-sizing: border-box;
- padding: var(--spacing-s);
- };
}
</style>
`;
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts
index 1ed0d9b..ccc1a61 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info.ts
@@ -3,8 +3,8 @@
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
-import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
import '@polymer/iron-input/iron-input';
+import '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
import '../../shared/gr-avatar/gr-avatar';
import '../../shared/gr-date-formatter/gr-date-formatter';
import '../../shared/gr-tooltip-content/gr-tooltip-content';
@@ -27,6 +27,7 @@
import {subscribe} from '../../lit/subscription-controller';
import {resolve} from '../../../models/dependency';
import {configModelToken} from '../../../models/config/config-model';
+import {GrAutogrowTextarea} from '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
@customElement('gr-account-info')
export class GrAccountInfo extends LitElement {
@@ -93,7 +94,7 @@
border-radius: var(--border-radius);
box-shadow: var(--elevation-level-5);
}
- iron-autogrow-textarea {
+ gr-autogrow-textarea {
background-color: var(--view-background-color);
color: var(--primary-text-color);
}
@@ -243,19 +244,20 @@
</div>
</span>
<span class="value">
- <iron-autogrow-textarea
+ <gr-autogrow-textarea
id="statusInput"
.label=${'statusInput'}
?disabled=${this.saving}
maxlength="140"
.value=${this.account?.status}
- @bind-value-changed=${(e: BindValueChangeEvent) => {
+ @input=${(e: InputEvent) => {
const oldAccount = this.account;
- if (!oldAccount || oldAccount.status === e.detail.value) return;
- this.account = {...oldAccount, status: e.detail.value};
+ const value = (e.target as GrAutogrowTextarea).value ?? '';
+ if (!oldAccount || oldAccount.status === value) return;
+ this.account = {...oldAccount, status: value};
this.hasStatusChange = true;
}}
- ></iron-autogrow-textarea>
+ ></gr-autogrow-textarea>
</span>
</section>
<section>
diff --git a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.ts b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.ts
index fda7b8a..e272c4e 100644
--- a/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.ts
+++ b/polygerrit-ui/app/elements/settings/gr-account-info/gr-account-info_test.ts
@@ -25,7 +25,7 @@
import {RestApiService} from '../../../services/gr-rest-api/gr-rest-api';
import {EditableAccountField} from '../../../api/rest-api';
import {assert, fixture, html} from '@open-wc/testing';
-import {IronAutogrowTextareaElement} from '@polymer/iron-autogrow-textarea';
+import {GrAutogrowTextarea} from '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
suite('gr-account-info tests', () => {
let element!: GrAccountInfo;
@@ -121,11 +121,7 @@
<div class="lengthCounter">0/140</div>
</span>
<span class="value">
- <iron-autogrow-textarea
- aria-disabled="false"
- id="statusInput"
- maxlength="140"
- />
+ <gr-autogrow-textarea id="statusInput" maxlength="140" />
</span>
</section>
<section>
@@ -296,11 +292,14 @@
test('status', async () => {
assert.isFalse(element.hasUnsavedChanges);
- const statusTextarea = queryAndAssert<IronAutogrowTextareaElement>(
+ const statusTextarea = queryAndAssert<GrAutogrowTextarea>(
element,
'#statusInput'
);
statusTextarea.value = 'new status';
+ statusTextarea.dispatchEvent(
+ new Event('input', {bubbles: true, composed: true})
+ );
await element.updateComplete;
assert.isFalse(element.hasNameChange);
assert.isTrue(element.hasStatusChange);
@@ -343,11 +342,14 @@
await element.updateComplete;
assert.isTrue(element.hasNameChange);
- const statusTextarea = queryAndAssert<IronAutogrowTextareaElement>(
+ const statusTextarea = queryAndAssert<GrAutogrowTextarea>(
element,
'#statusInput'
);
statusTextarea.value = 'new status';
+ statusTextarea.dispatchEvent(
+ new Event('input', {bubbles: true, composed: true})
+ );
await element.updateComplete;
assert.isTrue(element.hasStatusChange);
@@ -392,11 +394,14 @@
assert.equal(displaySpan.textContent, account.name);
assert.isUndefined(inputSpan);
- const statusTextarea = queryAndAssert<IronAutogrowTextareaElement>(
+ const statusTextarea = queryAndAssert<GrAutogrowTextarea>(
element,
'#statusInput'
);
statusTextarea.value = 'new status';
+ statusTextarea.dispatchEvent(
+ new Event('input', {bubbles: true, composed: true})
+ );
await element.updateComplete;
assert.isTrue(element.hasStatusChange);
diff --git a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.ts b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.ts
index 2fc93cf..98d0df9 100644
--- a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.ts
+++ b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor.ts
@@ -3,7 +3,7 @@
* Copyright 2017 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
-import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
+import '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
import '../../shared/gr-button/gr-button';
import '../../shared/gr-copy-clipboard/gr-copy-clipboard';
import {GpgKeyId, GpgKeyInfo} from '../../../types/common';
@@ -15,10 +15,10 @@
import {grFormStyles} from '../../../styles/gr-form-styles';
import {sharedStyles} from '../../../styles/shared-styles';
import {assertIsDefined} from '../../../utils/common-util';
-import {BindValueChangeEvent} from '../../../types/events';
import {fire} from '../../../utils/event-util';
import {modalStyles} from '../../../styles/gr-modal-styles';
import {formStyles} from '../../../styles/form-styles';
+import {GrAutogrowTextarea} from '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
declare global {
interface HTMLElementTagNameMap {
@@ -75,8 +75,19 @@
#existing {
margin-bottom: var(--spacing-l);
}
- iron-autogrow-textarea {
+ gr-autogrow-textarea {
background-color: var(--view-background-color);
+ position: relative;
+ height: auto;
+ min-height: 4em;
+ --gr-autogrow-textarea-border-width: 0px;
+ --gr-autogrow-textarea-border-color: var(--border-color);
+ --input-field-bg: var(--view-background-color);
+ --input-field-disabled-bg: var(--view-background-color);
+ --secondary-bg-color: var(--background-color-secondary);
+ --text-default: var(--primary-text-color);
+ --text-disabled: var(--deemphasized-text-color);
+ --text-secondary: var(--deemphasized-text-color);
}
`,
];
@@ -128,14 +139,13 @@
<section>
<span class="title">New GPG key</span>
<span class="value">
- <iron-autogrow-textarea
+ <gr-autogrow-textarea
id="newKey"
autocomplete="on"
- .bindValue=${this.newKey}
- @bind-value-changed=${(e: BindValueChangeEvent) =>
- this.handleNewKeyChanged(e)}
+ .value=${this.newKey}
+ @input=${(e: InputEvent) => this.handleNewKeyChanged(e)}
placeholder="New GPG Key"
- ></iron-autogrow-textarea>
+ ></gr-autogrow-textarea>
</span>
</section>
<gr-button
@@ -208,8 +218,9 @@
this.viewKeyModal?.showModal();
}
- private handleNewKeyChanged(e: BindValueChangeEvent) {
- this.newKey = e.detail.value ?? '';
+ private handleNewKeyChanged(e: InputEvent) {
+ const rawValue = (e.target as GrAutogrowTextarea).value ?? '';
+ this.newKey = rawValue;
}
private handleDeleteKey(index: number) {
diff --git a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.ts b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.ts
index f7c837d..0455eab 100644
--- a/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.ts
+++ b/polygerrit-ui/app/elements/settings/gr-gpg-editor/gr-gpg-editor_test.ts
@@ -170,13 +170,12 @@
<section>
<span class="title"> New GPG key </span>
<span class="value">
- <iron-autogrow-textarea
- aria-disabled="false"
+ <gr-autogrow-textarea
autocomplete="on"
id="newKey"
placeholder="New GPG Key"
>
- </iron-autogrow-textarea>
+ </gr-autogrow-textarea>
</span>
</section>
<gr-button
diff --git a/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor.ts b/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor.ts
index 0911c51..5de113c 100644
--- a/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor.ts
+++ b/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor.ts
@@ -3,20 +3,19 @@
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
-import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
+import '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
import '../../shared/gr-button/gr-button';
import '../../shared/gr-copy-clipboard/gr-copy-clipboard';
import {SshKeyInfo} from '../../../types/common';
import {GrButton} from '../../shared/gr-button/gr-button';
-import {IronAutogrowTextareaElement} from '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
import {getAppContext} from '../../../services/app-context';
import {css, html, LitElement, PropertyValues} from 'lit';
import {customElement, property, query, state} from 'lit/decorators.js';
import {grFormStyles} from '../../../styles/gr-form-styles';
import {sharedStyles} from '../../../styles/shared-styles';
import {fire} from '../../../utils/event-util';
-import {BindValueChangeEvent} from '../../../types/events';
import {modalStyles} from '../../../styles/gr-modal-styles';
+import {GrAutogrowTextarea} from '../../shared/gr-autogrow-textarea/gr-autogrow-textarea';
declare global {
interface HTMLElementTagNameMap {
@@ -44,7 +43,7 @@
@query('#addButton') addButton!: GrButton;
- @query('#newKey') newKeyEditor!: IronAutogrowTextareaElement;
+ @query('#newKey') newKeyEditor!: GrAutogrowTextarea;
@query('#viewKeyModal') viewKeyModal!: HTMLDialogElement;
@@ -86,7 +85,7 @@
min-width: 27em;
width: auto;
}
- iron-autogrow-textarea {
+ gr-autogrow-textarea {
background-color: var(--view-background-color);
}
`,
@@ -154,15 +153,16 @@
<section>
<span class="title">New SSH key</span>
<span class="value">
- <iron-autogrow-textarea
+ <gr-autogrow-textarea
id="newKey"
autocomplete="on"
placeholder="New SSH Key"
- .bindValue=${this.newKey}
- @bind-value-changed=${(e: BindValueChangeEvent) => {
- this.newKey = e.detail.value ?? '';
+ .value=${this.newKey}
+ @input=${(e: InputEvent) => {
+ const value = (e.target as GrAutogrowTextarea).value ?? '';
+ this.newKey = value;
}}
- ></iron-autogrow-textarea>
+ ></gr-autogrow-textarea>
</span>
</section>
<gr-button
diff --git a/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_test.ts b/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_test.ts
index c7a6c71..e3fbeb5 100644
--- a/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_test.ts
+++ b/polygerrit-ui/app/elements/settings/gr-ssh-editor/gr-ssh-editor_test.ts
@@ -165,13 +165,12 @@
<section>
<span class="title"> New SSH key </span>
<span class="value">
- <iron-autogrow-textarea
- aria-disabled="false"
+ <gr-autogrow-textarea
autocomplete="on"
id="newKey"
placeholder="New SSH Key"
>
- </iron-autogrow-textarea>
+ </gr-autogrow-textarea>
</span>
</section>
<gr-button
diff --git a/polygerrit-ui/app/elements/shared/gr-autogrow-textarea/gr-autogrow-textarea.ts b/polygerrit-ui/app/elements/shared/gr-autogrow-textarea/gr-autogrow-textarea.ts
new file mode 100644
index 0000000..dc3f814
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-autogrow-textarea/gr-autogrow-textarea.ts
@@ -0,0 +1,355 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+import {css, html, LitElement} from 'lit';
+import {
+ customElement,
+ property,
+ query,
+ queryAsync,
+ state,
+} from 'lit/decorators.js';
+import {ifDefined} from 'lit/directives/if-defined.js';
+import {
+ CursorPositionChangeEventDetail,
+ GrAutogrowTextarea as GrAutogrowTextareaApi,
+} from '../../../api/embed';
+
+/**
+ * Waits for the next animation frame.
+ */
+async function animationFrame(): Promise<void> {
+ return new Promise(resolve => {
+ requestAnimationFrame(() => {
+ resolve();
+ });
+ });
+}
+
+/**
+ * A custom textarea component which allows autocomplete functionality.
+ *
+ * Example usage:
+ * <gr-autogrow-textarea></gr-autogrow-textarea>
+ */
+@customElement('gr-autogrow-textarea')
+export class GrAutogrowTextarea
+ extends LitElement
+ implements GrAutogrowTextareaApi
+{
+ // editableTextAreaElement is available right away where it may be undefined. This
+ // is used for calls for scrollTop as if it is undefined then we can fallback
+ // to 0. For other usecases use editableTextArea.
+ @query('.editableTextArea')
+ private readonly editableTextAreaElement?: HTMLTextAreaElement;
+
+ @queryAsync('.editableTextArea')
+ private readonly editableTextArea?: Promise<HTMLTextAreaElement>;
+
+ @property({type: Boolean, reflect: true}) disabled = false;
+
+ @property({type: String, reflect: true}) placeholder: string | undefined;
+
+ @property({type: String}) value: string = '';
+
+ @property({type: Number}) rows = 1;
+
+ @property({type: Number}) maxRows = 0;
+
+ /**
+ * Sets cursor at the end of content on focus.
+ */
+ @property({type: Boolean}) putCursorAtEndOnFocus = false;
+
+ @property({type: String}) autocomplete = 'off';
+
+ @property({type: String}) inputmode?: string;
+
+ @property({type: String}) readonly?: string;
+
+ @property({type: Boolean}) required = false;
+
+ @property({type: Number}) minlength?: number;
+
+ @property({type: Number}) maxlength?: number;
+
+ @property({type: String}) label?: string;
+
+ /*
+ * Is textarea focused. This is a readonly property.
+ */
+ get isFocused(): boolean {
+ return !!this.focused;
+ }
+
+ /**
+ * Native element for editable div.
+ */
+ get nativeElement() {
+ return this.editableTextAreaElement;
+ }
+
+ /**
+ * Scroll Top for editable div.
+ */
+ override get scrollTop() {
+ return this.editableTextAreaElement?.scrollTop ?? 0;
+ }
+
+ private focused = false;
+
+ @state() private tokens: string[] = [];
+
+ static override get styles() {
+ return [
+ css`
+ :host {
+ display: inline-block;
+ position: relative;
+ width: 400px;
+ border: var(--gr-autogrow-textarea-border-width, 2px) solid
+ var(--gr-textarea-border-color, white);
+ border-radius: 4px;
+ padding: 2px;
+ -moz-appearance: textarea;
+ -webkit-appearance: textarea;
+ appearance: textarea;
+ overflow: hidden;
+ }
+ :host([disabled]) {
+ textarea {
+ background-color: var(--input-field-disabled-bg, lightgrey);
+ color: var(--text-disabled, black);
+ cursor: default;
+ }
+ }
+ .mirror-text {
+ visibility: hidden;
+ word-wrap: break-word;
+ padding: var(--gr-autogrow-textarea-padding);
+ box-sizing: var(--gr-autogrow-textarea-box-sizing);
+ }
+ .textarea-container {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ }
+ textarea {
+ position: relative;
+ outline: none;
+ border: none;
+ resize: none;
+ background: inherit;
+ color: inherit;
+ width: 100%;
+ height: 100%;
+ font-size: inherit;
+ font-family: inherit;
+ line-height: inherit;
+ text-align: inherit;
+ padding: var(--gr-autogrow-textarea-padding);
+ box-sizing: var(--gr-autogrow-textarea-box-sizing);
+ }
+ textarea:focus-visible {
+ border-color: var(--gr-textarea-focus-outline-color, black);
+ outline: none;
+ }
+ `,
+ ];
+ }
+
+ override render() {
+ return html` <div id="mirror" class="mirror-text" aria-hidden="true">
+ ${this.tokens.length === 1 && this.tokens[0] === ''
+ ? html` `
+ : this.tokens.map((t, i) =>
+ i === this.tokens.length - 1 ? html`${t} ` : html`${t}<br />`
+ )}
+ </div>
+ <div class="textarea-container">
+ <textarea
+ class="editableTextArea"
+ .value=${this.value}
+ aria-label=${ifDefined(this.label)}
+ aria-disabled=${this.disabled}
+ aria-multiline="true"
+ aria-placeholder=${ifDefined(this.placeholder)}
+ autocomplete=${this.autocomplete}
+ ?autofocus=${this.autofocus}
+ autocapitalize=${this.autocapitalize}
+ inputmode=${ifDefined(this.inputmode)}
+ placeholder=${ifDefined(this.placeholder)}
+ ?disabled=${this.disabled}
+ rows=${this.rows}
+ minlength=${ifDefined(this.minlength)}
+ maxlength=${ifDefined(this.maxlength)}
+ spellcheck=${this.spellcheck}
+ @input=${this.onInput}
+ @focus=${this.onFocus}
+ @blur=${this.onBlur}
+ @keyup=${this.handleKeyUp}
+ @mouseup=${this.handleMouseUp}
+ ></textarea>
+ </div>`;
+ }
+
+ override updated(changed: Map<string, unknown>) {
+ if (changed.has('value')) {
+ if (
+ this.editableTextAreaElement &&
+ this.editableTextAreaElement.value !== this.value
+ ) {
+ this.editableTextAreaElement.value = this.value ?? '';
+ }
+ this.updateMirror();
+ }
+ if (changed.has('rows') || changed.has('maxRows')) {
+ this.updateMirror();
+ }
+ }
+
+ override async focus() {
+ const editableTextAreaElement = await this.editableTextArea;
+ const isFocused = this.isFocused;
+ editableTextAreaElement?.focus?.();
+ // If already focused, do not change the cursor position.
+ if (this.putCursorAtEndOnFocus && !isFocused) {
+ await this.putCursorAtEnd();
+ }
+ }
+
+ /**
+ * Puts the cursor at the end of existing content.
+ * Scrolls the content of textarea towards the end.
+ */
+ async putCursorAtEnd() {
+ const editableTextAreaElement = await this.editableTextArea;
+ if (!editableTextAreaElement) return;
+
+ const length = this.value.length;
+ editableTextAreaElement.selectionStart = length;
+ editableTextAreaElement.selectionEnd = length;
+ editableTextAreaElement.focus();
+ }
+
+ /**
+ * Sets cursor position to given position and scrolls the content to cursor
+ * position.
+ *
+ * If position is out of bounds of value of textarea then cursor is places at
+ * end of content of textarea.
+ */
+ public setCursorPosition(position: number) {
+ if (!this.editableTextAreaElement) return;
+
+ this.editableTextAreaElement.selectionStart = position;
+ this.editableTextAreaElement.selectionEnd = position;
+
+ this.onCursorPositionChange();
+ }
+
+ /**
+ * Replaces text from start and end cursor position.
+ */
+ async setRangeText(replacement: string, start: number, end: number) {
+ const pre = this.value?.substring(0, start) ?? '';
+ const post = this.value?.substring(end, this.value?.length ?? 0) ?? '';
+ this.value = pre + replacement + post;
+
+ await animationFrame();
+
+ this.setCursorPosition(pre.length + replacement.length);
+ }
+
+ private onInput(event: Event) {
+ event.preventDefault();
+ event.stopImmediatePropagation();
+
+ const target = event.target as HTMLTextAreaElement;
+ this.value = target.value;
+
+ this.fire('input', {value: this.value});
+ }
+
+ private onFocus() {
+ this.focused = true;
+ this.onCursorPositionChange();
+ }
+
+ private onBlur() {
+ this.focused = false;
+ this.onCursorPositionChange();
+ }
+
+ private handleKeyUp() {
+ this.onCursorPositionChange();
+ }
+
+ private handleMouseUp() {
+ this.onCursorPositionChange();
+ }
+
+ private fire<T>(type: string, detail?: T) {
+ this.dispatchEvent(
+ new CustomEvent(type, {detail, bubbles: true, composed: true})
+ );
+ }
+
+ private onCursorPositionChange() {
+ const cursorPosition = this.getCursorPosition();
+ this.fire('cursorPositionChange', {position: cursorPosition});
+ }
+
+ public getCursorPosition() {
+ return this.editableTextAreaElement?.selectionStart ?? -1;
+ }
+
+ public async getCursorPositionAsync() {
+ const editableTextAreaElement = await this.editableTextArea;
+ return editableTextAreaElement?.selectionStart ?? -1;
+ }
+
+ private updateMirror() {
+ if (!this.editableTextAreaElement) return;
+ this.tokens = this.constrain(
+ this.tokenize(this.editableTextAreaElement.value)
+ );
+ }
+
+ private tokenize(val: string): string[] {
+ return val
+ ? val
+ .replace(/&/g, '&')
+ .replace(/"/g, '"')
+ .replace(/'/g, ''')
+ .replace(/</g, '<')
+ .replace(/>/g, '>')
+ .split('\n')
+ : [''];
+ }
+
+ private constrain(tokens: string[]): string[] {
+ let result = tokens.slice();
+ if (this.maxRows > 0 && result.length > this.maxRows) {
+ result = result.slice(0, this.maxRows);
+ }
+ while (this.rows > 0 && result.length < this.rows) {
+ result.push('');
+ }
+ return result;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'gr-autogrow-textarea': GrAutogrowTextarea;
+ }
+ interface HTMLElementEventMap {
+ // prettier-ignore
+ 'cursorPositionChange': CustomEvent<CursorPositionChangeEventDetail>;
+ }
+}
diff --git a/polygerrit-ui/app/elements/shared/gr-autogrow-textarea/gr-autogrow-textarea_test.ts b/polygerrit-ui/app/elements/shared/gr-autogrow-textarea/gr-autogrow-textarea_test.ts
new file mode 100644
index 0000000..9b33189
--- /dev/null
+++ b/polygerrit-ui/app/elements/shared/gr-autogrow-textarea/gr-autogrow-textarea_test.ts
@@ -0,0 +1,46 @@
+/**
+ * @license
+ * Copyright 2025 Google LLC
+ * SPDX-License-Identifier: Apache-2.0
+ */
+import '../../../test/common-test-setup';
+import {assert, fixture, html} from '@open-wc/testing';
+import {GrAutogrowTextarea} from './gr-autogrow-textarea';
+import './gr-autogrow-textarea';
+
+suite('gr-autogrow-textarea tests', () => {
+ let element: GrAutogrowTextarea;
+
+ setup(async () => {
+ element = await fixture(
+ html`<gr-autogrow-textarea></gr-autogrow-textarea>`
+ );
+ });
+
+ test('render', async () => {
+ // prettier and shadowDom string disagree about wrapping in <p> tag.
+ assert.shadowDom.equal(
+ element,
+ /* prettier-ignore */ /* HTML */ `
+ <div
+ aria-hidden="true"
+ class="mirror-text"
+ id="mirror"
+ >
+ </div>
+ <div class="textarea-container">
+ <textarea
+ aria-disabled="false"
+ aria-multiline="true"
+ autocapitalize=""
+ autocomplete="off"
+ class="editableTextArea"
+ rows="1"
+ spellcheck="true"
+ >
+ </textarea>
+ </div>
+ `
+ );
+ });
+});
diff --git a/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.ts b/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.ts
index ab04d00..c011476 100644
--- a/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.ts
+++ b/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog.ts
@@ -6,12 +6,11 @@
import '../gr-dialog/gr-dialog';
import {css, html, LitElement} from 'lit';
import {customElement, property, query} from 'lit/decorators.js';
-import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
-import {IronAutogrowTextareaElement} from '@polymer/iron-autogrow-textarea';
+import '../gr-autogrow-textarea/gr-autogrow-textarea';
import {sharedStyles} from '../../../styles/shared-styles';
import {assertIsDefined} from '../../../utils/common-util';
-import {BindValueChangeEvent} from '../../../types/events';
import {fireNoBubble} from '../../../utils/event-util';
+import {GrAutogrowTextarea} from '../gr-autogrow-textarea/gr-autogrow-textarea';
declare global {
interface HTMLElementTagNameMap {
@@ -34,7 +33,7 @@
*/
@query('#messageInput')
- messageInput?: IronAutogrowTextareaElement;
+ messageInput?: GrAutogrowTextarea;
@property({type: String})
message = '';
@@ -63,7 +62,7 @@
display: block;
width: 100%;
}
- iron-autogrow-textarea {
+ gr-autogrow-textarea {
font-family: var(--monospace-font-family);
font-size: var(--font-size-mono);
line-height: var(--line-height-mono);
@@ -87,23 +86,24 @@
circumstances.
</p>
<label for="messageInput">Enter comment delete reason</label>
- <iron-autogrow-textarea
+ <gr-autogrow-textarea
id="messageInput"
class="message"
autocomplete="on"
placeholder="<Insert reasoning here>"
- .bindValue=${this.message}
- @bind-value-changed=${(e: BindValueChangeEvent) => {
- this.message = e.detail.value ?? '';
+ .value=${this.message}
+ @input=${(e: InputEvent) => {
+ const value = (e.target as GrAutogrowTextarea).value ?? '';
+ this.message = value;
}}
- ></iron-autogrow-textarea>
+ ></gr-autogrow-textarea>
</div>
</gr-dialog>`;
}
resetFocus() {
assertIsDefined(this.messageInput, 'messageInput');
- this.messageInput.textarea.focus();
+ this.messageInput.focus();
}
private handleConfirmTap(e: Event) {
diff --git a/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog_test.ts b/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog_test.ts
index ac041586..366edbd 100644
--- a/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-confirm-delete-comment-dialog/gr-confirm-delete-comment-dialog_test.ts
@@ -34,14 +34,13 @@
circumstances.
</p>
<label for="messageInput"> Enter comment delete reason </label>
- <iron-autogrow-textarea
- aria-disabled="false"
+ <gr-autogrow-textarea
autocomplete="on"
class="message"
id="messageInput"
placeholder="<Insert reasoning here>"
>
- </iron-autogrow-textarea>
+ </gr-autogrow-textarea>
</div>
</gr-dialog>
`
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.ts b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.ts
index 00b67f4..d490423 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.ts
+++ b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content.ts
@@ -3,7 +3,7 @@
* Copyright 2016 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
-import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
+import '../gr-autogrow-textarea/gr-autogrow-textarea';
import '../../../styles/shared-styles';
import '../gr-button/gr-button';
import '../gr-icon/gr-icon';
@@ -17,7 +17,6 @@
import {getAppContext} from '../../../services/app-context';
import {debounce, DelayedTask} from '../../../utils/async-util';
import {assertIsDefined} from '../../../utils/common-util';
-import {IronAutogrowTextareaElement} from '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
import {Interaction} from '../../../constants/reporting';
import {html, LitElement} from 'lit';
import {customElement, property, query, state} from 'lit/decorators.js';
@@ -25,7 +24,6 @@
import {css} from 'lit';
import {PropertyValues} from 'lit';
import {
- BindValueChangeEvent,
EditableContentSaveEvent,
ValueChangedEvent,
} from '../../../types/events';
@@ -52,6 +50,7 @@
FormattingError,
} from '../../../utils/commit-message-formatter-util';
import {modalStyles} from '../../../styles/gr-modal-styles';
+import {GrAutogrowTextarea} from '../gr-autogrow-textarea/gr-autogrow-textarea';
const RESTORED_MESSAGE = 'Content restored from a previous edit.';
const STORAGE_DEBOUNCE_INTERVAL_MS = 400;
@@ -76,8 +75,8 @@
*/
@customElement('gr-editable-content')
export class GrEditableContent extends LitElement {
- @query('iron-autogrow-textarea')
- private textarea?: IronAutogrowTextareaElement;
+ @query('gr-autogrow-textarea')
+ private textarea?: GrAutogrowTextarea;
@query('#uploaderConfirmDialog')
private readonly uploaderConfirmDialog?: HTMLDialogElement;
@@ -221,7 +220,7 @@
:host {
display: block;
}
- :host([disabled]) iron-autogrow-textarea {
+ :host([disabled]) gr-autogrow-textarea {
opacity: 0.5;
}
.viewer {
@@ -236,15 +235,15 @@
max-height: var(--collapsed-max-height, 300px);
overflow: hidden;
}
- .editor iron-autogrow-textarea,
+ .editor gr-autogrow-textarea,
.viewer {
min-height: 100px;
}
- .editor iron-autogrow-textarea {
+ .editor gr-autogrow-textarea {
background-color: var(--view-background-color);
width: 100%;
display: block;
- --iron-autogrow-textarea_-_padding: var(--spacing-m);
+ --gr-autogrow-textarea-padding: var(--spacing-m);
}
.editButtons {
display: flex;
@@ -338,14 +337,15 @@
return html`
<div class="editor">
<div>
- <iron-autogrow-textarea
+ <gr-autogrow-textarea
autocomplete="on"
- .bindValue=${this.newContent}
+ .value=${this.newContent}
?disabled=${this.disabled}
- @bind-value-changed=${(e: BindValueChangeEvent) => {
- this.newContent = e.detail.value ?? '';
+ @input=${(e: InputEvent) => {
+ const value = (e.target as GrAutogrowTextarea).value ?? '';
+ this.newContent = value;
}}
- ></iron-autogrow-textarea>
+ ></gr-autogrow-textarea>
</div>
</div>
`;
@@ -488,7 +488,7 @@
}
focusTextarea() {
- this.textarea?.textarea.focus();
+ this.textarea?.focus();
}
/**
@@ -693,7 +693,7 @@
handleFormat(e: Event) {
e.preventDefault();
- const textarea = this.textarea?.textarea;
+ const textarea = this.textarea?.nativeElement;
if (!textarea) return;
// If we have lastFormattedContent, we're undoing
@@ -757,7 +757,7 @@
}
private getCurrentCursorLine(): number {
- const textarea = this.textarea?.textarea;
+ const textarea = this.textarea?.nativeElement;
if (!textarea) return -1;
// Calculate which line the cursor is on
diff --git a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.ts b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.ts
index c0c9938..60cfc34 100644
--- a/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-editable-content/gr-editable-content_test.ts
@@ -22,8 +22,8 @@
RevisionPatchSetNum,
} from '../../../api/rest-api';
import {changeViewModelToken} from '../../../models/views/change';
-import {IronAutogrowTextareaElement} from '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
import {GrDialog} from '../gr-dialog/gr-dialog';
+import {GrAutogrowTextarea} from '../gr-autogrow-textarea/gr-autogrow-textarea';
const emails = [
{
@@ -428,10 +428,10 @@
);
element.newContent = 'line1\nline2 \nline3';
- const textarea = queryAndAssert<IronAutogrowTextareaElement>(
+ const textarea = queryAndAssert<GrAutogrowTextarea>(
element,
- 'iron-autogrow-textarea'
- ).textarea;
+ 'gr-autogrow-textarea'
+ ).nativeElement!;
textarea.setSelectionRange(7, 7); // Position cursor after "line2"
await element.updateComplete;
@@ -451,10 +451,10 @@
);
element.newContent = 'line1 \nline2 \nline3 ';
- const textarea = queryAndAssert<IronAutogrowTextareaElement>(
+ const textarea = queryAndAssert<GrAutogrowTextarea>(
element,
- 'iron-autogrow-textarea'
- ).textarea;
+ 'gr-autogrow-textarea'
+ ).nativeElement!;
textarea.setSelectionRange(7, 7); // Position cursor after "line2"
await element.updateComplete;
diff --git a/polygerrit-ui/app/elements/shared/gr-suggestion-textarea/gr-suggestion-textarea.ts b/polygerrit-ui/app/elements/shared/gr-suggestion-textarea/gr-suggestion-textarea.ts
index 17461c7..ac87d07 100644
--- a/polygerrit-ui/app/elements/shared/gr-suggestion-textarea/gr-suggestion-textarea.ts
+++ b/polygerrit-ui/app/elements/shared/gr-suggestion-textarea/gr-suggestion-textarea.ts
@@ -5,7 +5,6 @@
*/
import '../gr-autocomplete-dropdown/gr-autocomplete-dropdown';
import '../gr-cursor-manager/gr-cursor-manager';
-import '@polymer/iron-autogrow-textarea/iron-autogrow-textarea';
import '../../../styles/shared-styles';
import '../../../embed/gr-textarea';
import {getAppContext} from '../../../services/app-context';
@@ -252,7 +251,6 @@
--text-default: var(--primary-text-color);
--text-disabled: var(--deemphasized-text-color);
--text-secondary: var(--deemphasized-text-color);
- --iron-autogrow-textarea_-_padding: var(--spacing-s);
}
#hiddenText #emojiSuggestions {
visibility: visible;
diff --git a/polygerrit-ui/app/package.json b/polygerrit-ui/app/package.json
index e136ae2..e327117 100644
--- a/polygerrit-ui/app/package.json
+++ b/polygerrit-ui/app/package.json
@@ -7,7 +7,6 @@
"@polymer/decorators": "^3.0.0",
"@polymer/font-roboto-local": "^3.0.2",
"@polymer/iron-a11y-announcer": "^3.2.0",
- "@polymer/iron-autogrow-textarea": "^3.0.3",
"@polymer/iron-input": "^3.0.1",
"@polymer/paper-button": "^3.0.1",
"@polymer/paper-input": "^3.2.1",
diff --git a/polygerrit-ui/app/styles/form-styles.ts b/polygerrit-ui/app/styles/form-styles.ts
index 47f610e03..1b9d3a4 100644
--- a/polygerrit-ui/app/styles/form-styles.ts
+++ b/polygerrit-ui/app/styles/form-styles.ts
@@ -18,18 +18,18 @@
}
/* prettier formatter removes semi-colons after css mixins. */
/* prettier-ignore */
- iron-autogrow-textarea {
+ gr-autogrow-textarea {
background-color: inherit;
color: var(--primary-text-color);
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
padding: 0;
box-sizing: border-box;
- /* iron-autogrow-textarea has a "-webkit-appearance: textarea" :host
+ /* gr-autogrow-textarea has a "-webkit-appearance: textarea" :host
css rule, which prevents overriding the border color. Clear that. */
-webkit-appearance: none;
- --iron-autogrow-textarea_-_box-sizing: border-box;
- --iron-autogrow-textarea_-_padding: var(--spacing-s);
+ --gr-autogrow-textarea-box-sizing: border-box;
+ --gr-autogrow-textarea-padding: var(--spacing-s);
}
input,
textarea,
diff --git a/polygerrit-ui/app/styles/gr-form-styles.ts b/polygerrit-ui/app/styles/gr-form-styles.ts
index 283dadc..58a1c74 100644
--- a/polygerrit-ui/app/styles/gr-form-styles.ts
+++ b/polygerrit-ui/app/styles/gr-form-styles.ts
@@ -82,7 +82,7 @@
.gr-form-styles td:last-child gr-button {
width: 100%;
}
- .gr-form-styles iron-autogrow-textarea {
+ .gr-form-styles gr-autogrow-textarea {
height: auto;
min-height: 4em;
}
diff --git a/polygerrit-ui/app/yarn.lock b/polygerrit-ui/app/yarn.lock
index 2b0477f..4ebb3fe 100644
--- a/polygerrit-ui/app/yarn.lock
+++ b/polygerrit-ui/app/yarn.lock
@@ -68,7 +68,7 @@
dependencies:
"@polymer/polymer" "^3.0.0"
-"@polymer/iron-autogrow-textarea@^3.0.0-pre.26", "@polymer/iron-autogrow-textarea@^3.0.3":
+"@polymer/iron-autogrow-textarea@^3.0.0-pre.26":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@polymer/iron-autogrow-textarea/-/iron-autogrow-textarea-3.0.3.tgz#b75dbebc23ce47d428a26156709d4a8a4c05823e"
integrity sha512-5r0VkWrIlm0JIp5E5wlnvkw7slK72lFRZXncmrsLZF+6n1dg2rI8jt7xpFzSmUWrqpcyXwyKaGaDvUjl3j4JLA==
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-rule-editor-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-rule-editor-dark.png
index 77839e2..cfa4162c 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/gr-rule-editor-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-rule-editor-dark.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-rule-editor.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-rule-editor.png
index 6a6f015..134237b 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/gr-rule-editor.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-rule-editor.png
Binary files differ
diff --git a/polygerrit-ui/screenshots/Chromium/baseline/gr-user-suggestion-fix-dark.png b/polygerrit-ui/screenshots/Chromium/baseline/gr-user-suggestion-fix-dark.png
index b8bd9f4..34fca7b 100644
--- a/polygerrit-ui/screenshots/Chromium/baseline/gr-user-suggestion-fix-dark.png
+++ b/polygerrit-ui/screenshots/Chromium/baseline/gr-user-suggestion-fix-dark.png
Binary files differ