ngx-recipe-forms 0.1.1 → 0.1.2

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.
@@ -5332,6 +5332,7 @@ var RecipeFieldComponent = class RecipeFieldComponent {
5332
5332
  idPrefix = input.required(...ngDevMode ? [{ debugName: "idPrefix" }] : /* istanbul ignore next */ []);
5333
5333
  serverPrefix = input("", ...ngDevMode ? [{ debugName: "serverPrefix" }] : /* istanbul ignore next */ []);
5334
5334
  hideLabel = input(false, ...ngDevMode ? [{ debugName: "hideLabel" }] : /* istanbul ignore next */ []);
5335
+ inline = input(false, ...ngDevMode ? [{ debugName: "inline" }] : /* istanbul ignore next */ []);
5335
5336
  extraMessage = input(...ngDevMode ? [void 0, { debugName: "extraMessage" }] : /* istanbul ignore next */ []);
5336
5337
  extraDescribedBy = input(...ngDevMode ? [void 0, { debugName: "extraDescribedBy" }] : /* istanbul ignore next */ []);
5337
5338
  context = inject(RecipeFormContext, { optional: true }) ?? new RecipeFormContext();
@@ -5551,6 +5552,13 @@ var RecipeFieldComponent = class RecipeFieldComponent {
5551
5552
  isRequired: false,
5552
5553
  transformFunction: null
5553
5554
  },
5555
+ inline: {
5556
+ classPropertyName: "inline",
5557
+ publicName: "inline",
5558
+ isSignal: true,
5559
+ isRequired: false,
5560
+ transformFunction: null
5561
+ },
5554
5562
  extraMessage: {
5555
5563
  classPropertyName: "extraMessage",
5556
5564
  publicName: "extraMessage",
@@ -5568,7 +5576,7 @@ var RecipeFieldComponent = class RecipeFieldComponent {
5568
5576
  },
5569
5577
  host: { properties: { "class": "hostClasses()" } },
5570
5578
  ngImport: i0,
5571
- template: "@let n = node();\r\n@let s = state();\r\n@if (!s.hidden()) {\r\n <label\r\n [for]=\"inputId()\"\r\n [id]=\"labelId()\"\r\n [class]=\"hideLabel() ? 'sr-only' : 'text-sm font-semibold text-slate-800'\"\r\n >\r\n {{ n.labelKey | recipeTranslate }}\r\n @if (s.required() && !s.readonly()) {\r\n <span aria-hidden=\"true\" class=\"text-red-600\">*</span>\r\n }\r\n </label>\r\n @switch (n.control.type) {\r\n @case (types.DISPLAY) {\r\n <output [id]=\"inputId()\" class=\"rounded-md bg-slate-50 px-3 py-2 text-sm text-slate-700\">{{\r\n displayValue()\r\n }}</output>\r\n }\r\n @case (types.SLOT) {\r\n @if (slotTemplate(); as template) {\r\n <ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"slotContext()\" />\r\n }\r\n }\r\n @default {\r\n <!-- Gabarit du registre : celui de l'hôte (`provideRecipeForms({ ui })`), sinon celui par défaut. -->\r\n @if (control(); as c) {\r\n <ng-container [ngTemplateOutlet]=\"c.template\" [ngTemplateOutletContext]=\"c.context\" />\r\n }\r\n }\r\n }\r\n @if (hintKey(); as hint) {\r\n <p [id]=\"hintId()\" class=\"text-xs text-slate-500\">{{ hint | recipeTranslate }}</p>\r\n }\r\n <!-- Raison d'une règle `disabled` active : comme l'aide, après elle, retirée dès que le champ est réactivé. -->\r\n @if (disabledReasonKeys().length > 0) {\r\n <p [id]=\"reasonId()\" class=\"text-xs text-slate-500\">\r\n @for (reasonKey of disabledReasonKeys(); track reasonKey) {\r\n <span class=\"block\">{{ reasonKey | recipeTranslate }}</span>\r\n }\r\n </p>\r\n }\r\n @if (s.pending()) {\r\n <app-recipe-message\r\n [severity]=\"severities.SECONDARY\"\r\n [inline]=\"true\"\r\n [text]=\"'forms.pending' | recipeTranslate\"\r\n />\r\n }\r\n @if (warnings().length > 0) {\r\n <div [id]=\"warningsId()\" role=\"status\" class=\"flex flex-col gap-0.5\">\r\n @for (w of warnings(); track $index) {\r\n <app-recipe-message\r\n [severity]=\"severities.WARNING\"\r\n [inline]=\"true\"\r\n [text]=\"w.key | recipeTranslate: w.params : w.text\"\r\n />\r\n }\r\n </div>\r\n }\r\n @if (message(); as m) {\r\n <app-recipe-message\r\n [id]=\"messageId()\"\r\n [severity]=\"severities.DANGER\"\r\n [inline]=\"true\"\r\n [text]=\"m.key | recipeTranslate: m.params : m.text\"\r\n />\r\n }\r\n}\r\n",
5579
+ template: "@let n = node();\n@let s = state();\n@if (!s.hidden()) {\n @if (inline()) {\n <!-- En ligne (cellule de tableau) : le contrôle, centré sur la hauteur d'un champ de saisie, puis son libellé. -->\n <div class=\"flex min-h-9 items-center gap-1.5\">\n <ng-container [ngTemplateOutlet]=\"controlTemplate\" />\n <ng-container [ngTemplateOutlet]=\"labelTemplate\" />\n </div>\n } @else {\n <ng-container [ngTemplateOutlet]=\"labelTemplate\" />\n <ng-container [ngTemplateOutlet]=\"controlTemplate\" />\n }\n @if (hintKey(); as hint) {\n <p [id]=\"hintId()\" class=\"text-xs text-slate-500\">{{ hint | recipeTranslate }}</p>\n }\n <!-- Raison d'une règle `disabled` active : comme l'aide, après elle, retirée dès que le champ est réactivé. -->\n @if (disabledReasonKeys().length > 0) {\n <p [id]=\"reasonId()\" class=\"text-xs text-slate-500\">\n @for (reasonKey of disabledReasonKeys(); track reasonKey) {\n <span class=\"block\">{{ reasonKey | recipeTranslate }}</span>\n }\n </p>\n }\n @if (s.pending()) {\n <app-recipe-message\n [severity]=\"severities.SECONDARY\"\n [inline]=\"true\"\n [text]=\"'forms.pending' | recipeTranslate\"\n />\n }\n @if (warnings().length > 0) {\n <div [id]=\"warningsId()\" role=\"status\" class=\"flex flex-col gap-0.5\">\n @for (w of warnings(); track $index) {\n <app-recipe-message\n [severity]=\"severities.WARNING\"\n [inline]=\"true\"\n [text]=\"w.key | recipeTranslate: w.params : w.text\"\n />\n }\n </div>\n }\n @if (message(); as m) {\n <app-recipe-message\n [id]=\"messageId()\"\n [severity]=\"severities.DANGER\"\n [inline]=\"true\"\n [text]=\"m.key | recipeTranslate: m.params : m.text\"\n />\n }\n}\n\n<ng-template #labelTemplate>\n <label\n [for]=\"inputId()\"\n [id]=\"labelId()\"\n [class]=\"hideLabel() ? 'sr-only' : 'text-sm font-semibold text-slate-800'\"\n >\n {{ n.labelKey | recipeTranslate }}\n @if (s.required() && !s.readonly()) {\n <span aria-hidden=\"true\" class=\"text-red-600\">*</span>\n }\n </label>\n</ng-template>\n\n<ng-template #controlTemplate>\n @switch (n.control.type) {\n @case (types.DISPLAY) {\n <output [id]=\"inputId()\" class=\"rounded-md bg-slate-50 px-3 py-2 text-sm text-slate-700\">{{\n displayValue()\n }}</output>\n }\n @case (types.SLOT) {\n @if (slotTemplate(); as template) {\n <ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"slotContext()\" />\n }\n }\n @default {\n <!-- Gabarit du registre : celui de l'hôte (`provideRecipeForms({ ui })`), sinon celui par défaut. -->\n @if (control(); as c) {\n <ng-container [ngTemplateOutlet]=\"c.template\" [ngTemplateOutletContext]=\"c.context\" />\n }\n }\n }\n</ng-template>\n",
5572
5580
  dependencies: [
5573
5581
  {
5574
5582
  kind: "directive",
@@ -5615,7 +5623,7 @@ i0.ɵɵngDeclareClassMetadata({
5615
5623
  ],
5616
5624
  changeDetection: ChangeDetectionStrategy.OnPush,
5617
5625
  host: { "[class]": "hostClasses()" },
5618
- template: "@let n = node();\r\n@let s = state();\r\n@if (!s.hidden()) {\r\n <label\r\n [for]=\"inputId()\"\r\n [id]=\"labelId()\"\r\n [class]=\"hideLabel() ? 'sr-only' : 'text-sm font-semibold text-slate-800'\"\r\n >\r\n {{ n.labelKey | recipeTranslate }}\r\n @if (s.required() && !s.readonly()) {\r\n <span aria-hidden=\"true\" class=\"text-red-600\">*</span>\r\n }\r\n </label>\r\n @switch (n.control.type) {\r\n @case (types.DISPLAY) {\r\n <output [id]=\"inputId()\" class=\"rounded-md bg-slate-50 px-3 py-2 text-sm text-slate-700\">{{\r\n displayValue()\r\n }}</output>\r\n }\r\n @case (types.SLOT) {\r\n @if (slotTemplate(); as template) {\r\n <ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"slotContext()\" />\r\n }\r\n }\r\n @default {\r\n <!-- Gabarit du registre : celui de l'hôte (`provideRecipeForms({ ui })`), sinon celui par défaut. -->\r\n @if (control(); as c) {\r\n <ng-container [ngTemplateOutlet]=\"c.template\" [ngTemplateOutletContext]=\"c.context\" />\r\n }\r\n }\r\n }\r\n @if (hintKey(); as hint) {\r\n <p [id]=\"hintId()\" class=\"text-xs text-slate-500\">{{ hint | recipeTranslate }}</p>\r\n }\r\n <!-- Raison d'une règle `disabled` active : comme l'aide, après elle, retirée dès que le champ est réactivé. -->\r\n @if (disabledReasonKeys().length > 0) {\r\n <p [id]=\"reasonId()\" class=\"text-xs text-slate-500\">\r\n @for (reasonKey of disabledReasonKeys(); track reasonKey) {\r\n <span class=\"block\">{{ reasonKey | recipeTranslate }}</span>\r\n }\r\n </p>\r\n }\r\n @if (s.pending()) {\r\n <app-recipe-message\r\n [severity]=\"severities.SECONDARY\"\r\n [inline]=\"true\"\r\n [text]=\"'forms.pending' | recipeTranslate\"\r\n />\r\n }\r\n @if (warnings().length > 0) {\r\n <div [id]=\"warningsId()\" role=\"status\" class=\"flex flex-col gap-0.5\">\r\n @for (w of warnings(); track $index) {\r\n <app-recipe-message\r\n [severity]=\"severities.WARNING\"\r\n [inline]=\"true\"\r\n [text]=\"w.key | recipeTranslate: w.params : w.text\"\r\n />\r\n }\r\n </div>\r\n }\r\n @if (message(); as m) {\r\n <app-recipe-message\r\n [id]=\"messageId()\"\r\n [severity]=\"severities.DANGER\"\r\n [inline]=\"true\"\r\n [text]=\"m.key | recipeTranslate: m.params : m.text\"\r\n />\r\n }\r\n}\r\n"
5626
+ template: "@let n = node();\n@let s = state();\n@if (!s.hidden()) {\n @if (inline()) {\n <!-- En ligne (cellule de tableau) : le contrôle, centré sur la hauteur d'un champ de saisie, puis son libellé. -->\n <div class=\"flex min-h-9 items-center gap-1.5\">\n <ng-container [ngTemplateOutlet]=\"controlTemplate\" />\n <ng-container [ngTemplateOutlet]=\"labelTemplate\" />\n </div>\n } @else {\n <ng-container [ngTemplateOutlet]=\"labelTemplate\" />\n <ng-container [ngTemplateOutlet]=\"controlTemplate\" />\n }\n @if (hintKey(); as hint) {\n <p [id]=\"hintId()\" class=\"text-xs text-slate-500\">{{ hint | recipeTranslate }}</p>\n }\n <!-- Raison d'une règle `disabled` active : comme l'aide, après elle, retirée dès que le champ est réactivé. -->\n @if (disabledReasonKeys().length > 0) {\n <p [id]=\"reasonId()\" class=\"text-xs text-slate-500\">\n @for (reasonKey of disabledReasonKeys(); track reasonKey) {\n <span class=\"block\">{{ reasonKey | recipeTranslate }}</span>\n }\n </p>\n }\n @if (s.pending()) {\n <app-recipe-message\n [severity]=\"severities.SECONDARY\"\n [inline]=\"true\"\n [text]=\"'forms.pending' | recipeTranslate\"\n />\n }\n @if (warnings().length > 0) {\n <div [id]=\"warningsId()\" role=\"status\" class=\"flex flex-col gap-0.5\">\n @for (w of warnings(); track $index) {\n <app-recipe-message\n [severity]=\"severities.WARNING\"\n [inline]=\"true\"\n [text]=\"w.key | recipeTranslate: w.params : w.text\"\n />\n }\n </div>\n }\n @if (message(); as m) {\n <app-recipe-message\n [id]=\"messageId()\"\n [severity]=\"severities.DANGER\"\n [inline]=\"true\"\n [text]=\"m.key | recipeTranslate: m.params : m.text\"\n />\n }\n}\n\n<ng-template #labelTemplate>\n <label\n [for]=\"inputId()\"\n [id]=\"labelId()\"\n [class]=\"hideLabel() ? 'sr-only' : 'text-sm font-semibold text-slate-800'\"\n >\n {{ n.labelKey | recipeTranslate }}\n @if (s.required() && !s.readonly()) {\n <span aria-hidden=\"true\" class=\"text-red-600\">*</span>\n }\n </label>\n</ng-template>\n\n<ng-template #controlTemplate>\n @switch (n.control.type) {\n @case (types.DISPLAY) {\n <output [id]=\"inputId()\" class=\"rounded-md bg-slate-50 px-3 py-2 text-sm text-slate-700\">{{\n displayValue()\n }}</output>\n }\n @case (types.SLOT) {\n @if (slotTemplate(); as template) {\n <ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"slotContext()\" />\n }\n }\n @default {\n <!-- Gabarit du registre : celui de l'hôte (`provideRecipeForms({ ui })`), sinon celui par défaut. -->\n @if (control(); as c) {\n <ng-container [ngTemplateOutlet]=\"c.template\" [ngTemplateOutletContext]=\"c.context\" />\n }\n }\n }\n</ng-template>\n"
5619
5627
  }]
5620
5628
  }],
5621
5629
  propDecorators: {
@@ -5659,6 +5667,14 @@ i0.ɵɵngDeclareClassMetadata({
5659
5667
  required: false
5660
5668
  }]
5661
5669
  }],
