@yuuvis/client-framework 3.10.0 → 3.11.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.
- package/fesm2022/yuuvis-client-framework-object-details.mjs +76 -10
- package/fesm2022/yuuvis-client-framework-object-details.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-renderer.mjs +26 -6
- package/fesm2022/yuuvis-client-framework-renderer.mjs.map +1 -1
- package/fesm2022/yuuvis-client-framework-tile-list.mjs +9 -1
- package/fesm2022/yuuvis-client-framework-tile-list.mjs.map +1 -1
- package/package.json +5 -5
- package/types/yuuvis-client-framework-object-details.d.ts +47 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i1 from '@angular/common';
|
|
2
2
|
import { CommonModule, NgTemplateOutlet } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { inject, signal, computed, input, effect, Component, ChangeDetectionStrategy, Injectable, viewChild, linkedSignal, untracked, output, viewChildren, NgModule, Pipe } from '@angular/core';
|
|
4
|
+
import { inject, signal, computed, input, effect, Component, ChangeDetectionStrategy, Injectable, viewChild, linkedSignal, afterNextRender, untracked, output, viewChildren, NgModule, Pipe } from '@angular/core';
|
|
5
5
|
import { takeUntilDestroyed, toSignal, rxResource } from '@angular/core/rxjs-interop';
|
|
6
6
|
import { ReactiveFormsModule } from '@angular/forms';
|
|
7
7
|
import * as i2 from '@angular/material/icon';
|
|
@@ -315,8 +315,32 @@ class ObjectMetadataSectionComponent {
|
|
|
315
315
|
this.expandedInput = input(false, { ...(ngDevMode ? { debugName: "expandedInput" } : /* istanbul ignore next */ {}), alias: 'expanded' });
|
|
316
316
|
this.elementExtensions = input([], ...(ngDevMode ? [{ debugName: "elementExtensions" }] : /* istanbul ignore next */ []));
|
|
317
317
|
this.readonly = input(...(ngDevMode ? [undefined, { debugName: "readonly" }] : /* istanbul ignore next */ []));
|
|
318
|
+
/**
|
|
319
|
+
* When `true`, the section's expand/collapse feature is removed: the content is
|
|
320
|
+
* always visible, cannot be collapsed, and the accordion toggle (arrow) is hidden.
|
|
321
|
+
*/
|
|
322
|
+
this.skipExpand = input(...(ngDevMode ? [undefined, { debugName: "skipExpand" }] : /* istanbul ignore next */ []));
|
|
323
|
+
/**
|
|
324
|
+
* When `true`, the section header (title, icon and toggle) is not rendered while the
|
|
325
|
+
* content region is still shown. Typically combined with {@link skipExpand} to display
|
|
326
|
+
* a title-less, always-open section.
|
|
327
|
+
*/
|
|
328
|
+
this.skipTitle = input(...(ngDevMode ? [undefined, { debugName: "skipTitle" }] : /* istanbul ignore next */ []));
|
|
318
329
|
this.expanded = linkedSignal(this.expandedInput, ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
|
|
330
|
+
/**
|
|
331
|
+
* Effective expanded state. When `skipExpand` is set the section is always visible
|
|
332
|
+
* and cannot be collapsed, so it is treated as permanently expanded.
|
|
333
|
+
*/
|
|
334
|
+
this.isExpanded = computed(() => !!this.skipExpand() || this.expanded(), ...(ngDevMode ? [{ debugName: "isExpanded" }] : /* istanbul ignore next */ []));
|
|
319
335
|
this.busy = signal(false, ...(ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []));
|
|
336
|
+
/**
|
|
337
|
+
* Gate for the reveal/collapse transition. Stays `false` for the first render so a
|
|
338
|
+
* section that mounts already expanded (auto-expanded first section or {@link skipExpand})
|
|
339
|
+
* appears instantly without a slide. Enabled after the initial render so that only
|
|
340
|
+
* subsequent user-driven toggles animate.
|
|
341
|
+
*/
|
|
342
|
+
this.animate = signal(false, ...(ngDevMode ? [{ debugName: "animate" }] : /* istanbul ignore next */ []));
|
|
343
|
+
this.#enableAnimateOnMount = afterNextRender(() => this.animate.set(true));
|
|
320
344
|
// linkedSignal instead of plain signal so that formOptions resets to undefined whenever
|
|
321
345
|
// the section input changes (e.g. a different object is loaded). This ensures the form
|
|
322
346
|
// is reloaded with fresh data for the new section while still allowing .set() mutations
|
|
@@ -327,7 +351,7 @@ class ObjectMetadataSectionComponent {
|
|
|
327
351
|
// Load the object form when the section is first expanded.
|
|
328
352
|
// Don't use rxResource here because it messes with the state of the formOptions.
|
|
329
353
|
const section = this.section();
|
|
330
|
-
const expanded = this.
|
|
354
|
+
const expanded = this.isExpanded();
|
|
331
355
|
// untracked() reads formOptions without adding it as a reactive dependency of this
|
|
332
356
|
// effect (which would cause an infinite loop). The guard ensures we only fetch once
|
|
333
357
|
// per section: subsequent expand cycles reuse the existing formOptions so that any
|
|
@@ -358,11 +382,36 @@ class ObjectMetadataSectionComponent {
|
|
|
358
382
|
* classes when the default `yuv-object-form` (and thus `objectForm()`) is absent.
|
|
359
383
|
*/
|
|
360
384
|
this.customStatus = signal(undefined, ...(ngDevMode ? [{ debugName: "customStatus" }] : /* istanbul ignore next */ []));
|
|
385
|
+
/**
|
|
386
|
+
* Settled status of the default `yuv-object-form`, captured from its `statusChanged`
|
|
387
|
+
* output. The host classes read this signal instead of the live `form.invalid`/
|
|
388
|
+
* `form.dirty` for two reasons:
|
|
389
|
+
* - it is only updated once the form has emitted a settled status (after the model
|
|
390
|
+
* is built and its values are patched), so the transient window where required
|
|
391
|
+
* controls are momentarily invalid never reaches the DOM (no red flash);
|
|
392
|
+
* - a signal value is stable within a change-detection cycle, so expanding a section
|
|
393
|
+
* mid-cycle no longer throws NG0100 (removing the consumer-side "defer expand by a
|
|
394
|
+
* tick" workaround).
|
|
395
|
+
*/
|
|
396
|
+
this.formStatus = signal(undefined, ...(ngDevMode ? [{ debugName: "formStatus" }] : /* istanbul ignore next */ []));
|
|
397
|
+
/** Active status: the custom renderer's when present, otherwise the object-form's. */
|
|
398
|
+
this.#status = computed(() => (this.customTemplate() ? this.customStatus() : this.formStatus()), ...(ngDevMode ? [{ debugName: "#status" }] : /* istanbul ignore next */ []));
|
|
399
|
+
/**
|
|
400
|
+
* Reflect the invalid styling only once the form has been edited (dirty). This
|
|
401
|
+
* suppresses the load transient and follows the convention of not surfacing errors
|
|
402
|
+
* before the user interacts. A form that is genuinely invalid after user interaction
|
|
403
|
+
* still shows the red border/outline.
|
|
404
|
+
*/
|
|
405
|
+
this.showInvalid = computed(() => {
|
|
406
|
+
const status = this.#status();
|
|
407
|
+
return !!status?.invalid && !!status?.dirty;
|
|
408
|
+
}, ...(ngDevMode ? [{ debugName: "showInvalid" }] : /* istanbul ignore next */ []));
|
|
409
|
+
this.showDirty = computed(() => !!this.#status()?.dirty, ...(ngDevMode ? [{ debugName: "showDirty" }] : /* istanbul ignore next */ []));
|
|
361
410
|
// Keep the custom renderer mounted once the section has been expanded so user edits
|
|
362
411
|
// persist across collapse/expand cycles (mirrors the default form's `[hidden]` approach).
|
|
363
412
|
this.#hasExpanded = signal(false, ...(ngDevMode ? [{ debugName: "#hasExpanded" }] : /* istanbul ignore next */ []));
|
|
364
413
|
this.#expandTrackEffect = effect(() => {
|
|
365
|
-
if (this.
|
|
414
|
+
if (this.isExpanded())
|
|
366
415
|
this.#hasExpanded.set(true);
|
|
367
416
|
}, ...(ngDevMode ? [{ debugName: "#expandTrackEffect" }] : /* istanbul ignore next */ []));
|
|
368
417
|
this.renderCustom = computed(() => !!this.customTemplate() && this.#hasExpanded(), ...(ngDevMode ? [{ debugName: "renderCustom" }] : /* istanbul ignore next */ []));
|
|
@@ -388,7 +437,10 @@ class ObjectMetadataSectionComponent {
|
|
|
388
437
|
}
|
|
389
438
|
#system;
|
|
390
439
|
#sotRenderers;
|
|
440
|
+
#enableAnimateOnMount;
|
|
391
441
|
#formOptionsEffect;
|
|
442
|
+
/** Active status: the custom renderer's when present, otherwise the object-form's. */
|
|
443
|
+
#status;
|
|
392
444
|
// Keep the custom renderer mounted once the section has been expanded so user edits
|
|
393
445
|
// persist across collapse/expand cycles (mirrors the default form's `[hidden]` approach).
|
|
394
446
|
#hasExpanded;
|
|
@@ -396,6 +448,16 @@ class ObjectMetadataSectionComponent {
|
|
|
396
448
|
// INBOUND command channel: reset/pristine triggered by the surrounding metadata form.
|
|
397
449
|
#commandSubject;
|
|
398
450
|
#setCustomStatus;
|
|
451
|
+
toggle() {
|
|
452
|
+
if (this.skipExpand())
|
|
453
|
+
return;
|
|
454
|
+
this.expanded.set(!this.expanded());
|
|
455
|
+
}
|
|
456
|
+
/** Capture the default form's settled status, then re-emit it to consumers. */
|
|
457
|
+
onFormStatusChanged(evt) {
|
|
458
|
+
this.formStatus.set(evt);
|
|
459
|
+
this.statusChanged.emit(evt);
|
|
460
|
+
}
|
|
399
461
|
resetForm() {
|
|
400
462
|
if (this.customTemplate())
|
|
401
463
|
this.#commandSubject.next({ type: 'reset' });
|
|
@@ -407,19 +469,23 @@ class ObjectMetadataSectionComponent {
|
|
|
407
469
|
this.#commandSubject.next({ type: 'pristine' });
|
|
408
470
|
this.customStatus.set(undefined);
|
|
409
471
|
}
|
|
410
|
-
else
|
|
472
|
+
else {
|
|
411
473
|
this.objectForm()?.setFormPristine();
|
|
474
|
+
// setFormPristine() marks the form pristine without emitting statusChanged, so
|
|
475
|
+
// clear the settled status here to drop the dirty/invalid host styling.
|
|
476
|
+
this.formStatus.set(undefined);
|
|
477
|
+
}
|
|
412
478
|
}
|
|
413
479
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ObjectMetadataSectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
414
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: ObjectMetadataSectionComponent, isStandalone: true, selector: "yuv-object-metadata-section", inputs: { section: { classPropertyName: "section", publicName: "section", isSignal: true, isRequired: true, transformFunction: null }, expandedInput: { classPropertyName: "expandedInput", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, elementExtensions: { classPropertyName: "elementExtensions", publicName: "elementExtensions", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { statusChanged: "statusChanged" }, host: { properties: { "class.invalid": "
|
|
480
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: ObjectMetadataSectionComponent, isStandalone: true, selector: "yuv-object-metadata-section", inputs: { section: { classPropertyName: "section", publicName: "section", isSignal: true, isRequired: true, transformFunction: null }, expandedInput: { classPropertyName: "expandedInput", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, elementExtensions: { classPropertyName: "elementExtensions", publicName: "elementExtensions", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, skipExpand: { classPropertyName: "skipExpand", publicName: "skipExpand", isSignal: true, isRequired: false, transformFunction: null }, skipTitle: { classPropertyName: "skipTitle", publicName: "skipTitle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { statusChanged: "statusChanged" }, host: { properties: { "class.invalid": "showInvalid()", "class.dirty": "showDirty()" } }, viewQueries: [{ propertyName: "objectForm", first: true, predicate: ObjectFormComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@let _section = section();\n@let fo = formOptions();\n\n@if (!skipTitle()) {\n <h3>\n <button\n type=\"button\"\n [attr.aria-expanded]=\"isExpanded()\"\n class=\"accordion-trigger\"\n [class.non-collapsible]=\"skipExpand()\"\n [attr.aria-controls]=\"'sect_' + _section.id\"\n [id]=\"'accordion_' + _section.id\"\n [disabled]=\"skipExpand()\"\n (click)=\"toggle()\"\n [attr.aria-busy]=\"busy()\"\n >\n @if (_section.icon) {\n @if (_section.svgIcon) {\n <mat-icon [svgIcon]=\"_section.icon\" aria-hidden=\"true\" />\n } @else {\n <mat-icon aria-hidden=\"true\">{{ _section.icon }}</mat-icon>\n }\n }\n <span>{{ _section.label }}</span>\n @if (busy()) {\n <mat-spinner diameter=\"24\" />\n }\n @if (!skipExpand()) {\n <mat-icon class=\"arr\" aria-hidden=\"true\">keyboard_arrow_down</mat-icon>\n }\n </button>\n </h3>\n}\n<div\n [id]=\"'sect_' + _section.id\"\n role=\"region\"\n [attr.aria-labelledby]=\"'accordion_' + _section.id\"\n class=\"accordion-panel\"\n [class.expanded]=\"isExpanded()\"\n [class.animate]=\"animate()\"\n [attr.inert]=\"isExpanded() ? null : ''\"\n>\n <div class=\"accordion-panel-content\">\n @if (customTemplate()) {\n @if (renderCustom()) {\n <div>\n <ng-container *ngTemplateOutlet=\"customTemplate()!; context: { $implicit: sotContext() }\" />\n </div>\n }\n } @else if (fo) {\n <yuv-object-form\n #objectForm\n [readonly]=\"readonly()\"\n [formOptions]=\"fo\"\n [elementExtensions]=\"elementExtensions()\"\n (statusChanged)=\"onFormStatusChanged($event)\"\n />\n }\n </div>\n</div>\n", styles: [":host{--section-state-border-color: var(--ymt-outline-variant);--section-state-outline-color: transparent;background-color:var(--_object-metadata-section-background);border:1px solid var(--section-state-border-color);border-radius:var(--_object-metadata-section-corner);outline:3px solid var(--section-state-outline-color)}:host.invalid{--section-state-border-color: var(--ymt-danger);--section-state-outline-color: rgb(from var(--ymt-danger) r g b / .2)}:host.dirty:not(.invalid){--section-state-border-color: var(--ymt-success);--section-state-outline-color: rgb(from var(--ymt-success) r g b / .2)}:host h3{margin:0;padding:0;display:flex}:host h3 button{margin:var(--ymt-spacing-2xs);border-radius:calc(var(--_object-metadata-section-corner) * .5);flex:1;padding:var(--ymt-spacing-xs);cursor:pointer;display:flex;gap:var(--ymt-spacing-xs);align-items:center;font-weight:700;color:var(--ymt-text-color-subtle);background-color:transparent;border:none}:host h3 button.non-collapsible{cursor:default}:host h3 button.non-collapsible:hover{background-color:transparent}:host h3 button:not(.non-collapsible):hover{background-color:var(--ymt-hover-background)}:host h3 button:focus-visible{background-color:var(--ymt-hover-background);outline:2px solid var(--ymt-outline);outline-offset:-2px}:host h3 button[aria-expanded=true] mat-icon.arr{transform:rotate(180deg)}:host h3 button span{flex:1;text-align:start}:host h3 button mat-icon{margin-inline-end:var(--ymt-spacing-xs);transition:transform .3s ease}:host .accordion-panel{display:grid;grid-template-rows:0fr;opacity:0}:host .accordion-panel.expanded{grid-template-rows:1fr;opacity:1}:host .accordion-panel.animate{transition:grid-template-rows .2s ease-out,opacity .2s ease-out}:host .accordion-panel .accordion-panel-content{overflow:hidden;min-height:0}:host details{background-color:var(--_object-metadata-section-background);border:1px solid var(--ymt-outline-variant);border-radius:var(--_object-metadata-section-corner)}:host details:not(:last-child){margin-block-end:var(--ymt-spacing-m)}:host details[open] yuv-icon.arr{transform:rotate(180deg)}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i2$1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: ObjectFormComponent, selector: "yuv-object-form", inputs: ["formOptions", "inert", "readonly", "elementExtensions", "isInnerTableForm"], outputs: ["statusChanged", "onFormReady"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); }
|
|
415
481
|
}
|
|
416
482
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ObjectMetadataSectionComponent, decorators: [{
|
|
417
483
|
type: Component,
|
|
418
484
|
args: [{ selector: 'yuv-object-metadata-section', imports: [MatIconModule, MatProgressSpinnerModule, ObjectFormComponent, NgTemplateOutlet], host: {
|
|
419
|
-
'[class.invalid]': '
|
|
420
|
-
'[class.dirty]': '
|
|
421
|
-
}, template: "@let _section = section();\n@let fo = formOptions();\n\n<h3>\n
|
|
422
|
-
}], propDecorators: { objectForm: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ObjectFormComponent), { isSignal: true }] }], section: [{ type: i0.Input, args: [{ isSignal: true, alias: "section", required: true }] }], expandedInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }], elementExtensions: [{ type: i0.Input, args: [{ isSignal: true, alias: "elementExtensions", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], statusChanged: [{ type: i0.Output, args: ["statusChanged"] }] } });
|
|
485
|
+
'[class.invalid]': 'showInvalid()',
|
|
486
|
+
'[class.dirty]': 'showDirty()'
|
|
487
|
+
}, template: "@let _section = section();\n@let fo = formOptions();\n\n@if (!skipTitle()) {\n <h3>\n <button\n type=\"button\"\n [attr.aria-expanded]=\"isExpanded()\"\n class=\"accordion-trigger\"\n [class.non-collapsible]=\"skipExpand()\"\n [attr.aria-controls]=\"'sect_' + _section.id\"\n [id]=\"'accordion_' + _section.id\"\n [disabled]=\"skipExpand()\"\n (click)=\"toggle()\"\n [attr.aria-busy]=\"busy()\"\n >\n @if (_section.icon) {\n @if (_section.svgIcon) {\n <mat-icon [svgIcon]=\"_section.icon\" aria-hidden=\"true\" />\n } @else {\n <mat-icon aria-hidden=\"true\">{{ _section.icon }}</mat-icon>\n }\n }\n <span>{{ _section.label }}</span>\n @if (busy()) {\n <mat-spinner diameter=\"24\" />\n }\n @if (!skipExpand()) {\n <mat-icon class=\"arr\" aria-hidden=\"true\">keyboard_arrow_down</mat-icon>\n }\n </button>\n </h3>\n}\n<div\n [id]=\"'sect_' + _section.id\"\n role=\"region\"\n [attr.aria-labelledby]=\"'accordion_' + _section.id\"\n class=\"accordion-panel\"\n [class.expanded]=\"isExpanded()\"\n [class.animate]=\"animate()\"\n [attr.inert]=\"isExpanded() ? null : ''\"\n>\n <div class=\"accordion-panel-content\">\n @if (customTemplate()) {\n @if (renderCustom()) {\n <div>\n <ng-container *ngTemplateOutlet=\"customTemplate()!; context: { $implicit: sotContext() }\" />\n </div>\n }\n } @else if (fo) {\n <yuv-object-form\n #objectForm\n [readonly]=\"readonly()\"\n [formOptions]=\"fo\"\n [elementExtensions]=\"elementExtensions()\"\n (statusChanged)=\"onFormStatusChanged($event)\"\n />\n }\n </div>\n</div>\n", styles: [":host{--section-state-border-color: var(--ymt-outline-variant);--section-state-outline-color: transparent;background-color:var(--_object-metadata-section-background);border:1px solid var(--section-state-border-color);border-radius:var(--_object-metadata-section-corner);outline:3px solid var(--section-state-outline-color)}:host.invalid{--section-state-border-color: var(--ymt-danger);--section-state-outline-color: rgb(from var(--ymt-danger) r g b / .2)}:host.dirty:not(.invalid){--section-state-border-color: var(--ymt-success);--section-state-outline-color: rgb(from var(--ymt-success) r g b / .2)}:host h3{margin:0;padding:0;display:flex}:host h3 button{margin:var(--ymt-spacing-2xs);border-radius:calc(var(--_object-metadata-section-corner) * .5);flex:1;padding:var(--ymt-spacing-xs);cursor:pointer;display:flex;gap:var(--ymt-spacing-xs);align-items:center;font-weight:700;color:var(--ymt-text-color-subtle);background-color:transparent;border:none}:host h3 button.non-collapsible{cursor:default}:host h3 button.non-collapsible:hover{background-color:transparent}:host h3 button:not(.non-collapsible):hover{background-color:var(--ymt-hover-background)}:host h3 button:focus-visible{background-color:var(--ymt-hover-background);outline:2px solid var(--ymt-outline);outline-offset:-2px}:host h3 button[aria-expanded=true] mat-icon.arr{transform:rotate(180deg)}:host h3 button span{flex:1;text-align:start}:host h3 button mat-icon{margin-inline-end:var(--ymt-spacing-xs);transition:transform .3s ease}:host .accordion-panel{display:grid;grid-template-rows:0fr;opacity:0}:host .accordion-panel.expanded{grid-template-rows:1fr;opacity:1}:host .accordion-panel.animate{transition:grid-template-rows .2s ease-out,opacity .2s ease-out}:host .accordion-panel .accordion-panel-content{overflow:hidden;min-height:0}:host details{background-color:var(--_object-metadata-section-background);border:1px solid var(--ymt-outline-variant);border-radius:var(--_object-metadata-section-corner)}:host details:not(:last-child){margin-block-end:var(--ymt-spacing-m)}:host details[open] yuv-icon.arr{transform:rotate(180deg)}\n"] }]
|
|
488
|
+
}], propDecorators: { objectForm: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ObjectFormComponent), { isSignal: true }] }], section: [{ type: i0.Input, args: [{ isSignal: true, alias: "section", required: true }] }], expandedInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }], elementExtensions: [{ type: i0.Input, args: [{ isSignal: true, alias: "elementExtensions", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], skipExpand: [{ type: i0.Input, args: [{ isSignal: true, alias: "skipExpand", required: false }] }], skipTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "skipTitle", required: false }] }], statusChanged: [{ type: i0.Output, args: ["statusChanged"] }] } });
|
|
423
489
|
|
|
424
490
|
class ObjectMetadataComponent {
|
|
425
491
|
constructor() {
|
|
@@ -746,7 +812,7 @@ class ObjectMetadataComponent {
|
|
|
746
812
|
// fresh writable signal per <yuv-object-metadata> instance → per-object scope.
|
|
747
813
|
// Element templates read it (read-only) via the metadata form field context.
|
|
748
814
|
{ provide: OBJECT_CONTEXT, useFactory: () => signal(undefined) }
|
|
749
|
-
], viewQueries: [{ propertyName: "objectForms", predicate: ObjectFormComponent, descendants: true, isSignal: true }, { propertyName: "objectMetadataSectionForms", predicate: ObjectMetadataSectionComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<main [yuvBusyOverlay]=\"busySaving() || busyLoading() || mainFormOptionsIsLoading()\">\n @if (empty()) {\n <p>{{ 'yuv.object-metadata.empty.message' | translate }}</p>\n }\n @if (!mainFormOptions()) {\n <yuv-object-form\n [readonly]=\"!hasWritePermission()\"\n [formOptions]=\"mainFormOptions()\"\n [elementExtensions]=\"elementExtensions()\"\n (statusChanged)=\"onFormStatusChanged('main', $event)\"\n />\n }\n @for (fo of flavorFormOptions(); track $index) {\n <yuv-object-metadata-section\n [readonly]=\"!hasWritePermission()\"\n [section]=\"fo\"\n [elementExtensions]=\"elementExtensions()\"\n [expanded]=\"$index === 0\"\n (statusChanged)=\"onFormStatusChanged(fo.id, $event)\"\n />\n }\n\n <!-- base data -->\n @let object = dmsObject() ?? dmsObject();\n @if (object && !disableBasicMetadata()) {\n <yuv-object-summary-data [dmsObject]=\"object\" />\n }\n</main>\n\n<footer [attr.inert]=\"disableControls() || !controlsVisible() || null\">\n <div class=\"container\">\n <button\n ymtButton=\"secondary\"\n button-size=\"small\"\n [disabled]=\"busySaving() || busyLoading()\"\n (click)=\"resetForm()\"\n [hidden]=\"!combinedFormState?.dirty\"\n [disabled]=\"!combinedFormState?.dirty\"\n >\n {{ 'yuv.object-metadata.button.reset' | translate }}\n </button>\n <button\n ymtButton=\"primary\"\n button-size=\"small\"\n (click)=\"save()\"\n [disabled]=\"!combinedFormState?.dirty || combinedFormState?.invalid || busySaving() || busyLoading()\"\n >\n {{ 'yuv.object-metadata.button.save' | translate }}\n </button>\n </div>\n</footer>\n", styles: [":host{--_object-metadata-panel-background: var(--object-metadata-panel-background, var(--ymt-surface-container-low));--_object-metadata-section-background: var(--object-metadata-section-background, var(--ymt-surface));--_object-metadata-section-corner: var(--object-metadata-section-corner, var(--ymt-corner-m));--_object-metadata-footer-background: var(--object-metadata-footer-background, var(--ymt-surface-container));--_object-metadata-footer-border: 1px solid var(--object-metadata-footer-border, var(--ymt-outline-variant));--_object-metadata-footer-indent: var(--object-metadata-footer-indent, var(--ymt-spacing-xs));--_object-metadata-footer-height: 4rem;--_object-metadata-footer-corner: var(--object-metadata-footer-corner, var(--ymt-corner-s));display:grid;grid-template-rows:1fr auto;grid-template-columns:1fr;height:100%;overflow:hidden;position:relative;background-color:var(--_object-metadata-panel-background)}:host.empty main{justify-content:center;align-items:center}:host.loading main>*{opacity:0}:host main{grid-row:1/span 3;grid-column:1;overflow-y:auto;width:100%;display:flex;flex-flow:column;padding:var(--ymt-spacing-3xl) var(--ymt-spacing-l) var(--_object-metadata-footer-height) var(--ymt-spacing-l)}:host footer{grid-row:-1;grid-column:1;padding:var(--_object-metadata-footer-indent);opacity:0;z-index:101}:host footer .container{background:var(--_object-metadata-footer-background);padding:var(--ymt-spacing-s);display:flex;align-items:center;justify-content:end;gap:var(--ymt-spacing-s);border-radius:var(--_object-metadata-footer-corner);border:var(--_object-metadata-footer-border)}:host footer:not([inert]){animation:controlsAppear .2s ease-in-out forwards}:host main yuv-object-metadata-section{margin-block-end:var(--ymt-spacing-m)}:host main yuv-object-summary-data{background-color:var(--_object-metadata-section-background);border:1px solid var(--ymt-outline-variant);border-radius:var(--_object-metadata-section-corner);padding:var(--ymt-spacing-m)}@keyframes controlsAppear{0%{opacity:0;translate:0 var(--ymt-spacing-m)}to{opacity:1;translate:0 0}}\n"], dependencies: [{ kind: "component", type: ObjectFormComponent, selector: "yuv-object-form", inputs: ["formOptions", "inert", "readonly", "elementExtensions", "isInnerTableForm"], outputs: ["statusChanged", "onFormReady"] }, { kind: "component", type: ObjectSummaryDataComponent, selector: "yuv-object-summary-data", inputs: ["dmsObject", "flavors", "showAppliedFlavors"] }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay", "yuvBusyOverlayConfig", "yuvBusyError"], outputs: ["yuvBusyErrorDismiss"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: ObjectMetadataSectionComponent, selector: "yuv-object-metadata-section", inputs: ["section", "expanded", "elementExtensions", "readonly"], outputs: ["statusChanged"] }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
815
|
+
], viewQueries: [{ propertyName: "objectForms", predicate: ObjectFormComponent, descendants: true, isSignal: true }, { propertyName: "objectMetadataSectionForms", predicate: ObjectMetadataSectionComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<main [yuvBusyOverlay]=\"busySaving() || busyLoading() || mainFormOptionsIsLoading()\">\n @if (empty()) {\n <p>{{ 'yuv.object-metadata.empty.message' | translate }}</p>\n }\n @if (!mainFormOptions()) {\n <yuv-object-form\n [readonly]=\"!hasWritePermission()\"\n [formOptions]=\"mainFormOptions()\"\n [elementExtensions]=\"elementExtensions()\"\n (statusChanged)=\"onFormStatusChanged('main', $event)\"\n />\n }\n @for (fo of flavorFormOptions(); track $index) {\n <yuv-object-metadata-section\n [readonly]=\"!hasWritePermission()\"\n [section]=\"fo\"\n [elementExtensions]=\"elementExtensions()\"\n [expanded]=\"$index === 0\"\n (statusChanged)=\"onFormStatusChanged(fo.id, $event)\"\n />\n }\n\n <!-- base data -->\n @let object = dmsObject() ?? dmsObject();\n @if (object && !disableBasicMetadata()) {\n <yuv-object-summary-data [dmsObject]=\"object\" />\n }\n</main>\n\n<footer [attr.inert]=\"disableControls() || !controlsVisible() || null\">\n <div class=\"container\">\n <button\n ymtButton=\"secondary\"\n button-size=\"small\"\n [disabled]=\"busySaving() || busyLoading()\"\n (click)=\"resetForm()\"\n [hidden]=\"!combinedFormState?.dirty\"\n [disabled]=\"!combinedFormState?.dirty\"\n >\n {{ 'yuv.object-metadata.button.reset' | translate }}\n </button>\n <button\n ymtButton=\"primary\"\n button-size=\"small\"\n (click)=\"save()\"\n [disabled]=\"!combinedFormState?.dirty || combinedFormState?.invalid || busySaving() || busyLoading()\"\n >\n {{ 'yuv.object-metadata.button.save' | translate }}\n </button>\n </div>\n</footer>\n", styles: [":host{--_object-metadata-panel-background: var(--object-metadata-panel-background, var(--ymt-surface-container-low));--_object-metadata-section-background: var(--object-metadata-section-background, var(--ymt-surface));--_object-metadata-section-corner: var(--object-metadata-section-corner, var(--ymt-corner-m));--_object-metadata-footer-background: var(--object-metadata-footer-background, var(--ymt-surface-container));--_object-metadata-footer-border: 1px solid var(--object-metadata-footer-border, var(--ymt-outline-variant));--_object-metadata-footer-indent: var(--object-metadata-footer-indent, var(--ymt-spacing-xs));--_object-metadata-footer-height: 4rem;--_object-metadata-footer-corner: var(--object-metadata-footer-corner, var(--ymt-corner-s));display:grid;grid-template-rows:1fr auto;grid-template-columns:1fr;height:100%;overflow:hidden;position:relative;background-color:var(--_object-metadata-panel-background)}:host.empty main{justify-content:center;align-items:center}:host.loading main>*{opacity:0}:host main{grid-row:1/span 3;grid-column:1;overflow-y:auto;width:100%;display:flex;flex-flow:column;padding:var(--ymt-spacing-3xl) var(--ymt-spacing-l) var(--_object-metadata-footer-height) var(--ymt-spacing-l)}:host footer{grid-row:-1;grid-column:1;padding:var(--_object-metadata-footer-indent);opacity:0;z-index:101}:host footer .container{background:var(--_object-metadata-footer-background);padding:var(--ymt-spacing-s);display:flex;align-items:center;justify-content:end;gap:var(--ymt-spacing-s);border-radius:var(--_object-metadata-footer-corner);border:var(--_object-metadata-footer-border)}:host footer:not([inert]){animation:controlsAppear .2s ease-in-out forwards}:host main yuv-object-metadata-section{margin-block-end:var(--ymt-spacing-m)}:host main yuv-object-summary-data{background-color:var(--_object-metadata-section-background);border:1px solid var(--ymt-outline-variant);border-radius:var(--_object-metadata-section-corner);padding:var(--ymt-spacing-m)}@keyframes controlsAppear{0%{opacity:0;translate:0 var(--ymt-spacing-m)}to{opacity:1;translate:0 0}}\n"], dependencies: [{ kind: "component", type: ObjectFormComponent, selector: "yuv-object-form", inputs: ["formOptions", "inert", "readonly", "elementExtensions", "isInnerTableForm"], outputs: ["statusChanged", "onFormReady"] }, { kind: "component", type: ObjectSummaryDataComponent, selector: "yuv-object-summary-data", inputs: ["dmsObject", "flavors", "showAppliedFlavors"] }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay", "yuvBusyOverlayConfig", "yuvBusyError"], outputs: ["yuvBusyErrorDismiss"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: ObjectMetadataSectionComponent, selector: "yuv-object-metadata-section", inputs: ["section", "expanded", "elementExtensions", "readonly", "skipExpand", "skipTitle"], outputs: ["statusChanged"] }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
750
816
|
}
|
|
751
817
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ObjectMetadataComponent, decorators: [{
|
|
752
818
|
type: Component,
|