From 9a125e3111154c8077237500f609adc30d0bfdc2 Mon Sep 17 00:00:00 2001
From: Danny Morabito
Date: Tue, 25 Mar 2025 19:00:41 +0100
Subject: [PATCH] fix repeat events bug with input and textarea
---
src/components/DateTimeSettings.ts | 11 ++---
src/components/General/Input.ts | 68 +++++++++++++-----------------
src/components/General/Prompt.ts | 8 ++--
src/components/General/Textarea.ts | 9 +---
src/components/Header.ts | 54 +++++++++++++-----------
src/components/InitialSetup.ts | 29 +++++++------
src/routes/Arbor/NewPost.ts | 7 +--
src/routes/Arbor/NewTopic.ts | 15 ++++---
src/routes/Settings.ts | 22 +++++-----
9 files changed, 109 insertions(+), 114 deletions(-)
diff --git a/src/components/DateTimeSettings.ts b/src/components/DateTimeSettings.ts
index 2bebba0..0910025 100644
--- a/src/components/DateTimeSettings.ts
+++ b/src/components/DateTimeSettings.ts
@@ -1,9 +1,10 @@
import { StyledToggle } from '@/components/General/Toggle';
+import { ArxInputChangeEvent, type StyledInput } from '@components/General/Input';
import { LitElement, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
-import '@components/General/Input';
import '@components/General/Fieldset';
+import '@components/General/Input';
import '@components/General/Select';
interface DateTimeFormatOptions {
@@ -71,10 +72,10 @@ export class DateTimeSettings extends LitElement {
}
private handleChange(key: keyof DateTimeFormatOptions, e: Event) {
- const target = e.target as HTMLSelectElement | HTMLInputElement | StyledToggle;
- let value: string | boolean | undefined = target.value;
+ let value = e instanceof ArxInputChangeEvent ? e.detail.value : (e.target as HTMLSelectElement).value;
+ const target = e.target as StyledInput | HTMLSelectElement | HTMLInputElement | StyledToggle;
- if (key === 'hour12' && target instanceof StyledToggle) value = target.checked;
+ if (key === 'hour12' && target instanceof StyledToggle) value = target.checked.toString();
this.options = {
...this.options,
@@ -126,7 +127,7 @@ export class DateTimeSettings extends LitElement {
label="Locale"
type="text"
.value=${this.options.locale}
- @input=${(e: Event) => this.handleChange('locale', e)}
+ @change=${(e: Event) => this.handleChange('locale', e)}
>
diff --git a/src/components/General/Input.ts b/src/components/General/Input.ts
index 2936518..3b20e82 100644
--- a/src/components/General/Input.ts
+++ b/src/components/General/Input.ts
@@ -1,17 +1,35 @@
-import { LitElement, css, html } from 'lit';
-import { customElement, property } from 'lit/decorators.js';
+import { LitElement, type PropertyValues, css, html } from 'lit';
+import { customElement, property, query, state } from 'lit/decorators.js';
import { when } from 'lit/directives/when.js';
+export class ArxInputChangeEvent extends CustomEvent<{ value: string }> {
+ constructor(value: string) {
+ super('change', { detail: { value } });
+ }
+}
+
@customElement('arx-input')
export class StyledInput extends LitElement {
@property() placeholder = '';
@property() value = '';
@property({ type: Boolean }) disabled = false;
- @property() type = 'text';
+ @property() type: 'text' | 'number' | 'password' = 'text';
@property() name = '';
@property({ type: Boolean }) required = false;
@property() label = '';
+ @query('input') private _input!: HTMLInputElement;
+
+ @state() private _value = '';
+
+ protected override firstUpdated(_changedProperties: PropertyValues): void {
+ this._value = this.value;
+ }
+
+ protected override updated(changedProperties: PropertyValues): void {
+ if (changedProperties.has('value')) this._value = this.value;
+ }
+
static override styles = css`
:host {
display: inline-block;
@@ -98,7 +116,7 @@ export class StyledInput extends LitElement {
return html`
${when(this.label, () => html``)}
`
diff --git a/src/components/General/Textarea.ts b/src/components/General/Textarea.ts
index 93e2791..e799a8f 100644
--- a/src/components/General/Textarea.ts
+++ b/src/components/General/Textarea.ts
@@ -1,6 +1,7 @@
import { LitElement, css, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { when } from 'lit/directives/when.js';
+import { ArxInputChangeEvent } from './Input';
@customElement('arx-textarea')
export class StyledTextarea extends LitElement {
@@ -201,12 +202,6 @@ export class StyledTextarea extends LitElement {
private _handleInput(e: InputEvent) {
const textarea = e.target as HTMLTextAreaElement;
this.value = textarea.value;
- this.dispatchEvent(
- new CustomEvent('input', {
- detail: { value: this.value },
- bubbles: true,
- composed: true,
- }),
- );
+ this.dispatchEvent(new ArxInputChangeEvent(this.value));
}
}
diff --git a/src/components/Header.ts b/src/components/Header.ts
index 4834ab3..e8745c9 100644
--- a/src/components/Header.ts
+++ b/src/components/Header.ts
@@ -1,4 +1,5 @@
import { ndk } from '@/ndk';
+import type { ArxInputChangeEvent } from '@components/General/Input';
import type { NDKEvent } from '@nostr-dev-kit/ndk';
import * as nip19 from '@nostr/tools/nip19';
import { LitElement, css, html } from 'lit';
@@ -8,8 +9,8 @@ import { keyed } from 'lit/directives/keyed.js';
import { map } from 'lit/directives/map.js';
import { when } from 'lit/directives/when.js';
-import '@components/HeaderSugestion';
import '@components/General/Input';
+import '@components/HeaderSugestion';
@customElement('arx-header')
export class Header extends LitElement {
@@ -49,10 +50,10 @@ export class Header extends LitElement {
.nav-buttons {
display: flex;
gap: var(--space-xs, 0.5rem);
- padding-right: var(--space-xs, 0.5rem);
+ padding: 0 var(--space-xs, 0.5rem);
}
- .nav-buttons button {
+ button {
text-decoration: none;
color: var(--color-primary-content);
background: oklch(from var(--color-primary-content) l c h / 0.1);
@@ -66,23 +67,21 @@ export class Header extends LitElement {
align-items: center;
justify-content: center;
transition: all 0.2s ease;
- }
+ &:hover {
+ background: oklch(from var(--color-primary-content) l c h / 0.2);
+ transform: translateY(-2px);
+ box-shadow: calc(var(--depth) * 2px) calc(var(--depth) * 2px)
+ calc(var(--depth) * 4px)
+ oklch(from var(--color-base-content) l c h / 0.15);
+ }
+ &:active {
+ transform: translateY(1px);
+ }
- .nav-buttons button:hover {
- background: oklch(from var(--color-primary-content) l c h / 0.2);
- transform: translateY(-2px);
- box-shadow: calc(var(--depth) * 2px) calc(var(--depth) * 2px)
- calc(var(--depth) * 4px)
- oklch(from var(--color-base-content) l c h / 0.15);
- }
-
- .nav-buttons button:active {
- transform: translateY(1px);
- }
-
- .nav-buttons button.disabled {
- opacity: 0.5;
- pointer-events: none;
+ &.disabled {
+ opacity: 0.5;
+ pointer-events: none;
+ }
}
.search-container {
@@ -153,7 +152,7 @@ export class Header extends LitElement {
placeholder=${this.url}
@keyup=${this._handleSearch}
@focus=${this._handleFocus}
- @input=${this._handleInput}
+ @change=${this._handleInput}
>
${when(
this.showSuggestions,
@@ -175,16 +174,25 @@ export class Header extends LitElement {
`,
)}
+
+
+
`;
}
+ private _goToWallet() {
+ window.location.hash = 'wallet';
+ }
+
private _handleFocus() {
this.showSuggestions = true;
}
- private _handleInput(e: InputEvent) {
- this.searchQuery = (e.target as HTMLInputElement).value;
+ private _handleInput(e: ArxInputChangeEvent) {
+ this.searchQuery = e.detail.value;
if (this._debounceTimeout) {
clearTimeout(this._debounceTimeout);
}
@@ -245,8 +253,6 @@ export class Header extends LitElement {
private _handleSearch(e: KeyboardEvent) {
if (e.key !== 'Enter') return;
- const target = e.target as HTMLInputElement;
- this.searchQuery = target.value;
this.showSuggestions = false;
if (this.searchQuery.startsWith('npub1')) {
diff --git a/src/components/InitialSetup.ts b/src/components/InitialSetup.ts
index a947959..06210c9 100644
--- a/src/components/InitialSetup.ts
+++ b/src/components/InitialSetup.ts
@@ -1,4 +1,5 @@
import { ndk, setSigner } from '@/ndk';
+import type { ArxInputChangeEvent } from '@components/General/Input';
import { animate } from '@lit-labs/motion';
import { randomBytes } from '@noble/ciphers/webcrypto';
import { NDKEvent, NDKKind, NDKPrivateKeySigner } from '@nostr-dev-kit/ndk';
@@ -10,10 +11,10 @@ import { encodeBase64 } from '@std/encoding/base64';
import { LitElement, css, html } from 'lit';
import { customElement, state } from 'lit/decorators.js';
-import '@components/LoadingView';
import '@components/General/Button';
-import '@components/General/Input';
import '@components/General/Fieldset';
+import '@components/General/Input';
+import '@components/LoadingView';
@customElement('arx-initial-setup')
export class InitialSetup extends LitElement {
@@ -201,8 +202,8 @@ export class InitialSetup extends LitElement {
}, 300);
}
- private onSeedPhraseInput(event: Event) {
- this.seedPhrase = (event.target as HTMLInputElement).value;
+ private onSeedPhraseInput(event: ArxInputChangeEvent) {
+ this.seedPhrase = event.detail.value;
}
private generateSeedPhrase() {
@@ -300,7 +301,7 @@ export class InitialSetup extends LitElement {