5670
+ inline: [{
5671
+ type: i0.Input,
5672
+ args: [{
5673
+ isSignal: true,
5674
+ alias: "inline",
5675
+ required: false
5676
+ }]
5677
+ }],
5662
5678
  extraMessage: [{
5663
5679
  type: i0.Input,
5664
5680
  args: [{
@@ -6606,7 +6622,7 @@ var RecipeNodeComponent = class RecipeNodeComponent {
6606
6622
  },
6607
6623
  host: { properties: { "class": "hostClasses()" } },
6608
6624
  ngImport: i0,
6609
- template: "@let n = node();\n@switch (n.kind) {\n @case (kinds.SECTION) {\n @if (!sectionHidden()) {\n <fieldset\n [id]=\"idPrefix() + '-' + n.id\"\n [class]=\"hideLegend() ? 'min-w-0' : 'min-w-0 rounded-lg border border-slate-200 p-4'\"\n >\n @if (n.legendKey; as legendKey) {\n <legend\n [class]=\"hideLegend() ? 'sr-only' : 'px-1 text-base font-semibold text-slate-900'\"\n >\n {{ legendKey | recipeTranslate }}\n </legend>\n }\n <div [class]=\"containerClasses()\">\n @for (child of n.nodes; track $index) {\n <app-recipe-node\n [node]=\"child\"\n [tree]=\"tree()\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n />\n }\n </div>\n </fieldset>\n }\n }\n @case (kinds.ROW) {\n <div [class]=\"containerClasses()\">\n @for (child of n.nodes; track $index) {\n <app-recipe-node\n [node]=\"child\"\n [tree]=\"tree()\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n />\n }\n </div>\n }\n @case (kinds.SECTION_GROUP) {\n <app-recipe-section-group\n [node]=\"n\"\n [tree]=\"tree()\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n />\n }\n @case (kinds.FIELD) {\n <app-recipe-field\n [node]=\"n\"\n [field]=\"fieldTreeOf(n.key)\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n [hideLabel]=\"hideLabel()\"\n />\n }\n @case (kinds.LINKED) {\n <fieldset\n class=\"min-w-0 rounded-lg border border-slate-200 p-3\"\n [attr.aria-describedby]=\"\n linkedTarget() === undefined && linkedMessage() ? linkedMessageId() : null\n \"\n >\n <legend [class]=\"hideLabel() ? 'sr-only' : 'px-1 text-sm font-semibold text-slate-800'\">\n {{ n.legendKey | recipeTranslate }}\n </legend>\n <div [class]=\"linkedContainerClasses()\">\n @for (fieldNode of linkedFieldNodes(); track fieldNode.key) {\n <app-recipe-field\n [node]=\"fieldNode\"\n [field]=\"fieldTreeOf(fieldNode.key)\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n [extraMessage]=\"fieldNode.key === linkedTarget() ? linkedMessage() : undefined\"\n [extraDescribedBy]=\"\n linkedTarget() === undefined && linkedMessage() ? linkedMessageId() : undefined\n \"\n />\n }\n </div>\n @if (linkedTarget() === undefined) {\n @if (linkedMessage(); as m) {\n <app-recipe-message\n [id]=\"linkedMessageId()\"\n class=\"mt-2\"\n [severity]=\"severities.DANGER\"\n [inline]=\"true\"\n [text]=\"m.key | recipeTranslate: m.params : m.text\"\n />\n }\n }\n </fieldset>\n }\n @case (kinds.ARRAY) {\n @if (!arrayHidden()) {\n <fieldset\n class=\"min-w-0 rounded-lg border border-slate-200 p-3\"\n [attr.aria-describedby]=\"listMessage() ? listMessageId() : null\"\n >\n @if (n.legendKey; as legendKey) {\n <legend class=\"px-1 text-sm font-semibold text-slate-800\">\n {{ legendKey | recipeTranslate }}\n </legend>\n }\n @if (n.slot?.position === 'before') {\n <ng-container\n [ngTemplateOutlet]=\"arraySlotTemplate()\"\n [ngTemplateOutletContext]=\"arraySlotContext()\"\n />\n }\n @if (n.display === displays.TABLE) {\n <!-- Sur un écran étroit, le tableau défile dans son conteneur au lieu d'élargir la page ou de passer ses en-têtes à la ligne. -->\n <div class=\"overflow-x-auto\">\n <table [id]=\"listId()\" class=\"w-full border-collapse text-sm\">\n <thead>\n <tr class=\"text-left\">\n @for (column of tableColumns(); track $index) {\n <th\n scope=\"col\"\n class=\"px-2 py-1 font-semibold whitespace-nowrap text-slate-800\"\n >\n {{ columnLabel(column) | recipeTranslate }}\n </th>\n }\n @if (n.removable !== false && !listReadonly()) {\n <th scope=\"col\" class=\"px-2 py-1\">\n <span class=\"sr-only\">{{\n n.removeLabelKey ?? 'forms.array.remove' | recipeTranslate\n }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (item of arrayItems(); track item) {\n <tr class=\"border-t border-slate-100 align-top\">\n @for (column of tableColumns(); track $index) {\n <!-- Un message de la cellule ne compte pas dans la largeur de la colonne : il passe à la ligne. -->\n <td\n class=\"px-2 py-1 [&_app-recipe-message]:w-0 [&_app-recipe-message]:min-w-full\"\n >\n <app-recipe-node\n [node]=\"column\"\n [tree]=\"item\"\n [idPrefix]=\"itemPrefix(item)\"\n [serverPrefix]=\"itemServerPrefix(item)\"\n [hideLabel]=\"true\"\n />\n </td>\n }\n @if (n.removable !== false && !listReadonly()) {\n <td class=\"px-2 py-1 text-right\">\n <app-recipe-button\n [label]=\"n.removeLabelKey ?? 'forms.array.remove' | recipeTranslate\"\n [variant]=\"variants.TEXT\"\n [severity]=\"severities.DANGER\"\n (clicked)=\"removeItem(itemKey(item))\"\n />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n } @else {\n <ol [id]=\"listId()\" class=\"flex flex-col gap-3\">\n @for (item of arrayItems(); track item) {\n <li class=\"flex flex-col gap-3 rounded-md border border-slate-100 bg-slate-50 p-3\">\n <div class=\"flex flex-wrap items-end gap-4\">\n @for (child of n.item; track $index) {\n <app-recipe-node\n [node]=\"child\"\n [tree]=\"item\"\n [idPrefix]=\"itemPrefix(item)\"\n [serverPrefix]=\"itemServerPrefix(item)\"\n />\n }\n </div>\n @if (n.removable !== false && !listReadonly()) {\n <app-recipe-button\n class=\"self-end\"\n [label]=\"n.removeLabelKey ?? 'forms.array.remove' | recipeTranslate\"\n [variant]=\"variants.TEXT\"\n [severity]=\"severities.DANGER\"\n (clicked)=\"removeItem(itemKey(item))\"\n />\n }\n </li>\n }\n </ol>\n }\n @if (n.slot?.position === 'after') {\n <ng-container\n [ngTemplateOutlet]=\"arraySlotTemplate()\"\n [ngTemplateOutletContext]=\"arraySlotContext()\"\n />\n }\n @if (listMessage(); as m) {\n <app-recipe-message\n [id]=\"listMessageId()\"\n class=\"mt-2\"\n [severity]=\"severities.DANGER\"\n [inline]=\"true\"\n [text]=\"m.key | recipeTranslate: m.params : m.text\"\n />\n }\n @if (n.addLabelKey; as addLabelKey) {\n @if (!listReadonly()) {\n <app-recipe-button\n class=\"mt-3 block\"\n [label]=\"addLabelKey | recipeTranslate\"\n [variant]=\"variants.OUTLINED\"\n [severity]=\"severities.SECONDARY\"\n (clicked)=\"addItem()\"\n />\n }\n }\n </fieldset>\n }\n }\n}\n",
6625
+ template: "@let n = node();\n@switch (n.kind) {\n @case (kinds.SECTION) {\n @if (!sectionHidden()) {\n <fieldset\n [id]=\"idPrefix() + '-' + n.id\"\n [class]=\"\n hideLegend()\n ? 'relative min-w-0'\n : 'relative min-w-0 rounded-lg border border-slate-200 p-4'\n \"\n >\n @if (n.legendKey; as legendKey) {\n <legend\n [class]=\"hideLegend() ? 'sr-only' : 'px-1 text-base font-semibold text-slate-900'\"\n >\n {{ legendKey | recipeTranslate }}\n </legend>\n }\n <div [class]=\"containerClasses()\">\n @for (child of n.nodes; track $index) {\n <app-recipe-node\n [node]=\"child\"\n [tree]=\"tree()\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n />\n }\n </div>\n </fieldset>\n }\n }\n @case (kinds.ROW) {\n <div [class]=\"containerClasses()\">\n @for (child of n.nodes; track $index) {\n <app-recipe-node\n [node]=\"child\"\n [tree]=\"tree()\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n />\n }\n </div>\n }\n @case (kinds.SECTION_GROUP) {\n <app-recipe-section-group\n [node]=\"n\"\n [tree]=\"tree()\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n />\n }\n @case (kinds.FIELD) {\n <app-recipe-field\n [node]=\"n\"\n [field]=\"fieldTreeOf(n.key)\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n [hideLabel]=\"hideLabel()\"\n [inline]=\"hideLabel()\"\n />\n }\n @case (kinds.LINKED) {\n <!-- Dans une cellule de tableau, l'en-tête de colonne titre le groupe : ni cadre ni légende visible, champs en ligne. -->\n <fieldset\n [class]=\"\n hideLabel() ? 'relative min-w-0' : 'relative min-w-0 rounded-lg border border-slate-200 p-3'\n \"\n [attr.aria-describedby]=\"\n linkedTarget() === undefined && linkedMessage() ? linkedMessageId() : null\n \"\n >\n <legend [class]=\"hideLabel() ? 'sr-only' : 'px-1 text-sm font-semibold text-slate-800'\">\n {{ n.legendKey | recipeTranslate }}\n </legend>\n <div [class]=\"hideLabel() ? 'flex items-start gap-x-4' : linkedContainerClasses()\">\n @for (fieldNode of linkedFieldNodes(); track fieldNode.key) {\n <app-recipe-field\n [node]=\"fieldNode\"\n [field]=\"fieldTreeOf(fieldNode.key)\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n [inline]=\"hideLabel()\"\n [extraMessage]=\"fieldNode.key === linkedTarget() ? linkedMessage() : undefined\"\n [extraDescribedBy]=\"\n linkedTarget() === undefined && linkedMessage() ? linkedMessageId() : undefined\n \"\n />\n }\n </div>\n @if (linkedTarget() === undefined) {\n @if (linkedMessage(); as m) {\n <app-recipe-message\n [id]=\"linkedMessageId()\"\n class=\"mt-2\"\n [severity]=\"severities.DANGER\"\n [inline]=\"true\"\n [text]=\"m.key | recipeTranslate: m.params : m.text\"\n />\n }\n }\n </fieldset>\n }\n @case (kinds.ARRAY) {\n @if (!arrayHidden()) {\n <fieldset\n class=\"relative min-w-0 rounded-lg border border-slate-200 p-3\"\n [attr.aria-describedby]=\"listMessage() ? listMessageId() : null\"\n >\n @if (n.legendKey; as legendKey) {\n <legend class=\"px-1 text-sm font-semibold text-slate-800\">\n {{ legendKey | recipeTranslate }}\n </legend>\n }\n @if (n.slot?.position === 'before') {\n <ng-container\n [ngTemplateOutlet]=\"arraySlotTemplate()\"\n [ngTemplateOutletContext]=\"arraySlotContext()\"\n />\n }\n @if (n.display === displays.TABLE) {\n <!-- Sur un écran étroit, le tableau défile dans son conteneur au lieu d'élargir la page ou de passer ses en-têtes à la ligne.\n `relative` garde dans ce conteneur le titre `sr-only` de la colonne de retrait, sinon placé hors de la page. -->\n <div class=\"relative overflow-x-auto\">\n <table [id]=\"listId()\" class=\"w-full border-collapse text-sm\">\n <thead>\n <tr class=\"text-left\">\n @for (column of tableColumns(); track $index) {\n <th\n scope=\"col\"\n class=\"px-2 py-1 font-semibold whitespace-nowrap text-slate-800\"\n >\n {{ columnLabel(column) | recipeTranslate }}\n </th>\n }\n @if (n.removable !== false && !listReadonly()) {\n <th scope=\"col\" class=\"px-2 py-1\">\n <span class=\"sr-only\">{{\n n.removeLabelKey ?? 'forms.array.remove' | recipeTranslate\n }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (item of arrayItems(); track item) {\n <tr class=\"border-t border-slate-100 align-top\">\n @for (column of tableColumns(); track $index) {\n <!-- Un message de la cellule ne compte pas dans la largeur de la colonne : il passe à la ligne. -->\n <td\n class=\"px-2 py-1 [&_app-recipe-message]:w-0 [&_app-recipe-message]:min-w-full\"\n >\n <app-recipe-node\n [node]=\"column\"\n [tree]=\"item\"\n [idPrefix]=\"itemPrefix(item)\"\n [serverPrefix]=\"itemServerPrefix(item)\"\n [hideLabel]=\"true\"\n />\n </td>\n }\n @if (n.removable !== false && !listReadonly()) {\n <td class=\"px-2 py-1 text-right\">\n <app-recipe-button\n [label]=\"n.removeLabelKey ?? 'forms.array.remove' | recipeTranslate\"\n [variant]=\"variants.TEXT\"\n [severity]=\"severities.DANGER\"\n (clicked)=\"removeItem(itemKey(item))\"\n />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n } @else {\n <ol [id]=\"listId()\" class=\"flex flex-col gap-3\">\n @for (item of arrayItems(); track item) {\n <li class=\"flex flex-col gap-3 rounded-md border border-slate-100 bg-slate-50 p-3\">\n <div class=\"flex flex-wrap items-end gap-4\">\n @for (child of n.item; track $index) {\n <app-recipe-node\n [node]=\"child\"\n [tree]=\"item\"\n [idPrefix]=\"itemPrefix(item)\"\n [serverPrefix]=\"itemServerPrefix(item)\"\n />\n }\n </div>\n @if (n.removable !== false && !listReadonly()) {\n <app-recipe-button\n class=\"self-end\"\n [label]=\"n.removeLabelKey ?? 'forms.array.remove' | recipeTranslate\"\n [variant]=\"variants.TEXT\"\n [severity]=\"severities.DANGER\"\n (clicked)=\"removeItem(itemKey(item))\"\n />\n }\n </li>\n }\n </ol>\n }\n @if (n.slot?.position === 'after') {\n <ng-container\n [ngTemplateOutlet]=\"arraySlotTemplate()\"\n [ngTemplateOutletContext]=\"arraySlotContext()\"\n />\n }\n @if (listMessage(); as m) {\n <app-recipe-message\n [id]=\"listMessageId()\"\n class=\"mt-2\"\n [severity]=\"severities.DANGER\"\n [inline]=\"true\"\n [text]=\"m.key | recipeTranslate: m.params : m.text\"\n />\n }\n @if (n.addLabelKey; as addLabelKey) {\n @if (!listReadonly()) {\n <app-recipe-button\n class=\"mt-3 block\"\n [label]=\"addLabelKey | recipeTranslate\"\n [variant]=\"variants.OUTLINED\"\n [severity]=\"severities.SECONDARY\"\n (clicked)=\"addItem()\"\n />\n }\n }\n </fieldset>\n }\n }\n}\n",
6610
6626
  dependencies: [
6611
6627
  {
6612
6628
  kind: "component",
@@ -6641,6 +6657,7 @@ var RecipeNodeComponent = class RecipeNodeComponent {
6641
6657
  "idPrefix",
6642
6658
  "serverPrefix",
6643
6659
  "hideLabel",
6660
+ "inline",
6644
6661
  "extraMessage",
6645
6662
  "extraDescribedBy"
6646
6663
  ]
@@ -6705,7 +6722,7 @@ i0.ɵɵngDeclareClassMetadata({
6705
6722
  ],
6706
6723
  changeDetection: ChangeDetectionStrategy.OnPush,
6707
6724
  host: { "[class]": "hostClasses()" },
6708
- template: "@let n = node();\n@switch (n.kind) {\n @case (kinds.SECTION) {\n @if (!sectionHidden()) {\n <fieldset\n [id]=\"idPrefix() + '-' + n.id\"\n [class]=\"hideLegend() ? 'min-w-0' : 'min-w-0 rounded-lg border border-slate-200 p-4'\"\n >\n @if (n.legendKey; as legendKey) {\n <legend\n [class]=\"hideLegend() ? 'sr-only' : 'px-1 text-base font-semibold text-slate-900'\"\n >\n {{ legendKey | recipeTranslate }}\n </legend>\n }\n <div [class]=\"containerClasses()\">\n @for (child of n.nodes; track $index) {\n <app-recipe-node\n [node]=\"child\"\n [tree]=\"tree()\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n />\n }\n </div>\n </fieldset>\n }\n }\n @case (kinds.ROW) {\n <div [class]=\"containerClasses()\">\n @for (child of n.nodes; track $index) {\n <app-recipe-node\n [node]=\"child\"\n [tree]=\"tree()\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n />\n }\n </div>\n }\n @case (kinds.SECTION_GROUP) {\n <app-recipe-section-group\n [node]=\"n\"\n [tree]=\"tree()\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n />\n }\n @case (kinds.FIELD) {\n <app-recipe-field\n [node]=\"n\"\n [field]=\"fieldTreeOf(n.key)\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n [hideLabel]=\"hideLabel()\"\n />\n }\n @case (kinds.LINKED) {\n <fieldset\n class=\"min-w-0 rounded-lg border border-slate-200 p-3\"\n [attr.aria-describedby]=\"\n linkedTarget() === undefined && linkedMessage() ? linkedMessageId() : null\n \"\n >\n <legend [class]=\"hideLabel() ? 'sr-only' : 'px-1 text-sm font-semibold text-slate-800'\">\n {{ n.legendKey | recipeTranslate }}\n </legend>\n <div [class]=\"linkedContainerClasses()\">\n @for (fieldNode of linkedFieldNodes(); track fieldNode.key) {\n <app-recipe-field\n [node]=\"fieldNode\"\n [field]=\"fieldTreeOf(fieldNode.key)\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n [extraMessage]=\"fieldNode.key === linkedTarget() ? linkedMessage() : undefined\"\n [extraDescribedBy]=\"\n linkedTarget() === undefined && linkedMessage() ? linkedMessageId() : undefined\n \"\n />\n }\n </div>\n @if (linkedTarget() === undefined) {\n @if (linkedMessage(); as m) {\n <app-recipe-message\n [id]=\"linkedMessageId()\"\n class=\"mt-2\"\n [severity]=\"severities.DANGER\"\n [inline]=\"true\"\n [text]=\"m.key | recipeTranslate: m.params : m.text\"\n />\n }\n }\n </fieldset>\n }\n @case (kinds.ARRAY) {\n @if (!arrayHidden()) {\n <fieldset\n class=\"min-w-0 rounded-lg border border-slate-200 p-3\"\n [attr.aria-describedby]=\"listMessage() ? listMessageId() : null\"\n >\n @if (n.legendKey; as legendKey) {\n <legend class=\"px-1 text-sm font-semibold text-slate-800\">\n {{ legendKey | recipeTranslate }}\n </legend>\n }\n @if (n.slot?.position === 'before') {\n <ng-container\n [ngTemplateOutlet]=\"arraySlotTemplate()\"\n [ngTemplateOutletContext]=\"arraySlotContext()\"\n />\n }\n @if (n.display === displays.TABLE) {\n <!-- Sur un écran étroit, le tableau défile dans son conteneur au lieu d'élargir la page ou de passer ses en-têtes à la ligne. -->\n <div class=\"overflow-x-auto\">\n <table [id]=\"listId()\" class=\"w-full border-collapse text-sm\">\n <thead>\n <tr class=\"text-left\">\n @for (column of tableColumns(); track $index) {\n <th\n scope=\"col\"\n class=\"px-2 py-1 font-semibold whitespace-nowrap text-slate-800\"\n >\n {{ columnLabel(column) | recipeTranslate }}\n </th>\n }\n @if (n.removable !== false && !listReadonly()) {\n <th scope=\"col\" class=\"px-2 py-1\">\n <span class=\"sr-only\">{{\n n.removeLabelKey ?? 'forms.array.remove' | recipeTranslate\n }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (item of arrayItems(); track item) {\n <tr class=\"border-t border-slate-100 align-top\">\n @for (column of tableColumns(); track $index) {\n <!-- Un message de la cellule ne compte pas dans la largeur de la colonne : il passe à la ligne. -->\n <td\n class=\"px-2 py-1 [&_app-recipe-message]:w-0 [&_app-recipe-message]:min-w-full\"\n >\n <app-recipe-node\n [node]=\"column\"\n [tree]=\"item\"\n [idPrefix]=\"itemPrefix(item)\"\n [serverPrefix]=\"itemServerPrefix(item)\"\n [hideLabel]=\"true\"\n />\n </td>\n }\n @if (n.removable !== false && !listReadonly()) {\n <td class=\"px-2 py-1 text-right\">\n <app-recipe-button\n [label]=\"n.removeLabelKey ?? 'forms.array.remove' | recipeTranslate\"\n [variant]=\"variants.TEXT\"\n [severity]=\"severities.DANGER\"\n (clicked)=\"removeItem(itemKey(item))\"\n />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n } @else {\n <ol [id]=\"listId()\" class=\"flex flex-col gap-3\">\n @for (item of arrayItems(); track item) {\n <li class=\"flex flex-col gap-3 rounded-md border border-slate-100 bg-slate-50 p-3\">\n <div class=\"flex flex-wrap items-end gap-4\">\n @for (child of n.item; track $index) {\n <app-recipe-node\n [node]=\"child\"\n [tree]=\"item\"\n [idPrefix]=\"itemPrefix(item)\"\n [serverPrefix]=\"itemServerPrefix(item)\"\n />\n }\n </div>\n @if (n.removable !== false && !listReadonly()) {\n <app-recipe-button\n class=\"self-end\"\n [label]=\"n.removeLabelKey ?? 'forms.array.remove' | recipeTranslate\"\n [variant]=\"variants.TEXT\"\n [severity]=\"severities.DANGER\"\n (clicked)=\"removeItem(itemKey(item))\"\n />\n }\n </li>\n }\n </ol>\n }\n @if (n.slot?.position === 'after') {\n <ng-container\n [ngTemplateOutlet]=\"arraySlotTemplate()\"\n [ngTemplateOutletContext]=\"arraySlotContext()\"\n />\n }\n @if (listMessage(); as m) {\n <app-recipe-message\n [id]=\"listMessageId()\"\n class=\"mt-2\"\n [severity]=\"severities.DANGER\"\n [inline]=\"true\"\n [text]=\"m.key | recipeTranslate: m.params : m.text\"\n />\n }\n @if (n.addLabelKey; as addLabelKey) {\n @if (!listReadonly()) {\n <app-recipe-button\n class=\"mt-3 block\"\n [label]=\"addLabelKey | recipeTranslate\"\n [variant]=\"variants.OUTLINED\"\n [severity]=\"severities.SECONDARY\"\n (clicked)=\"addItem()\"\n />\n }\n }\n </fieldset>\n }\n }\n}\n"
6725
+ template: "@let n = node();\n@switch (n.kind) {\n @case (kinds.SECTION) {\n @if (!sectionHidden()) {\n <fieldset\n [id]=\"idPrefix() + '-' + n.id\"\n [class]=\"\n hideLegend()\n ? 'relative min-w-0'\n : 'relative min-w-0 rounded-lg border border-slate-200 p-4'\n \"\n >\n @if (n.legendKey; as legendKey) {\n <legend\n [class]=\"hideLegend() ? 'sr-only' : 'px-1 text-base font-semibold text-slate-900'\"\n >\n {{ legendKey | recipeTranslate }}\n </legend>\n }\n <div [class]=\"containerClasses()\">\n @for (child of n.nodes; track $index) {\n <app-recipe-node\n [node]=\"child\"\n [tree]=\"tree()\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n />\n }\n </div>\n </fieldset>\n }\n }\n @case (kinds.ROW) {\n <div [class]=\"containerClasses()\">\n @for (child of n.nodes; track $index) {\n <app-recipe-node\n [node]=\"child\"\n [tree]=\"tree()\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n />\n }\n </div>\n }\n @case (kinds.SECTION_GROUP) {\n <app-recipe-section-group\n [node]=\"n\"\n [tree]=\"tree()\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n />\n }\n @case (kinds.FIELD) {\n <app-recipe-field\n [node]=\"n\"\n [field]=\"fieldTreeOf(n.key)\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n [hideLabel]=\"hideLabel()\"\n [inline]=\"hideLabel()\"\n />\n }\n @case (kinds.LINKED) {\n <!-- Dans une cellule de tableau, l'en-tête de colonne titre le groupe : ni cadre ni légende visible, champs en ligne. -->\n <fieldset\n [class]=\"\n hideLabel() ? 'relative min-w-0' : 'relative min-w-0 rounded-lg border border-slate-200 p-3'\n \"\n [attr.aria-describedby]=\"\n linkedTarget() === undefined && linkedMessage() ? linkedMessageId() : null\n \"\n >\n <legend [class]=\"hideLabel() ? 'sr-only' : 'px-1 text-sm font-semibold text-slate-800'\">\n {{ n.legendKey | recipeTranslate }}\n </legend>\n <div [class]=\"hideLabel() ? 'flex items-start gap-x-4' : linkedContainerClasses()\">\n @for (fieldNode of linkedFieldNodes(); track fieldNode.key) {\n <app-recipe-field\n [node]=\"fieldNode\"\n [field]=\"fieldTreeOf(fieldNode.key)\"\n [idPrefix]=\"idPrefix()\"\n [serverPrefix]=\"serverPrefix()\"\n [inline]=\"hideLabel()\"\n [extraMessage]=\"fieldNode.key === linkedTarget() ? linkedMessage() : undefined\"\n [extraDescribedBy]=\"\n linkedTarget() === undefined && linkedMessage() ? linkedMessageId() : undefined\n \"\n />\n }\n </div>\n @if (linkedTarget() === undefined) {\n @if (linkedMessage(); as m) {\n <app-recipe-message\n [id]=\"linkedMessageId()\"\n class=\"mt-2\"\n [severity]=\"severities.DANGER\"\n [inline]=\"true\"\n [text]=\"m.key | recipeTranslate: m.params : m.text\"\n />\n }\n }\n </fieldset>\n }\n @case (kinds.ARRAY) {\n @if (!arrayHidden()) {\n <fieldset\n class=\"relative min-w-0 rounded-lg border border-slate-200 p-3\"\n [attr.aria-describedby]=\"listMessage() ? listMessageId() : null\"\n >\n @if (n.legendKey; as legendKey) {\n <legend class=\"px-1 text-sm font-semibold text-slate-800\">\n {{ legendKey | recipeTranslate }}\n </legend>\n }\n @if (n.slot?.position === 'before') {\n <ng-container\n [ngTemplateOutlet]=\"arraySlotTemplate()\"\n [ngTemplateOutletContext]=\"arraySlotContext()\"\n />\n }\n @if (n.display === displays.TABLE) {\n <!-- Sur un écran étroit, le tableau défile dans son conteneur au lieu d'élargir la page ou de passer ses en-têtes à la ligne.\n `relative` garde dans ce conteneur le titre `sr-only` de la colonne de retrait, sinon placé hors de la page. -->\n <div class=\"relative overflow-x-auto\">\n <table [id]=\"listId()\" class=\"w-full border-collapse text-sm\">\n <thead>\n <tr class=\"text-left\">\n @for (column of tableColumns(); track $index) {\n <th\n scope=\"col\"\n class=\"px-2 py-1 font-semibold whitespace-nowrap text-slate-800\"\n >\n {{ columnLabel(column) | recipeTranslate }}\n </th>\n }\n @if (n.removable !== false && !listReadonly()) {\n <th scope=\"col\" class=\"px-2 py-1\">\n <span class=\"sr-only\">{{\n n.removeLabelKey ?? 'forms.array.remove' | recipeTranslate\n }}</span>\n </th>\n }\n </tr>\n </thead>\n <tbody>\n @for (item of arrayItems(); track item) {\n <tr class=\"border-t border-slate-100 align-top\">\n @for (column of tableColumns(); track $index) {\n <!-- Un message de la cellule ne compte pas dans la largeur de la colonne : il passe à la ligne. -->\n <td\n class=\"px-2 py-1 [&_app-recipe-message]:w-0 [&_app-recipe-message]:min-w-full\"\n >\n <app-recipe-node\n [node]=\"column\"\n [tree]=\"item\"\n [idPrefix]=\"itemPrefix(item)\"\n [serverPrefix]=\"itemServerPrefix(item)\"\n [hideLabel]=\"true\"\n />\n </td>\n }\n @if (n.removable !== false && !listReadonly()) {\n <td class=\"px-2 py-1 text-right\">\n <app-recipe-button\n [label]=\"n.removeLabelKey ?? 'forms.array.remove' | recipeTranslate\"\n [variant]=\"variants.TEXT\"\n [severity]=\"severities.DANGER\"\n (clicked)=\"removeItem(itemKey(item))\"\n />\n </td>\n }\n </tr>\n }\n </tbody>\n </table>\n </div>\n } @else {\n <ol [id]=\"listId()\" class=\"flex flex-col gap-3\">\n @for (item of arrayItems(); track item) {\n <li class=\"flex flex-col gap-3 rounded-md border border-slate-100 bg-slate-50 p-3\">\n <div class=\"flex flex-wrap items-end gap-4\">\n @for (child of n.item; track $index) {\n <app-recipe-node\n [node]=\"child\"\n [tree]=\"item\"\n [idPrefix]=\"itemPrefix(item)\"\n [serverPrefix]=\"itemServerPrefix(item)\"\n />\n }\n </div>\n @if (n.removable !== false && !listReadonly()) {\n <app-recipe-button\n class=\"self-end\"\n [label]=\"n.removeLabelKey ?? 'forms.array.remove' | recipeTranslate\"\n [variant]=\"variants.TEXT\"\n [severity]=\"severities.DANGER\"\n (clicked)=\"removeItem(itemKey(item))\"\n />\n }\n </li>\n }\n </ol>\n }\n @if (n.slot?.position === 'after') {\n <ng-container\n [ngTemplateOutlet]=\"arraySlotTemplate()\"\n [ngTemplateOutletContext]=\"arraySlotContext()\"\n />\n }\n @if (listMessage(); as m) {\n <app-recipe-message\n [id]=\"listMessageId()\"\n class=\"mt-2\"\n [severity]=\"severities.DANGER\"\n [inline]=\"true\"\n [text]=\"m.key | recipeTranslate: m.params : m.text\"\n />\n }\n @if (n.addLabelKey; as addLabelKey) {\n @if (!listReadonly()) {\n <app-recipe-button\n class=\"mt-3 block\"\n [label]=\"addLabelKey | recipeTranslate\"\n [variant]=\"variants.OUTLINED\"\n [severity]=\"severities.SECONDARY\"\n (clicked)=\"addItem()\"\n />\n }\n }\n </fieldset>\n }\n }\n}\n"
6709
6726
  }]
6710
6727
  }],
6711
6728
  propDecorators: {