chore: consolidate platform split checks
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useId, useMemo, useRef, useState } from "react";
|
||||
import { i18nMessage } from "../../i18n/LanguageContext";import { useEffect, useId, useMemo, useRef, useState } from "react";
|
||||
import type { CSSProperties, KeyboardEvent } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import Button from "../Button";
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
isValidEmailAddress,
|
||||
normalizeEmailAddress,
|
||||
parseMailboxAddressText,
|
||||
type MailboxAddress
|
||||
} from "../../utils/emailAddresses";
|
||||
type MailboxAddress } from
|
||||
"../../utils/emailAddresses";
|
||||
|
||||
type EmailAddressInputProps = {
|
||||
value: MailboxAddress[];
|
||||
@@ -35,10 +35,10 @@ export default function EmailAddressInput({
|
||||
allowMultiple = true,
|
||||
clearOnAdd = false,
|
||||
disabled = false,
|
||||
addLabel = "Add",
|
||||
namePlaceholder = "Name",
|
||||
addLabel = "i18n:govoplan-core.add.61cc55aa",
|
||||
namePlaceholder = "i18n:govoplan-core.name.709a2322",
|
||||
emailPlaceholder = "email@example.org",
|
||||
emptyText = "No address added yet.",
|
||||
emptyText = "i18n:govoplan-core.no_address_added_yet.809c4247",
|
||||
compact = false,
|
||||
showAddButton
|
||||
}: EmailAddressInputProps) {
|
||||
@@ -57,9 +57,9 @@ export default function EmailAddressInput({
|
||||
const filteredSuggestions = useMemo(() => {
|
||||
const query = entryText.trim().toLowerCase();
|
||||
if (!query) return normalizedSuggestions.slice(0, 6);
|
||||
return normalizedSuggestions
|
||||
.filter((item) => `${item.name ?? ""} ${item.email}`.toLowerCase().includes(query))
|
||||
.slice(0, 6);
|
||||
return normalizedSuggestions.
|
||||
filter((item) => `${item.name ?? ""} ${item.email}`.toLowerCase().includes(query)).
|
||||
slice(0, 6);
|
||||
}, [entryText, normalizedSuggestions]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -103,17 +103,17 @@ export default function EmailAddressInput({
|
||||
function commitAddress(candidate: MailboxAddress | null, sourceText = "") {
|
||||
if (disabled) return false;
|
||||
if (!candidate?.email) {
|
||||
setError(sourceText ? "Use a valid address such as Name <email@example.org>." : "Enter an email address first.");
|
||||
setError(sourceText ? "i18n:govoplan-core.use_a_valid_address_such_as_name_email_example_o.39cdbc3c" : "i18n:govoplan-core.enter_an_email_address_first.6d55dfd1");
|
||||
return false;
|
||||
}
|
||||
|
||||
const normalized = normalizeEmailAddress(candidate);
|
||||
if (!isValidEmailAddress(normalized.email)) {
|
||||
setError("Enter a valid email address.");
|
||||
setError("i18n:govoplan-core.enter_a_valid_email_address.2e09edea");
|
||||
return false;
|
||||
}
|
||||
if (allowMultiple && normalizedValue.some((address) => address.email === normalized.email)) {
|
||||
setError("This address is already listed.");
|
||||
setError("i18n:govoplan-core.this_address_is_already_listed.0f6d0ff2");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -166,19 +166,19 @@ export default function EmailAddressInput({
|
||||
aria-labelledby={`${inputId}-dialog-title`}
|
||||
onKeyDown={(event) => {
|
||||
if (event.key === "Escape") setDialogOpen(false);
|
||||
}}
|
||||
>
|
||||
<h4 id={`${inputId}-dialog-title`}>Add address</h4>
|
||||
}}>
|
||||
|
||||
<h4 id={`${inputId}-dialog-title`}>i18n:govoplan-core.add_address.a71075c4</h4>
|
||||
<label>
|
||||
<span>Name</span>
|
||||
<span>i18n:govoplan-core.name.709a2322</span>
|
||||
<input value={dialogName} onChange={(event) => setDialogName(event.target.value)} placeholder={namePlaceholder} autoFocus />
|
||||
</label>
|
||||
<label>
|
||||
<span>Email address</span>
|
||||
<span>i18n:govoplan-core.email_address.c94d3175</span>
|
||||
<input value={dialogEmail} onChange={(event) => setDialogEmail(event.target.value)} placeholder={emailPlaceholder} inputMode="email" />
|
||||
</label>
|
||||
<div className="button-row compact-actions">
|
||||
<Button type="button" onClick={() => setDialogOpen(false)}>Cancel</Button>
|
||||
<Button type="button" onClick={() => setDialogOpen(false)}>i18n:govoplan-core.cancel.77dfd213</Button>
|
||||
<Button type="button" variant="primary" onClick={commitDialogAddress}>{addLabel}</Button>
|
||||
</div>
|
||||
</div>,
|
||||
@@ -193,54 +193,54 @@ export default function EmailAddressInput({
|
||||
{normalizedValue.map((address) => {
|
||||
const valid = isValidEmailAddress(address.email);
|
||||
return (
|
||||
<span className={`email-chip ${valid ? "" : "invalid"}`} key={address.email} title={valid ? address.email : "Invalid email address"}>
|
||||
<span className={`email-chip ${valid ? "" : "invalid"}`} key={address.email} title={valid ? address.email : "i18n:govoplan-core.invalid_email_address.9e4ee6d7"}>
|
||||
<span className="email-chip-main">{addressDisplayName(address)}</span>
|
||||
{address.name && <span className="email-chip-address">{address.email}</span>}
|
||||
{!disabled && (
|
||||
<button type="button" className="email-chip-remove" aria-label={`Remove ${address.email}`} onClick={() => removeAddress(address.email)}>
|
||||
{!disabled &&
|
||||
<button type="button" className="email-chip-remove" aria-label={i18nMessage("i18n:govoplan-core.remove_value.a2d40d33", { value0: address.email })} onClick={() => removeAddress(address.email)}>
|
||||
×
|
||||
</button>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
</span>);
|
||||
|
||||
})}
|
||||
</div>
|
||||
{!disabled && (
|
||||
<>
|
||||
{!disabled &&
|
||||
<>
|
||||
<textarea
|
||||
id={inputId}
|
||||
className="email-address-textarea"
|
||||
rows={1}
|
||||
value={entryText}
|
||||
onChange={(event) => {
|
||||
setEntryText(event.target.value);
|
||||
setError("");
|
||||
}}
|
||||
onKeyDown={handleTextKeyDown}
|
||||
placeholder={`${namePlaceholder} <${emailPlaceholder}>`}
|
||||
aria-label="Type a name and email address, then press Enter"
|
||||
/>
|
||||
{canUseAddButton && (
|
||||
<button ref={addButtonRef} type="button" className="email-address-plus" aria-label="Open address form" title="Add address with form" onClick={() => setDialogOpen((open) => !open)}>
|
||||
id={inputId}
|
||||
className="email-address-textarea"
|
||||
rows={1}
|
||||
value={entryText}
|
||||
onChange={(event) => {
|
||||
setEntryText(event.target.value);
|
||||
setError("");
|
||||
}}
|
||||
onKeyDown={handleTextKeyDown}
|
||||
placeholder={i18nMessage("i18n:govoplan-core.value_value.27085f09", { value0: namePlaceholder, value1: emailPlaceholder })}
|
||||
aria-label="i18n:govoplan-core.type_a_name_and_email_address_then_press_enter.7c8d43f0" />
|
||||
|
||||
{canUseAddButton &&
|
||||
<button ref={addButtonRef} type="button" className="email-address-plus" aria-label="i18n:govoplan-core.open_address_form.f8ee560f" title="i18n:govoplan-core.add_address_with_form.13b3b3e7" onClick={() => setDialogOpen((open) => !open)}>
|
||||
+
|
||||
</button>
|
||||
)}
|
||||
}
|
||||
</>
|
||||
)}
|
||||
}
|
||||
</div>
|
||||
|
||||
{!disabled && filteredSuggestions.length > 0 && entryText.trim() && (
|
||||
<div className="email-address-suggestions" role="listbox" aria-label="Address suggestions">
|
||||
{filteredSuggestions.map((item) => (
|
||||
<button type="button" key={item.email} onClick={() => applySuggestion(item)} role="option">
|
||||
{!disabled && filteredSuggestions.length > 0 && entryText.trim() &&
|
||||
<div className="email-address-suggestions" role="listbox" aria-label="i18n:govoplan-core.address_suggestions.45ba4a20">
|
||||
{filteredSuggestions.map((item) =>
|
||||
<button type="button" key={item.email} onClick={() => applySuggestion(item)} role="option">
|
||||
<span>{addressDisplayName(item)}</span>
|
||||
{item.name && <small>{item.email}</small>}
|
||||
</button>
|
||||
))}
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
}
|
||||
{error && <p className="form-help danger-text">{error}</p>}
|
||||
{addressDialog}
|
||||
</div>
|
||||
);
|
||||
</div>);
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user