@esfaenza/flow-builder 20.3.9 → 20.3.10

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.
package/README.md CHANGED
@@ -254,6 +254,26 @@ Restano fuori i percorsi radicati sul risultato **automatico** di un elemento
254
254
  (`Leggi_Contatti.Owner.Name`): la validazione non li verifica, e l'editor non accusa cio' che il
255
255
  backend non verifica.
256
256
 
257
+ Il filtro di tipo di un campo (§6.4) guarda il tipo della **radice**, e quindi non basta: in un
258
+ parametro `String` una variabile `Structure` non e' compatibile, ma `Richiesta.Ragione` sì. Per
259
+ questo `<fb-reference-picker>`, dove un filtro c'e', chiede al backend **anche** l'elenco non
260
+ filtrato, e ne ricava due cose: i contenitori compaiono come righe in cui si **entra** — cliccarle
261
+ apre il percorso invece di scegliere un valore del tipo sbagliato — e le radici si riconoscono
262
+ tutte, così un `Leggi_Ordine.Numero` già scritto in un campo `String` non viene accusato di non
263
+ esistere. Le proposte le filtra il backend come prima; i segmenti di un percorso li filtra
264
+ l'editor con la stessa regola, tenendo comunque quelli da cui si scende.
265
+
266
+ **Le globali si navigano come le risorse.** Un percorso dichiarato dall'host puo' portare un
267
+ contenitore, e allora `objectType` dice di che tipo: `$User.Anagrafica.Citta` si propone e si
268
+ verifica come `Richiesta.Ragione`. La regola da non sbagliare e' che vince il **prefisso dichiarato
269
+ piu' lungo** — non tutto cio' che segue lo scope — perche' altrimenti un percorso giusto viene
270
+ segnalato come rotto (§4.1). Dove il catalogo dichiara il contenitore ma non il tipo il rilievo e'
271
+ `PATH_NOT_VERIFIABLE`, e la correzione sta nel catalogo dell'host; navigare uno scalare
272
+ (`$User.Email.Dominio`) e' invece `GLOBAL_UNKNOWN`. Sulle **destinazioni** non cambia niente da
273
+ sapere: le globali sono di sola lettura, membri compresi — le assegnabili sono `$Flow.CurrentStage`,
274
+ `$Flow.ActiveStages` e i campi di `$Record` — e il picker lo dice con `TARGET_NOT_WRITABLE` invece
275
+ di far sembrare il nome inesistente (§5.2).
276
+
257
277
  Su una destinazione la colonna che decide non e' la stessa nei due mondi: un membro porta il proprio
258
278
  `isWritable`, un campo no. Fuori da un Create o da un Update il contesto non c'e' — un Assignment su
259
279
  `Cliente.Codice` non sa se quel record verra' creato o aggiornato — quindi lì basta `isCreateable`
@@ -3739,6 +3739,20 @@ class ReferencePickerComponent {
3739
3739
  elementsOnly = input(false, ...(ngDevMode ? [{ debugName: "elementsOnly" }] : []));
3740
3740
  valueChange = output();
3741
3741
  references = signal([], ...(ngDevMode ? [{ debugName: "references" }] : []));
3742
+ /**
3743
+ * L'elenco **senza** il filtro di tipo, che serve solo a riconoscere le radici dei percorsi.
3744
+ *
3745
+ * Il filtro (§6.4) guarda il tipo della **radice**, e una radice scartata si porta via anche cio'
3746
+ * che sta sotto: in un parametro `String` una variabile `Structure` non e' compatibile, ma
3747
+ * `Richiesta.Ragione` lo e', e `Leggi_Ordine` non e' un `String` mentre `Leggi_Ordine.Numero` lo
3748
+ * e'. Senza questo elenco il primo membro non si puo' proporre e il secondo viene accusato di non
3749
+ * esistere pur essendo un riferimento valido (§4.5).
3750
+ *
3751
+ * Vuoto dove il filtro non c'e': lì {@link references} e' già l'elenco completo.
3752
+ */
3753
+ unfiltered = signal([], ...(ngDevMode ? [{ debugName: "unfiltered" }] : []));
3754
+ /** Tutto cio' che puo' essere la radice di un percorso, filtrato o no. */
3755
+ roots = computed(() => [...this.references(), ...this.unfiltered()], ...(ngDevMode ? [{ debugName: "roots" }] : []));
3742
3756
  isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : []));
3743
3757
  loadError = signal(null, ...(ngDevMode ? [{ debugName: "loadError" }] : []));
3744
3758
  isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
