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

# `lr-graph-query-builder`

- **Import** `import '@aceshooting/lyra-ui/components/lr-graph-query-builder.js';` (stable tag alias; registers the tag)
- **Class** `LyraGraphQueryBuilder`, also available unregistered from `@aceshooting/lyra-ui/components/data/graph-query-builder/graph-query-builder.class.js`
- **Family** `components/data/` — see `llms/index.md` for its siblings
- **Status** `stable` since `4.1.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** 27 parts, 16 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-graph-query-builder`

Form-associated editor for a typed graph relationship/path query, including entity anchors,
relationship and node-type filters, hop limits, validation, and saved queries.

When the DOM cannot provide `activeElement`, the builder skips focus restoration while chip removal
and saved-query updates continue normally. Each minimum/maximum-hop select choice updates the query
once and emits one `lr-input` with the complete `{ value: GraphQuery }` snapshot. Native value
events, prefixed value aliases and listbox show/hide lifecycle events from those child selects are
contained. Programmatic query assignments remain silent.

The normalized `value` present at the first update is the form reset default. Later property writes
and user edits change only the live query; `form.reset()` restores that initial model, clears
interaction/touched state and the save-name draft, and retains a caller-set custom validity message
like a native control.

Removing a focused relationship/node filter chip moves focus to the adjacent chip, or to that
filter's add picker when no chips remain. `savedQueries` is controlled: when the host applies a
focused accepted `lr-query-delete` notification, focus follows the adjacent saved-query delete
action, or the stable save-name input when the list becomes empty. Updates that did not remove the
focused control never move external focus.

**Properties and getters:** clone-owned frozen `value: GraphQuery`; `customError` (`custom-error`),
`label`, `labels`, `name`, `disabled`, `effectiveDisabled`; clone-owned frozen
`nodeTypeOptions: readonly GraphQueryTypeOption[]`, `relationshipTypeOptions: readonly
GraphQueryTypeOption[]`, and `savedQueries: readonly GraphQuerySavedItem[]`; `hopLimit`, frozen
`errors`, `form`, `validity`, `validationMessage`, and `willValidate`. Type-option values and saved
query ids are nonblank unique first-wins identities; malformed/hostile records are skipped, nested queries
are normalized snapshots, collections are capped at 500 options / 200 saved queries, and strings
at 256 characters. `value.relationshipTypes` and `value.nodeTypes` are each capped at 500 entries.
Create and reassign a new value, options array, or saved-query array after changes; mutating a
previous caller-owned object cannot change the builder's assigned snapshots.

**Methods and form callbacks:** `getForm()`, `focus(options?)`, `blur()`, `click()`,
`checkValidity()`, `reportValidity()`, `setCustomValidity(message)`, `formDisabledCallback(disabled)`,
`formResetCallback()`, and `formStateRestoreCallback(state, mode?)`.

`setCustomValidity(message)` (new in 8.0.0) is the standard channel for a server-side rejection
("no graph is loaded for that tenant") that neither of the control's own constraints can express. A
non-empty `message` raises `customError` and becomes `validationMessage`, so the builder fails
`checkValidity()`, blocks submission and matches `:state(invalid)`; `''` clears it. Clearing
restores the control's own computed validity rather than forcing it valid — a query with no
`startId` stays `valueMissing` — and the custom error survives both intrinsic recomputation (every
field edit) and `form.reset()`, exactly like a native control, where only another
`setCustomValidity('')` clears it. The message is caller-supplied and is used verbatim, never
localized, and it is whole-control state exposed as `errors.base`; intrinsic errors remain keyed
by their field csspart. The start-ID `lr-input` is natively required, matching
the aggregate `valueMissing` constraint. `focus(options?)` and `click()` target the first rendered
field (start/end/hop-limit/direction/save-name, in that order), `blur()` releases whichever nested
owner contains deep focus, and all entry actions are inert while directly or fieldset disabled.

The group is named by a host `aria-label` when present; otherwise `aria-labelledby` points to the
visible label element, so slotted/property/localized label text is also the announced name.

**Events:** all query/model details are readonly frozen snapshots. `lr-validity-change` publishes
effective native validity, including custom errors and own/fieldset validation barring.
`lr-invalid` is a cancelable bubbling/composed alias; vetoing it suppresses the native invalid
default. Run, save, load, and delete share one two-phase contract: cancelable
`lr-before-query-run`, `lr-before-query-save`, `lr-before-query-load`, and
`lr-before-query-delete` requests precede any local effect; non-cancelable `lr-query-run`,
`lr-query-save`, `lr-query-load`, and `lr-query-delete` notifications follow only when accepted.
The matching before/accepted pair reuses one frozen payload: `{ query }` for run,
`{ name, query }` for save, `{ queryId, query }` for load, and `{ queryId }` for delete.
Run validates before its request. Save veto preserves the draft name. Load requests frozen
`{ queryId, query }` before changing `value`, so veto preserves the current query; its accepted event
fires after the new value is applied. Delete remains controlled, so the host removes the accepted
id from `savedQueries`. The full set is `lr-input`, `lr-validity-change`, `lr-invalid`, and those
eight phased action events.

Migration note: veto save in `lr-before-query-save`, not `lr-query-save`; the existing
`lr-query-*` action events are accepted, non-cancelable notifications. **Slots:** `actions`,
`label`, `hint`, `error`. **CSS
parts:** `base`, `label`, `hint`, `error` (the three form-control chrome parts every
form-associated control in this library exposes — see `lr-select`), `path-fields`, `start-input`,
`end-input`, `relationship-picker`, `relationship-chips`, `node-type-picker`, `node-type-chips`,
`direction`, `filter-group`, `min-hops`, `max-hops`, `footer`, `run-button`, `save-button`,
`save-row`, `save-name-input`, `saved-queries`, `saved-queries-label`, `saved-list`, `saved-item`,
`saved-load-button`, `saved-delete-button`, `saved-empty`.

**Themeable custom properties:** the Run button exposes `--lr-graph-query-builder-run-bg`,
`--lr-graph-query-builder-run-border-color`, and `--lr-graph-query-builder-run-color` for its
resting longhands plus `--lr-graph-query-builder-run-hover-bg` and
`--lr-graph-query-builder-run-active-bg`; the Save button exposes
`--lr-graph-query-builder-save-bg`, `--lr-graph-query-builder-save-border-color`,
`--lr-graph-query-builder-save-color`, `--lr-graph-query-builder-save-hover-bg`, and
`--lr-graph-query-builder-save-active-bg`. Saved-query actions use
`--lr-graph-query-builder-saved-load-color`, `--lr-graph-query-builder-saved-load-active-bg`,
`--lr-graph-query-builder-saved-delete-color`,
`--lr-graph-query-builder-saved-delete-hover-color`,
`--lr-graph-query-builder-saved-delete-active-color`, and
`--lr-graph-query-builder-saved-delete-active-bg`. Unset hooks preserve the current shared
surface/text/brand/danger colors and hover/active mixes. They are inline `var()` fallbacks at the
longhand that consumes them, so an override on a parent themes every descendant builder without
being shadowed by a declaration on the component host.

**Additional API surface:**

- `errorText` — Caller-supplied outer error text. Field-level validation remains on the affected controls. Type: `string`.
- `hint` — Supporting text rendered below the outer label. Type: `string`.
- `error-text` attribute — Caller-supplied outer error text. Field-level validation remains on the affected controls.
- `hint` attribute — Supporting text rendered below the outer label.
- `hint` slot — Supporting text for the complete form control.
- `part="hint"` — Supporting text for the complete form control.
