@masmarino/gabarit 1.0.3 → 1.1.0

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, inject, input, computed, ChangeDetectionStrategy, Component, output, signal, viewChild, HostListener, booleanAttribute, ElementRef, forwardRef, effect, contentChildren, viewChildren, model, InjectionToken, isDevMode, Injector, afterNextRender, TemplateRef } from '@angular/core';
2
+ import { Injectable, inject, input, computed, ChangeDetectionStrategy, Component, output, signal, viewChild, HostListener, booleanAttribute, ElementRef, forwardRef, effect, contentChildren, viewChildren, model, InjectionToken, isDevMode, Injector, afterNextRender, TemplateRef, DestroyRef, afterRenderEffect } from '@angular/core';
3
3
  import { DomSanitizer } from '@angular/platform-browser';
4
4
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
5
  import * as i1 from '@angular/forms';
@@ -7,7 +7,7 @@ import { NG_VALUE_ACCESSOR, FormControl, ReactiveFormsModule, FormsModule } from
7
7
  import { NgTemplateOutlet } from '@angular/common';
8
8
  import { isObservable } from 'rxjs';
9
9
 
10
- const GABARIT_VERSION = '1.0.3';
10
+ const GABARIT_VERSION = '1.1.0';
11
11
 
12
12
  const BUILT_IN_ICONS = {
13
13
  search: `<path d="m21 21-4.34-4.34" />
@@ -1598,12 +1598,12 @@ function formatPercent(ratio, locale, decimals = 0) {
1598
1598
  }).format(ratio);
1599
1599
  }
1600
1600
 
1601
- const round = (n) => Number(n.toFixed(2));
1601
+ const round$1 = (n) => Number(n.toFixed(2));
1602
1602
  function linePath(points) {
1603
1603
  if (points.length === 0)
1604
1604
  return '';
1605
1605
  return points
1606
- .map((point, index) => `${index === 0 ? 'M' : 'L'}${round(point.x)},${round(point.y)}`)
1606
+ .map((point, index) => `${index === 0 ? 'M' : 'L'}${round$1(point.x)},${round$1(point.y)}`)
1607
1607
  .join('');
1608
1608
  }
1609
1609
  function areaPath(points, baseline) {
@@ -1611,13 +1611,13 @@ function areaPath(points, baseline) {
1611
1611
  return '';
1612
1612
  const last = points[points.length - 1];
1613
1613
  const first = points[0];
1614
- return `${linePath(points)}L${round(last.x)},${round(baseline)}L${round(first.x)},${round(baseline)}Z`;
1614
+ return `${linePath(points)}L${round$1(last.x)},${round$1(baseline)}L${round$1(first.x)},${round$1(baseline)}Z`;
1615
1615
  }
1616
1616
  function arcPoint(radius, angle) {
1617
1617
  return { x: radius * Math.sin(angle), y: -radius * Math.cos(angle) };
1618
1618
  }
1619
1619
  function point(p) {
1620
- return `${round(p.x)},${round(p.y)}`;
1620
+ return `${round$1(p.x)},${round$1(p.y)}`;
1621
1621
  }
1622
1622
  const FULL_CIRCLE = Math.PI * 2;
1623
1623
  function arcPath(arc) {
@@ -1633,13 +1633,13 @@ function arcPath(arc) {
1633
1633
  const largeArc = span > Math.PI ? 1 : 0;
1634
1634
  const outerStart = arcPoint(outerRadius, startAngle);
1635
1635
  const outerEnd = arcPoint(outerRadius, endAngle);
1636
- const outerArc = `A${round(outerRadius)},${round(outerRadius)} 0 ${largeArc},1 ${point(outerEnd)}`;
1636
+ const outerArc = `A${round$1(outerRadius)},${round$1(outerRadius)} 0 ${largeArc},1 ${point(outerEnd)}`;
1637
1637
  if (innerRadius <= 0) {
1638
1638
  return `M0,0L${point(outerStart)}${outerArc}Z`;
1639
1639
  }
1640
1640
  const innerStart = arcPoint(innerRadius, startAngle);
1641
1641
  const innerEnd = arcPoint(innerRadius, endAngle);
1642
- const innerArc = `A${round(innerRadius)},${round(innerRadius)} 0 ${largeArc},0 ${point(innerStart)}`;
1642
+ const innerArc = `A${round$1(innerRadius)},${round$1(innerRadius)} 0 ${largeArc},0 ${point(innerStart)}`;
1643
1643
  return `M${point(outerStart)}${outerArc}L${point(innerEnd)}${innerArc}Z`;
1644
1644
  }
1645
1645
 
@@ -4958,6 +4958,17 @@ class Stepper {
4958
4958
  ...(ngDevMode ? [{ debugName: "completedLabel" }] : /* istanbul ignore next */ []));
4959
4959
  errorLabel = input('Error', /* @ts-ignore */
4960
4960
  ...(ngDevMode ? [{ debugName: "errorLabel" }] : /* istanbul ignore next */ []));
4961
+ interactive = input(false, { ...(ngDevMode ? { debugName: "interactive" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
4962
+ selectedIndex = model(null, /* @ts-ignore */
4963
+ ...(ngDevMode ? [{ debugName: "selectedIndex" }] : /* istanbul ignore next */ []));
4964
+ selectedLabel = input('Selected', /* @ts-ignore */
4965
+ ...(ngDevMode ? [{ debugName: "selectedLabel" }] : /* istanbul ignore next */ []));
4966
+ select(index) {
4967
+ this.selectedIndex.set(index);
4968
+ }
4969
+ isSelected(index) {
4970
+ return this.interactive() && this.selectedIndex() === index;
4971
+ }
4961
4972
  statusOf(index) {
4962
4973
  const step = this.steps()[index];
4963
4974
  const active = this.activeIndex();
@@ -4973,12 +4984,104 @@ class Stepper {
4973
4984
  return 'upcoming';
4974
4985
  }
4975
4986
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: Stepper, deps: [], target: i0.ɵɵFactoryTarget.Component });
4976
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: Stepper, isStandalone: true, selector: "gbt-stepper", inputs: { steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: true, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, completedLabel: { classPropertyName: "completedLabel", publicName: "completedLabel", isSignal: true, isRequired: false, transformFunction: null }, errorLabel: { classPropertyName: "errorLabel", publicName: "errorLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeIndex: "activeIndexChange" }, ngImport: i0, template: "<ol class=\"gbt-stepper\" [attr.data-orientation]=\"orientation()\">\n @for (step of steps(); track $index) {\n <li\n class=\"gbt-stepper__step\"\n [attr.data-status]=\"statusOf($index)\"\n [attr.aria-current]=\"statusOf($index) === 'current' ? 'step' : null\"\n >\n <span class=\"gbt-stepper__indicator\">\n @switch (statusOf($index)) {\n @case ('completed') {\n <gbt-icon name=\"check\" aria-hidden=\"true\" />\n }\n @case ('error') {\n <gbt-icon name=\"alert-triangle\" aria-hidden=\"true\" />\n }\n @default {\n {{ $index + 1 }}\n }\n }\n </span>\n <span class=\"gbt-stepper__label\">\n {{ step.label }}\n @if (statusOf($index) === 'completed') {\n <span class=\"sr-only\"> \u2014 {{ completedLabel() }}</span>\n } @else if (statusOf($index) === 'error') {\n <span class=\"sr-only\"> \u2014 {{ errorLabel() }}</span>\n }\n </span>\n </li>\n }\n</ol>\n", styles: [".gbt-stepper{display:flex;margin:0;padding:0;list-style:none}.gbt-stepper[data-orientation=horizontal]{flex-direction:row}.gbt-stepper[data-orientation=vertical]{flex-direction:column;gap:.5rem}.gbt-stepper__step{position:relative;display:flex;flex:1;align-items:center;gap:.5rem}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step{flex-direction:column}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step:not(:first-child):before{content:\"\";position:absolute;top:15px;right:calc(50% + 16px);left:calc(-50% + 16px);height:2px;background:var(--border-color)}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step[data-status=completed]:not(:first-child):before{background:var(--primary)}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step{flex:none;flex-direction:row}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step:not(:last-child):before{content:\"\";position:absolute;top:32px;bottom:-8px;left:15px;width:2px;background:var(--border-color)}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step[data-status=completed]:not(:last-child):before{background:var(--primary)}.gbt-stepper__indicator{position:relative;z-index:1;box-sizing:border-box;display:flex;flex-shrink:0;align-items:center;justify-content:center;width:32px;height:32px;background:var(--bg-principal);border:2px solid var(--border-color);border-radius:50%;color:var(--text-secondary);font-size:13px;font-weight:600}.gbt-stepper__step[data-status=current] .gbt-stepper__indicator{border-color:var(--primary);color:var(--primary)}.gbt-stepper__step[data-status=completed] .gbt-stepper__indicator{background:var(--primary);border-color:var(--primary);color:var(--text-on-primary)}.gbt-stepper__step[data-status=error] .gbt-stepper__indicator{border-color:var(--color-error-text);color:var(--color-error-text)}.gbt-stepper__label{font-size:13px;font-weight:600;color:var(--text-secondary);text-align:center}.gbt-stepper[data-orientation=vertical] .gbt-stepper__label{text-align:left}.gbt-stepper__step[data-status=current] .gbt-stepper__label{color:var(--text-primary)}.gbt-stepper__step[data-status=error] .gbt-stepper__label{color:var(--color-error-text)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4987
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: Stepper, isStandalone: true, selector: "gbt-stepper", inputs: { steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: true, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, completedLabel: { classPropertyName: "completedLabel", publicName: "completedLabel", isSignal: true, isRequired: false, transformFunction: null }, errorLabel: { classPropertyName: "errorLabel", publicName: "errorLabel", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, selectedIndex: { classPropertyName: "selectedIndex", publicName: "selectedIndex", isSignal: true, isRequired: false, transformFunction: null }, selectedLabel: { classPropertyName: "selectedLabel", publicName: "selectedLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { activeIndex: "activeIndexChange", selectedIndex: "selectedIndexChange" }, ngImport: i0, template: "<ng-template #content let-index=\"index\" let-step=\"step\">\n <span class=\"gbt-stepper__indicator\">\n @switch (statusOf(index)) {\n @case ('completed') {\n <gbt-icon name=\"check\" aria-hidden=\"true\" />\n }\n @case ('error') {\n <gbt-icon name=\"alert-triangle\" aria-hidden=\"true\" />\n }\n @default {\n {{ index + 1 }}\n }\n }\n </span>\n <span class=\"gbt-stepper__label\">\n {{ step.label }}\n @if (statusOf(index) === 'completed') {\n <span class=\"sr-only\"> \u2014 {{ completedLabel() }}</span>\n } @else if (statusOf(index) === 'error') {\n <span class=\"sr-only\"> \u2014 {{ errorLabel() }}</span>\n }\n @if (isSelected(index)) {\n <span class=\"sr-only\"> \u2014 {{ selectedLabel() }}</span>\n }\n </span>\n</ng-template>\n\n<ol class=\"gbt-stepper\" [attr.data-orientation]=\"orientation()\">\n @for (step of steps(); track $index) {\n <li\n class=\"gbt-stepper__step\"\n [attr.data-status]=\"statusOf($index)\"\n [attr.data-selected]=\"isSelected($index) ? '' : null\"\n [attr.aria-current]=\"statusOf($index) === 'current' ? 'step' : null\"\n >\n @if (interactive()) {\n <button type=\"button\" class=\"gbt-stepper__button\" (click)=\"select($index)\">\n <ng-container *ngTemplateOutlet=\"content; context: { index: $index, step: step }\" />\n </button>\n } @else {\n <ng-container *ngTemplateOutlet=\"content; context: { index: $index, step: step }\" />\n }\n </li>\n }\n</ol>\n", styles: [".gbt-stepper{display:flex;margin:0;padding:0;list-style:none}.gbt-stepper[data-orientation=horizontal]{flex-direction:row}.gbt-stepper[data-orientation=vertical]{flex-direction:column;gap:.5rem}.gbt-stepper__step{position:relative;display:flex;flex:1;align-items:center;gap:.5rem}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step{flex-direction:column}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step:not(:first-child):before{content:\"\";position:absolute;top:15px;right:calc(50% + 16px);left:calc(-50% + 16px);height:2px;background:var(--border-color)}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step[data-status=completed]:not(:first-child):before{background:var(--primary)}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step{flex:none;flex-direction:row}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step:not(:last-child):before{content:\"\";position:absolute;top:32px;bottom:-8px;left:15px;width:2px;background:var(--border-color)}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step[data-status=completed]:not(:last-child):before{background:var(--primary)}.gbt-stepper__indicator{position:relative;z-index:1;box-sizing:border-box;display:flex;flex-shrink:0;align-items:center;justify-content:center;width:32px;height:32px;background:var(--bg-principal);border:2px solid var(--border-color);border-radius:50%;color:var(--text-secondary);font-size:13px;font-weight:600}.gbt-stepper__step[data-status=current] .gbt-stepper__indicator{border-color:var(--primary);color:var(--primary)}.gbt-stepper__step[data-status=completed] .gbt-stepper__indicator{background:var(--primary);border-color:var(--primary);color:var(--text-on-primary)}.gbt-stepper__step[data-status=error] .gbt-stepper__indicator{border-color:var(--color-error-text);color:var(--color-error-text)}.gbt-stepper__label{font-size:13px;font-weight:600;color:var(--text-secondary);text-align:center}.gbt-stepper[data-orientation=vertical] .gbt-stepper__label{text-align:left}.gbt-stepper__step[data-status=current] .gbt-stepper__label{color:var(--text-primary)}.gbt-stepper__step[data-status=error] .gbt-stepper__label{color:var(--color-error-text)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.gbt-stepper__button{display:flex;align-items:center;gap:.5rem;padding:0;background:none;border:0;border-radius:4px;font:inherit;color:inherit;cursor:pointer}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__button{flex-direction:column}.gbt-stepper[data-orientation=vertical] .gbt-stepper__button{flex-direction:row}.gbt-stepper__button:focus-visible{outline:2px solid var(--primary);outline-offset:4px}.gbt-stepper__step[data-selected] .gbt-stepper__indicator{box-shadow:0 0 0 3px color-mix(in srgb,var(--primary) 30%,transparent)}.gbt-stepper__step[data-selected] .gbt-stepper__label{text-decoration:underline;text-underline-offset:4px}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4977
4988
  }
4978
4989
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: Stepper, decorators: [{
4979
4990
  type: Component,
4980
- args: [{ selector: 'gbt-stepper', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ol class=\"gbt-stepper\" [attr.data-orientation]=\"orientation()\">\n @for (step of steps(); track $index) {\n <li\n class=\"gbt-stepper__step\"\n [attr.data-status]=\"statusOf($index)\"\n [attr.aria-current]=\"statusOf($index) === 'current' ? 'step' : null\"\n >\n <span class=\"gbt-stepper__indicator\">\n @switch (statusOf($index)) {\n @case ('completed') {\n <gbt-icon name=\"check\" aria-hidden=\"true\" />\n }\n @case ('error') {\n <gbt-icon name=\"alert-triangle\" aria-hidden=\"true\" />\n }\n @default {\n {{ $index + 1 }}\n }\n }\n </span>\n <span class=\"gbt-stepper__label\">\n {{ step.label }}\n @if (statusOf($index) === 'completed') {\n <span class=\"sr-only\"> \u2014 {{ completedLabel() }}</span>\n } @else if (statusOf($index) === 'error') {\n <span class=\"sr-only\"> \u2014 {{ errorLabel() }}</span>\n }\n </span>\n </li>\n }\n</ol>\n", styles: [".gbt-stepper{display:flex;margin:0;padding:0;list-style:none}.gbt-stepper[data-orientation=horizontal]{flex-direction:row}.gbt-stepper[data-orientation=vertical]{flex-direction:column;gap:.5rem}.gbt-stepper__step{position:relative;display:flex;flex:1;align-items:center;gap:.5rem}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step{flex-direction:column}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step:not(:first-child):before{content:\"\";position:absolute;top:15px;right:calc(50% + 16px);left:calc(-50% + 16px);height:2px;background:var(--border-color)}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step[data-status=completed]:not(:first-child):before{background:var(--primary)}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step{flex:none;flex-direction:row}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step:not(:last-child):before{content:\"\";position:absolute;top:32px;bottom:-8px;left:15px;width:2px;background:var(--border-color)}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step[data-status=completed]:not(:last-child):before{background:var(--primary)}.gbt-stepper__indicator{position:relative;z-index:1;box-sizing:border-box;display:flex;flex-shrink:0;align-items:center;justify-content:center;width:32px;height:32px;background:var(--bg-principal);border:2px solid var(--border-color);border-radius:50%;color:var(--text-secondary);font-size:13px;font-weight:600}.gbt-stepper__step[data-status=current] .gbt-stepper__indicator{border-color:var(--primary);color:var(--primary)}.gbt-stepper__step[data-status=completed] .gbt-stepper__indicator{background:var(--primary);border-color:var(--primary);color:var(--text-on-primary)}.gbt-stepper__step[data-status=error] .gbt-stepper__indicator{border-color:var(--color-error-text);color:var(--color-error-text)}.gbt-stepper__label{font-size:13px;font-weight:600;color:var(--text-secondary);text-align:center}.gbt-stepper[data-orientation=vertical] .gbt-stepper__label{text-align:left}.gbt-stepper__step[data-status=current] .gbt-stepper__label{color:var(--text-primary)}.gbt-stepper__step[data-status=error] .gbt-stepper__label{color:var(--color-error-text)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
4981
- }], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }, { type: i0.Output, args: ["activeIndexChange"] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], completedLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "completedLabel", required: false }] }], errorLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorLabel", required: false }] }] } });
4991
+ args: [{ selector: 'gbt-stepper', standalone: true, imports: [Icon, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #content let-index=\"index\" let-step=\"step\">\n <span class=\"gbt-stepper__indicator\">\n @switch (statusOf(index)) {\n @case ('completed') {\n <gbt-icon name=\"check\" aria-hidden=\"true\" />\n }\n @case ('error') {\n <gbt-icon name=\"alert-triangle\" aria-hidden=\"true\" />\n }\n @default {\n {{ index + 1 }}\n }\n }\n </span>\n <span class=\"gbt-stepper__label\">\n {{ step.label }}\n @if (statusOf(index) === 'completed') {\n <span class=\"sr-only\"> \u2014 {{ completedLabel() }}</span>\n } @else if (statusOf(index) === 'error') {\n <span class=\"sr-only\"> \u2014 {{ errorLabel() }}</span>\n }\n @if (isSelected(index)) {\n <span class=\"sr-only\"> \u2014 {{ selectedLabel() }}</span>\n }\n </span>\n</ng-template>\n\n<ol class=\"gbt-stepper\" [attr.data-orientation]=\"orientation()\">\n @for (step of steps(); track $index) {\n <li\n class=\"gbt-stepper__step\"\n [attr.data-status]=\"statusOf($index)\"\n [attr.data-selected]=\"isSelected($index) ? '' : null\"\n [attr.aria-current]=\"statusOf($index) === 'current' ? 'step' : null\"\n >\n @if (interactive()) {\n <button type=\"button\" class=\"gbt-stepper__button\" (click)=\"select($index)\">\n <ng-container *ngTemplateOutlet=\"content; context: { index: $index, step: step }\" />\n </button>\n } @else {\n <ng-container *ngTemplateOutlet=\"content; context: { index: $index, step: step }\" />\n }\n </li>\n }\n</ol>\n", styles: [".gbt-stepper{display:flex;margin:0;padding:0;list-style:none}.gbt-stepper[data-orientation=horizontal]{flex-direction:row}.gbt-stepper[data-orientation=vertical]{flex-direction:column;gap:.5rem}.gbt-stepper__step{position:relative;display:flex;flex:1;align-items:center;gap:.5rem}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step{flex-direction:column}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step:not(:first-child):before{content:\"\";position:absolute;top:15px;right:calc(50% + 16px);left:calc(-50% + 16px);height:2px;background:var(--border-color)}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__step[data-status=completed]:not(:first-child):before{background:var(--primary)}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step{flex:none;flex-direction:row}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step:not(:last-child):before{content:\"\";position:absolute;top:32px;bottom:-8px;left:15px;width:2px;background:var(--border-color)}.gbt-stepper[data-orientation=vertical] .gbt-stepper__step[data-status=completed]:not(:last-child):before{background:var(--primary)}.gbt-stepper__indicator{position:relative;z-index:1;box-sizing:border-box;display:flex;flex-shrink:0;align-items:center;justify-content:center;width:32px;height:32px;background:var(--bg-principal);border:2px solid var(--border-color);border-radius:50%;color:var(--text-secondary);font-size:13px;font-weight:600}.gbt-stepper__step[data-status=current] .gbt-stepper__indicator{border-color:var(--primary);color:var(--primary)}.gbt-stepper__step[data-status=completed] .gbt-stepper__indicator{background:var(--primary);border-color:var(--primary);color:var(--text-on-primary)}.gbt-stepper__step[data-status=error] .gbt-stepper__indicator{border-color:var(--color-error-text);color:var(--color-error-text)}.gbt-stepper__label{font-size:13px;font-weight:600;color:var(--text-secondary);text-align:center}.gbt-stepper[data-orientation=vertical] .gbt-stepper__label{text-align:left}.gbt-stepper__step[data-status=current] .gbt-stepper__label{color:var(--text-primary)}.gbt-stepper__step[data-status=error] .gbt-stepper__label{color:var(--color-error-text)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.gbt-stepper__button{display:flex;align-items:center;gap:.5rem;padding:0;background:none;border:0;border-radius:4px;font:inherit;color:inherit;cursor:pointer}.gbt-stepper[data-orientation=horizontal] .gbt-stepper__button{flex-direction:column}.gbt-stepper[data-orientation=vertical] .gbt-stepper__button{flex-direction:row}.gbt-stepper__button:focus-visible{outline:2px solid var(--primary);outline-offset:4px}.gbt-stepper__step[data-selected] .gbt-stepper__indicator{box-shadow:0 0 0 3px color-mix(in srgb,var(--primary) 30%,transparent)}.gbt-stepper__step[data-selected] .gbt-stepper__label{text-decoration:underline;text-underline-offset:4px}\n"] }]
4992
+ }], propDecorators: { steps: [{ type: i0.Input, args: [{ isSignal: true, alias: "steps", required: true }] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }, { type: i0.Output, args: ["activeIndexChange"] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], completedLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "completedLabel", required: false }] }], errorLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorLabel", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], selectedIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIndex", required: false }] }, { type: i0.Output, args: ["selectedIndexChange"] }], selectedLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedLabel", required: false }] }] } });
4993
+
4994
+ function graphEdges(stages) {
4995
+ const names = new Set(stages.flatMap((stage) => stage.jobs.map((job) => job.name)));
4996
+ return stages.flatMap((stage) => stage.jobs.flatMap((job) => job.needs.filter((need) => names.has(need)).map((need) => ({ from: need, to: job.name }))));
4997
+ }
4998
+ const round = (value) => Math.round(value * 10) / 10;
4999
+ function linkPath(from, to) {
5000
+ const x1 = from.left + from.width;
5001
+ const y1 = from.top + from.height / 2;
5002
+ const x2 = to.left;
5003
+ const y2 = to.top + to.height / 2;
5004
+ const dx = Math.max(24, (x2 - x1) / 2);
5005
+ return `M ${round(x1)} ${round(y1)} C ${round(x1 + dx)} ${round(y1)}, ${round(x2 - dx)} ${round(y2)}, ${round(x2)} ${round(y2)}`;
5006
+ }
5007
+
5008
+ const DEFAULT_STATUS_LABELS = {
5009
+ pending: 'Pending',
5010
+ running: 'Running',
5011
+ success: 'Succeeded',
5012
+ failed: 'Failed',
5013
+ canceled: 'Canceled',
5014
+ };
5015
+ class JobGraph {
5016
+ stages = input.required(/* @ts-ignore */
5017
+ ...(ngDevMode ? [{ debugName: "stages" }] : /* istanbul ignore next */ []));
5018
+ selectedJobId = input(null, /* @ts-ignore */
5019
+ ...(ngDevMode ? [{ debugName: "selectedJobId" }] : /* istanbul ignore next */ []));
5020
+ statusLabels = input(DEFAULT_STATUS_LABELS, /* @ts-ignore */
5021
+ ...(ngDevMode ? [{ debugName: "statusLabels" }] : /* istanbul ignore next */ []));
5022
+ needsLabel = input('Needs', /* @ts-ignore */
5023
+ ...(ngDevMode ? [{ debugName: "needsLabel" }] : /* istanbul ignore next */ []));
5024
+ ariaLabel = input('Pipeline jobs', /* @ts-ignore */
5025
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
5026
+ jobSelected = output();
5027
+ links = signal([], /* @ts-ignore */
5028
+ ...(ngDevMode ? [{ debugName: "links" }] : /* istanbul ignore next */ []));
5029
+ graph = viewChild('graph', /* @ts-ignore */
5030
+ ...(ngDevMode ? [{ debugName: "graph" }] : /* istanbul ignore next */ []));
5031
+ destroyRef = inject(DestroyRef);
5032
+ constructor() {
5033
+ afterRenderEffect(() => {
5034
+ this.stages();
5035
+ this.measure();
5036
+ });
5037
+ afterNextRender(() => {
5038
+ const root = this.graph()?.nativeElement;
5039
+ if (!root || typeof ResizeObserver === 'undefined') {
5040
+ return;
5041
+ }
5042
+ const observer = new ResizeObserver(() => this.measure());
5043
+ observer.observe(root);
5044
+ this.destroyRef.onDestroy(() => observer.disconnect());
5045
+ });
5046
+ }
5047
+ measure() {
5048
+ const root = this.graph()?.nativeElement;
5049
+ if (!root) {
5050
+ return;
5051
+ }
5052
+ const origin = root.getBoundingClientRect();
5053
+ const boxes = new Map();
5054
+ root.querySelectorAll('[data-job-name]').forEach((node) => {
5055
+ const rect = node.getBoundingClientRect();
5056
+ boxes.set(node.dataset['jobName'] ?? '', {
5057
+ left: rect.left - origin.left + root.scrollLeft,
5058
+ top: rect.top - origin.top + root.scrollTop,
5059
+ width: rect.width,
5060
+ height: rect.height,
5061
+ });
5062
+ });
5063
+ const statuses = new Map(this.stages().flatMap((s) => s.jobs.map((j) => [j.name, j.status])));
5064
+ this.links.set(graphEdges(this.stages()).flatMap((edge) => {
5065
+ const from = boxes.get(edge.from);
5066
+ const to = boxes.get(edge.to);
5067
+ return from && to
5068
+ ? [
5069
+ {
5070
+ key: `${edge.from}->${edge.to}`,
5071
+ d: linkPath(from, to),
5072
+ done: statuses.get(edge.from) === 'success',
5073
+ },
5074
+ ]
5075
+ : [];
5076
+ }));
5077
+ }
5078
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: JobGraph, deps: [], target: i0.ɵɵFactoryTarget.Component });
5079
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: JobGraph, isStandalone: true, selector: "gbt-job-graph", inputs: { stages: { classPropertyName: "stages", publicName: "stages", isSignal: true, isRequired: true, transformFunction: null }, selectedJobId: { classPropertyName: "selectedJobId", publicName: "selectedJobId", isSignal: true, isRequired: false, transformFunction: null }, statusLabels: { classPropertyName: "statusLabels", publicName: "statusLabels", isSignal: true, isRequired: false, transformFunction: null }, needsLabel: { classPropertyName: "needsLabel", publicName: "needsLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { jobSelected: "jobSelected" }, viewQueries: [{ propertyName: "graph", first: true, predicate: ["graph"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"gbt-job-graph\" #graph>\n <ol class=\"gbt-job-graph__stages\" [attr.aria-label]=\"ariaLabel()\">\n @for (stage of stages(); track stage.name) {\n <li class=\"gbt-job-graph__stage\">\n <h3 class=\"gbt-job-graph__stage-name\">{{ stage.name }}</h3>\n <ul class=\"gbt-job-graph__jobs\">\n @for (job of stage.jobs; track job.id) {\n <li>\n <button\n type=\"button\"\n class=\"gbt-job-graph__node\"\n [attr.data-job-name]=\"job.name\"\n [attr.data-status]=\"job.status\"\n [attr.aria-current]=\"job.id === selectedJobId() ? 'true' : null\"\n (click)=\"jobSelected.emit(job.id)\"\n >\n <span class=\"gbt-job-graph__glyph\" data-glyph aria-hidden=\"true\">\n @switch (job.status) {\n @case ('success') {\n <gbt-icon name=\"check-circle\" />\n }\n @case ('failed') {\n <gbt-icon name=\"alert-circle\" />\n }\n @case ('canceled') {\n <gbt-icon name=\"x\" />\n }\n @default {\n <span class=\"gbt-job-graph__dot\"></span>\n }\n }\n </span>\n <span class=\"gbt-job-graph__name\">{{ job.name }}</span>\n @if (job.durationLabel) {\n <span class=\"gbt-job-graph__duration\">{{ job.durationLabel }}</span>\n }\n <span class=\"sr-only\">\n \u2014 {{ statusLabels()[job.status] }}@if (job.needs.length > 0) {. {{ needsLabel() }}: {{ job.needs.join(', ') }}}\n </span>\n </button>\n </li>\n }\n </ul>\n </li>\n }\n </ol>\n <svg class=\"gbt-job-graph__links\" aria-hidden=\"true\" focusable=\"false\">\n @for (link of links(); track link.key) {\n <path [attr.d]=\"link.d\" [attr.data-done]=\"link.done ? '' : null\" />\n }\n </svg>\n</div>\n", styles: [".gbt-job-graph{position:relative;overflow-x:auto}.gbt-job-graph__stages{position:relative;z-index:1;display:flex;gap:4rem;margin:0;padding:.5rem;list-style:none}.gbt-job-graph__stage-name{margin:0 0 .75rem;font-size:13px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--text-secondary)}.gbt-job-graph__jobs{display:flex;flex-direction:column;gap:.75rem;margin:0;padding:0;list-style:none}.gbt-job-graph__node{display:flex;align-items:center;gap:.5rem;min-width:13rem;padding:.5rem .75rem;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:8px;color:var(--text-primary);font:inherit;text-align:left;cursor:pointer}.gbt-job-graph__node:hover{border-color:var(--primary)}.gbt-job-graph__node:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-job-graph__node[aria-current=true]{border-color:var(--primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--primary) 30%,transparent)}.gbt-job-graph__glyph{display:inline-flex;flex-shrink:0}.gbt-job-graph__node[data-status=success] .gbt-job-graph__glyph{color:var(--color-success-text)}.gbt-job-graph__node[data-status=failed] .gbt-job-graph__glyph{color:var(--color-error-text)}.gbt-job-graph__node[data-status=canceled] .gbt-job-graph__glyph{color:var(--text-secondary)}.gbt-job-graph__dot{box-sizing:border-box;width:16px;height:16px;border:2px solid var(--border-color);border-radius:50%}.gbt-job-graph__node[data-status=running] .gbt-job-graph__dot{border-color:var(--primary);border-top-color:transparent;animation:gbt-job-graph-spin .9s linear infinite}@media(prefers-reduced-motion:reduce){.gbt-job-graph__node[data-status=running] .gbt-job-graph__dot{animation:none;border-top-color:var(--primary);background:var(--primary)}}@keyframes gbt-job-graph-spin{to{transform:rotate(360deg)}}.gbt-job-graph__name{flex:1;font-weight:600}.gbt-job-graph__duration{font-size:12px;color:var(--text-secondary)}.gbt-job-graph__links{position:absolute;inset:0;z-index:0;width:100%;height:100%;pointer-events:none;overflow:visible}.gbt-job-graph__links path{fill:none;stroke:var(--border-color);stroke-width:2}.gbt-job-graph__links path[data-done]{stroke:var(--color-success-base)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"], dependencies: [{ kind: "component", type: Icon, selector: "gbt-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5080
+ }
5081
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: JobGraph, decorators: [{
5082
+ type: Component,
5083
+ args: [{ selector: 'gbt-job-graph', standalone: true, imports: [Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"gbt-job-graph\" #graph>\n <ol class=\"gbt-job-graph__stages\" [attr.aria-label]=\"ariaLabel()\">\n @for (stage of stages(); track stage.name) {\n <li class=\"gbt-job-graph__stage\">\n <h3 class=\"gbt-job-graph__stage-name\">{{ stage.name }}</h3>\n <ul class=\"gbt-job-graph__jobs\">\n @for (job of stage.jobs; track job.id) {\n <li>\n <button\n type=\"button\"\n class=\"gbt-job-graph__node\"\n [attr.data-job-name]=\"job.name\"\n [attr.data-status]=\"job.status\"\n [attr.aria-current]=\"job.id === selectedJobId() ? 'true' : null\"\n (click)=\"jobSelected.emit(job.id)\"\n >\n <span class=\"gbt-job-graph__glyph\" data-glyph aria-hidden=\"true\">\n @switch (job.status) {\n @case ('success') {\n <gbt-icon name=\"check-circle\" />\n }\n @case ('failed') {\n <gbt-icon name=\"alert-circle\" />\n }\n @case ('canceled') {\n <gbt-icon name=\"x\" />\n }\n @default {\n <span class=\"gbt-job-graph__dot\"></span>\n }\n }\n </span>\n <span class=\"gbt-job-graph__name\">{{ job.name }}</span>\n @if (job.durationLabel) {\n <span class=\"gbt-job-graph__duration\">{{ job.durationLabel }}</span>\n }\n <span class=\"sr-only\">\n \u2014 {{ statusLabels()[job.status] }}@if (job.needs.length > 0) {. {{ needsLabel() }}: {{ job.needs.join(', ') }}}\n </span>\n </button>\n </li>\n }\n </ul>\n </li>\n }\n </ol>\n <svg class=\"gbt-job-graph__links\" aria-hidden=\"true\" focusable=\"false\">\n @for (link of links(); track link.key) {\n <path [attr.d]=\"link.d\" [attr.data-done]=\"link.done ? '' : null\" />\n }\n </svg>\n</div>\n", styles: [".gbt-job-graph{position:relative;overflow-x:auto}.gbt-job-graph__stages{position:relative;z-index:1;display:flex;gap:4rem;margin:0;padding:.5rem;list-style:none}.gbt-job-graph__stage-name{margin:0 0 .75rem;font-size:13px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--text-secondary)}.gbt-job-graph__jobs{display:flex;flex-direction:column;gap:.75rem;margin:0;padding:0;list-style:none}.gbt-job-graph__node{display:flex;align-items:center;gap:.5rem;min-width:13rem;padding:.5rem .75rem;background:var(--bg-principal);border:1px solid var(--border-color);border-radius:8px;color:var(--text-primary);font:inherit;text-align:left;cursor:pointer}.gbt-job-graph__node:hover{border-color:var(--primary)}.gbt-job-graph__node:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.gbt-job-graph__node[aria-current=true]{border-color:var(--primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--primary) 30%,transparent)}.gbt-job-graph__glyph{display:inline-flex;flex-shrink:0}.gbt-job-graph__node[data-status=success] .gbt-job-graph__glyph{color:var(--color-success-text)}.gbt-job-graph__node[data-status=failed] .gbt-job-graph__glyph{color:var(--color-error-text)}.gbt-job-graph__node[data-status=canceled] .gbt-job-graph__glyph{color:var(--text-secondary)}.gbt-job-graph__dot{box-sizing:border-box;width:16px;height:16px;border:2px solid var(--border-color);border-radius:50%}.gbt-job-graph__node[data-status=running] .gbt-job-graph__dot{border-color:var(--primary);border-top-color:transparent;animation:gbt-job-graph-spin .9s linear infinite}@media(prefers-reduced-motion:reduce){.gbt-job-graph__node[data-status=running] .gbt-job-graph__dot{animation:none;border-top-color:var(--primary);background:var(--primary)}}@keyframes gbt-job-graph-spin{to{transform:rotate(360deg)}}.gbt-job-graph__name{flex:1;font-weight:600}.gbt-job-graph__duration{font-size:12px;color:var(--text-secondary)}.gbt-job-graph__links{position:absolute;inset:0;z-index:0;width:100%;height:100%;pointer-events:none;overflow:visible}.gbt-job-graph__links path{fill:none;stroke:var(--border-color);stroke-width:2}.gbt-job-graph__links path[data-done]{stroke:var(--color-success-base)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}\n"] }]
5084
+ }], ctorParameters: () => [], propDecorators: { stages: [{ type: i0.Input, args: [{ isSignal: true, alias: "stages", required: true }] }], selectedJobId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedJobId", required: false }] }], statusLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "statusLabels", required: false }] }], needsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "needsLabel", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], jobSelected: [{ type: i0.Output, args: ["jobSelected"] }], graph: [{ type: i0.ViewChild, args: ['graph', { isSignal: true }] }] } });
4982
5085
 
4983
5086
  let nextId$1 = 0;
4984
5087
  function formatFileSize(bytes) {
@@ -5405,5 +5508,5 @@ function cssEscape(value) {
5405
5508
  * Generated bundle index. Do not edit.
5406
5509
  */
5407
5510
 
5408
- export { Accordion, AccordionItem, Alert, AppShell, Autocomplete, Avatar, AvatarGroup, Badge, BarChart, BarSeries, Breadcrumb, Button, CHART_CONTEXT, Card, ChartAxis, ChartEmpty, ChartFrame, ChartLegend, ChartTable, ChartTooltip, Checkbox, ConfirmDangerModal, DatePicker, DateRangePicker, DescriptionList, DimensionCard, Divider, Drawer, EmptyState, FileUpload, FunnelChart, GABARIT_VERSION, GaugeBar, GbtInput, Icon, IconRegistry, LineChart, LineSeries, ListToolbar, Menu, Modal, NotificationDot, Pagination, PieChart, Popover, RadioGroup, SearchBar, SegmentedControl, Select, Skeleton, Slider, Sparkline, Spinner, Stepper, Switch, Tab, Table, Tabs, Tag, TagInput, Textarea, TimelineChart, TimelineSeries, Toaster, Tooltip, Tree, arcPath, areaPath, bandScale, formatCompact, formatDuration, formatNumber, formatPercent, linePath, linearScale, nearestIndex, niceTicks, niceXDomain, niceYDomain, timeScale, timeTicks };
5511
+ export { Accordion, AccordionItem, Alert, AppShell, Autocomplete, Avatar, AvatarGroup, Badge, BarChart, BarSeries, Breadcrumb, Button, CHART_CONTEXT, Card, ChartAxis, ChartEmpty, ChartFrame, ChartLegend, ChartTable, ChartTooltip, Checkbox, ConfirmDangerModal, DatePicker, DateRangePicker, DescriptionList, DimensionCard, Divider, Drawer, EmptyState, FileUpload, FunnelChart, GABARIT_VERSION, GaugeBar, GbtInput, Icon, IconRegistry, JobGraph, LineChart, LineSeries, ListToolbar, Menu, Modal, NotificationDot, Pagination, PieChart, Popover, RadioGroup, SearchBar, SegmentedControl, Select, Skeleton, Slider, Sparkline, Spinner, Stepper, Switch, Tab, Table, Tabs, Tag, TagInput, Textarea, TimelineChart, TimelineSeries, Toaster, Tooltip, Tree, arcPath, areaPath, bandScale, formatCompact, formatDuration, formatNumber, formatPercent, linePath, linearScale, nearestIndex, niceTicks, niceXDomain, niceYDomain, timeScale, timeTicks };
5409
5512
  //# sourceMappingURL=masmarino-gabarit.mjs.map