<!-- GENERATED by scripts/build-llms.mjs from llms/data.md — do not edit this file. -->

# `lr-condition-builder`

- **Import** `import '@aceshooting/lyra-ui/components/lr-condition-builder.js';` (stable tag alias; registers the tag)
- **Class** `LyraConditionBuilder`, also available unregistered from `@aceshooting/lyra-ui/components/data/condition-builder/condition-builder.class.js`
- **Family** `components/data/` — see `llms/index.md` for its siblings
- **Status** `stable` since `9.0.0` — see the maturity and deprecation policy in `llms/shared.md`
- **Release history** [CHANGELOG.md](../../CHANGELOG.md); family-wide breaking-change summaries: [llms-full.txt](../../llms-full.txt)
- **Deprecations** none
- **Optional peers** none
- **Themeable via** 10 parts, 0 custom properties — see this component's own `@csspart`/`@cssprop` list below
- **Library-wide behavior** (events, form association, `locale`/`strings`, tokens, TS types): `llms/shared.md`

---

## `lr-condition-builder`

Composable flat condition builder for tabular or dashboard data: condition rows combined with an
AND/OR combinator, distinct by name and model from `lr-graph-query-builder`.

A field or operator select choice updates the builder once and emits one `lr-input` carrying the
complete `{ value: ConditionBuilderValue }` snapshot. Child native `input`/`change`, prefixed value
aliases and listbox show/hide lifecycle events remain inside those pickers. Programmatic `value`
assignments remain silent.

**9.0 migration:** `lr-query-builder` / `LyraQueryBuilder` / `QueryBuilder*` were renamed without
aliases to `lr-condition-builder` / `LyraConditionBuilder` / `ConditionBuilder*`. Update the tag,
granular import path, class/type imports, selectors, and framework bindings together.

**Properties:** clone-owned readonly `fields`, clone-owned readonly `value`, and `disabled`.
Structured inputs are bounded (200 fields and conditions, 500 options per field, 256 characters
per string), malformed records and blank field names/option values/condition ids are skipped,
duplicates use the first valid record, and unknown closed-vocabulary values normalize to their
documented fallback. A retained, known operator and its value payload are not rewritten merely
because they disagree with the current field metadata. That preservation also applies when fields
arrive after `value` or their operator/type definition later changes.
Returned arrays and records are frozen snapshots, so mutate-and-reuse does not bypass Lit's
assignment boundary. Create and reassign a new `fields` array or `value` record after changes.

`validationIssues` is a live frozen list of `{ conditionId, code }` rows, where `code` is
`field-unavailable`, `operator-not-allowed`, `operator-arity`, or `value-type`.
`invalidConditionIds` projects their ids in model order, `checkValidity()` tests the current model,
and `reportValidity()` additionally focuses the first affected field/operator/value control. The
root group and every condition render explicit `aria-invalid="true"|"false"`. A non-finite
controlled number is therefore preserved and reported as `value-type`; numeric text entered through
the UI still becomes unset when parsing overflows. Check validity before sending restored data to a
backend, particularly because JSON serializes non-finite numbers as `null`.

`ConditionBuilderField.min`/`max` accept finite numbers for `type: 'number'` and bounded strings for
`type: 'date'`; `step` accepts a positive finite number for numeric fields. These constraints are
forwarded to the composed `lr-input`/`lr-date-input`. They are omitted for other field types, and
leaving all three unset preserves the previous unconstrained controls.

**Methods:** `addCondition()` appends a condition using the first available field and emits a frozen
`lr-add-condition`; it is a no-op while disabled or when there are no fields. `checkValidity()` and
`reportValidity()` validate without changing `value`.
`removeCondition(id)` removes the matching condition and emits `lr-remove-condition`
(`detail: { conditionId }`); it is a
no-op while disabled or when the id is absent.

**Events:** `lr-input`, `lr-add-condition`, `lr-remove-condition`; all details and nested model
snapshots are readonly and frozen. **CSS parts:** `base`, `conditions`,
`condition`, `field-select`, `operator-select`, `value`, `combinator`, `add-button`,
`remove-button`, `empty`.

`conditions` is a semantic list and every `condition` is a list item, so repeated Field/Operator/
Value labels retain a row relationship in the accessibility tree. The localized, indexed remove
name continues to identify each row's destructive action.

At allocations of 320px or less, each condition stacks its composed field/operator/value controls
into one column. Long field labels and localized operator text remain contained and ellipsize inside
the nested `lr-select` triggers in both LTR and RTL; they do not widen the host or document.
