@forgeroute/ui 0.4.55 → 0.4.56

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.
@@ -11982,7 +11982,7 @@ var DataTableComponent = class DataTableComponent {
11982
11982
  label: "Default"
11983
11983
  }];
11984
11984
  for (const col of this.visibleCols()) {
11985
- if (!this._isSortable(col)) continue;
11985
+ if (!this._isSortable(col) || this._emptyColumnKeys().has(col.key)) continue;
11986
11986
  opts.push({
11987
11987
  value: `${col.key}:asc`,
11988
11988
  label: `${col.label} ↑`
@@ -11999,6 +11999,31 @@ var DataTableComponent = class DataTableComponent {
11999
11999
  cf: this.getColFilter(col)
12000
12000
  })).filter((f) => f.cf !== null), ...ngDevMode ? [{ debugName: "_phoneFilterCols" }] : /* istanbul ignore next */ []);
12001
12001
  this._showColumnControls = computed(() => !this._error() && (this._items().length > 0 || !!this._sortField() || Object.values(this._colFilterValues()).some((v) => v.length > 0)), ...ngDevMode ? [{ debugName: "_showColumnControls" }] : /* istanbul ignore next */ []);
12002
+ this._emptyColumnKeys = computed(() => {
12003
+ const items = this._items();
12004
+ const out = /* @__PURE__ */ new Set();
12005
+ if (items.length === 0) return out;
12006
+ for (const col of this.visibleCols()) {
12007
+ if (!this._isSortable(col) || this._sortField() === col.key) continue;
12008
+ let hasValue = false;
12009
+ for (const item of items) {
12010
+ let text;
12011
+ try {
12012
+ text = this.cardCellText(col, item);
12013
+ } catch {
12014
+ hasValue = true;
12015
+ break;
12016
+ }
12017
+ const t = text === null || text === void 0 ? "" : String(text).trim();
12018
+ if (t !== "" && t !== "—") {
12019
+ hasValue = true;
12020
+ break;
12021
+ }
12022
+ }
12023
+ if (!hasValue) out.add(col.key);
12024
+ }
12025
+ return out;
12026
+ }, ...ngDevMode ? [{ debugName: "_emptyColumnKeys" }] : /* istanbul ignore next */ []);
12002
12027
  this._hasPhoneControls = computed(() => this._phoneSortOptions().length > 1 || this._phoneFilterCols().length > 0, ...ngDevMode ? [{ debugName: "_hasPhoneControls" }] : /* istanbul ignore next */ []);
12003
12028
  this._injector = inject(Injector);
12004
12029
  this._silentNext = false;
@@ -12120,6 +12145,9 @@ var DataTableComponent = class DataTableComponent {
12120
12145
  this.load();
12121
12146
  this._fetchCounts();
12122
12147
  }
