@yuuvis/client-framework 3.7.1 → 3.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,652 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { FormControl } from '@angular/forms';
3
+ import * as _yuuvis_client_core from '@yuuvis/client-core';
4
+ import { ObjectTypeField, GenericObjectType } from '@yuuvis/client-core';
5
+ import * as _yuuvis_client_framework_smart_search from '@yuuvis/client-framework/smart-search';
6
+ import { MatAutocomplete, MatAutocompleteTrigger, MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
7
+ import { RendererDirectiveInput } from '@yuuvis/client-framework/renderer';
8
+
9
+ /**
10
+ * A single committed `field operator value` condition (e.g. `name LIKE 'foo'`).
11
+ * The `*Label` fields are display strings for the chip; `fieldId`, `operator` and
12
+ * `value` are what actually drive the CMIS clause. `value` is a `string[]` for
13
+ * multi-value operators (which render as `IN (...)`), a string otherwise.
14
+ */
15
+ interface FieldCondition {
16
+ /** The queryable property id (or bare column id inside a table). */
17
+ fieldId: string;
18
+ /** The field's internal form-element type (e.g. `string`, `datetime`, `string:catalog`). */
19
+ internalType: string;
20
+ /** Localized field label shown on the chip. */
21
+ fieldLabel: string;
22
+ /** Operator id (e.g. `eq`, `like`, `gt`, `empty`, `date:today`). */
23
+ operator: string;
24
+ /** Display label for the operator (symbol or translated text). */
25
+ operatorLabel: string;
26
+ /** The comparison value; an array for multi-value `IN`-style conditions. */
27
+ value: string | string[];
28
+ /** Full human-readable label for the chip (`"Name like foo"`). */
29
+ conditionLabel: string;
30
+ /**
31
+ * Marked by the user as a *dynamic* condition: it is surfaced in the generated
32
+ * fill-out form (see form mode) so its value can be supplied/overridden at run time
33
+ * without rebuilding the query. Purely a builder annotation — it does not affect the
34
+ * emitted query on its own.
35
+ */
36
+ dynamic?: boolean;
37
+ }
38
+ /**
39
+ * A parenthesized sub-expression with its own AND/OR combinator. Groups can
40
+ * hold conditions and further groups recursively, allowing deeply nested
41
+ * boolean expressions.
42
+ */
43
+ interface ConditionGroup {
44
+ kind: 'group';
45
+ conditions: ConditionNode[];
46
+ combinator: Combinator;
47
+ }
48
+ /**
49
+ * A condition on a queryable `table`-type property. A table has no operator of its own;
50
+ * instead it holds column conditions directly — `FieldCondition`s targeting the table's
51
+ * columns, joined by `combinator` and matched against any row. Maps to
52
+ * `tableField[*].(col op val AND/OR …)` in CMIS (`[*]` = any row).
53
+ */
54
+ interface TableCondition {
55
+ kind: 'table';
56
+ /** The table property id. */
57
+ fieldId: string;
58
+ fieldLabel: string;
59
+ /** Column conditions (`FieldCondition`s targeting the table's columns). */
60
+ conditions: ConditionNode[];
61
+ /** How the column conditions combine (AND/OR). */
62
+ combinator: Combinator;
63
+ }
64
+ /** A child of a `SearchBlock` or `ConditionGroup`. */
65
+ type ConditionNode = FieldCondition | ConditionGroup | TableCondition;
66
+ declare function isConditionGroup(node: ConditionNode | SearchBlock): node is ConditionGroup;
67
+ declare function isTableCondition(node: ConditionNode | SearchBlock): node is TableCondition;
68
+ declare function isFieldCondition(node: ConditionNode): node is FieldCondition;
69
+ /** One target object type within a (potentially multi-type) search block. */
70
+ interface SearchBlockType {
71
+ id: string;
72
+ label: string;
73
+ isSot?: boolean;
74
+ }
75
+ interface SearchBlock {
76
+ /** Stable key for `@for` tracking — generated, not derived from a type id. */
77
+ id: string;
78
+ /** The object types this block targets. Conditions apply to their shared fields. */
79
+ types: SearchBlockType[];
80
+ conditions: ConditionNode[];
81
+ conditionCombinator: Combinator;
82
+ }
83
+ /**
84
+ * A container whose `conditions` can be mutated by the edit flow. A `TableCondition` is a
85
+ * container too: its children are row-groups; each row-group's children are column conditions.
86
+ */
87
+ type ConditionContainer = SearchBlock | ConditionGroup | TableCondition;
88
+ /**
89
+ * Where a full-text search looks. Maps to the column-qualified CONTAINS forms:
90
+ * `all` → `CONTAINS('q')` (metadata + content), `content` → `system:content CONTAINS('q')`,
91
+ * `metadata` → `system:metadata CONTAINS('q')`.
92
+ */
93
+ type FulltextScope = 'all' | 'content' | 'metadata';
94
+ /**
95
+ * The whole-object full-text search unit. Independent of the condition blocks: it carries its own
96
+ * target types and renders a single `CONTAINS` predicate.
97
+ */
98
+ interface FulltextSearch {
99
+ term: string;
100
+ scope: FulltextScope;
101
+ types: SearchBlockType[];
102
+ }
103
+ type Combinator = 'AND' | 'OR';
104
+ type BuildStep = 'type' | 'field' | 'operator' | 'value';
105
+ interface SuggestionItem {
106
+ kind: 'type' | 'field' | 'operator' | 'date-preset';
107
+ id: string;
108
+ label: string;
109
+ internalType?: string;
110
+ /** Set when a field has been paired with an operator while building a condition. */
111
+ operator?: string;
112
+ }
113
+ /**
114
+ * Serializable snapshot of a SmartSearch query.
115
+ *
116
+ * Capture via {@link SmartSearchComponent.getState} and restore via
117
+ * {@link SmartSearchComponent.loadState}. Safe for `JSON.stringify` /
118
+ * `JSON.parse` roundtrips (plain data, no class instances or signals).
119
+ */
120
+ interface SmartSearchState {
121
+ blocks: SearchBlock[];
122
+ combinator: Combinator;
123
+ /** Optional so states saved before full-text support remain loadable. */
124
+ fulltext?: FulltextSearch;
125
+ }
126
+
127
+ /**
128
+ * A single row of the generated fill-out form: the dynamic condition it edits, its
129
+ * resolved value-editor field definition (or `null` to fall back to a plain text input)
130
+ * and the `FormControl` bound to the value widget.
131
+ */
132
+ interface DynamicFormField {
133
+ condition: FieldCondition;
134
+ def: ObjectTypeField | null;
135
+ control: FormControl;
136
+ }
137
+ /**
138
+ * A block's worth of dynamic form rows. The generated fill-out form mirrors the builder's
139
+ * block layout: each block contributes a muted header listing its target types, followed by
140
+ * the dynamic conditions ({@link DynamicFormField}s) collected from anywhere within that block.
141
+ * Blocks with no dynamic conditions are omitted.
142
+ */
143
+ interface DynamicFormBlock {
144
+ block: SearchBlock;
145
+ fields: DynamicFormField[];
146
+ }
147
+ /**
148
+ * State + mutators for SmartSearch, shared between the host component and the
149
+ * recursive `SmartSearchGroupComponent`. Provided at the host component level
150
+ * so each `<yuv-smart-search>` instance gets its own controller.
151
+ *
152
+ * UI concerns (focus management, autocomplete plumbing, blur suppression) stay
153
+ * in the host component; this controller is purely about data.
154
+ */
155
+ declare class SmartSearchEditController {
156
+ #private;
157
+ /** The set of object type IDs that can be used as search blocks. */
158
+ allowedTypes: _angular_core.WritableSignal<string[]>;
159
+ /** ObjectTypeField IDs to exclude from the field-step autocomplete suggestions. */
160
+ skipProperties: _angular_core.WritableSignal<string[]>;
161
+ fieldCtrl: FormControl<string | null>;
162
+ operatorCtrl: FormControl<string | null>;
163
+ valueCtrl: FormControl<unknown>;
164
+ /** Current input step */
165
+ step: _angular_core.WritableSignal<BuildStep>;
166
+ /** The owning top-level block (drives field suggestions for the active edit) */
167
+ activeBlock: _angular_core.WritableSignal<SearchBlock | null>;
168
+ /** The immediate parent container the new condition will land in */
169
+ activeContainer: _angular_core.WritableSignal<ConditionContainer | null>;
170
+ /** Field selected waiting for operator/value */
171
+ pendingField: _angular_core.WritableSignal<SuggestionItem | null>;
172
+ /** Operator label for the pending operator (displayed as a pill) */
173
+ pendingOperatorLabel: _angular_core.WritableSignal<string>;
174
+ /** The accumulated search blocks */
175
+ blocks: _angular_core.WritableSignal<SearchBlock[]>;
176
+ /** Types staged in the multi-select before the block is committed (type step). */
177
+ draftTypes: _angular_core.WritableSignal<SearchBlockType[]>;
178
+ /** Index of the condition being edited (-1 = new condition) */
179
+ editingConditionIndex: _angular_core.WritableSignal<number>;
180
+ /**
181
+ * How to combine the top-level units (full-text unit + type blocks). These are
182
+ * type-scoped, so they always join with OR ("this as well as that"); the UI no
183
+ * longer exposes a toggle. Kept as a signal so saved states still round-trip.
184
+ */
185
+ combinator: _angular_core.WritableSignal<Combinator>;
186
+ /** The current filter term for autocomplete suggestions */
187
+ inputTerm: _angular_core.WritableSignal<string>;
188
+ /** The whole-object full-text search unit (independent of the condition blocks). */
189
+ fulltext: _angular_core.WritableSignal<FulltextSearch>;
190
+ /** Whether the dynamic-conditions feature is enabled (mirrors the host `supportDynamicConditions` input). */
191
+ supportDynamic: _angular_core.WritableSignal<boolean>;
192
+ /**
193
+ * Form mode: replace the builder with a generated form of the user-marked dynamic
194
+ * conditions. View state only — the template ({@link blocks}) is never mutated; the
195
+ * form's values are overlaid onto the dynamic conditions to drive {@link cmisQuery},
196
+ * so the template stays reusable.
197
+ */
198
+ formMode: _angular_core.WritableSignal<boolean>;
199
+ /** The dynamic conditions surfaced as form rows; rebuilt on each {@link enterFormMode}. */
200
+ formFields: _angular_core.WritableSignal<DynamicFormField[]>;
201
+ /**
202
+ * The dynamic form rows grouped by their owning block (each carrying a muted header of
203
+ * target types); rebuilt on each {@link enterFormMode}. Blocks combine with `OR`
204
+ * ("as well as"), matching the builder.
205
+ */
206
+ formBlocks: _angular_core.WritableSignal<DynamicFormBlock[]>;
207
+ /** Whether any condition is marked dynamic (gates the form-mode toggle). */
208
+ hasDynamicConditions: _angular_core.Signal<boolean>;
209
+ objectTypes: _angular_core.Signal<GenericObjectType[]>;
210
+ /** Fields for the active top-level block, used by the field-step suggestions. */
211
+ activeBlockFields: _angular_core.Signal<SuggestionItem[]>;
212
+ /**
213
+ * When the active edit is scoped inside a table, the resolved column definitions
214
+ * of that table (as full `ObjectTypeField`s with `_internalType`). `null` when
215
+ * not editing inside a table.
216
+ */
217
+ activeTableColumns: _angular_core.Signal<ObjectTypeField[] | null>;
218
+ /**
219
+ * The fields offered at the field step: a table's **columns** when editing
220
+ * inside a table, otherwise the active block's shared fields.
221
+ */
222
+ activeFields: _angular_core.Signal<SuggestionItem[]>;
223
+ suggestions: _angular_core.Signal<SuggestionItem[]>;
224
+ /** Number of top-level query units: the full-text unit (when it has a term) plus each block. */
225
+ unitCount: _angular_core.Signal<number>;
226
+ showCombinator: _angular_core.Signal<boolean>;
227
+ cmisQuery: _angular_core.Signal<string>;
228
+ /** The active input control for the current step. */
229
+ activeCtrl: _angular_core.Signal<FormControl<unknown>>;
230
+ /** Deep-clone the current blocks, combinator and full-text unit into a serializable {@link SmartSearchState}. */
231
+ getState(): SmartSearchState;
232
+ /** Replace the current state with a saved one, normalizing legacy blocks and cancelling any in-progress edit. */
233
+ loadState(state: SmartSearchState): void;
234
+ /** Reset all search state back to its initial empty values. */
235
+ reset(): void;
236
+ /** Mark or unmark a condition as dynamic (immutably replaces the node in its container). */
237
+ setConditionDynamic(container: ConditionContainer, condition: FieldCondition, dynamic: boolean): void;
238
+ /**
239
+ * Enter form mode: collect every dynamic condition, resolve its value editor and seed a
240
+ * `FormControl` with its current value. The blocks themselves are left untouched — the
241
+ * form's edits are overlaid via {@link setFormValue} / {@link cmisQuery}.
242
+ */
243
+ enterFormMode(): void;
244
+ /** Leave form mode and discard the transient form state (the template is untouched). */
245
+ exitFormMode(): void;
246
+ /** Toggle form mode (rebuilds the form rows on each entry). */
247
+ toggleFormMode(): void;
248
+ /** Record a value entered in the form for a dynamic condition (drives the overlaid {@link cmisQuery}). */
249
+ setFormValue(condition: FieldCondition, raw: unknown): void;
250
+ /** Set the full-text search term. */
251
+ setFulltextTerm(term: string): void;
252
+ /** Set the full-text search scope (`all` / `metadata` / `content`). */
253
+ setFulltextScope(scope: FulltextScope): void;
254
+ /** Add a target type to the full-text unit (no-op if already present). */
255
+ addFulltextType(type: GenericObjectType, label: string): void;
256
+ /** Remove a target type from the full-text unit by id. */
257
+ removeFulltextType(id: string): void;
258
+ /** Replace the full-text target types from a list of object-type ids (unknown ids are dropped). */
259
+ setFulltextTypes(ids: string[]): void;
260
+ /** Stage a type in the draft multi-select (no-op if already staged). */
261
+ addDraftType(type: GenericObjectType, label: string): void;
262
+ /** Remove a staged type from the draft multi-select. */
263
+ removeDraftType(id: string): void;
264
+ /**
265
+ * Commit the staged draft types into a new block and clear the draft.
266
+ * Returns the created block, or `null` when the draft is empty.
267
+ */
268
+ confirmDraftTypes(): SearchBlock | null;
269
+ /** Remove a whole block; cancels the in-progress edit if it belonged to that block. */
270
+ removeBlock(block: SearchBlock): void;
271
+ /** Append an empty `ConditionGroup` to a container and start adding inside it. */
272
+ addGroup(parent: ConditionContainer): ConditionGroup;
273
+ /**
274
+ * Remove a group from its parent container. If the parent group becomes
275
+ * empty, it is also removed (cascading up). Top-level blocks are preserved.
276
+ */
277
+ removeGroup(group: ConditionGroup): void;
278
+ /** Remove a condition from the tree; empty parent groups/tables are pruned by the cascade. */
279
+ removeCondition(_container: ConditionContainer, condition: FieldCondition): void;
280
+ /** Set the top-level combinator joining the query units (full-text unit + blocks). */
281
+ setCombinator(value: Combinator): void;
282
+ /** Set the AND/OR combinator of a single container (block, group or table). */
283
+ setContainerCombinator(container: ConditionContainer, value: Combinator): void;
284
+ /**
285
+ * The picked field resolves to a queryable `table` type. A table has no operator
286
+ * of its own; instead it holds column conditions directly. Insert an empty
287
+ * {@link TableCondition} and scope the edit into it so the user picks a column next.
288
+ */
289
+ addTableCondition(field: SuggestionItem): void;
290
+ /** Begin adding a condition inside `container`. */
291
+ startAddCondition(container: ConditionContainer): void;
292
+ /** Begin editing an existing condition inside `container`. */
293
+ editCondition(container: ConditionContainer, condition: FieldCondition, index: number): void;
294
+ /** Jump back to the field step and clear the input so the user can re-type. */
295
+ editField(): void;
296
+ /** Jump back to the operator step and clear the input so the user can re-type. */
297
+ editOperator(): void;
298
+ /** Abandon the in-progress edit, restoring state and pruning any empty container created for it. */
299
+ cancelPending(): void;
300
+ /** Insert (or, when editing, re-insert at its original index) the finished condition into the active container. */
301
+ commitCondition(condition: FieldCondition): void;
302
+ /**
303
+ * On blur with an incomplete edit of an existing condition, reinsert the
304
+ * original verbatim at its original index.
305
+ */
306
+ restoreEditingSnapshot(): void;
307
+ /**
308
+ * Whether the in-progress condition has all parts needed to be committed. A value
309
+ * is *not* required: a field + operator with a blank value commits as an unset
310
+ * placeholder (see {@link isConditionUnset}).
311
+ */
312
+ isConditionComplete(): boolean;
313
+ /** The operators available for a field's internal type, as autocomplete items. */
314
+ operatorsForField(field: SuggestionItem): SuggestionItem[];
315
+ /** Human-readable label for an operator id: a math symbol (`=`, `≠`, …), a translated key, or the id itself. */
316
+ operatorLabel(operator: string): string;
317
+ /** Build a condition record from a date preset / boolean operator / value. */
318
+ buildCommitCondition(field: SuggestionItem, operatorId: string, operatorLabelText: string, value: string | string[], internalTypeOverride?: string): FieldCondition;
319
+ /**
320
+ * Resolve a field definition by id across the given block types, falling back to
321
+ * the universal base fields. Used by the host to render the value editor for a
322
+ * picked field (including inherited base fields not present on any type).
323
+ */
324
+ resolveFieldDefinition(types: SearchBlockType[], fieldId: string): ObjectTypeField | null;
325
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SmartSearchEditController, never>;
326
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<SmartSearchEditController>;
327
+ }
328
+
329
+ /**
330
+ * Operators that carry their own meaning and need no value step: date presets,
331
+ * the boolean `= true/false` shortcuts, and the null checks (`empty`/`not_empty`).
332
+ * The build flow commits these immediately instead of advancing to the value editor.
333
+ */
334
+ declare function isValuelessOperator(operator: string): boolean;
335
+ /**
336
+ * Whether a condition is an *unset placeholder*: it uses a value-requiring operator
337
+ * (eq / like / gt / …) but carries no value yet. Such conditions are kept in the tree
338
+ * — so a saved query can act as a fill-in template — but contribute nothing to the
339
+ * emitted CMIS query. An empty value is unambiguously "unset" here because null-checks
340
+ * have their own `empty` / `not_empty` operators (offered on every queryable type).
341
+ */
342
+ declare function isConditionUnset(cond: FieldCondition): boolean;
343
+ /**
344
+ * Recursively render a condition node. Groups produce parenthesized
345
+ * sub-expressions; empty groups contribute nothing; single-child groups
346
+ * collapse their redundant parens. Table conditions delegate to
347
+ * {@link buildTableClause}.
348
+ */
349
+ declare function buildNodeClause(node: ConditionNode): string;
350
+ /**
351
+ * Build the whole-object full-text clause: a single `CONTAINS('term')` predicate, optionally scoped
352
+ * to a column and AND-ed with a type restriction. Returns `''` when the term is blank.
353
+ */
354
+ declare function buildFulltextClause(fulltext: FulltextSearch): string;
355
+ /**
356
+ * Assemble the full CMIS statement from the search state. Each unit — the
357
+ * full-text clause plus every type block (type restriction `AND`-ed with its
358
+ * conditions) — is parenthesized and joined by `combinator`. Returns `''` when
359
+ * nothing contributes a clause, so an empty search yields no query.
360
+ *
361
+ * @param blocks The type blocks with their conditions.
362
+ * @param combinator How the top-level units combine (`AND` / `OR`).
363
+ * @param fulltext Optional whole-object full-text unit.
364
+ * @returns A `SELECT * FROM system:object WHERE …` statement, or `''`.
365
+ */
366
+ declare function buildCmisQuery(blocks: SearchBlock[], combinator: Combinator, fulltext?: FulltextSearch): string;
367
+
368
+ /**
369
+ * Visual query builder that turns guided, chip-based user input into a CMIS query.
370
+ *
371
+ * The user composes a search in two independent parts:
372
+ * - a **full-text bar** (`CONTAINS`) with a scope (all / metadata / content) and an
373
+ * optional object-type restriction, and
374
+ * - one or more **type blocks**, each targeting one or more object types and holding
375
+ * field conditions, nested groups and table-column conditions.
376
+ *
377
+ * Conditions are built step by step (type → field → operator → value) with an inline
378
+ * autocomplete editor; the value step renders the field's real metadata widget
379
+ * (datepicker, catalog select, organization picker, …). The resulting CMIS query is
380
+ * emitted through {@link queryChange} on every change and can be saved/restored as a
381
+ * plain-data {@link SmartSearchState} via {@link getState} / {@link loadState}.
382
+ *
383
+ * State and mutators live in {@link SmartSearchEditController} (provided per instance);
384
+ * this component owns only the UI concerns (focus, autocomplete plumbing, blur handling).
385
+ *
386
+ * @example
387
+ * ```html
388
+ * <!-- Restrict the picker to two object types and skip a noisy property -->
389
+ * <yuv-smart-search
390
+ * [types]="['document', 'invoice']"
391
+ * [skipProperties]="['system:traceId']"
392
+ * (queryChange)="onQuery($event)"
393
+ * />
394
+ * ```
395
+ *
396
+ * @example
397
+ * ```ts
398
+ * // Save and restore the builder state (e.g. a stored search)
399
+ * const search = viewChild.required(SmartSearchComponent);
400
+ *
401
+ * onQuery(cmisQuery: string) {
402
+ * // empty string means "no query" — treat it as a cleared search
403
+ * this.results.set(cmisQuery ? this.backend.search(cmisQuery) : []);
404
+ * }
405
+ *
406
+ * persist() {
407
+ * localStorage.setItem('search', JSON.stringify(this.search().getState()));
408
+ * }
409
+ *
410
+ * restore() {
411
+ * const state = localStorage.getItem('search');
412
+ * if (state) this.search().loadState(JSON.parse(state));
413
+ * }
414
+ * ```
415
+ */
416
+ declare class SmartSearchComponent {
417
+ #private;
418
+ ctrl: SmartSearchEditController;
419
+ /**
420
+ * Object-type ids that may be searched. Restricts the type picker (both the
421
+ * full-text type filter and the type-block multi-select) to these types. When
422
+ * empty, no type is offered — set at least one id to enable building blocks.
423
+ */
424
+ types: _angular_core.InputSignal<string[]>;
425
+ /**
426
+ * Field ids to hide from the field-step autocomplete (e.g. internal/system
427
+ * properties that should not be user-queryable). Applies to block fields and
428
+ * table columns alike.
429
+ */
430
+ skipProperties: _angular_core.InputSignal<string[]>;
431
+ /**
432
+ * Enables the **dynamic conditions** feature. When `true`, each committed condition can
433
+ * be marked dynamic and a form-mode toggle appears that swaps the builder for a generated
434
+ * fill-out form of those conditions. Off by default — the builder then behaves exactly as
435
+ * it does without the feature.
436
+ */
437
+ supportDynamicConditions: _angular_core.InputSignal<boolean>;
438
+ /**
439
+ * Emits the current CMIS query string whenever the search changes. An empty
440
+ * string is emitted for an empty search (including the initial seed), so
441
+ * consumers should treat `''` as "no query" rather than expecting only
442
+ * non-empty values.
443
+ */
444
+ queryChange: _angular_core.OutputEmitterRef<string>;
445
+ auto: _angular_core.Signal<MatAutocomplete>;
446
+ /** Trigger of the currently-focused autocomplete input — used to re-open the
447
+ * panel after a type pick so the multi-select stays open. */
448
+ trigger: _angular_core.Signal<MatAutocompleteTrigger | undefined>;
449
+ /** Term control for the full-text bar (independent of the build-step controls). */
450
+ fulltextTermCtrl: FormControl<string | null>;
451
+ /** Sentinel option value representing "no type restriction" in the type multi-select. */
452
+ readonly ALL_TYPES = "__all__";
453
+ /**
454
+ * Guard that prevents `onInlineBlur` from cancelling the pending condition
455
+ * when we programmatically open the inline editor.
456
+ */
457
+ _suppressNextBlur: boolean;
458
+ /** Prevents the valueChanges subscriber from overwriting inputTerm during programmatic setValue */
459
+ _suppressInputTerm: boolean;
460
+ /**
461
+ * Set when a type is staged via the autocomplete so the ENTER that triggered the
462
+ * selection does not also fall through to `confirmTypes()`. Cleared on the next
463
+ * tick. Needed because the chip-input directive changes the keydown listener order,
464
+ * so `onTypeEnter` can run *after* the autocomplete has already closed its panel.
465
+ */
466
+ _suppressTypeConfirm: boolean;
467
+ /**
468
+ * Set while an autocomplete option is being applied so the panel's `closed`
469
+ * event (which Material emits synchronously right after `optionSelected`) is not
470
+ * mistaken for the user abandoning an empty property picker. Consumed
471
+ * synchronously in `onPickerClosed`.
472
+ */
473
+ _pickerJustSelected: boolean;
474
+ readonly blocks: _angular_core.WritableSignal<SearchBlock[]>;
475
+ readonly draftTypes: _angular_core.WritableSignal<_yuuvis_client_framework_smart_search.SearchBlockType[]>;
476
+ readonly combinator: _angular_core.WritableSignal<Combinator>;
477
+ readonly step: _angular_core.WritableSignal<_yuuvis_client_framework_smart_search.BuildStep>;
478
+ readonly activeBlock: _angular_core.WritableSignal<SearchBlock | null>;
479
+ readonly activeContainer: _angular_core.WritableSignal<ConditionContainer | null>;
480
+ readonly pendingField: _angular_core.WritableSignal<SuggestionItem | null>;
481
+ readonly pendingOperatorLabel: _angular_core.WritableSignal<string>;
482
+ readonly editingConditionIndex: _angular_core.WritableSignal<number>;
483
+ readonly inputTerm: _angular_core.WritableSignal<string>;
484
+ readonly cmisQuery: _angular_core.Signal<string>;
485
+ readonly showCombinator: _angular_core.Signal<boolean>;
486
+ readonly suggestions: _angular_core.Signal<SuggestionItem[]>;
487
+ readonly fulltext: _angular_core.WritableSignal<_yuuvis_client_framework_smart_search.FulltextSearch>;
488
+ readonly objectTypes: _angular_core.Signal<_yuuvis_client_core.GenericObjectType[]>;
489
+ readonly activeBlockFields: _angular_core.Signal<SuggestionItem[]>;
490
+ readonly formMode: _angular_core.WritableSignal<boolean>;
491
+ readonly formFields: _angular_core.WritableSignal<DynamicFormField[]>;
492
+ readonly formBlocks: _angular_core.WritableSignal<DynamicFormBlock[]>;
493
+ readonly hasDynamicConditions: _angular_core.Signal<boolean>;
494
+ /** Whether a committed condition is an unset placeholder (drives the chip's "fill me" affordance). */
495
+ isUnset: typeof isConditionUnset;
496
+ /**
497
+ * Whether an operator carries its own meaning and has no value input (`is empty`,
498
+ * `is not empty`, date presets). Such conditions can't be made dynamic — there is
499
+ * nothing to fill out in the form.
500
+ */
501
+ isValueless: typeof isValuelessOperator;
502
+ /**
503
+ * Selected ids for the type multi-select. Falls back to the `ALL_TYPES`
504
+ * sentinel when no concrete type is picked (empty selection = no restriction).
505
+ */
506
+ readonly fulltextTypeSelection: _angular_core.Signal<string[]>;
507
+ readonly fieldCtrl: FormControl<string | null>;
508
+ readonly operatorCtrl: FormControl<string | null>;
509
+ readonly valueCtrl: FormControl<unknown>;
510
+ /**
511
+ * Field definition driving the value-step editor. Memoized so the `[field]`
512
+ * reference stays stable across change-detection cycles — re-resolving on every
513
+ * CD (via a template method call) would re-create the editor and reset widgets
514
+ * like the catalog select before their options render.
515
+ */
516
+ readonly valueFieldDef: _angular_core.Signal<ObjectTypeField | null>;
517
+ constructor();
518
+ /** Set the AND/OR combinator that joins the conditions within a single container (block, group or table). */
519
+ setConditionCombinator(container: ConditionContainer, value: Combinator): void;
520
+ /**
521
+ * Capture the current search as a serializable snapshot. Safe for
522
+ * `JSON.stringify`/`JSON.parse` roundtrips — use it to persist a search and
523
+ * later restore it with {@link loadState}.
524
+ */
525
+ getState(): SmartSearchState;
526
+ /** Restore a previously {@link getState saved} search, replacing the current one. */
527
+ loadState(state: SmartSearchState): void;
528
+ /** Clear the whole search: discard all blocks, conditions and the full-text term. */
529
+ clear(): void;
530
+ /**
531
+ * Toggle form mode: swap the builder for a generated fill-out form of the user-marked
532
+ * dynamic conditions. The template is left intact — the form's values are overlaid onto
533
+ * the query. No-op unless {@link supportDynamicConditions} is set.
534
+ */
535
+ toggleFormMode(): void;
536
+ /** Enter form mode ("Essentials") — generated fill-out form of the dynamic conditions. */
537
+ enterFormMode(): void;
538
+ /** Leave form mode ("Full Form") — back to the full builder search. */
539
+ exitFormMode(): void;
540
+ /** Mark/unmark a committed condition as dynamic (surfaced in the fill-out form). */
541
+ toggleDynamic(container: ConditionContainer, condition: FieldCondition): void;
542
+ /**
543
+ * Set the top-level combinator joining the query units (the full-text unit and
544
+ * the type blocks). Kept for state round-tripping; the UI currently always
545
+ * joins units with `OR`.
546
+ */
547
+ setCombinator(value: Combinator): void;
548
+ /** Remove an entire type block and all of its conditions. */
549
+ removeBlock(block: SearchBlock): void;
550
+ /** Commit the staged draft types into a new block and reset the type input. */
551
+ confirmTypes(): void;
552
+ /** Start adding a new condition inside the given container and focus the inline editor. */
553
+ startAddCondition(block: SearchBlock): void;
554
+ /** Add a nested condition group inside the given container and focus the inline editor. */
555
+ addGroup(block: SearchBlock): void;
556
+ /**
557
+ * `displayWith` for the shared autocomplete. Suggestions are objects but the
558
+ * input text is driven by the form controls, so a picked option must not write
559
+ * a label back into the field — return the raw string, or empty otherwise.
560
+ */
561
+ displayFn: (item: SuggestionItem | string | null) => string;
562
+ /** Set where the full-text search looks: `all` (metadata + content), `metadata`, or `content`. */
563
+ setFulltextScope(scope: FulltextScope): void;
564
+ /**
565
+ * Reconcile the type multi-select with the "All types" sentinel. Picking
566
+ * "All types" while concrete types are selected clears the restriction;
567
+ * picking any concrete type drops the sentinel.
568
+ */
569
+ onFulltextTypesChange(ids: string[]): void;
570
+ /**
571
+ * Handle a pick from the shared autocomplete panel. Branches on the current
572
+ * build step: stages a type (keeping the panel open for more), advances a
573
+ * field to its operator (or opens a table container), or applies a chosen
574
+ * operator. Single-operator fields and valueless operators commit immediately.
575
+ */
576
+ onSuggestionSelected(event: MatAutocompleteSelectedEvent): void;
577
+ /**
578
+ * Enter in the add-type input. When the input is empty there's no option to
579
+ * pick, so Enter commits the staged types — even while the autocomplete panel
580
+ * is open. While the user is typing a filter term, Enter is left to the
581
+ * autocomplete so it can select the highlighted option.
582
+ */
583
+ onTypeEnter(): void;
584
+ /**
585
+ * Enter / confirm-button handler for the value step. Commits the in-progress
586
+ * condition when a value is present. No-op while the autocomplete panel is open
587
+ * (Enter selects the highlighted option there) or before the value step.
588
+ */
589
+ onEnter(): void;
590
+ /**
591
+ * Called when the inline-input wrapper loses focus.
592
+ * Commits the condition if complete, discards it if incomplete.
593
+ *
594
+ * Deferred via setTimeout(0): raw value renderers (datepicker dialog,
595
+ * mat-select panel, mat-autocomplete panel) mount their UI in the
596
+ * .cdk-overlay-container, which is OUTSIDE the wrapper. Reading
597
+ * document.activeElement on the next task lets us detect that focus
598
+ * is still in our logical scope.
599
+ */
600
+ onInlineBlur(event: FocusEvent): void;
601
+ /**
602
+ * Fired when the shared autocomplete panel closes. Starting a condition opens
603
+ * the property picker; if the user dismisses it (outside click, Escape) without
604
+ * choosing a field, there's an empty editor with nothing to commit — drop it.
605
+ *
606
+ * Only the field step is handled here: operator/value abandonment is already
607
+ * covered by `onInlineBlur` (those steps don't auto-open a picker the user can
608
+ * dismiss while keeping focus). Restores the original when editing an existing
609
+ * condition, mirroring the blur path.
610
+ */
611
+ onPickerClosed(): void;
612
+ /** Abandon the in-progress condition edit, discarding any partial input. */
613
+ cancelPending(): void;
614
+ /** Jump the inline editor back to the field step so the user can re-pick the field. */
615
+ editField(): void;
616
+ /** Jump the inline editor back to the operator step so the user can re-pick the operator. */
617
+ editOperator(): void;
618
+ /**
619
+ * Open an already-committed condition for editing in place. The condition is
620
+ * pulled out of the tree into the inline editor at its original index, pre-set
621
+ * to the appropriate step (value, or operator for valueless operators).
622
+ */
623
+ editCondition(container: ConditionContainer, condition: FieldCondition, index: number): void;
624
+ /** Remove a committed condition from its container. */
625
+ removeCondition(container: ConditionContainer, condition: FieldCondition): void;
626
+ /**
627
+ * Renderer input for a committed condition's value, or `null` when the value
628
+ * should render as plain text. id-based fields (e.g. organization) store an
629
+ * opaque id as the query value; routing it through the property renderer
630
+ * resolves it to a human-readable label for the chip. Valueless operators
631
+ * (empty/not_empty, date presets) and booleans keep their plain text: their
632
+ * stored value is synthetic/serialized, not the shape those renderers expect.
633
+ */
634
+ valueRendererInput(condition: FieldCondition): RendererDirectiveInput | null;
635
+ /**
636
+ * Resolve the full {@link ObjectTypeField} definition for a suggestion item in
637
+ * the active block, or `null` when none applies. Drives the value-step metadata
638
+ * widget so the right editor (datepicker, catalog, …) is rendered.
639
+ */
640
+ getObjectTypeField(item: SuggestionItem | null): ObjectTypeField | null;
641
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<SmartSearchComponent, never>;
642
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<SmartSearchComponent, "yuv-smart-search", never, { "types": { "alias": "types"; "required": false; "isSignal": true; }; "skipProperties": { "alias": "skipProperties"; "required": false; "isSignal": true; }; "supportDynamicConditions": { "alias": "supportDynamicConditions"; "required": false; "isSignal": true; }; }, { "queryChange": "queryChange"; }, never, never, true, never>;
643
+ }
644
+
645
+ declare class YuvSmartSearchModule {
646
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<YuvSmartSearchModule, never>;
647
+ static ɵmod: _angular_core.ɵɵNgModuleDeclaration<YuvSmartSearchModule, never, [typeof SmartSearchComponent], [typeof SmartSearchComponent]>;
648
+ static ɵinj: _angular_core.ɵɵInjectorDeclaration<YuvSmartSearchModule>;
649
+ }
650
+
651
+ export { SmartSearchComponent, YuvSmartSearchModule, buildCmisQuery, buildFulltextClause, buildNodeClause, isConditionGroup, isFieldCondition, isTableCondition };
652
+ export type { BuildStep, Combinator, ConditionContainer, ConditionGroup, ConditionNode, FieldCondition, FulltextScope, FulltextSearch, SearchBlock, SearchBlockType, SmartSearchState, SuggestionItem, TableCondition };