@@ -3754,6 +3768,7 @@ class ReferencePickerComponent {
3754
3768
  const objectType = this.objectType();
3755
3769
  if (this.elementsOnly()) {
3756
3770
  // I node li conosce già il documento: nessuna richiesta necessaria.
3771
+ this.unfiltered.set([]);
3757
3772
  this.references.set(this.store.nodes().map((reference) => ({
3758
3773
  name: reference.name,
3759
3774
  label: reference.node.label ?? null,
@@ -3786,8 +3801,53 @@ class ReferencePickerComponent {
3786
3801
  this.references.set([]);
3787
3802
  })
3788
3803
  .finally(() => this.isLoading.set(false));
3804
+ /**
3805
+ * Seconda richiesta **senza filtri**, per le sole radici: chi filtra le proposte resta il
3806
+ * backend — da qui non entra nessun valore del tipo sbagliato, entrano i contenitori in cui
3807
+ * scendere e i nomi da non accusare.
3808
+ *
3809
+ * Non filtrata vuol dire anche `getReferences` e non `getWritableReferences`, pure in un campo
3810
+ * di destinazione: la scrivibilita' e' del **percorso**, non della radice, e le radici scartate
3811
+ * sono quelle che servono per dire la cosa giusta — un `$User.Anagrafica.Citta` scritto a mano
3812
+ * e' `TARGET_NOT_WRITABLE`, non un nome che non esiste. Dove non c'e' filtro **ne'** vincolo di
3813
+ * scrittura la prima richiesta le contiene già, e la seconda non si fa.
3814
+ */
3815
+ const hasTypeFilter = !!query.dataType || query.isCollection != null || !!query.objectType;
3816
+ if (!hasTypeFilter && !writable) {
3817
+ this.unfiltered.set([]);
3818
+ return;
3819
+ }
3820
+ void this.api
3821
+ .getReferences({ definition })
3822
+ .then((list) => this.unfiltered.set(list ?? []))
3823
+ // Una radice in meno degrada le proposte, non il campo: nessun messaggio.
3824
+ .catch(() => this.unfiltered.set([]));
3789
3825
  });
3790
3826
  }
3827
+ /**
3828
+ * Il riferimento dichiarato piu' **lungo** che sia un prefisso del valore, sui confini del punto.
3829
+ *
3830
+ * Non basta il primo segmento: un nome dichiarato puo' contenere il punto. Le globali sono il caso
3831
+ * per cui la regola esiste — di `$User.Anagrafica.Citta` il dizionario dichiara `$User.Anagrafica`,
3832
+ * e cercare la corrispondenza esatta di tutto cio' che segue lo scope segnalerebbe come rotto un
3833
+ * percorso giusto (§4.1: vince il prefisso dichiarato piu' lungo).
3834
+ */
3835
+ declaredPrefix = computed(() => {
3836
+ const value = (this.value() ?? '')?.trim();
3837
+ if (!value) {
3838
+ return undefined;
3839
+ }
3840
+ let best;
3841
+ for (const candidate of this.roots()) {
3842
+ if (value !== candidate.name && !value.startsWith(`${candidate.name}.`)) {
3843
+ continue;
3844
+ }
3845
+ if (!best || candidate.name.length > best.name.length) {
3846
+ best = candidate;
3847
+ }
3848
+ }
3849
+ return best;
3850
+ }, ...(ngDevMode ? [{ debugName: "declaredPrefix" }] : []));
3791
3851
  /**
3792
3852
  * La risorsa da cui il valore corrente sta navigando, quando la sua forma e' **dichiarata**: una
3793
3853
  * `Structure` con la classe, un record con l'entita'. È cio' che rende il percorso verificabile.
@@ -3797,11 +3857,9 @@ class ReferencePickerComponent {
3797
3857
  * l'editor non deve accusare cio' che il backend non verifica.
3798
3858
  */
3799
3859
  navigableRoot = computed(() => {
3800
- const root = referenceRoot((this.value() ?? '')?.trim());
3801
- if (!root) {
3802
- return undefined;
3803
- }
3804
- const reference = this.references().find((candidate) => candidate.name === root);
3860
+ // Fra tutte le radici: quella di `Richiesta.Ragione` in un campo `String` sta solo nell'elenco
3861
+ // non filtrato.
3862
+ const reference = this.declaredPrefix();
3805
3863
  if (!reference || reference.kind === 'ElementOutput' || !reference.objectType || reference.isCollection) {
3806
3864
  return undefined;
3807
3865
  }
@@ -3830,6 +3888,16 @@ class ReferencePickerComponent {
3830
3888
  * segmento di sola lettura non si propone in un campo di destinazione, a meno che da lì il
3831
3889
  * percorso continui: `Richiesta.Cliente` non si assegna, ma `Richiesta.Cliente.Email` sì (§5.7).
3832
3890
  */
3891
+ /**
3892
+ * §5.2 — dentro una globale dell'host **niente** e' scrivibile, per quanto il membro si dichiari
3893
+ * tale: le globali le risolve un componente che non ha modo di scriverle, e proporle come
3894
+ * destinazione farebbe attivare un flow che poi fallisce davanti all'utente. L'eccezione sono i
3895
+ * campi del record che innesca, che si assegnano (§4.1).
3896
+ */
3897
+ isReadOnlyPath = computed(() => {
3898
+ const name = this.navigableRoot()?.reference.name;
3899
+ return !!name && isGlobalReference(name) && referenceRoot(name) !== '$Record';
3900
+ }, ...(ngDevMode ? [{ debugName: "isReadOnlyPath" }] : []));
3833
3901
  pathReferences = computed(() => {
3834
3902
  const root = this.navigableRoot();
3835
3903
  const tail = this.tail();
@@ -3839,7 +3907,9 @@ class ReferencePickerComponent {
3839
3907
  const prefix = tail.prefix ? `${root.reference.name}.${tail.prefix}` : root.reference.name;
3840
3908
  const kind = tail.level.container.kind === 'object' ? 'RecordField' : 'StructureMember';
3841
3909
  return tail.level.entries
3910
+ .map((entry) => (this.isReadOnlyPath() ? { ...entry, isWritable: false } : entry))
3842
3911
  .filter((entry) => !this.writableOnly() || entry.isWritable || !!entry.next)
3912
+ .filter((entry) => this.matchesTarget(entry))
3843
3913
  .map((entry) => ({
3844
3914
  name: `${prefix}.${entry.name}`,
3845
3915
  label: entry.label ?? null,
@@ -3851,12 +3921,53 @@ class ReferencePickerComponent {
3851
3921
  description: entry.isWritable ? (entry.description ?? null) : 'sola lettura',
3852
3922
  }));
3853
3923
  }, ...(ngDevMode ? [{ debugName: "pathReferences" }] : []));
3924
+ /**
3925
+ * Lo stesso filtro che il backend applica alle radici (§6.4), applicato ai segmenti di un
3926
+ * percorso: in un parametro `String` non si propone un membro `Date`. Un segmento da cui si
3927
+ * scende resta comunque proposto anche se il suo tipo non combacia — e' la strada per arrivare
3928
+ * al membro che combacia.
3929
+ */
3930
+ matchesTarget(entry) {
3931
+ if (entry.next) {
3932
+ return true;
3933
+ }
3934
+ const dataType = this.dataType();
3935
+ if (dataType && entry.dataType && entry.dataType !== dataType) {
3936
+ return false;
3937
+ }
3938
+ const isCollection = this.isCollection();
3939
+ if (isCollection != null && entry.isCollection != null && !!entry.isCollection !== isCollection) {
3940
+ return false;
3941
+ }
3942
+ const objectType = this.objectType();
3943
+ return !(objectType && entry.objectType && entry.objectType !== objectType);
3944
+ }
3945
+ /**
3946
+ * I contenitori che il filtro di tipo ha scartato: si mostrano per **entrarci**, non per
3947
+ * scegliersi. Quelli che il filtro ha tenuto stanno già fra le proposte normali.
3948
+ */
3949
+ containerOptions = computed(() => {
3950
+ const proposed = new Set(this.references().map((reference) => reference.name));
3951
+ return this.unfiltered().filter((candidate) => {
3952
+ if (proposed.has(candidate.name) || !this.canDescend(candidate)) {
3953
+ return false;
3954
+ }
3955
+ // In un campo di destinazione una globale dell'host non porta a niente di assegnabile (§5.2):
3956
+ // proporre di entrarci sarebbe un vicolo cieco. Resta nelle radici, per il messaggio giusto.
3957
+ return !(this.writableOnly() &&
3958
+ isGlobalReference(candidate.name) &&
3959
+ referenceRoot(candidate.name) !== '$Record');
3960
+ });
3961
+ }, ...(ngDevMode ? [{ debugName: "containerOptions" }] : []));
3962
+ /** `true` → questa riga apre il percorso e non e' un valore valido per il campo. */
3963
+ isContainerOnly(reference) {
3964
+ return this.containerOptions().some((candidate) => candidate.name === reference.name);
3965
+ }
3854
3966
  options = computed(() => {
3855
3967
  const needle = this.query()?.trim().toLowerCase();
3856
- // Le globali assegnabili — `$Flow.CurrentStage`, `$Flow.ActiveStages` e quelle che l'host
3857
- // dichiara scrivibili — le comprende già `POST /flows/references/writable`: aggiungerle
3858
- // qui le duplicherebbe (§5.2, §6.4).
3859
- const all = [...this.references(), ...this.pathReferences()];
3968
+ // Le due globali assegnabili — `$Flow.CurrentStage` e `$Flow.ActiveStages` le comprende già
3969
+ // `POST /flows/references/writable`: aggiungerle qui le duplicherebbe (§5.2, §6.4).
3970
+ const all = [...this.references(), ...this.containerOptions(), ...this.pathReferences()];
3860
3971
  if (!needle) {
3861
3972
  return all;
3862
3973
  }
@@ -3913,11 +4024,16 @@ class ReferencePickerComponent {
3913
4024
  * elemento): il percorso resta fuori dalla validazione, quindi si accetta senza segnalare;
3914
4025
  * - `host`: scope del sistema ospite che **non dichiara percorsi**: non verificabile (§4.1);
3915
4026
  * - `member`: percorso dentro una forma dichiarata, verificato fino in fondo (§4.4, §4.7.1);
4027
+ * - `containerRoot`: il contenitore da solo in un campo che vuole un altro tipo: il valore e' un
4028
+ * suo membro, non lui;
3916
4029
  * - `memberUnknown`: un segmento non esiste nella sua tappa: `STRUCTURE_MEMBER_UNKNOWN` su una
3917
4030
  * classe, `FIELD_UNKNOWN` su un'entita', e a differenza di prima si sa per certo;
3918
4031
  * - `memberNotWritable`: il segmento esiste, non e' scrivibile, e questo campo vuole una
3919
4032
  * destinazione: `TARGET_NOT_WRITABLE`;
3920
4033
  * - `pathUnverified`: la catena si interrompe (`PATH_NOT_VERIFIABLE`): avviso, non errore;
4034
+ * - `globalPathUntyped`: percorso globale che porta un contenitore senza dichiararne il tipo:
4035
+ * `PATH_NOT_VERIFIABLE`, e la correzione sta nel catalogo dell'host, non nel flow (§4.1);
4036
+ * - `globalPathInvalid`: si naviga un percorso globale scalare o una collection: `GLOBAL_UNKNOWN`;
3921
4037
  * - `unknown`: nessuna corrispondenza: si avvisa, senza bloccare. Ci finisce anche il
3922
4038
  * percorso inesistente di uno scope che i percorsi li dichiara, perche' lì il backend
3923
4039
  * risponderebbe `GLOBAL_UNKNOWN`.
@@ -3937,6 +4053,11 @@ class ReferencePickerComponent {
3937
4053
  }
3938
4054
  // Dentro una forma dichiarata il percorso e' verificabile: dirlo "non verificato" sarebbe falso.
3939
4055
  if (this.navigableRoot()) {
4056
+ // Il contenitore da solo: non e' fra le proposte (lo avrebbe intercettato `known`), quindi il
4057
+ // filtro del campo lo ha scartato — e il valore giusto e' un suo membro, non lui.
4058
+ if (!this.navigatedPath()) {
4059
+ return 'containerRoot';
4060
+ }
3940
4061
  const resolution = this.resolution();
3941
4062
  switch (resolution?.status) {
3942
4063
  case 'unknown':
@@ -3944,13 +4065,30 @@ class ReferencePickerComponent {
3944
4065
  case 'unverifiable':
3945
4066
  return 'pathUnverified';
3946
4067
  case 'resolved':
3947
- return this.writableOnly() && !resolution.last?.isWritable ? 'memberNotWritable' : 'member';
4068
+ return this.writableOnly() && (this.isReadOnlyPath() || !resolution.last?.isWritable)
4069
+ ? 'memberNotWritable'
4070
+ : 'member';
3948
4071
  default:
3949
4072
  // Percorso ancora aperto (`Richiesta.`) o risposta non arrivata: non si accusa nessuno.
3950
4073
  return 'empty';
3951
4074
  }
3952
4075
  }
3953
- if (all.some((reference) => reference.name === root)) {
4076
+ /**
4077
+ * §4.1 — un percorso globale dichiarato che non porta a un contenitore. I due esiti sono
4078
+ * diversi e vanno detti diversi: senza `objectType` si sa che c'e' un contenitore ma non di che
4079
+ * tipo (`PATH_NOT_VERIFIABLE`, avviso), mentre su uno scalare o una collection non c'e'
4080
+ * proprio niente da navigare (`GLOBAL_UNKNOWN`, errore).
4081
+ */
4082
+ const prefix = this.declaredPrefix();
4083
+ if (prefix && prefix.name !== value && isGlobalReference(prefix.name)) {
4084
+ const isContainer = this.dictionaries.isStructure(prefix.dataType) || prefix.dataType === 'Object';
4085
+ return isContainer && !prefix.objectType && !prefix.isCollection
4086
+ ? 'globalPathUntyped'
4087
+ : 'globalPathInvalid';
4088
+ }
4089
+ // Fra **tutte** le radici: `Leggi_Ordine` non e' un `String`, ma `Leggi_Ordine.Numero` sì, e
4090
+ // accusarlo di non esistere sarebbe falso (§4.5).
4091
+ if (this.roots().some((reference) => reference.name === root)) {
3954
4092
  return 'navigated';
3955
4093
  }
3956
4094
  // Se l'elenco non e' arrivato, non si accusa nessuno.
@@ -3976,6 +4114,10 @@ class ReferencePickerComponent {
3976
4114
  const what = this.tailIsObject() ? 'Campo' : 'Membro';
3977
4115
  return `${what} di ${this.tailContainer()}: il percorso e’ verificato fino in fondo.`;
3978
4116
  }
4117
+ case 'containerRoot':
4118
+ return this.tailIsObject()
4119
+ ? 'Questo e’ il record intero, e il campo vuole un altro tipo: scegli un suo campo.'
4120
+ : 'Questa e’ l’istanza di classe, e il campo vuole un altro tipo: scegli un suo membro.';
3979
4121
  case 'memberUnknown': {
3980
4122
  if (!resolution) {
3981
4123
  return null;
@@ -3988,19 +4130,29 @@ class ReferencePickerComponent {
3988
4130
  return names ? `${head} Disponibili: ${names}.` : head;
3989
4131
  }
3990
4132
  case 'memberNotWritable':
4133
+ // Il motivo cambia la correzione: dentro una globale non c'e' niente da rendere scrivibile.
4134
+ if (this.isReadOnlyPath()) {
4135
+ return 'Le variabili globali sono di sola lettura, membri compresi: assegnarlo e’ TARGET_NOT_WRITABLE.';
4136
+ }
3991
4137
  return this.tailIsObject()
3992
4138
  ? 'Questo campo non si scrive ne’ creando ne’ aggiornando un record: assegnarlo e’ TARGET_NOT_WRITABLE.'
3993
4139
  : 'Questo membro e’ calcolato: si legge, ma assegnarlo e’ TARGET_NOT_WRITABLE.';
3994
4140
  case 'pathUnverified':
3995
4141
  return resolution ? pathNotVerifiableMessage(resolution) : null;
4142
+ case 'globalPathUntyped':
4143
+ return `«${this.declaredPrefix()?.name}» porta un contenitore, ma il catalogo non ne dichiara il tipo: il percorso non e’ verificabile (PATH_NOT_VERIFIABLE).`;
4144
+ case 'globalPathInvalid':
4145
+ return `«${this.declaredPrefix()?.name}» e’ un valore, non un contenitore: dopo il punto non c’e’ niente da navigare (GLOBAL_UNKNOWN).`;
3996
4146
  case 'unknown':
3997
4147
  return 'Questo nome non e’ fra i riferimenti disponibili: la validazione lo segnalerebbe.';
3998
4148
  default:
3999
4149
  return null;
4000
4150
  }
4001
4151
  }, ...(ngDevMode ? [{ debugName: "hint" }] : []));
4002
- /** I due stati che sono errori e non avvisi: il colore deve dirlo. */
4003
- isHintError = computed(() => this.valueState() === 'memberUnknown' || this.valueState() === 'memberNotWritable', ...(ngDevMode ? [{ debugName: "isHintError" }] : []));
4152
+ /** Gli stati che sono avvisi: «non lo so», o un valore da correggere che non blocca. */
4153
+ isHintWarning = computed(() => ['unknown', 'containerRoot', 'globalPathUntyped'].includes(this.valueState()), ...(ngDevMode ? [{ debugName: "isHintWarning" }] : []));
4154
+ /** Gli stati che sono errori e non avvisi: il colore deve dirlo. */
4155
+ isHintError = computed(() => ['memberUnknown', 'memberNotWritable', 'globalPathInvalid'].includes(this.valueState()), ...(ngDevMode ? [{ debugName: "isHintError" }] : []));
4004
4156
  errorMessage = computed(() => this.loadError(), ...(ngDevMode ? [{ debugName: "errorMessage" }] : []));
4005
4157
  open() {
4006
4158
  if (this.disabled()) {
@@ -4019,6 +4171,11 @@ class ReferencePickerComponent {
4019
4171
  this.query.set(value);
4020
4172
  }
4021
4173
  choose(reference) {
4174
+ // Un contenitore fuori tipo non e' un valore: cliccarlo vuol dire entrarci.
4175
+ if (this.isContainerOnly(reference)) {
4176
+ this.descend(reference);
4177
+ return;
4178
+ }
4022
4179
  this.valueChange.emit(reference.name);
4023
4180
  this.close();
4024
4181
  }
@@ -4056,14 +4213,18 @@ class ReferencePickerComponent {
4056
4213
  if (reference.description) {
4057
4214
  parts.push(reference.description);
4058
4215
  }
4216
+ if (this.isContainerOnly(reference)) {
4217
+ // Dirlo: la riga c'e' ma il valore non e' quello, e senza spiegazione sembra un errore.
4218
+ parts.push(reference.dataType === 'Object' ? 'entra e scegli un campo' : 'entra e scegli un membro');
4219
+ }
4059
4220
  return parts.join(' · ');
4060
4221
  }
4061
4222
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: ReferencePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4062
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.27", type: ReferencePickerComponent, isStandalone: true, selector: "fb-reference-picker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, dataType: { classPropertyName: "dataType", publicName: "dataType", isSignal: true, isRequired: false, transformFunction: null }, isCollection: { classPropertyName: "isCollection", publicName: "isCollection", isSignal: true, isRequired: false, transformFunction: null }, objectType: { classPropertyName: "objectType", publicName: "objectType", isSignal: true, isRequired: false, transformFunction: null }, writableOnly: { classPropertyName: "writableOnly", publicName: "writableOnly", isSignal: true, isRequired: false, transformFunction: null }, elementsOnly: { classPropertyName: "elementsOnly", publicName: "elementsOnly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: "<div class=\"fb-ref\" [class.fb-ref--open]=\"isOpen()\">\r\n <div class=\"fb-ref__control\">\r\n <input\r\n class=\"fb-ref__input\"\r\n type=\"text\"\r\n [value]=\"value() || ''\"\r\n [placeholder]=\"placeholder()\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"label()\"\r\n (input)=\"onManualInput($any($event.target).value)\"\r\n (focus)=\"open()\"\r\n />\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__toggle\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n aria-label=\"Mostra i riferimenti disponibili\"\r\n (click)=\"toggle()\"\r\n >\r\n \u25BE\r\n </button>\r\n @if (value()) {\r\n <button type=\"button\" class=\"fb-ref__clear\" aria-label=\"Svuota\" (click)=\"clear()\">\u00D7</button>\r\n }\r\n </div>\r\n\r\n @if (hint()) {\r\n <!-- Un membro inesistente o non scrivibile e' un **errore**: mostrarlo come avviso direbbe il falso. -->\r\n <p\r\n class=\"fb-ref__hint\"\r\n [class.fb-ref__hint--warn]=\"valueState() === 'unknown'\"\r\n [class.fb-ref__hint--error]=\"isHintError()\"\r\n >\r\n {{ hint() }}\r\n </p>\r\n }\r\n @if (errorMessage()) {\r\n <p class=\"fb-ref__hint fb-ref__hint--warn\">\r\n Elenco dei riferimenti non disponibile: puoi scrivere il nome a mano.\r\n </p>\r\n }\r\n\r\n @if (isOpen()) {\r\n <div class=\"fb-ref__panel\" role=\"listbox\">\r\n <input\r\n class=\"fb-ref__search\"\r\n type=\"search\"\r\n placeholder=\"Filtra\"\r\n aria-label=\"Filtra i riferimenti\"\r\n (input)=\"onQuery($any($event.target).value)\"\r\n />\r\n @if (groups().length === 0) {\r\n <p class=\"fb-ref__empty\">Nessun riferimento compatibile.</p>\r\n }\r\n @for (group of groups(); track group.kind) {\r\n <div class=\"fb-ref__group\">\r\n <span class=\"fb-ref__group-label\">{{ group.label }}</span>\r\n @for (item of group.items; track item.name) {\r\n <!-- Due bottoni dove il percorso continua: scegliere il riferimento e scendere di un\r\n livello sono cose diverse, e su una Structure o un record servono entrambe. -->\r\n <div class=\"fb-ref__row\">\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__option\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"item.name === value()\"\r\n (click)=\"choose(item)\"\r\n >\r\n <span class=\"fb-ref__name\">{{ item.name }}</span>\r\n <span class=\"fb-ref__meta\">{{ describe(item) }}</span>\r\n </button>\r\n @if (canDescend(item)) {\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__into\"\r\n [attr.aria-label]=\"'Entra in ' + item.name\"\r\n title=\"Entra e proponi i segmenti\"\r\n (click)=\"descend(item)\"\r\n >\r\n \u203A\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <button type=\"button\" class=\"fb-ref__close\" (click)=\"close()\">Chiudi</button>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block}.fb-ref{position:relative}.fb-ref__control{display:flex;align-items:stretch;gap:0;border:1px solid var(--fb-border, #d6dae1);border-radius:6px;background:var(--fb-surface, #fff);overflow:hidden}.fb-ref--open .fb-ref__control{border-color:var(--fb-accent, #2f6feb)}.fb-ref__input{flex:1;min-width:0;padding:5px 7px;border:0;background:transparent;color:var(--fb-text, #1d2939);font:inherit;font-size:12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.fb-ref__input:focus-visible{outline:none}.fb-ref__toggle,.fb-ref__clear{flex:0 0 auto;padding:0 7px;border:0;border-left:1px solid var(--fb-border-subtle, #e6e9ee);background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:12px;cursor:pointer}.fb-ref__toggle:hover,.fb-ref__clear:hover{background:var(--fb-surface-alt, #f8f9fb)}.fb-ref__hint{margin:3px 0 0;font-size:10px;line-height:1.35;color:var(--fb-text-subtle, #98a2b3)}.fb-ref__hint--warn{color:var(--fb-warning, #b7791f)}.fb-ref__hint--error{color:var(--fb-error, #c9372c)}.fb-ref__panel{position:absolute;z-index:30;top:calc(100% + 3px);left:0;right:0;max-height:260px;overflow-y:auto;padding:6px;border:1px solid var(--fb-border, #d6dae1);border-radius:6px;background:var(--fb-surface, #fff);box-shadow:0 6px 18px #10182829}.fb-ref__search{box-sizing:border-box;width:100%;margin-bottom:6px;padding:4px 6px;border:1px solid var(--fb-border, #d6dae1);border-radius:5px;font:inherit;font-size:12px}.fb-ref__group{margin-bottom:6px}.fb-ref__group-label{display:block;padding:2px 4px;font-size:9px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--fb-text-subtle, #98a2b3)}.fb-ref__row{display:flex;align-items:stretch;gap:2px}.fb-ref__into{flex:0 0 auto;padding:0 7px;border:0;border-radius:4px;background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:13px;cursor:pointer}.fb-ref__into:hover{background:var(--fb-surface-alt, #f8f9fb);color:var(--fb-accent, #2f6feb)}.fb-ref__option{display:flex;flex:1;flex-direction:column;min-width:0;width:100%;padding:4px 6px;border:0;border-radius:4px;background:transparent;color:var(--fb-text, #1d2939);font:inherit;text-align:left;cursor:pointer}.fb-ref__option:hover,.fb-ref__option[aria-selected=true]{background:var(--fb-surface-alt, #f8f9fb)}.fb-ref__name{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.fb-ref__meta{font-size:10px;color:var(--fb-text-muted, #667085)}.fb-ref__empty{margin:4px;font-size:11px;color:var(--fb-text-muted, #667085)}.fb-ref__close{width:100%;margin-top:4px;padding:4px;border:0;border-top:1px solid var(--fb-border-subtle, #e6e9ee);background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:11px;cursor:pointer}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4223
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.27", type: ReferencePickerComponent, isStandalone: true, selector: "fb-reference-picker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, dataType: { classPropertyName: "dataType", publicName: "dataType", isSignal: true, isRequired: false, transformFunction: null }, isCollection: { classPropertyName: "isCollection", publicName: "isCollection", isSignal: true, isRequired: false, transformFunction: null }, objectType: { classPropertyName: "objectType", publicName: "objectType", isSignal: true, isRequired: false, transformFunction: null }, writableOnly: { classPropertyName: "writableOnly", publicName: "writableOnly", isSignal: true, isRequired: false, transformFunction: null }, elementsOnly: { classPropertyName: "elementsOnly", publicName: "elementsOnly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: "<div class=\"fb-ref\" [class.fb-ref--open]=\"isOpen()\">\r\n <div class=\"fb-ref__control\">\r\n <input\r\n class=\"fb-ref__input\"\r\n type=\"text\"\r\n [value]=\"value() || ''\"\r\n [placeholder]=\"placeholder()\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"label()\"\r\n (input)=\"onManualInput($any($event.target).value)\"\r\n (focus)=\"open()\"\r\n />\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__toggle\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n aria-label=\"Mostra i riferimenti disponibili\"\r\n (click)=\"toggle()\"\r\n >\r\n \u25BE\r\n </button>\r\n @if (value()) {\r\n <button type=\"button\" class=\"fb-ref__clear\" aria-label=\"Svuota\" (click)=\"clear()\">\u00D7</button>\r\n }\r\n </div>\r\n\r\n @if (hint()) {\r\n <!-- Un membro inesistente o non scrivibile e' un **errore**: mostrarlo come avviso direbbe il falso. -->\r\n <p\r\n class=\"fb-ref__hint\"\r\n [class.fb-ref__hint--warn]=\"isHintWarning()\"\r\n [class.fb-ref__hint--error]=\"isHintError()\"\r\n >\r\n {{ hint() }}\r\n </p>\r\n }\r\n @if (errorMessage()) {\r\n <p class=\"fb-ref__hint fb-ref__hint--warn\">\r\n Elenco dei riferimenti non disponibile: puoi scrivere il nome a mano.\r\n </p>\r\n }\r\n\r\n @if (isOpen()) {\r\n <div class=\"fb-ref__panel\" role=\"listbox\">\r\n <input\r\n class=\"fb-ref__search\"\r\n type=\"search\"\r\n placeholder=\"Filtra\"\r\n aria-label=\"Filtra i riferimenti\"\r\n (input)=\"onQuery($any($event.target).value)\"\r\n />\r\n @if (groups().length === 0) {\r\n <p class=\"fb-ref__empty\">Nessun riferimento compatibile.</p>\r\n }\r\n @for (group of groups(); track group.kind) {\r\n <div class=\"fb-ref__group\">\r\n <span class=\"fb-ref__group-label\">{{ group.label }}</span>\r\n @for (item of group.items; track item.name) {\r\n <!-- Due bottoni dove il percorso continua: scegliere il riferimento e scendere di un\r\n livello sono cose diverse, e su una Structure o un record servono entrambe. -->\r\n <div class=\"fb-ref__row\">\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__option\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"item.name === value()\"\r\n [title]=\"isContainerOnly(item) ? 'Il tipo non e\u2019 quello del campo: entra e scegli dentro' : ''\"\r\n (click)=\"choose(item)\"\r\n >\r\n <span class=\"fb-ref__name\">{{ item.name }}</span>\r\n <span class=\"fb-ref__meta\">{{ describe(item) }}</span>\r\n </button>\r\n @if (canDescend(item)) {\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__into\"\r\n [attr.aria-label]=\"'Entra in ' + item.name\"\r\n title=\"Entra e proponi i segmenti\"\r\n (click)=\"descend(item)\"\r\n >\r\n \u203A\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <button type=\"button\" class=\"fb-ref__close\" (click)=\"close()\">Chiudi</button>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block}.fb-ref{position:relative}.fb-ref__control{display:flex;align-items:stretch;gap:0;border:1px solid var(--fb-border, #d6dae1);border-radius:6px;background:var(--fb-surface, #fff);overflow:hidden}.fb-ref--open .fb-ref__control{border-color:var(--fb-accent, #2f6feb)}.fb-ref__input{flex:1;min-width:0;padding:5px 7px;border:0;background:transparent;color:var(--fb-text, #1d2939);font:inherit;font-size:12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.fb-ref__input:focus-visible{outline:none}.fb-ref__toggle,.fb-ref__clear{flex:0 0 auto;padding:0 7px;border:0;border-left:1px solid var(--fb-border-subtle, #e6e9ee);background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:12px;cursor:pointer}.fb-ref__toggle:hover,.fb-ref__clear:hover{background:var(--fb-surface-alt, #f8f9fb)}.fb-ref__hint{margin:3px 0 0;font-size:10px;line-height:1.35;color:var(--fb-text-subtle, #98a2b3)}.fb-ref__hint--warn{color:var(--fb-warning, #b7791f)}.fb-ref__hint--error{color:var(--fb-error, #c9372c)}.fb-ref__panel{position:absolute;z-index:30;top:calc(100% + 3px);left:0;right:0;max-height:260px;overflow-y:auto;padding:6px;border:1px solid var(--fb-border, #d6dae1);border-radius:6px;background:var(--fb-surface, #fff);box-shadow:0 6px 18px #10182829}.fb-ref__search{box-sizing:border-box;width:100%;margin-bottom:6px;padding:4px 6px;border:1px solid var(--fb-border, #d6dae1);border-radius:5px;font:inherit;font-size:12px}.fb-ref__group{margin-bottom:6px}.fb-ref__group-label{display:block;padding:2px 4px;font-size:9px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--fb-text-subtle, #98a2b3)}.fb-ref__row{display:flex;align-items:stretch;gap:2px}.fb-ref__into{flex:0 0 auto;padding:0 7px;border:0;border-radius:4px;background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:13px;cursor:pointer}.fb-ref__into:hover{background:var(--fb-surface-alt, #f8f9fb);color:var(--fb-accent, #2f6feb)}.fb-ref__option{display:flex;flex:1;flex-direction:column;min-width:0;width:100%;padding:4px 6px;border:0;border-radius:4px;background:transparent;color:var(--fb-text, #1d2939);font:inherit;text-align:left;cursor:pointer}.fb-ref__option:hover,.fb-ref__option[aria-selected=true]{background:var(--fb-surface-alt, #f8f9fb)}.fb-ref__name{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.fb-ref__meta{font-size:10px;color:var(--fb-text-muted, #667085)}.fb-ref__empty{margin:4px;font-size:11px;color:var(--fb-text-muted, #667085)}.fb-ref__close{width:100%;margin-top:4px;padding:4px;border:0;border-top:1px solid var(--fb-border-subtle, #e6e9ee);background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:11px;cursor:pointer}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4063
4224
  }
4064
4225
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImport: i0, type: ReferencePickerComponent, decorators: [{
4065
4226
  type: Component,
4066
- args: [{ selector: 'fb-reference-picker', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-ref\" [class.fb-ref--open]=\"isOpen()\">\r\n <div class=\"fb-ref__control\">\r\n <input\r\n class=\"fb-ref__input\"\r\n type=\"text\"\r\n [value]=\"value() || ''\"\r\n [placeholder]=\"placeholder()\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"label()\"\r\n (input)=\"onManualInput($any($event.target).value)\"\r\n (focus)=\"open()\"\r\n />\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__toggle\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n aria-label=\"Mostra i riferimenti disponibili\"\r\n (click)=\"toggle()\"\r\n >\r\n \u25BE\r\n </button>\r\n @if (value()) {\r\n <button type=\"button\" class=\"fb-ref__clear\" aria-label=\"Svuota\" (click)=\"clear()\">\u00D7</button>\r\n }\r\n </div>\r\n\r\n @if (hint()) {\r\n <!-- Un membro inesistente o non scrivibile e' un **errore**: mostrarlo come avviso direbbe il falso. -->\r\n <p\r\n class=\"fb-ref__hint\"\r\n [class.fb-ref__hint--warn]=\"valueState() === 'unknown'\"\r\n [class.fb-ref__hint--error]=\"isHintError()\"\r\n >\r\n {{ hint() }}\r\n </p>\r\n }\r\n @if (errorMessage()) {\r\n <p class=\"fb-ref__hint fb-ref__hint--warn\">\r\n Elenco dei riferimenti non disponibile: puoi scrivere il nome a mano.\r\n </p>\r\n }\r\n\r\n @if (isOpen()) {\r\n <div class=\"fb-ref__panel\" role=\"listbox\">\r\n <input\r\n class=\"fb-ref__search\"\r\n type=\"search\"\r\n placeholder=\"Filtra\"\r\n aria-label=\"Filtra i riferimenti\"\r\n (input)=\"onQuery($any($event.target).value)\"\r\n />\r\n @if (groups().length === 0) {\r\n <p class=\"fb-ref__empty\">Nessun riferimento compatibile.</p>\r\n }\r\n @for (group of groups(); track group.kind) {\r\n <div class=\"fb-ref__group\">\r\n <span class=\"fb-ref__group-label\">{{ group.label }}</span>\r\n @for (item of group.items; track item.name) {\r\n <!-- Due bottoni dove il percorso continua: scegliere il riferimento e scendere di un\r\n livello sono cose diverse, e su una Structure o un record servono entrambe. -->\r\n <div class=\"fb-ref__row\">\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__option\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"item.name === value()\"\r\n (click)=\"choose(item)\"\r\n >\r\n <span class=\"fb-ref__name\">{{ item.name }}</span>\r\n <span class=\"fb-ref__meta\">{{ describe(item) }}</span>\r\n </button>\r\n @if (canDescend(item)) {\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__into\"\r\n [attr.aria-label]=\"'Entra in ' + item.name\"\r\n title=\"Entra e proponi i segmenti\"\r\n (click)=\"descend(item)\"\r\n >\r\n \u203A\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <button type=\"button\" class=\"fb-ref__close\" (click)=\"close()\">Chiudi</button>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block}.fb-ref{position:relative}.fb-ref__control{display:flex;align-items:stretch;gap:0;border:1px solid var(--fb-border, #d6dae1);border-radius:6px;background:var(--fb-surface, #fff);overflow:hidden}.fb-ref--open .fb-ref__control{border-color:var(--fb-accent, #2f6feb)}.fb-ref__input{flex:1;min-width:0;padding:5px 7px;border:0;background:transparent;color:var(--fb-text, #1d2939);font:inherit;font-size:12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.fb-ref__input:focus-visible{outline:none}.fb-ref__toggle,.fb-ref__clear{flex:0 0 auto;padding:0 7px;border:0;border-left:1px solid var(--fb-border-subtle, #e6e9ee);background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:12px;cursor:pointer}.fb-ref__toggle:hover,.fb-ref__clear:hover{background:var(--fb-surface-alt, #f8f9fb)}.fb-ref__hint{margin:3px 0 0;font-size:10px;line-height:1.35;color:var(--fb-text-subtle, #98a2b3)}.fb-ref__hint--warn{color:var(--fb-warning, #b7791f)}.fb-ref__hint--error{color:var(--fb-error, #c9372c)}.fb-ref__panel{position:absolute;z-index:30;top:calc(100% + 3px);left:0;right:0;max-height:260px;overflow-y:auto;padding:6px;border:1px solid var(--fb-border, #d6dae1);border-radius:6px;background:var(--fb-surface, #fff);box-shadow:0 6px 18px #10182829}.fb-ref__search{box-sizing:border-box;width:100%;margin-bottom:6px;padding:4px 6px;border:1px solid var(--fb-border, #d6dae1);border-radius:5px;font:inherit;font-size:12px}.fb-ref__group{margin-bottom:6px}.fb-ref__group-label{display:block;padding:2px 4px;font-size:9px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--fb-text-subtle, #98a2b3)}.fb-ref__row{display:flex;align-items:stretch;gap:2px}.fb-ref__into{flex:0 0 auto;padding:0 7px;border:0;border-radius:4px;background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:13px;cursor:pointer}.fb-ref__into:hover{background:var(--fb-surface-alt, #f8f9fb);color:var(--fb-accent, #2f6feb)}.fb-ref__option{display:flex;flex:1;flex-direction:column;min-width:0;width:100%;padding:4px 6px;border:0;border-radius:4px;background:transparent;color:var(--fb-text, #1d2939);font:inherit;text-align:left;cursor:pointer}.fb-ref__option:hover,.fb-ref__option[aria-selected=true]{background:var(--fb-surface-alt, #f8f9fb)}.fb-ref__name{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.fb-ref__meta{font-size:10px;color:var(--fb-text-muted, #667085)}.fb-ref__empty{margin:4px;font-size:11px;color:var(--fb-text-muted, #667085)}.fb-ref__close{width:100%;margin-top:4px;padding:4px;border:0;border-top:1px solid var(--fb-border-subtle, #e6e9ee);background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:11px;cursor:pointer}\n"] }]
4227
+ args: [{ selector: 'fb-reference-picker', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"fb-ref\" [class.fb-ref--open]=\"isOpen()\">\r\n <div class=\"fb-ref__control\">\r\n <input\r\n class=\"fb-ref__input\"\r\n type=\"text\"\r\n [value]=\"value() || ''\"\r\n [placeholder]=\"placeholder()\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-label]=\"label()\"\r\n (input)=\"onManualInput($any($event.target).value)\"\r\n (focus)=\"open()\"\r\n />\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__toggle\"\r\n [disabled]=\"disabled()\"\r\n [attr.aria-expanded]=\"isOpen()\"\r\n aria-label=\"Mostra i riferimenti disponibili\"\r\n (click)=\"toggle()\"\r\n >\r\n \u25BE\r\n </button>\r\n @if (value()) {\r\n <button type=\"button\" class=\"fb-ref__clear\" aria-label=\"Svuota\" (click)=\"clear()\">\u00D7</button>\r\n }\r\n </div>\r\n\r\n @if (hint()) {\r\n <!-- Un membro inesistente o non scrivibile e' un **errore**: mostrarlo come avviso direbbe il falso. -->\r\n <p\r\n class=\"fb-ref__hint\"\r\n [class.fb-ref__hint--warn]=\"isHintWarning()\"\r\n [class.fb-ref__hint--error]=\"isHintError()\"\r\n >\r\n {{ hint() }}\r\n </p>\r\n }\r\n @if (errorMessage()) {\r\n <p class=\"fb-ref__hint fb-ref__hint--warn\">\r\n Elenco dei riferimenti non disponibile: puoi scrivere il nome a mano.\r\n </p>\r\n }\r\n\r\n @if (isOpen()) {\r\n <div class=\"fb-ref__panel\" role=\"listbox\">\r\n <input\r\n class=\"fb-ref__search\"\r\n type=\"search\"\r\n placeholder=\"Filtra\"\r\n aria-label=\"Filtra i riferimenti\"\r\n (input)=\"onQuery($any($event.target).value)\"\r\n />\r\n @if (groups().length === 0) {\r\n <p class=\"fb-ref__empty\">Nessun riferimento compatibile.</p>\r\n }\r\n @for (group of groups(); track group.kind) {\r\n <div class=\"fb-ref__group\">\r\n <span class=\"fb-ref__group-label\">{{ group.label }}</span>\r\n @for (item of group.items; track item.name) {\r\n <!-- Due bottoni dove il percorso continua: scegliere il riferimento e scendere di un\r\n livello sono cose diverse, e su una Structure o un record servono entrambe. -->\r\n <div class=\"fb-ref__row\">\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__option\"\r\n role=\"option\"\r\n [attr.aria-selected]=\"item.name === value()\"\r\n [title]=\"isContainerOnly(item) ? 'Il tipo non e\u2019 quello del campo: entra e scegli dentro' : ''\"\r\n (click)=\"choose(item)\"\r\n >\r\n <span class=\"fb-ref__name\">{{ item.name }}</span>\r\n <span class=\"fb-ref__meta\">{{ describe(item) }}</span>\r\n </button>\r\n @if (canDescend(item)) {\r\n <button\r\n type=\"button\"\r\n class=\"fb-ref__into\"\r\n [attr.aria-label]=\"'Entra in ' + item.name\"\r\n title=\"Entra e proponi i segmenti\"\r\n (click)=\"descend(item)\"\r\n >\r\n \u203A\r\n </button>\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n <button type=\"button\" class=\"fb-ref__close\" (click)=\"close()\">Chiudi</button>\r\n </div>\r\n }\r\n</div>\r\n", styles: [":host{display:block}.fb-ref{position:relative}.fb-ref__control{display:flex;align-items:stretch;gap:0;border:1px solid var(--fb-border, #d6dae1);border-radius:6px;background:var(--fb-surface, #fff);overflow:hidden}.fb-ref--open .fb-ref__control{border-color:var(--fb-accent, #2f6feb)}.fb-ref__input{flex:1;min-width:0;padding:5px 7px;border:0;background:transparent;color:var(--fb-text, #1d2939);font:inherit;font-size:12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.fb-ref__input:focus-visible{outline:none}.fb-ref__toggle,.fb-ref__clear{flex:0 0 auto;padding:0 7px;border:0;border-left:1px solid var(--fb-border-subtle, #e6e9ee);background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:12px;cursor:pointer}.fb-ref__toggle:hover,.fb-ref__clear:hover{background:var(--fb-surface-alt, #f8f9fb)}.fb-ref__hint{margin:3px 0 0;font-size:10px;line-height:1.35;color:var(--fb-text-subtle, #98a2b3)}.fb-ref__hint--warn{color:var(--fb-warning, #b7791f)}.fb-ref__hint--error{color:var(--fb-error, #c9372c)}.fb-ref__panel{position:absolute;z-index:30;top:calc(100% + 3px);left:0;right:0;max-height:260px;overflow-y:auto;padding:6px;border:1px solid var(--fb-border, #d6dae1);border-radius:6px;background:var(--fb-surface, #fff);box-shadow:0 6px 18px #10182829}.fb-ref__search{box-sizing:border-box;width:100%;margin-bottom:6px;padding:4px 6px;border:1px solid var(--fb-border, #d6dae1);border-radius:5px;font:inherit;font-size:12px}.fb-ref__group{margin-bottom:6px}.fb-ref__group-label{display:block;padding:2px 4px;font-size:9px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--fb-text-subtle, #98a2b3)}.fb-ref__row{display:flex;align-items:stretch;gap:2px}.fb-ref__into{flex:0 0 auto;padding:0 7px;border:0;border-radius:4px;background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:13px;cursor:pointer}.fb-ref__into:hover{background:var(--fb-surface-alt, #f8f9fb);color:var(--fb-accent, #2f6feb)}.fb-ref__option{display:flex;flex:1;flex-direction:column;min-width:0;width:100%;padding:4px 6px;border:0;border-radius:4px;background:transparent;color:var(--fb-text, #1d2939);font:inherit;text-align:left;cursor:pointer}.fb-ref__option:hover,.fb-ref__option[aria-selected=true]{background:var(--fb-surface-alt, #f8f9fb)}.fb-ref__name{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}.fb-ref__meta{font-size:10px;color:var(--fb-text-muted, #667085)}.fb-ref__empty{margin:4px;font-size:11px;color:var(--fb-text-muted, #667085)}.fb-ref__close{width:100%;margin-top:4px;padding:4px;border:0;border-top:1px solid var(--fb-border-subtle, #e6e9ee);background:transparent;color:var(--fb-text-muted, #667085);font:inherit;font-size:11px;cursor:pointer}\n"] }]
4067
4228
  }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], dataType: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataType", required: false }] }], isCollection: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCollection", required: false }] }], objectType: [{ type: i0.Input, args: [{ isSignal: true, alias: "objectType", required: false }] }], writableOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "writableOnly", required: false }] }], elementsOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "elementsOnly", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
4068
4229
 
4069
4230
  /**
@@ -6118,9 +6279,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.27", ngImpo
6118
6279
  * 1. **Le operazioni sono eseguite nell'ordine dichiarato**, quindi devono essere
6119
6280
  * riordinabili: un'interfaccia che le presenta come un insieme nasconde la semantica.
6120
6281
  * 2. **Cosa puo' stare in `assignToReference`**: una variabile, un campo di una variabile
6121
- * record, un campo di `$Record` e, fra le globali, `$Flow.CurrentStage`,
6122
- * `$Flow.ActiveStages` e quelle che il sistema ospite dichiara scrivibili le propone
6123
- * già `POST /flows/references/writable`. Tutto il resto e' di sola lettura.
6282
+ * record, un campo di `$Record` e, fra le globali, soltanto `$Flow.CurrentStage` e
6283
+ * `$Flow.ActiveStages` le propone già `POST /flows/references/writable`. Tutto il resto e'
6284
+ * di sola lettura, comprese le globali dell'host e i loro membri (§5.2).
6124
6285
  * 3. Gli operatori marcati `expectsCollection` hanno senso **solo** su destinazioni
6125
6286
  * collection: su una variabile singola non falliscono, non fanno nulla.
6126
6287
  */