---
id: CMP-CRM-ENT-005
title: E-mail List Editor
product_area: crm
module: entities
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
purpose: Lets staff maintain a contact’s ordered e-mail addresses and make one address primary while staying in
  the contact form.
reuse: Used by the E-mail Addresses form adapter in Create Contact and Edit Contact; it edits contact collections
  and provides no organization e-mail contract.
supports:
- CAP-CRM-ENT-005
realises:
- CON-CRM-ENT-001
- CON-CRM-ENT-034
props:
- name: value
  type: ordered e-mail entries
  required: true
  default: none
  meaning: Supplies row keys and e-mail address text; the first committed row is primary.
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- name: onChange
  type: handler receiving replacement collection
  required: true
  default: none
  meaning: Receives additions, removals, edits and primary reordering.
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- name: getError
  type: message lookup by field identifier
  required: true
  default: none
  meaning: Provides per-input validation text.
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- name: currentContactId
  type: record identifier
  required: false
  default: none
  meaning: Excludes the current record from the fixture duplicate lookup.
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- name: onOpenContact
  type: handler receiving record identifier
  required: true
  default: none
  meaning: Opens the record named by a fixture duplicate notice.
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
events:
- name: change
  when: Text changes, blur normalization, Add, Remove or Make Primary occurs.
  payload: The complete ordered replacement collection.
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- name: open contact
  when: Open is activated on the duplicate notice.
  payload: The fixture contact identifier.
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
states:
- state: empty
  experience: A provisional first input appears with no Add or Remove action and a disabled primary star.
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- state: populated
  experience: Committed rows appear in order; the first is primary.
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- state: limit reached
  experience: Add Email is disabled at three committed entries.
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- state: invalid
  experience: The input is marked invalid and its supplied error is an alert.
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- state: fixture duplicate
  experience: The primary row offers a nonblocking notice and an Open action when the mock lookup finds a match.
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
validation:
- BR-CAP-CRM-ENT-005-01
accessibility: Inputs use e-mail mode and primary or numbered accessible names. Remove identifies the address; the
  star has pressed state and a disabled explanation. Errors have alert semantics. Added rows request focus; the
  initial provisional row does not. Keyboard and screen-reader coverage beyond these attributes is unverified.
design_system:
- button
- email input
- preferred star
depends_on: []
implementation: CMI-CRM-ENT-005
acceptance:
- id: AC-CMP-CRM-ENT-005-01
  proved_by: []
  statement: An empty collection shows one input and no Add Email or Remove button.
  level: unit
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- id: AC-CMP-CRM-ENT-005-02
  proved_by: []
  statement: Selecting a secondary row as primary moves it to index zero while preserving row identity.
  level: unit
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- id: AC-CMP-CRM-ENT-005-03
  proved_by: []
  statement: Add Email is disabled at three committed entries.
  level: unit
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- id: AC-CMP-CRM-ENT-005-04
  proved_by: []
  statement: A supplied validation error marks the input invalid and renders alert text.
  level: unit
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
controls: []
evidence:
- react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
  react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
  react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
narrative_sources:
- section: What It Is For
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- section: Where It Is Used
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- section: How It Behaves
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- section: Its Contract
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- section: States
  provenance: observed
  source: react-console:components/contact-editor/collections/email-list-editor.tsx; react-console:components/contact-editor/collections/blank-row.ts;
    react-console:components/contact-editor/fields/preferred-star.tsx; react-console:components/contact-editor/format.ts;
    react-console:components/contact-editor/constants.ts; react-console:components/contact-editor/types.ts; react-console:components/forms/contacts/collection-components.tsx
- section: Accessibility
  provenance: unknown
  source: FND-CRM-ENT-161
- section: Open Design Questions
  provenance: unknown
  source: FND-CRM-ENT-161; FND-CRM-ENT-162; FND-CRM-ENT-163
used_by: []
---

# E-mail List Editor

## What It Is For

Lets staff maintain a contact’s ordered e-mail addresses and make one address primary while staying in the contact form. The ordered e-mail collection and its form adapter provide first-row primary selection, row editing and supplied validation. The local duplicate hint reads fixture contacts; it has no live duplicate or uniqueness request.

## Where It Is Used

Used by the E-mail Addresses form adapter in Create Contact and Edit Contact; it edits contact collections and provides no organization e-mail contract. The shared E-mail Addresses form adapter embeds the list in Create Contact and Edit Contact. The enclosing screen supplies error text and navigation to a duplicate record.

## How It Behaves

An empty collection already presents its first input. The shared blank-row mechanism leaves a still-blank provisional row outside the committed list. The first committed row is primary; choosing another star moves that entire entry to the front without changing its key. Add appends a blank committed row and requests focus, while Remove filters the selected key out. Blur normalizes the address through the shared formatter, and Enter is prevented from submitting the enclosing form. The counter and Add limit use the committed list.

## Its Contract

The caller owns the ordered list, error lookup and navigation. Every edit reports a replacement list, leaving saving and server uniqueness checks to the contact screen. The duplicate notice searches the console’s mock contact data for the normalized primary address; it is not a live uniqueness query. The notice says saving can continue, which describes that advisory interaction rather than a guarantee that the service will accept the record.

## States

Empty: A provisional first input appears with no Add or Remove action and a disabled primary star. Populated: Committed rows appear in order; the first is primary. Limit reached: Add Email is disabled at three committed entries. Invalid: The input is marked invalid and its supplied error is an alert. Fixture duplicate: The primary row offers a nonblocking notice and an Open action when the mock lookup finds a match.

## Accessibility

Inputs use e-mail mode and primary or numbered accessible names. Remove identifies the address; the star has pressed state and a disabled explanation. Errors have alert semantics. Added rows request focus; the initial provisional row does not. Keyboard and screen-reader coverage beyond these attributes is unverified. Accessibility verification is an open obligation recorded in the component accessibility finding.

## Open Design Questions

The recorded interaction is observed implementation, with proposed design intent. Component criteria need complete executable bindings and browser accessibility review. Screen owners must wire the registered components into their designs; this slice records usage without changing those screen contracts.