12148
+ _canShowSort(col) {
12149
+ return this._isSortable(col) && this._showColumnControls() && !this._emptyColumnKeys().has(col.key);
12150
+ }
12123
12151
  onPhoneSort(value) {
12124
12152
  if (!value) {
12125
12153
  this._sortField.set(null);
@@ -13017,11 +13045,11 @@ var DataTableComponent = class DataTableComponent {
13017
13045
  [style.width]="col.width ?? null"
13018
13046
  [style.min-width]="col.width ?? null"
13019
13047
  [style.max-width]="col.width ?? null"
13020
- [attr.aria-sort]="_isSortable(col) && _showColumnControls() ? sortAriaLabel(col.key) : null"
13048
+ [attr.aria-sort]="_canShowSort(col) ? sortAriaLabel(col.key) : null"
13021
13049
  [class.dt-th-sorted]="_sortField() === col.key"
13022
13050
  [class.dt-th-actions]="col.cellType === 'actions'">
13023
13051
  <div class="dt-th-inner">
13024
- @if (_isSortable(col) && _showColumnControls()) {
13052
+ @if (_canShowSort(col)) {
13025
13053
  <button
13026
13054
  class="dt-sort-btn"
13027
13055
  (click)="onSort(col.key)"
@@ -14085,11 +14113,11 @@ i0.ɵɵngDeclareClassMetadata({
14085
14113
  [style.width]="col.width ?? null"
14086
14114
  [style.min-width]="col.width ?? null"
14087
14115
  [style.max-width]="col.width ?? null"
14088
- [attr.aria-sort]="_isSortable(col) && _showColumnControls() ? sortAriaLabel(col.key) : null"
14116
+ [attr.aria-sort]="_canShowSort(col) ? sortAriaLabel(col.key) : null"
14089
14117
  [class.dt-th-sorted]="_sortField() === col.key"
14090
14118
  [class.dt-th-actions]="col.cellType === 'actions'">
14091
14119
  <div class="dt-th-inner">
14092
- @if (_isSortable(col) && _showColumnControls()) {
14120
+ @if (_canShowSort(col)) {
14093
14121
  <button
14094
14122
  class="dt-sort-btn"
14095
14123
  (click)="onSort(col.key)"
@@ -27282,6 +27310,7 @@ const ICON_PATHS = {
27282
27310
  };
27283
27311
  const CALENDAR_PATH = "M5 4h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z M16 2v4 M8 2v4 M3 10h18";
27284
27312
  const EDIT_PATH = "M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7 M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z";
27313
+ const TRASH_PATH = "M3 6h18 M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2 M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6 M10 11v6 M14 11v6";
27285
27314
  const INDICATOR_LABEL = {
27286
27315
  high: "High priority",
27287
27316
  medium: "Medium priority",
@@ -27303,10 +27332,19 @@ var CardListItemComponent = class CardListItemComponent {
27303
27332
  this.viewButton = input(false, ...ngDevMode ? [{ debugName: "viewButton" }] : /* istanbul ignore next */ []);
27304
27333
  this.editAriaLabel = input("", ...ngDevMode ? [{ debugName: "editAriaLabel" }] : /* istanbul ignore next */ []);
27305
27334
  this.viewAriaLabel = input("", ...ngDevMode ? [{ debugName: "viewAriaLabel" }] : /* istanbul ignore next */ []);
27335
+ this.deletable = input(false, ...ngDevMode ? [{ debugName: "deletable" }] : /* istanbul ignore next */ []);
27336
+ this.deleteLabel = input("Delete", ...ngDevMode ? [{ debugName: "deleteLabel" }] : /* istanbul ignore next */ []);
27337
+ this.deleteTestId = input("", ...ngDevMode ? [{ debugName: "deleteTestId" }] : /* istanbul ignore next */ []);
27338
+ this.actionLabel = input("", ...ngDevMode ? [{ debugName: "actionLabel" }] : /* istanbul ignore next */ []);
27339
+ this.actionTestId = input("", ...ngDevMode ? [{ debugName: "actionTestId" }] : /* istanbul ignore next */ []);
27340
+ this.actionAriaLabel = input("", ...ngDevMode ? [{ debugName: "actionAriaLabel" }] : /* istanbul ignore next */ []);
27306
27341
  this.editClick = output();
27307
27342
  this.viewClick = output();
27343
+ this.delete = output();
27344
+ this.action = output();
27308
27345
  this.calendarPath = CALENDAR_PATH;
27309
27346
  this.editPath = EDIT_PATH;
27347
+ this.trashPath = TRASH_PATH;
27310
27348
  this.iconPath = computed(() => {
27311
27349
  const i = this.icon();
27312
27350
  return i ? ICON_PATHS[i] ?? null : null;
@@ -27421,11 +27459,55 @@ var CardListItemComponent = class CardListItemComponent {
27421
27459
  isSignal: true,
27422
27460
  isRequired: false,
27423
27461
  transformFunction: null
27462
+ },
27463
+ deletable: {
27464
+ classPropertyName: "deletable",
27465
+ publicName: "deletable",
27466
+ isSignal: true,
27467
+ isRequired: false,
27468
+ transformFunction: null
27469
+ },
27470
+ deleteLabel: {
27471
+ classPropertyName: "deleteLabel",
27472
+ publicName: "deleteLabel",
27473
+ isSignal: true,
27474
+ isRequired: false,
27475
+ transformFunction: null
27476
+ },
27477
+ deleteTestId: {
27478
+ classPropertyName: "deleteTestId",
27479
+ publicName: "deleteTestId",
27480
+ isSignal: true,
27481
+ isRequired: false,
27482
+ transformFunction: null
27483
+ },
27484
+ actionLabel: {
27485
+ classPropertyName: "actionLabel",
27486
+ publicName: "actionLabel",
27487
+ isSignal: true,
27488
+ isRequired: false,
27489
+ transformFunction: null
27490
+ },
27491
+ actionTestId: {
27492
+ classPropertyName: "actionTestId",
27493
+ publicName: "actionTestId",
27494
+ isSignal: true,
27495
+ isRequired: false,
27496
+ transformFunction: null
27497
+ },
27498
+ actionAriaLabel: {
27499
+ classPropertyName: "actionAriaLabel",
27500
+ publicName: "actionAriaLabel",
27501
+ isSignal: true,
27502
+ isRequired: false,
27503
+ transformFunction: null
27424
27504
  }
27425
27505
  },
27426
27506
  outputs: {
27427
27507
  editClick: "editClick",
27428
- viewClick: "viewClick"
27508
+ viewClick: "viewClick",
27509
+ delete: "delete",
27510
+ action: "action"
27429
27511
  },
27430
27512
  ngImport: i0,
27431
27513
  template: `
@@ -27473,6 +27555,14 @@ var CardListItemComponent = class CardListItemComponent {
27473
27555
  @if (viewButton()) {
27474
27556
  <button class="cli-chip cli-chip--view" type="button" [attr.aria-label]="viewAriaLabel() || null" (click)="viewClick.emit()">View</button>
27475
27557
  }
27558
+ @if (actionLabel()) {
27559
+ <button class="cli-chip cli-chip--action" type="button" [attr.data-testid]="actionTestId() || null" [attr.aria-label]="actionAriaLabel() || null" (click)="action.emit()">{{ actionLabel() }}</button>
27560
+ }
27561
+ @if (deletable()) {
27562
+ <button class="cli-chip cli-chip--delete" type="button" [attr.data-testid]="deleteTestId() || null" [attr.aria-label]="deleteLabel() || 'Delete'" (click)="delete.emit()">
27563
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="trashPath" /></svg>
27564
+ </button>
27565
+ }
27476
27566
  <ng-content select="[card-list-action]" />
27477
27567
  <ng-content />
27478
27568
  </div>
@@ -27480,7 +27570,7 @@ var CardListItemComponent = class CardListItemComponent {
27480
27570
  <ng-content select="[card-detail]" />
27481
27571
  `,
27482
27572
  isInline: true,
27483
- styles: ["ui-card-list-item{position:relative;display:block;border:1px solid #e2e8f0;border-radius:8px;overflow:hidden;margin-bottom:8px}ui-card-list-item:last-child{margin-bottom:0}ui-card-list-item .cli-row{display:flex;align-items:flex-start;gap:12px;padding:13px 18px;transition:background .12s}ui-card-list-item .cli-row:hover{background:#f8fafc}@media(prefers-reduced-motion:reduce){ui-card-list-item .cli-row{transition:none}}ui-card-list-item .cli-dot{width:9px;height:9px;border-radius:50%;flex-shrink:0;margin-top:5px}ui-card-list-item .cli-dot:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}ui-card-list-item .cli-dot--high{background:#ef4444}ui-card-list-item .cli-dot--medium{background:#f59e0b}ui-card-list-item .cli-dot--low{background:#94a3b8}ui-card-list-item .cli-dot--blue{background:#3b82f6}ui-card-list-item .cli-dot--green{background:#22c55e}ui-card-list-item .cli-icon-circle{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0}ui-card-list-item .cli-icon-circle--call{background:#dbeafe;color:#2563eb}ui-card-list-item .cli-icon-circle--email{background:#dcfce7;color:#16a34a}ui-card-list-item .cli-icon-circle--sms{background:#fef9c3;color:#ca8a04}ui-card-list-item .cli-icon-circle--task{background:#dbeafe;color:#2563eb}ui-card-list-item .cli-icon-circle--doc{background:#ffedd5;color:#ea580c}ui-card-list-item .cli-icon-circle--money{background:#d1fae5;color:#059669}ui-card-list-item .cli-icon-circle--deal{background:#e0f2fe;color:#0284c7}ui-card-list-item .cli-icon-circle--survey{background:#dbeafe;color:#2563eb}ui-card-list-item .cli-icon-circle--property{background:#fef3c7;color:#d97706}ui-card-list-item .cli-icon-circle--search{background:#e0f2fe;color:#0284c7}ui-card-list-item .cli-icon-circle--heart{background:#fce7f3;color:#db2777}ui-card-list-item .cli-icon-circle--calc{background:#d1fae5;color:#059669}ui-card-list-item .cli-icon-circle--repeat{background:#e0f2fe;color:#0284c7}ui-card-list-item .cli-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px;overflow-wrap:anywhere;word-break:break-word}ui-card-list-item .cli-badges{position:absolute;top:10px;right:12px;display:flex;align-items:center;gap:6px;z-index:1}ui-card-list-item .cli-row--badges .cli-body{padding-right:96px}ui-card-list-item .cli-row--badges-2 .cli-body{padding-right:190px}ui-card-list-item .cli-row--badges .cli-chip{align-self:flex-end}ui-card-list-item .cli-title-row{display:flex;align-items:center;gap:7px;flex-wrap:wrap}ui-card-list-item .cli-title{font-size:.875rem;font-weight:600;color:#1e293b}ui-card-list-item .cli-desc-row{display:flex;align-items:center;gap:8px}ui-card-list-item .cli-desc-row:empty{display:none}ui-card-list-item .cli-description{font-size:.8125rem;color:#64748b;min-width:0}ui-card-list-item .cli-date{display:flex;align-items:center;gap:4px;font-size:.75rem;color:#64748b}ui-card-list-item .cli-chip{flex-shrink:0;display:inline-flex;align-items:center;gap:5px;align-self:center;box-sizing:border-box;font-family:inherit;font-size:.8rem;font-weight:500;line-height:1.4;background:none;cursor:pointer;padding:4px 10px;border-radius:6px;text-decoration:none;transition:background .15s,color .15s,border-color .15s}ui-card-list-item .cli-chip--edit{color:#64748b;border:1px solid #e2e8f0}ui-card-list-item .cli-chip--edit:hover{background:#f1f5f9;color:#1e293b}ui-card-list-item .cli-chip--view{color:#2563eb;border:1px solid #dbeafe}ui-card-list-item .cli-chip--view:hover{background:#eff6ff;border-color:#bfdbfe;color:#1d4ed8}ui-card-list-item .cli-chip:focus-visible,ui-card-list-item .cli-inline-link:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}ui-card-list-item .cli-inline-link{flex-shrink:0;margin-left:auto;display:inline-flex;align-items:center;gap:4px;font-size:.8rem;font-weight:500;color:#2563eb;text-decoration:none;transition:color .15s}ui-card-list-item .cli-inline-link:hover{color:#1d4ed8}@media(pointer:coarse),(max-width:480px){ui-card-list-item .cli-chip{min-height:44px;padding:4px 14px}}ui-card-list-item [card-stats]{display:flex;align-items:stretch;background:#f8fafc;border-top:1px solid #f1f5f9}ui-card-list-item [card-detail]{background:#f8fafc;border-top:1px solid #e2e8f0}ui-card-list-item .cli-stat{flex:1;display:flex;flex-direction:column;gap:2px;padding:10px 14px}ui-card-list-item .cli-stat-label{font-size:.6875rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:#64748b}ui-card-list-item .cli-stat-value{font-size:.9375rem;font-weight:600;color:#0f172a}ui-card-list-item .cli-stat-divider{width:1px;background:#e2e8f0;margin:8px 0}\n"],
27573
+ styles: ["ui-card-list-item{position:relative;display:block;border:1px solid #e2e8f0;border-radius:8px;overflow:hidden;margin-bottom:8px}ui-card-list-item:last-child{margin-bottom:0}ui-card-list-item .cli-row{display:flex;align-items:flex-start;gap:12px;padding:13px 18px;transition:background .12s}ui-card-list-item .cli-row:hover{background:#f8fafc}@media(prefers-reduced-motion:reduce){ui-card-list-item .cli-row{transition:none}}ui-card-list-item .cli-dot{width:9px;height:9px;border-radius:50%;flex-shrink:0;margin-top:5px}ui-card-list-item .cli-dot:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}ui-card-list-item .cli-dot--high{background:#ef4444}ui-card-list-item .cli-dot--medium{background:#f59e0b}ui-card-list-item .cli-dot--low{background:#94a3b8}ui-card-list-item .cli-dot--blue{background:#3b82f6}ui-card-list-item .cli-dot--green{background:#22c55e}ui-card-list-item .cli-icon-circle{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0}ui-card-list-item .cli-icon-circle--call{background:#dbeafe;color:#2563eb}ui-card-list-item .cli-icon-circle--email{background:#dcfce7;color:#16a34a}ui-card-list-item .cli-icon-circle--sms{background:#fef9c3;color:#ca8a04}ui-card-list-item .cli-icon-circle--task{background:#dbeafe;color:#2563eb}ui-card-list-item .cli-icon-circle--doc{background:#ffedd5;color:#ea580c}ui-card-list-item .cli-icon-circle--money{background:#d1fae5;color:#059669}ui-card-list-item .cli-icon-circle--deal{background:#e0f2fe;color:#0284c7}ui-card-list-item .cli-icon-circle--survey{background:#dbeafe;color:#2563eb}ui-card-list-item .cli-icon-circle--property{background:#fef3c7;color:#d97706}ui-card-list-item .cli-icon-circle--search{background:#e0f2fe;color:#0284c7}ui-card-list-item .cli-icon-circle--heart{background:#fce7f3;color:#db2777}ui-card-list-item .cli-icon-circle--calc{background:#d1fae5;color:#059669}ui-card-list-item .cli-icon-circle--repeat{background:#e0f2fe;color:#0284c7}ui-card-list-item .cli-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px;overflow-wrap:anywhere;word-break:break-word}ui-card-list-item .cli-badges{position:absolute;top:10px;right:12px;display:flex;align-items:center;gap:6px;z-index:1}ui-card-list-item .cli-row--badges .cli-body{padding-right:96px}ui-card-list-item .cli-row--badges-2 .cli-body{padding-right:190px}ui-card-list-item .cli-row--badges .cli-chip{align-self:flex-end}ui-card-list-item .cli-title-row{display:flex;align-items:center;gap:7px;flex-wrap:wrap}ui-card-list-item .cli-title{font-size:.875rem;font-weight:600;color:#1e293b}ui-card-list-item .cli-desc-row{display:flex;align-items:center;gap:8px}ui-card-list-item .cli-desc-row:empty{display:none}ui-card-list-item .cli-description{font-size:.8125rem;color:#64748b;min-width:0}ui-card-list-item .cli-date{display:flex;align-items:center;gap:4px;font-size:.75rem;color:#64748b}ui-card-list-item .cli-chip{flex-shrink:0;display:inline-flex;align-items:center;gap:5px;align-self:center;box-sizing:border-box;font-family:inherit;font-size:.8rem;font-weight:500;line-height:1.4;background:none;cursor:pointer;padding:4px 10px;border-radius:6px;text-decoration:none;transition:background .15s,color .15s,border-color .15s}ui-card-list-item .cli-chip--edit{color:#64748b;border:1px solid #e2e8f0}ui-card-list-item .cli-chip--edit:hover{background:#f1f5f9;color:#1e293b}ui-card-list-item .cli-chip--view{color:#2563eb;border:1px solid #dbeafe}ui-card-list-item .cli-chip--view:hover{background:#eff6ff;border-color:#bfdbfe;color:#1d4ed8}ui-card-list-item .cli-chip--action{color:#475569;border:1px solid #e2e8f0}ui-card-list-item .cli-chip--action:hover{background:#f1f5f9;color:#1e293b}ui-card-list-item .cli-chip--delete{position:relative;justify-content:center;width:28px;height:28px;padding:0;color:#b91c1c;border:1px solid #fecaca}ui-card-list-item .cli-chip--delete:hover{background:#fef2f2;border-color:#fca5a5;color:#991b1b}ui-card-list-item .cli-chip--delete:after{content:\"\";position:absolute;top:50%;left:50%;width:44px;height:44px;transform:translate(-50%,-50%)}ui-card-list-item .cli-chip:focus-visible,ui-card-list-item .cli-inline-link:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}ui-card-list-item .cli-inline-link{flex-shrink:0;margin-left:auto;display:inline-flex;align-items:center;gap:4px;font-size:.8rem;font-weight:500;color:#2563eb;text-decoration:none;transition:color .15s}ui-card-list-item .cli-inline-link:hover{color:#1d4ed8}@media(pointer:coarse),(max-width:480px){ui-card-list-item .cli-chip{min-height:44px;padding:4px 14px}ui-card-list-item .cli-chip--delete{min-height:28px;padding:0}}ui-card-list-item [card-stats]{display:flex;align-items:stretch;background:#f8fafc;border-top:1px solid #f1f5f9}ui-card-list-item [card-detail]{background:#f8fafc;border-top:1px solid #e2e8f0}ui-card-list-item .cli-stat{flex:1;display:flex;flex-direction:column;gap:2px;padding:10px 14px}ui-card-list-item .cli-stat-label{font-size:.6875rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:#64748b}ui-card-list-item .cli-stat-value{font-size:.9375rem;font-weight:600;color:#0f172a}ui-card-list-item .cli-stat-divider{width:1px;background:#e2e8f0;margin:8px 0}\n"],
27484
27574
  dependencies: [{
27485
27575
  kind: "component",
27486
27576
  type: BadgeComponent,
@@ -27555,13 +27645,21 @@ i0.ɵɵngDeclareClassMetadata({
27555
27645
  @if (viewButton()) {
27556
27646
  <button class="cli-chip cli-chip--view" type="button" [attr.aria-label]="viewAriaLabel() || null" (click)="viewClick.emit()">View</button>
27557
27647
  }
27648
+ @if (actionLabel()) {
27649
+ <button class="cli-chip cli-chip--action" type="button" [attr.data-testid]="actionTestId() || null" [attr.aria-label]="actionAriaLabel() || null" (click)="action.emit()">{{ actionLabel() }}</button>
27650
+ }
27651
+ @if (deletable()) {
27652
+ <button class="cli-chip cli-chip--delete" type="button" [attr.data-testid]="deleteTestId() || null" [attr.aria-label]="deleteLabel() || 'Delete'" (click)="delete.emit()">
27653
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path [attr.d]="trashPath" /></svg>
27654
+ </button>
27655
+ }
27558
27656
  <ng-content select="[card-list-action]" />
27559
27657
  <ng-content />
27560
27658
  </div>
27561
27659
  <ng-content select="[card-stats]" />
27562
27660
  <ng-content select="[card-detail]" />
27563
27661
  `,
27564
- styles: ["ui-card-list-item{position:relative;display:block;border:1px solid #e2e8f0;border-radius:8px;overflow:hidden;margin-bottom:8px}ui-card-list-item:last-child{margin-bottom:0}ui-card-list-item .cli-row{display:flex;align-items:flex-start;gap:12px;padding:13px 18px;transition:background .12s}ui-card-list-item .cli-row:hover{background:#f8fafc}@media(prefers-reduced-motion:reduce){ui-card-list-item .cli-row{transition:none}}ui-card-list-item .cli-dot{width:9px;height:9px;border-radius:50%;flex-shrink:0;margin-top:5px}ui-card-list-item .cli-dot:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}ui-card-list-item .cli-dot--high{background:#ef4444}ui-card-list-item .cli-dot--medium{background:#f59e0b}ui-card-list-item .cli-dot--low{background:#94a3b8}ui-card-list-item .cli-dot--blue{background:#3b82f6}ui-card-list-item .cli-dot--green{background:#22c55e}ui-card-list-item .cli-icon-circle{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0}ui-card-list-item .cli-icon-circle--call{background:#dbeafe;color:#2563eb}ui-card-list-item .cli-icon-circle--email{background:#dcfce7;color:#16a34a}ui-card-list-item .cli-icon-circle--sms{background:#fef9c3;color:#ca8a04}ui-card-list-item .cli-icon-circle--task{background:#dbeafe;color:#2563eb}ui-card-list-item .cli-icon-circle--doc{background:#ffedd5;color:#ea580c}ui-card-list-item .cli-icon-circle--money{background:#d1fae5;color:#059669}ui-card-list-item .cli-icon-circle--deal{background:#e0f2fe;color:#0284c7}ui-card-list-item .cli-icon-circle--survey{background:#dbeafe;color:#2563eb}ui-card-list-item .cli-icon-circle--property{background:#fef3c7;color:#d97706}ui-card-list-item .cli-icon-circle--search{background:#e0f2fe;color:#0284c7}ui-card-list-item .cli-icon-circle--heart{background:#fce7f3;color:#db2777}ui-card-list-item .cli-icon-circle--calc{background:#d1fae5;color:#059669}ui-card-list-item .cli-icon-circle--repeat{background:#e0f2fe;color:#0284c7}ui-card-list-item .cli-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px;overflow-wrap:anywhere;word-break:break-word}ui-card-list-item .cli-badges{position:absolute;top:10px;right:12px;display:flex;align-items:center;gap:6px;z-index:1}ui-card-list-item .cli-row--badges .cli-body{padding-right:96px}ui-card-list-item .cli-row--badges-2 .cli-body{padding-right:190px}ui-card-list-item .cli-row--badges .cli-chip{align-self:flex-end}ui-card-list-item .cli-title-row{display:flex;align-items:center;gap:7px;flex-wrap:wrap}ui-card-list-item .cli-title{font-size:.875rem;font-weight:600;color:#1e293b}ui-card-list-item .cli-desc-row{display:flex;align-items:center;gap:8px}ui-card-list-item .cli-desc-row:empty{display:none}ui-card-list-item .cli-description{font-size:.8125rem;color:#64748b;min-width:0}ui-card-list-item .cli-date{display:flex;align-items:center;gap:4px;font-size:.75rem;color:#64748b}ui-card-list-item .cli-chip{flex-shrink:0;display:inline-flex;align-items:center;gap:5px;align-self:center;box-sizing:border-box;font-family:inherit;font-size:.8rem;font-weight:500;line-height:1.4;background:none;cursor:pointer;padding:4px 10px;border-radius:6px;text-decoration:none;transition:background .15s,color .15s,border-color .15s}ui-card-list-item .cli-chip--edit{color:#64748b;border:1px solid #e2e8f0}ui-card-list-item .cli-chip--edit:hover{background:#f1f5f9;color:#1e293b}ui-card-list-item .cli-chip--view{color:#2563eb;border:1px solid #dbeafe}ui-card-list-item .cli-chip--view:hover{background:#eff6ff;border-color:#bfdbfe;color:#1d4ed8}ui-card-list-item .cli-chip:focus-visible,ui-card-list-item .cli-inline-link:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}ui-card-list-item .cli-inline-link{flex-shrink:0;margin-left:auto;display:inline-flex;align-items:center;gap:4px;font-size:.8rem;font-weight:500;color:#2563eb;text-decoration:none;transition:color .15s}ui-card-list-item .cli-inline-link:hover{color:#1d4ed8}@media(pointer:coarse),(max-width:480px){ui-card-list-item .cli-chip{min-height:44px;padding:4px 14px}}ui-card-list-item [card-stats]{display:flex;align-items:stretch;background:#f8fafc;border-top:1px solid #f1f5f9}ui-card-list-item [card-detail]{background:#f8fafc;border-top:1px solid #e2e8f0}ui-card-list-item .cli-stat{flex:1;display:flex;flex-direction:column;gap:2px;padding:10px 14px}ui-card-list-item .cli-stat-label{font-size:.6875rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:#64748b}ui-card-list-item .cli-stat-value{font-size:.9375rem;font-weight:600;color:#0f172a}ui-card-list-item .cli-stat-divider{width:1px;background:#e2e8f0;margin:8px 0}\n"]
27662
+ styles: ["ui-card-list-item{position:relative;display:block;border:1px solid #e2e8f0;border-radius:8px;overflow:hidden;margin-bottom:8px}ui-card-list-item:last-child{margin-bottom:0}ui-card-list-item .cli-row{display:flex;align-items:flex-start;gap:12px;padding:13px 18px;transition:background .12s}ui-card-list-item .cli-row:hover{background:#f8fafc}@media(prefers-reduced-motion:reduce){ui-card-list-item .cli-row{transition:none}}ui-card-list-item .cli-dot{width:9px;height:9px;border-radius:50%;flex-shrink:0;margin-top:5px}ui-card-list-item .cli-dot:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}ui-card-list-item .cli-dot--high{background:#ef4444}ui-card-list-item .cli-dot--medium{background:#f59e0b}ui-card-list-item .cli-dot--low{background:#94a3b8}ui-card-list-item .cli-dot--blue{background:#3b82f6}ui-card-list-item .cli-dot--green{background:#22c55e}ui-card-list-item .cli-icon-circle{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0}ui-card-list-item .cli-icon-circle--call{background:#dbeafe;color:#2563eb}ui-card-list-item .cli-icon-circle--email{background:#dcfce7;color:#16a34a}ui-card-list-item .cli-icon-circle--sms{background:#fef9c3;color:#ca8a04}ui-card-list-item .cli-icon-circle--task{background:#dbeafe;color:#2563eb}ui-card-list-item .cli-icon-circle--doc{background:#ffedd5;color:#ea580c}ui-card-list-item .cli-icon-circle--money{background:#d1fae5;color:#059669}ui-card-list-item .cli-icon-circle--deal{background:#e0f2fe;color:#0284c7}ui-card-list-item .cli-icon-circle--survey{background:#dbeafe;color:#2563eb}ui-card-list-item .cli-icon-circle--property{background:#fef3c7;color:#d97706}ui-card-list-item .cli-icon-circle--search{background:#e0f2fe;color:#0284c7}ui-card-list-item .cli-icon-circle--heart{background:#fce7f3;color:#db2777}ui-card-list-item .cli-icon-circle--calc{background:#d1fae5;color:#059669}ui-card-list-item .cli-icon-circle--repeat{background:#e0f2fe;color:#0284c7}ui-card-list-item .cli-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px;overflow-wrap:anywhere;word-break:break-word}ui-card-list-item .cli-badges{position:absolute;top:10px;right:12px;display:flex;align-items:center;gap:6px;z-index:1}ui-card-list-item .cli-row--badges .cli-body{padding-right:96px}ui-card-list-item .cli-row--badges-2 .cli-body{padding-right:190px}ui-card-list-item .cli-row--badges .cli-chip{align-self:flex-end}ui-card-list-item .cli-title-row{display:flex;align-items:center;gap:7px;flex-wrap:wrap}ui-card-list-item .cli-title{font-size:.875rem;font-weight:600;color:#1e293b}ui-card-list-item .cli-desc-row{display:flex;align-items:center;gap:8px}ui-card-list-item .cli-desc-row:empty{display:none}ui-card-list-item .cli-description{font-size:.8125rem;color:#64748b;min-width:0}ui-card-list-item .cli-date{display:flex;align-items:center;gap:4px;font-size:.75rem;color:#64748b}ui-card-list-item .cli-chip{flex-shrink:0;display:inline-flex;align-items:center;gap:5px;align-self:center;box-sizing:border-box;font-family:inherit;font-size:.8rem;font-weight:500;line-height:1.4;background:none;cursor:pointer;padding:4px 10px;border-radius:6px;text-decoration:none;transition:background .15s,color .15s,border-color .15s}ui-card-list-item .cli-chip--edit{color:#64748b;border:1px solid #e2e8f0}ui-card-list-item .cli-chip--edit:hover{background:#f1f5f9;color:#1e293b}ui-card-list-item .cli-chip--view{color:#2563eb;border:1px solid #dbeafe}ui-card-list-item .cli-chip--view:hover{background:#eff6ff;border-color:#bfdbfe;color:#1d4ed8}ui-card-list-item .cli-chip--action{color:#475569;border:1px solid #e2e8f0}ui-card-list-item .cli-chip--action:hover{background:#f1f5f9;color:#1e293b}ui-card-list-item .cli-chip--delete{position:relative;justify-content:center;width:28px;height:28px;padding:0;color:#b91c1c;border:1px solid #fecaca}ui-card-list-item .cli-chip--delete:hover{background:#fef2f2;border-color:#fca5a5;color:#991b1b}ui-card-list-item .cli-chip--delete:after{content:\"\";position:absolute;top:50%;left:50%;width:44px;height:44px;transform:translate(-50%,-50%)}ui-card-list-item .cli-chip:focus-visible,ui-card-list-item .cli-inline-link:focus-visible{outline:2px solid #3b82f6;outline-offset:2px}ui-card-list-item .cli-inline-link{flex-shrink:0;margin-left:auto;display:inline-flex;align-items:center;gap:4px;font-size:.8rem;font-weight:500;color:#2563eb;text-decoration:none;transition:color .15s}ui-card-list-item .cli-inline-link:hover{color:#1d4ed8}@media(pointer:coarse),(max-width:480px){ui-card-list-item .cli-chip{min-height:44px;padding:4px 14px}ui-card-list-item .cli-chip--delete{min-height:28px;padding:0}}ui-card-list-item [card-stats]{display:flex;align-items:stretch;background:#f8fafc;border-top:1px solid #f1f5f9}ui-card-list-item [card-detail]{background:#f8fafc;border-top:1px solid #e2e8f0}ui-card-list-item .cli-stat{flex:1;display:flex;flex-direction:column;gap:2px;padding:10px 14px}ui-card-list-item .cli-stat-label{font-size:.6875rem;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:#64748b}ui-card-list-item .cli-stat-value{font-size:.9375rem;font-weight:600;color:#0f172a}ui-card-list-item .cli-stat-divider{width:1px;background:#e2e8f0;margin:8px 0}\n"]
27565
27663
  }]
27566
27664
  }],
27567
27665
  propDecorators: {
@@ -27669,6 +27767,54 @@ i0.ɵɵngDeclareClassMetadata({
27669
27767
  required: false
27670
27768
  }]
27671
27769
  }],
27770
+ deletable: [{
27771
+ type: i0.Input,
27772
+ args: [{
27773
+ isSignal: true,
27774
+ alias: "deletable",
27775
+ required: false
27776
+ }]
27777
+ }],
27778
+ deleteLabel: [{
27779
+ type: i0.Input,
27780
+ args: [{
27781
+ isSignal: true,
27782
+ alias: "deleteLabel",
27783
+ required: false
27784
+ }]
27785
+ }],
27786
+ deleteTestId: [{
27787
+ type: i0.Input,
27788
+ args: [{
27789
+ isSignal: true,
27790
+ alias: "deleteTestId",
27791
+ required: false
27792
+ }]
27793
+ }],
27794
+ actionLabel: [{
27795
+ type: i0.Input,
27796
+ args: [{
27797
+ isSignal: true,
27798
+ alias: "actionLabel",
27799
+ required: false
27800
+ }]
27801
+ }],
27802
+ actionTestId: [{
27803
+ type: i0.Input,
27804
+ args: [{
27805
+ isSignal: true,
27806
+ alias: "actionTestId",
27807
+ required: false
27808
+ }]
27809
+ }],
27810
+ actionAriaLabel: [{
27811
+ type: i0.Input,
27812
+ args: [{
27813
+ isSignal: true,
27814
+ alias: "actionAriaLabel",
27815
+ required: false
27816
+ }]
27817
+ }],
27672
27818
  editClick: [{
27673
27819
  type: i0.Output,
27674
27820
  args: ["editClick"]
@@ -27676,6 +27822,14 @@ i0.ɵɵngDeclareClassMetadata({
27676
27822
  viewClick: [{
27677
27823
  type: i0.Output,
27678
27824
  args: ["viewClick"]
27825
+ }],
27826
+ delete: [{
27827
+ type: i0.Output,
27828
+ args: ["delete"]
27829
+ }],
27830
+ action: [{
27831
+ type: i0.Output,
27832
+ args: ["action"]
27679
27833
  }]
27680
27834
  }
27681
27835
  });
@@ -27756,26 +27910,44 @@ var NotesComponent = class NotesComponent {
27756
27910
  return ((parts[0]?.[0] ?? "") + (parts.length > 1 ? parts[parts.length - 1][0] : "")).toUpperCase();
27757
27911
  }
27758
27912
  tooLong(text) {
27759
- return text.trim().length > NOTES_MAX_LENGTH;
27913
+ return text.trim().length > this.maxLength();
27760
27914
  }
27761
27915
  validBody(text) {
27762
27916
  const n = text.trim().length;
27763
- return n > 0 && n <= 1e4;
27917
+ return n > 0 && n <= this.maxLength();
27764
27918
  }
27765
27919
  get listUrl() {
27766
- return `${this.apiBase}/notes/${this.resourceType()}/${this.resourceId()}`;
27920
+ return this.basePath() ? `${this.apiBase}${this.basePath()}` : `${this.apiBase}/notes/${this.resourceType()}/${this.resourceId()}`;
27921
+ }
27922
+ noteUrl(id) {
27923
+ return this.basePath() ? `${this.apiBase}${this.basePath()}/${id}` : `${this.apiBase}/notes/${id}`;
27924
+ }
27925
+ get ready() {
27926
+ return !!this.basePath() || !!this.resourceType() && !!this.resourceId();
27927
+ }
27928
+ payload(text) {
27929
+ return this.basePath() ? { content: text.trim() } : { body: text.trim() };
27930
+ }
27931
+ normalize(n) {
27932
+ return {
27933
+ ...n,
27934
+ body: n.body ?? n.content ?? "",
27935
+ updatedAt: n.updatedAt ?? n.createdAt
27936
+ };
27767
27937
  }
27768
27938
  constructor() {
27769
27939
  this.resourceType = input("", ...ngDevMode ? [{ debugName: "resourceType" }] : /* istanbul ignore next */ []);
27770
27940
  this.resourceId = input("", ...ngDevMode ? [{ debugName: "resourceId" }] : /* istanbul ignore next */ []);
27941
+ this.basePath = input("", ...ngDevMode ? [{ debugName: "basePath" }] : /* istanbul ignore next */ []);
27771
27942
  this.readOnly = input(false, ...ngDevMode ? [{ debugName: "readOnly" }] : /* istanbul ignore next */ []);
27943
+ this.editable = input(true, ...ngDevMode ? [{ debugName: "editable" }] : /* istanbul ignore next */ []);
27944
+ this.maxLength = input(NOTES_MAX_LENGTH, ...ngDevMode ? [{ debugName: "maxLength" }] : /* istanbul ignore next */ []);
27772
27945
  this.totalChange = output();
27773
27946
  this.http = inject(HttpClient);
27774
27947
  this.toast = inject(ToastService);
27775
27948
  this.destroyRef = inject(DestroyRef);
27776
27949
  this.apiBase = inject(FORGEROUTE_CONFIG, { optional: true })?.baseUrl ?? "/api";
27777
27950
  this.pageSize = NOTES_PAGE_SIZE;
27778
- this.maxLength = NOTES_MAX_LENGTH;
27779
27951
  this.notes = signal([], ...ngDevMode ? [{ debugName: "notes" }] : /* istanbul ignore next */ []);
27780
27952
  this.loading = signal(false, ...ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []);
27781
27953
  this.saving = signal(false, ...ngDevMode ? [{ debugName: "saving" }] : /* istanbul ignore next */ []);
@@ -27788,16 +27960,16 @@ var NotesComponent = class NotesComponent {
27788
27960
  effect(() => {
27789
27961
  const id = this.resourceId();
27790
27962
  const type = this.resourceType();
27791
- if (id && type) untracked(() => this.loadPage(0));
27963
+ if (this.basePath() || id && type) untracked(() => this.loadPage(0));
27792
27964
  });
27793
27965
  }
27794
27966
  loadPage(p) {
27795
- if (!this.resourceType() || !this.resourceId()) return;
27967
+ if (!this.ready) return;
27796
27968
  this.loading.set(true);
27797
27969
  this.http.get(`${this.listUrl}?page=${p}&size=${this.pageSize}`).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
27798
27970
  next: (res) => {
27799
- this.notes.set(res.content);
27800
- this.page.set(res.page);
27971
+ this.notes.set(res.content.map((n) => this.normalize(n)));
27972
+ this.page.set(res.page ?? res.number ?? p);
27801
27973
  this.totalElements.set(res.totalElements);
27802
27974
  this.loading.set(false);
27803
27975
  this.totalChange.emit(res.totalElements);
@@ -27811,7 +27983,7 @@ var NotesComponent = class NotesComponent {
27811
27983
  addNote() {
27812
27984
  if (this.readOnly() || !this.validBody(this.newBody) || this.saving()) return;
27813
27985
  this.saving.set(true);
27814
- this.http.post(this.listUrl, { body: this.newBody.trim() }).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
27986
+ this.http.post(this.listUrl, this.payload(this.newBody)).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
27815
27987
  next: () => {
27816
27988
  this.newBody = "";
27817
27989
  this.saving.set(false);
@@ -27824,7 +27996,7 @@ var NotesComponent = class NotesComponent {
27824
27996
  });
27825
27997
  }
27826
27998
  startEdit(note) {
27827
- if (this.readOnly()) return;
27999
+ if (this.readOnly() || !this.editable()) return;
27828
28000
  this.editingId.set(note.id);
27829
28001
  this.editBody = note.body;
27830
28002
  }
@@ -27833,11 +28005,11 @@ var NotesComponent = class NotesComponent {
27833
28005
  this.editBody = "";
27834
28006
  }
27835
28007
  saveEdit(noteId) {
27836
- if (this.readOnly() || !this.validBody(this.editBody) || this.saving()) return;
28008
+ if (this.readOnly() || !this.editable() || !this.validBody(this.editBody) || this.saving()) return;
27837
28009
  this.saving.set(true);
27838
- this.http.put(`${this.apiBase}/notes/${noteId}`, { body: this.editBody.trim() }).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
28010
+ this.http.put(this.noteUrl(noteId), this.payload(this.editBody)).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
27839
28011
  next: (updated) => {
27840
- this.notes.update((arr) => arr.map((n) => n.id === noteId ? updated : n));
28012
+ this.notes.update((arr) => arr.map((n) => n.id === noteId ? this.normalize(updated) : n));
27841
28013
  this.editingId.set(null);
27842
28014
  this.saving.set(false);
27843
28015
  },
@@ -27855,7 +28027,7 @@ var NotesComponent = class NotesComponent {
27855
28027
  const id = this.deletingId();
27856
28028
  if (this.readOnly() || !id || this.saving()) return;
27857
28029
  this.saving.set(true);
27858
- this.http.delete(`${this.apiBase}/notes/${id}`).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
28030
+ this.http.delete(this.noteUrl(id)).pipe(takeUntilDestroyed(this.destroyRef)).subscribe({
27859
28031
  next: () => {
27860
28032
  this.deletingId.set(null);
27861
28033
  this.saving.set(false);
@@ -27900,12 +28072,33 @@ var NotesComponent = class NotesComponent {
27900
28072
  isRequired: false,
27901
28073
  transformFunction: null
27902
28074
  },
28075
+ basePath: {
28076
+ classPropertyName: "basePath",
28077
+ publicName: "basePath",
28078
+ isSignal: true,
28079
+ isRequired: false,
28080
+ transformFunction: null
28081
+ },
27903
28082
  readOnly: {
27904
28083
  classPropertyName: "readOnly",
27905
28084
  publicName: "readOnly",
27906
28085
  isSignal: true,
27907
28086
  isRequired: false,
27908
28087
  transformFunction: null
28088
+ },
28089
+ editable: {
28090
+ classPropertyName: "editable",
28091
+ publicName: "editable",
28092
+ isSignal: true,
28093
+ isRequired: false,
28094
+ transformFunction: null
28095
+ },
28096
+ maxLength: {
28097
+ classPropertyName: "maxLength",
28098
+ publicName: "maxLength",
28099
+ isSignal: true,
28100
+ isRequired: false,
28101
+ transformFunction: null
27909
28102
  }
27910
28103
  },
27911
28104
  outputs: { totalChange: "totalChange" },
@@ -27913,7 +28106,7 @@ var NotesComponent = class NotesComponent {
27913
28106
  template: `
27914
28107
  @if (!readOnly()) {
27915
28108
  <div class="note-add">
27916
- <ui-textarea-input ariaLabel="Add a note" placeholder="Add a note..." [rows]="3" [maxlength]="maxLength" [showErrors]="tooLong(newBody)" [disabled]="saving()" [(ngModel)]="newBody"
28109
+ <ui-textarea-input ariaLabel="Add a note" placeholder="Add a note..." [rows]="3" [maxlength]="maxLength()" [showErrors]="tooLong(newBody)" [disabled]="saving()" [(ngModel)]="newBody"
27917
28110
  (keydown.meta.enter)="addNote()" (keydown.control.enter)="addNote()" />
27918
28111
  <div class="note-add-footer">
27919
28112
  <ui-button variant="primary" size="sm" data-testid="note-add-btn" [loading]="saving()" [disabled]="!validBody(newBody)" (click)="addNote()">Add Note</ui-button>
@@ -27940,13 +28133,15 @@ var NotesComponent = class NotesComponent {
27940
28133
  }
27941
28134
  @if (!readOnly() && editingId() !== note.id) {
27942
28135
  <div class="note-actions">
27943
- <ui-icon name="edit" [size]="14" tooltip="Edit note" (iconClick)="startEdit(note)" />
28136
+ @if (editable()) {
28137
+ <ui-icon name="edit" [size]="14" tooltip="Edit note" (iconClick)="startEdit(note)" />
28138
+ }
27944
28139
  <ui-icon name="delete" variant="danger" [size]="14" tooltip="Delete note" (iconClick)="confirmDelete(note.id)" />
27945
28140
  </div>
27946
28141
  }
27947
28142
  </div>
27948
28143
  @if (editingId() === note.id) {
27949
- <ui-textarea-input ariaLabel="Edit note" [rows]="3" [maxlength]="maxLength" [showErrors]="tooLong(editBody)" [disabled]="saving()" [(ngModel)]="editBody" />
28144
+ <ui-textarea-input ariaLabel="Edit note" [rows]="3" [maxlength]="maxLength()" [showErrors]="tooLong(editBody)" [disabled]="saving()" [(ngModel)]="editBody" />
27950
28145
  <div class="note-item-footer">
27951
28146
  <ui-button variant="secondary" size="sm" (click)="cancelEdit()">Cancel</ui-button>
27952
28147
  <ui-button variant="primary" size="sm" [loading]="saving()" [disabled]="!validBody(editBody)" (click)="saveEdit(note.id)">Save</ui-button>
@@ -28156,7 +28351,7 @@ i0.ɵɵngDeclareClassMetadata({
28156
28351
  template: `
28157
28352
  @if (!readOnly()) {
28158
28353
  <div class="note-add">
28159
- <ui-textarea-input ariaLabel="Add a note" placeholder="Add a note..." [rows]="3" [maxlength]="maxLength" [showErrors]="tooLong(newBody)" [disabled]="saving()" [(ngModel)]="newBody"
28354
+ <ui-textarea-input ariaLabel="Add a note" placeholder="Add a note..." [rows]="3" [maxlength]="maxLength()" [showErrors]="tooLong(newBody)" [disabled]="saving()" [(ngModel)]="newBody"
28160
28355
  (keydown.meta.enter)="addNote()" (keydown.control.enter)="addNote()" />
28161
28356
  <div class="note-add-footer">
28162
28357
  <ui-button variant="primary" size="sm" data-testid="note-add-btn" [loading]="saving()" [disabled]="!validBody(newBody)" (click)="addNote()">Add Note</ui-button>
@@ -28183,13 +28378,15 @@ i0.ɵɵngDeclareClassMetadata({
28183
28378
  }
28184
28379
  @if (!readOnly() && editingId() !== note.id) {
28185
28380
  <div class="note-actions">
28186
- <ui-icon name="edit" [size]="14" tooltip="Edit note" (iconClick)="startEdit(note)" />
28381
+ @if (editable()) {
28382
+ <ui-icon name="edit" [size]="14" tooltip="Edit note" (iconClick)="startEdit(note)" />
28383
+ }
28187
28384
  <ui-icon name="delete" variant="danger" [size]="14" tooltip="Delete note" (iconClick)="confirmDelete(note.id)" />
28188
28385
  </div>
28189
28386
  }
28190
28387
  </div>
28191
28388
  @if (editingId() === note.id) {
28192
- <ui-textarea-input ariaLabel="Edit note" [rows]="3" [maxlength]="maxLength" [showErrors]="tooLong(editBody)" [disabled]="saving()" [(ngModel)]="editBody" />
28389
+ <ui-textarea-input ariaLabel="Edit note" [rows]="3" [maxlength]="maxLength()" [showErrors]="tooLong(editBody)" [disabled]="saving()" [(ngModel)]="editBody" />
28193
28390
  <div class="note-item-footer">
28194
28391
  <ui-button variant="secondary" size="sm" (click)="cancelEdit()">Cancel</ui-button>
28195
28392
  <ui-button variant="primary" size="sm" [loading]="saving()" [disabled]="!validBody(editBody)" (click)="saveEdit(note.id)">Save</ui-button>
@@ -28231,6 +28428,14 @@ i0.ɵɵngDeclareClassMetadata({
28231
28428
  required: false
28232
28429
  }]
28233
28430
  }],
28431
+ basePath: [{
28432
+ type: i0.Input,
28433
+ args: [{
28434
+ isSignal: true,
28435
+ alias: "basePath",
28436
+ required: false
28437
+ }]
28438
+ }],
28234
28439
  readOnly: [{
28235
28440
  type: i0.Input,
28236
28441
  args: [{
@@ -28239,6 +28444,22 @@ i0.ɵɵngDeclareClassMetadata({
28239
28444
  required: false
28240
28445
  }]
28241
28446
  }],
28447
+ editable: [{
28448
+ type: i0.Input,
28449
+ args: [{
28450
+ isSignal: true,
28451
+ alias: "editable",
28452
+ required: false
28453
+ }]
28454
+ }],
28455
+ maxLength: [{
28456
+ type: i0.Input,
28457
+ args: [{
28458
+ isSignal: true,
28459
+ alias: "maxLength",
28460
+ required: false
28461
+ }]
28462
+ }],
28242
28463
  totalChange: [{
28243
28464
  type: i0.Output,
28244
28465
  args: ["totalChange"]