@forgeroute/ui 0.4.28 → 0.4.31

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.
@@ -42113,6 +42113,9 @@ var SetupWizardStepDirective = class SetupWizardStepDirective {
42113
42113
  });
42114
42114
  this.template = inject(TemplateRef);
42115
42115
  }
42116
+ static ngTemplateContextGuard(_dir, _ctx) {
42117
+ return true;
42118
+ }
42116
42119
  static {
42117
42120
  this.ɵfac = i0.ɵɵngDeclareFactory({
42118
42121
  minVersion: "12.0.0",
@@ -42186,6 +42189,16 @@ const DEFAULT_TEXTS = {
42186
42189
  areaCode: "Area code",
42187
42190
  connectIntegrationFailed: (title) => `Failed to connect ${title}. Please try again from the Integrations page after setup.`
42188
42191
  };
42192
+ function splitIntro(description) {
42193
+ const m = /^(.+?[.!?])\s+(.+)$/s.exec(description.trim());
42194
+ return m ? {
42195
+ title: m[1],
42196
+ text: m[2]
42197
+ } : {
42198
+ title: description.trim(),
42199
+ text: ""
42200
+ };
42201
+ }
42189
42202
  const SETUP_DONE_KEY = "done";
42190
42203
  var SetupWizardComponent = class SetupWizardComponent {
42191
42204
  constructor() {
@@ -42209,6 +42222,10 @@ var SetupWizardComponent = class SetupWizardComponent {
42209
42222
  this.imports = signal({}, ...ngDevMode ? [{ debugName: "imports" }] : /* istanbul ignore next */ []);
42210
42223
  this.statuses = signal({}, ...ngDevMode ? [{ debugName: "statuses" }] : /* istanbul ignore next */ []);
42211
42224
  this.busy = signal(false, ...ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []);
42225
+ this.api = {
42226
+ saveAndContinue: () => this.saveAndContinue(),
42227
+ busy: () => this.busy()
42228
+ };
42212
42229
  this.error = signal("", ...ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []);
42213
42230
  this.areaCodeOpen = signal("", ...ngDevMode ? [{ debugName: "areaCodeOpen" }] : /* istanbul ignore next */ []);
42214
42231
  this.areaCode = signal("", ...ngDevMode ? [{ debugName: "areaCode" }] : /* istanbul ignore next */ []);
@@ -42221,6 +42238,10 @@ var SetupWizardComponent = class SetupWizardComponent {
42221
42238
  }], ...ngDevMode ? [{ debugName: "allSteps" }] : /* istanbul ignore next */ []);
42222
42239
  this.index = computed(() => Math.max(0, this.allSteps().findIndex((s) => s.key === this.currentKey())), ...ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []);
42223
42240
  this.current = computed(() => this.allSteps()[this.index()], ...ngDevMode ? [{ debugName: "current" }] : /* istanbul ignore next */ []);
42241
+ this.intro = computed(() => {
42242
+ const d = this.current().description?.trim();
42243
+ return d ? splitIntro(d) : null;
42244
+ }, ...ngDevMode ? [{ debugName: "intro" }] : /* istanbul ignore next */ []);
42224
42245
  this.isDone = computed(() => this.current().key === SETUP_DONE_KEY, ...ngDevMode ? [{ debugName: "isDone" }] : /* istanbul ignore next */ []);
42225
42246
  this.completedCount = computed(() => this.allSteps().filter((s) => this.completed().has(s.key) || this.skipped().has(s.key)).length, ...ngDevMode ? [{ debugName: "completedCount" }] : /* istanbul ignore next */ []);
42226
42247
  this.stepperSteps = computed(() => this.allSteps().map((s) => ({
@@ -42379,6 +42400,9 @@ var SetupWizardComponent = class SetupWizardComponent {
42379
42400
  error: () => this.error.set(this.t().connectIntegrationFailed(i.title))
42380
42401
  });
42381
42402
  }
42403
+ iconD(name) {
42404
+ return iconPath(name) ?? "";
42405
+ }
42382
42406
  areaCodeLabelFor(i) {
42383
42407
  return (i.connect.type === "area-code" ? i.connect.areaCodeLabel : void 0) ?? this.t().areaCode;
42384
42408
  }
@@ -42473,7 +42497,7 @@ var SetupWizardComponent = class SetupWizardComponent {
42473
42497
  <main class="sw-content">
42474
42498
  <div class="sw-content-header">
42475
42499
  <h1 class="sw-step-title" data-testid="wizard-step-title">{{ current().label }}</h1>
42476
- <ui-button variant="ghost" size="sm" data-testid="wizard-exit" (click)="exited.emit()">{{ t().exit }}</ui-button>
42500
+ <ui-button variant="ghost" size="sm" data-testid="wizard-exit" (click)="exited.emit()"><svg class="sw-ico" 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]="iconD('close')" /></svg> {{ t().exit }}</ui-button>
42477
42501
  </div>
42478
42502
 
42479
42503
  @if (isDone()) {
@@ -42481,15 +42505,15 @@ var SetupWizardComponent = class SetupWizardComponent {
42481
42505
  <p class="sw-step-desc">{{ t().doneDescription }}</p>
42482
42506
  <ui-panel-info-list class="sw-summary" data-testid="wizard-summary" [sections]="summarySections()" />
42483
42507
  <p class="sw-done-hint">{{ t().doneHint }}</p>
42484
- <ui-button variant="primary" size="lg" data-testid="wizard-finish" (click)="finished.emit()">{{ t().finish }}</ui-button>
42508
+ <ui-button variant="primary" size="sm" data-testid="wizard-finish" (click)="finished.emit()"><svg class="sw-ico" 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]="iconD('check')" /></svg> {{ t().finish }}</ui-button>
42485
42509
  </div>
42486
42510
  } @else {
42487
42511
  <div class="sw-step-content" [attr.data-step]="current().key">
42488
- @if (current().description) { <p class="sw-step-desc">{{ current().description }}</p> }
42512
+ @if (intro(); as i) { <ui-section-header class="sw-intro" data-testid="wizard-step-intro" size="sm" background="#eaf3ff" [title]="i.title" [description]="i.text" /> }
42489
42513
 
42490
42514
  @switch (current().kind) {
42491
42515
  @case ('custom') {
42492
- @if (templateFor(current().key); as tpl) { <ng-container [ngTemplateOutlet]="tpl" /> }
42516
+ @if (templateFor(current().key); as tpl) { <ng-container [ngTemplateOutlet]="tpl" [ngTemplateOutletContext]="{ $implicit: api }" /> }
42493
42517
  }
42494
42518
  @case ('import') {
42495
42519
  @if (current().import; as imp) {
@@ -42502,11 +42526,11 @@ var SetupWizardComponent = class SetupWizardComponent {
42502
42526
  @if (importResult(current().key); as res) {
42503
42527
  <ui-alert variant="success" [title]="importTitle(current().key)" [attr.data-testid]="'import-result-' + current().key">
42504
42528
  {{ imp.resultText }}
42505
- <ui-button variant="link" size="sm" data-testid="import-more" (click)="clearImport(current().key)">{{ t().importMore }}</ui-button>
42529
+ <ui-button variant="link" size="sm" data-testid="import-more" (click)="clearImport(current().key)"><svg class="sw-ico" 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]="iconD('upload')" /></svg> {{ t().importMore }}</ui-button>
42506
42530
  </ui-alert>
42507
42531
  } @else {
42508
42532
  @if (imp.hint) { <p class="sw-hint">{{ imp.hint }}</p> }
42509
- <ui-button variant="primary" size="lg" [attr.data-testid]="'open-import-' + current().key" (click)="openImport(current().key)">{{ imp.buttonLabel }}</ui-button>
42533
+ <ui-button variant="primary" size="sm" [attr.data-testid]="'open-import-' + current().key" (click)="openImport(current().key)"><svg class="sw-ico" 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]="iconD('upload')" /></svg> {{ imp.buttonLabel }}</ui-button>
42510
42534
  }
42511
42535
  <ui-import-export #importer style="display:none" [config]="imp.config" [importSources]="imp.sources" (imported)="onImported(current().key)" />
42512
42536
  }
@@ -42518,13 +42542,13 @@ var SetupWizardComponent = class SetupWizardComponent {
42518
42542
  [icon]="it.icon ?? 'link'" iconColor="blue" [title]="it.title" [details]="[detailFor(it)]"
42519
42543
  [badge]="t().connected" badgeVariant="green" [alwaysShowBadge]="isConnected(it)">
42520
42544
  <ui-button list-item-action variant="secondary" size="sm" [ariaLabel]="(isConnected(it) ? t().reconnect : t().connect) + ' ' + it.title" (click)="connect(it)">
42521
- {{ isConnected(it) ? t().reconnect : t().connect }}
42545
+ <svg class="sw-ico" 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]="iconD('link')" /></svg> {{ isConnected(it) ? t().reconnect : t().connect }}
42522
42546
  </ui-button>
42523
42547
  </ui-list-item>
42524
42548
  @if (areaCodeOpen() === it.key) {
42525
42549
  <div class="sw-area-code" [attr.data-testid]="'area-code-' + it.key">
42526
42550
  <ui-text-input [label]="areaCodeLabelFor(it)" [maxlength]="3" inputmode="numeric" [ngModel]="areaCode()" (ngModelChange)="areaCode.set($event ?? '')" [inputTestId]="'area-code-input-' + it.key" />
42527
- <ui-button variant="primary" size="sm" [loading]="busy()" [disabled]="!validAreaCode()" (click)="submitAreaCode(it)">{{ t().connect }}</ui-button>
42551
+ <ui-button variant="primary" size="sm" [loading]="busy()" [disabled]="!validAreaCode()" (click)="submitAreaCode(it)"><svg class="sw-ico" 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]="iconD('link')" /></svg> {{ t().connect }}</ui-button>
42528
42552
  </div>
42529
42553
  }
42530
42554
  }
@@ -42535,19 +42559,21 @@ var SetupWizardComponent = class SetupWizardComponent {
42535
42559
  @if (error()) { <ui-alert variant="danger" data-testid="wizard-save-error">{{ error() }}</ui-alert> }
42536
42560
 
42537
42561
  <div class="sw-step-actions">
42538
- @if (index() > 0) { <ui-button variant="ghost" size="md" data-testid="wizard-back" [disabled]="busy()" (click)="back()">{{ t().back }}</ui-button> } @else { <span></span> }
42562
+ @if (index() > 0) { <ui-button variant="ghost" size="sm" data-testid="wizard-back" [disabled]="busy()" (click)="back()"><svg class="sw-ico" 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]="iconD('arrow-left')" /></svg> {{ t().back }}</ui-button> } @else { <span></span> }
42539
42563
  <div class="sw-actions-right">
42540
42564
  @if (current().skippable !== false) {
42541
- <ui-button variant="ghost" size="md" data-testid="wizard-skip" [disabled]="busy()" (click)="skip()">{{ t().skip }}</ui-button>
42565
+ <ui-button variant="ghost" size="sm" data-testid="wizard-skip" [disabled]="busy()" (click)="skip()">{{ t().skip }} <svg class="sw-ico" 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]="iconD('chevron-right')" /></svg></ui-button>
42542
42566
  }
42543
42567
  @if (current().kind === 'custom') {
42544
- <ui-button variant="primary" size="lg" data-testid="wizard-save" [loading]="busy()" [disabled]="current().canContinue ? !current().canContinue!() : false" (click)="saveAndContinue()">
42545
- {{ current().saveLabel ?? t().saveAndContinue }}
42568
+ @if (!current().ownActions) {
42569
+ <ui-button variant="primary" size="sm" data-testid="wizard-save" [loading]="busy()" [disabled]="current().canContinue ? !current().canContinue!() : false" (click)="saveAndContinue()">
42570
+ {{ current().saveLabel ?? t().saveAndContinue }} <svg class="sw-ico" 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]="iconD('arrow-right')" /></svg>
42546
42571
  </ui-button>
42572
+ }
42547
42573
  } @else if (current().kind === 'integrations') {
42548
- <ui-button variant="primary" size="lg" data-testid="wizard-save" [loading]="busy()" (click)="saveAndContinue()">{{ t().saveAndContinue }}</ui-button>
42574
+ <ui-button variant="primary" size="sm" data-testid="wizard-save" [loading]="busy()" (click)="saveAndContinue()">{{ t().saveAndContinue }} <svg class="sw-ico" 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]="iconD('arrow-right')" /></svg></ui-button>
42549
42575
  } @else if (importResult(current().key)) {
42550
- <ui-button variant="primary" size="lg" data-testid="wizard-continue" (click)="continueFromImport()">{{ t().continue }}</ui-button>
42576
+ <ui-button variant="primary" size="sm" data-testid="wizard-continue" (click)="continueFromImport()">{{ t().continue }} <svg class="sw-ico" 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]="iconD('arrow-right')" /></svg></ui-button>
42551
42577
  }
42552
42578
  </div>
42553
42579
  </div>
@@ -42557,7 +42583,7 @@ var SetupWizardComponent = class SetupWizardComponent {
42557
42583
  </div>
42558
42584
  `,
42559
42585
  isInline: true,
42560
- styles: [".sw-page{display:flex;min-height:100vh;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.sw-sidebar{width:260px;min-width:260px;background:#faf9f7;border-right:1px solid #e5e2dc;display:flex;flex-direction:column;justify-content:space-between;padding:28px 20px}.sw-brand{display:flex;align-items:center;gap:10px;margin-bottom:28px}.sw-brand-text{font-size:1.125rem;font-weight:700;color:#1e293b}.sw-step-nav{display:block}.sw-sidebar-bottom{margin-top:24px}.sw-progress-text{display:block;margin-top:8px;font-size:.75rem;color:#94a3b8}.sw-content{flex:1;min-width:0;background:#fff;display:flex;flex-direction:column;overflow-y:auto}.sw-content-header{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:20px 32px;border-bottom:1px solid #f1f5f9}.sw-step-title{font-size:1.25rem;font-weight:700;color:#111827;margin:0}.sw-step-content{max-width:780px;padding:16px 48px 60px}.sw-step-desc{font-size:.9375rem;color:#6b7280;line-height:1.5;margin:0 0 32px}.sw-hint{font-size:.8125rem;color:#94a3b8;margin:0 0 16px}.sw-import-tags{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:28px}.sw-tag{font-size:.6875rem;font-weight:700;letter-spacing:1px;color:#6b7280}.sw-provider-grid{display:flex;flex-direction:column;gap:8px;margin-bottom:24px}.sw-area-code{display:flex;align-items:flex-end;gap:12px;padding:0 0 8px 4px;max-width:320px}.sw-area-code ui-text-input{flex:1}.sw-content ui-alert{display:block;margin-bottom:16px}.sw-step-actions{display:flex;justify-content:space-between;align-items:center;margin-top:16px;padding-top:20px;border-top:1px solid #f1f5f9}.sw-actions-right{display:flex;align-items:center;gap:16px}.sw-done{text-align:center;display:flex;flex-direction:column;align-items:center;max-width:none}.sw-done .sw-step-desc{max-width:480px}.sw-summary{display:block;width:100%;max-width:480px;margin-bottom:24px;text-align:left}.sw-done-hint{font-size:.8125rem;color:#9ca3af;margin-bottom:24px}@media(max-width:768px){.sw-page{flex-direction:column}.sw-sidebar{width:100%;min-width:unset;padding:16px}.sw-brand{margin-bottom:12px}.sw-sidebar-bottom{display:none}.sw-step-content{padding:12px 20px 40px}}\n"],
42586
+ styles: [".sw-page{display:flex;min-height:100vh;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.sw-sidebar{width:260px;min-width:260px;background:#faf9f7;border-right:1px solid #e5e2dc;display:flex;flex-direction:column;justify-content:space-between;padding:28px 20px}.sw-brand{display:flex;align-items:center;gap:10px;margin-bottom:28px}.sw-brand-text{font-size:1.125rem;font-weight:700;color:#1e293b}.sw-step-nav{display:block}.sw-sidebar-bottom{margin-top:24px}.sw-progress-text{display:block;margin-top:8px;font-size:.75rem;color:#94a3b8}.sw-content{flex:1;min-width:0;background:#fff;display:flex;flex-direction:column;overflow-y:auto}.sw-content-header{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:20px 32px;border-bottom:1px solid #f1f5f9}.sw-step-title{font-size:1.25rem;font-weight:700;color:#111827;margin:0}.sw-step-content{max-width:780px;padding:16px 48px 60px}.sw-intro{margin-bottom:24px}.sw-step-desc{font-size:.9375rem;color:#6b7280;line-height:1.5;margin:0 0 32px}.sw-hint{font-size:.8125rem;color:#94a3b8;margin:0 0 16px}.sw-import-tags{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:28px}.sw-tag{font-size:.6875rem;font-weight:700;letter-spacing:1px;color:#6b7280}.sw-provider-grid{display:flex;flex-direction:column;gap:8px;margin-bottom:24px}.sw-area-code{display:flex;align-items:flex-end;gap:12px;padding:0 0 8px 4px;max-width:320px}.sw-area-code ui-text-input{flex:1}.sw-content ui-alert{display:block;margin-bottom:16px}.sw-step-actions{display:flex;justify-content:space-between;align-items:center;margin-top:16px;padding-top:20px;border-top:1px solid #f1f5f9}.sw-ico{flex-shrink:0;vertical-align:-2px}.sw-actions-right{display:flex;align-items:center;gap:16px}.sw-done{text-align:center;display:flex;flex-direction:column;align-items:center;max-width:none}.sw-done .sw-step-desc{max-width:480px}.sw-summary{display:block;width:100%;max-width:480px;margin-bottom:24px;text-align:left}.sw-done-hint{font-size:.8125rem;color:#9ca3af;margin-bottom:24px}@media(max-width:768px){.sw-page{flex-direction:column}.sw-sidebar{width:100%;min-width:unset;padding:16px}.sw-brand{margin-bottom:12px}.sw-sidebar-bottom{display:none}.sw-step-content{padding:12px 20px 40px}}\n"],
42561
42587
  dependencies: [
42562
42588
  {
42563
42589
  kind: "directive",
@@ -42710,6 +42736,26 @@ var SetupWizardComponent = class SetupWizardComponent {
42710
42736
  "valueText"
42711
42737
  ]
42712
42738
  },
42739
+ {
42740
+ kind: "component",
42741
+ type: SectionHeaderComponent,
42742
+ selector: "ui-section-header",
42743
+ inputs: [
42744
+ "title",
42745
+ "description",
42746
+ "icon",
42747
+ "level",
42748
+ "background",
42749
+ "textColor",
42750
+ "iconColor",
42751
+ "iconBackground",
42752
+ "bordered",
42753
+ "size",
42754
+ "noPaddingTop",
42755
+ "noPaddingLeft",
42756
+ "noPaddingBottom"
42757
+ ]
42758
+ },
42713
42759
  {
42714
42760
  kind: "component",
42715
42761
  type: StepperComponent,
@@ -42802,6 +42848,7 @@ i0.ɵɵngDeclareClassMetadata({
42802
42848
  ListItemComponent,
42803
42849
  PanelInfoListComponent,
42804
42850
  ProgressBarComponent,
42851
+ SectionHeaderComponent,
42805
42852
  StepperComponent,
42806
42853
  TextInputComponent
42807
42854
  ],
@@ -42825,7 +42872,7 @@ i0.ɵɵngDeclareClassMetadata({
42825
42872
  <main class="sw-content">
42826
42873
  <div class="sw-content-header">
42827
42874
  <h1 class="sw-step-title" data-testid="wizard-step-title">{{ current().label }}</h1>
42828
- <ui-button variant="ghost" size="sm" data-testid="wizard-exit" (click)="exited.emit()">{{ t().exit }}</ui-button>
42875
+ <ui-button variant="ghost" size="sm" data-testid="wizard-exit" (click)="exited.emit()"><svg class="sw-ico" 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]="iconD('close')" /></svg> {{ t().exit }}</ui-button>
42829
42876
  </div>
42830
42877
 
42831
42878
  @if (isDone()) {
@@ -42833,15 +42880,15 @@ i0.ɵɵngDeclareClassMetadata({
42833
42880
  <p class="sw-step-desc">{{ t().doneDescription }}</p>
42834
42881
  <ui-panel-info-list class="sw-summary" data-testid="wizard-summary" [sections]="summarySections()" />
42835
42882
  <p class="sw-done-hint">{{ t().doneHint }}</p>
42836
- <ui-button variant="primary" size="lg" data-testid="wizard-finish" (click)="finished.emit()">{{ t().finish }}</ui-button>
42883
+ <ui-button variant="primary" size="sm" data-testid="wizard-finish" (click)="finished.emit()"><svg class="sw-ico" 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]="iconD('check')" /></svg> {{ t().finish }}</ui-button>
42837
42884
  </div>
42838
42885
  } @else {
42839
42886
  <div class="sw-step-content" [attr.data-step]="current().key">
42840
- @if (current().description) { <p class="sw-step-desc">{{ current().description }}</p> }
42887
+ @if (intro(); as i) { <ui-section-header class="sw-intro" data-testid="wizard-step-intro" size="sm" background="#eaf3ff" [title]="i.title" [description]="i.text" /> }
42841
42888
 
42842
42889
  @switch (current().kind) {
42843
42890
  @case ('custom') {
42844
- @if (templateFor(current().key); as tpl) { <ng-container [ngTemplateOutlet]="tpl" /> }
42891
+ @if (templateFor(current().key); as tpl) { <ng-container [ngTemplateOutlet]="tpl" [ngTemplateOutletContext]="{ $implicit: api }" /> }
42845
42892
  }
42846
42893
  @case ('import') {
42847
42894
  @if (current().import; as imp) {
@@ -42854,11 +42901,11 @@ i0.ɵɵngDeclareClassMetadata({
42854
42901
  @if (importResult(current().key); as res) {
42855
42902
  <ui-alert variant="success" [title]="importTitle(current().key)" [attr.data-testid]="'import-result-' + current().key">
42856
42903
  {{ imp.resultText }}
42857
- <ui-button variant="link" size="sm" data-testid="import-more" (click)="clearImport(current().key)">{{ t().importMore }}</ui-button>
42904
+ <ui-button variant="link" size="sm" data-testid="import-more" (click)="clearImport(current().key)"><svg class="sw-ico" 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]="iconD('upload')" /></svg> {{ t().importMore }}</ui-button>
42858
42905
  </ui-alert>
42859
42906
  } @else {
42860
42907
  @if (imp.hint) { <p class="sw-hint">{{ imp.hint }}</p> }
42861
- <ui-button variant="primary" size="lg" [attr.data-testid]="'open-import-' + current().key" (click)="openImport(current().key)">{{ imp.buttonLabel }}</ui-button>
42908
+ <ui-button variant="primary" size="sm" [attr.data-testid]="'open-import-' + current().key" (click)="openImport(current().key)"><svg class="sw-ico" 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]="iconD('upload')" /></svg> {{ imp.buttonLabel }}</ui-button>
42862
42909
  }
42863
42910
  <ui-import-export #importer style="display:none" [config]="imp.config" [importSources]="imp.sources" (imported)="onImported(current().key)" />
42864
42911
  }
@@ -42870,13 +42917,13 @@ i0.ɵɵngDeclareClassMetadata({
42870
42917
  [icon]="it.icon ?? 'link'" iconColor="blue" [title]="it.title" [details]="[detailFor(it)]"
42871
42918
  [badge]="t().connected" badgeVariant="green" [alwaysShowBadge]="isConnected(it)">
42872
42919
  <ui-button list-item-action variant="secondary" size="sm" [ariaLabel]="(isConnected(it) ? t().reconnect : t().connect) + ' ' + it.title" (click)="connect(it)">
42873
- {{ isConnected(it) ? t().reconnect : t().connect }}
42920
+ <svg class="sw-ico" 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]="iconD('link')" /></svg> {{ isConnected(it) ? t().reconnect : t().connect }}
42874
42921
  </ui-button>
42875
42922
  </ui-list-item>
42876
42923
  @if (areaCodeOpen() === it.key) {
42877
42924
  <div class="sw-area-code" [attr.data-testid]="'area-code-' + it.key">
42878
42925
  <ui-text-input [label]="areaCodeLabelFor(it)" [maxlength]="3" inputmode="numeric" [ngModel]="areaCode()" (ngModelChange)="areaCode.set($event ?? '')" [inputTestId]="'area-code-input-' + it.key" />
42879
- <ui-button variant="primary" size="sm" [loading]="busy()" [disabled]="!validAreaCode()" (click)="submitAreaCode(it)">{{ t().connect }}</ui-button>
42926
+ <ui-button variant="primary" size="sm" [loading]="busy()" [disabled]="!validAreaCode()" (click)="submitAreaCode(it)"><svg class="sw-ico" 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]="iconD('link')" /></svg> {{ t().connect }}</ui-button>
42880
42927
  </div>
42881
42928
  }
42882
42929
  }
@@ -42887,19 +42934,21 @@ i0.ɵɵngDeclareClassMetadata({
42887
42934
  @if (error()) { <ui-alert variant="danger" data-testid="wizard-save-error">{{ error() }}</ui-alert> }
42888
42935
 
42889
42936
  <div class="sw-step-actions">
42890
- @if (index() > 0) { <ui-button variant="ghost" size="md" data-testid="wizard-back" [disabled]="busy()" (click)="back()">{{ t().back }}</ui-button> } @else { <span></span> }
42937
+ @if (index() > 0) { <ui-button variant="ghost" size="sm" data-testid="wizard-back" [disabled]="busy()" (click)="back()"><svg class="sw-ico" 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]="iconD('arrow-left')" /></svg> {{ t().back }}</ui-button> } @else { <span></span> }
42891
42938
  <div class="sw-actions-right">
42892
42939
  @if (current().skippable !== false) {
42893
- <ui-button variant="ghost" size="md" data-testid="wizard-skip" [disabled]="busy()" (click)="skip()">{{ t().skip }}</ui-button>
42940
+ <ui-button variant="ghost" size="sm" data-testid="wizard-skip" [disabled]="busy()" (click)="skip()">{{ t().skip }} <svg class="sw-ico" 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]="iconD('chevron-right')" /></svg></ui-button>
42894
42941
  }
42895
42942
  @if (current().kind === 'custom') {
42896
- <ui-button variant="primary" size="lg" data-testid="wizard-save" [loading]="busy()" [disabled]="current().canContinue ? !current().canContinue!() : false" (click)="saveAndContinue()">
42897
- {{ current().saveLabel ?? t().saveAndContinue }}
42943
+ @if (!current().ownActions) {
42944
+ <ui-button variant="primary" size="sm" data-testid="wizard-save" [loading]="busy()" [disabled]="current().canContinue ? !current().canContinue!() : false" (click)="saveAndContinue()">
42945
+ {{ current().saveLabel ?? t().saveAndContinue }} <svg class="sw-ico" 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]="iconD('arrow-right')" /></svg>
42898
42946
  </ui-button>
42947
+ }
42899
42948
  } @else if (current().kind === 'integrations') {
42900
- <ui-button variant="primary" size="lg" data-testid="wizard-save" [loading]="busy()" (click)="saveAndContinue()">{{ t().saveAndContinue }}</ui-button>
42949
+ <ui-button variant="primary" size="sm" data-testid="wizard-save" [loading]="busy()" (click)="saveAndContinue()">{{ t().saveAndContinue }} <svg class="sw-ico" 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]="iconD('arrow-right')" /></svg></ui-button>
42901
42950
  } @else if (importResult(current().key)) {
42902
- <ui-button variant="primary" size="lg" data-testid="wizard-continue" (click)="continueFromImport()">{{ t().continue }}</ui-button>
42951
+ <ui-button variant="primary" size="sm" data-testid="wizard-continue" (click)="continueFromImport()">{{ t().continue }} <svg class="sw-ico" 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]="iconD('arrow-right')" /></svg></ui-button>
42903
42952
  }
42904
42953
  </div>
42905
42954
  </div>
@@ -42908,7 +42957,7 @@ i0.ɵɵngDeclareClassMetadata({
42908
42957
  </main>
42909
42958
  </div>
42910
42959
  `,
42911
- styles: [".sw-page{display:flex;min-height:100vh;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.sw-sidebar{width:260px;min-width:260px;background:#faf9f7;border-right:1px solid #e5e2dc;display:flex;flex-direction:column;justify-content:space-between;padding:28px 20px}.sw-brand{display:flex;align-items:center;gap:10px;margin-bottom:28px}.sw-brand-text{font-size:1.125rem;font-weight:700;color:#1e293b}.sw-step-nav{display:block}.sw-sidebar-bottom{margin-top:24px}.sw-progress-text{display:block;margin-top:8px;font-size:.75rem;color:#94a3b8}.sw-content{flex:1;min-width:0;background:#fff;display:flex;flex-direction:column;overflow-y:auto}.sw-content-header{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:20px 32px;border-bottom:1px solid #f1f5f9}.sw-step-title{font-size:1.25rem;font-weight:700;color:#111827;margin:0}.sw-step-content{max-width:780px;padding:16px 48px 60px}.sw-step-desc{font-size:.9375rem;color:#6b7280;line-height:1.5;margin:0 0 32px}.sw-hint{font-size:.8125rem;color:#94a3b8;margin:0 0 16px}.sw-import-tags{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:28px}.sw-tag{font-size:.6875rem;font-weight:700;letter-spacing:1px;color:#6b7280}.sw-provider-grid{display:flex;flex-direction:column;gap:8px;margin-bottom:24px}.sw-area-code{display:flex;align-items:flex-end;gap:12px;padding:0 0 8px 4px;max-width:320px}.sw-area-code ui-text-input{flex:1}.sw-content ui-alert{display:block;margin-bottom:16px}.sw-step-actions{display:flex;justify-content:space-between;align-items:center;margin-top:16px;padding-top:20px;border-top:1px solid #f1f5f9}.sw-actions-right{display:flex;align-items:center;gap:16px}.sw-done{text-align:center;display:flex;flex-direction:column;align-items:center;max-width:none}.sw-done .sw-step-desc{max-width:480px}.sw-summary{display:block;width:100%;max-width:480px;margin-bottom:24px;text-align:left}.sw-done-hint{font-size:.8125rem;color:#9ca3af;margin-bottom:24px}@media(max-width:768px){.sw-page{flex-direction:column}.sw-sidebar{width:100%;min-width:unset;padding:16px}.sw-brand{margin-bottom:12px}.sw-sidebar-bottom{display:none}.sw-step-content{padding:12px 20px 40px}}\n"]
42960
+ styles: [".sw-page{display:flex;min-height:100vh;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}.sw-sidebar{width:260px;min-width:260px;background:#faf9f7;border-right:1px solid #e5e2dc;display:flex;flex-direction:column;justify-content:space-between;padding:28px 20px}.sw-brand{display:flex;align-items:center;gap:10px;margin-bottom:28px}.sw-brand-text{font-size:1.125rem;font-weight:700;color:#1e293b}.sw-step-nav{display:block}.sw-sidebar-bottom{margin-top:24px}.sw-progress-text{display:block;margin-top:8px;font-size:.75rem;color:#94a3b8}.sw-content{flex:1;min-width:0;background:#fff;display:flex;flex-direction:column;overflow-y:auto}.sw-content-header{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:20px 32px;border-bottom:1px solid #f1f5f9}.sw-step-title{font-size:1.25rem;font-weight:700;color:#111827;margin:0}.sw-step-content{max-width:780px;padding:16px 48px 60px}.sw-intro{margin-bottom:24px}.sw-step-desc{font-size:.9375rem;color:#6b7280;line-height:1.5;margin:0 0 32px}.sw-hint{font-size:.8125rem;color:#94a3b8;margin:0 0 16px}.sw-import-tags{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:28px}.sw-tag{font-size:.6875rem;font-weight:700;letter-spacing:1px;color:#6b7280}.sw-provider-grid{display:flex;flex-direction:column;gap:8px;margin-bottom:24px}.sw-area-code{display:flex;align-items:flex-end;gap:12px;padding:0 0 8px 4px;max-width:320px}.sw-area-code ui-text-input{flex:1}.sw-content ui-alert{display:block;margin-bottom:16px}.sw-step-actions{display:flex;justify-content:space-between;align-items:center;margin-top:16px;padding-top:20px;border-top:1px solid #f1f5f9}.sw-ico{flex-shrink:0;vertical-align:-2px}.sw-actions-right{display:flex;align-items:center;gap:16px}.sw-done{text-align:center;display:flex;flex-direction:column;align-items:center;max-width:none}.sw-done .sw-step-desc{max-width:480px}.sw-summary{display:block;width:100%;max-width:480px;margin-bottom:24px;text-align:left}.sw-done-hint{font-size:.8125rem;color:#9ca3af;margin-bottom:24px}@media(max-width:768px){.sw-page{flex-direction:column}.sw-sidebar{width:100%;min-width:unset;padding:16px}.sw-brand{margin-bottom:12px}.sw-sidebar-bottom{display:none}.sw-step-content{padding:12px 20px 40px}}\n"]
42912
42961
  }]
42913
42962
  }],
42914
42963
  ctorParameters: () => [],
@@ -43206,12 +43255,6 @@ const PLAYBACK_OPTIONS = [{
43206
43255
  value: "autoplay",
43207
43256
  label: "Autoplay"
43208
43257
  }];
43209
- const DEFAULT_AI_EXAMPLES = [
43210
- "Follow up after a showing",
43211
- "Open house invitation",
43212
- "Market update",
43213
- "Thank you after closing"
43214
- ];
43215
43258
  const DEFAULT_VIDEO_LINK = (video) => video.shareLink;
43216
43259
  const EMPTY_VIDEO_DEFAULTS = {
43217
43260
  autoplay: false,
@@ -43235,12 +43278,8 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
43235
43278
  this.textEnabled = input(false, ...ngDevMode ? [{ debugName: "textEnabled" }] : /* istanbul ignore next */ []);
43236
43279
  this.variableGroups = input(DEFAULT_EMAIL_TEMPLATE_VARIABLE_GROUPS, ...ngDevMode ? [{ debugName: "variableGroups" }] : /* istanbul ignore next */ []);
43237
43280
  this.blockGroups = input(DEFAULT_EMAIL_TEMPLATE_BLOCK_GROUPS, ...ngDevMode ? [{ debugName: "blockGroups" }] : /* istanbul ignore next */ []);
43238
- this.aiExamples = input(DEFAULT_AI_EXAMPLES, ...ngDevMode ? [{ debugName: "aiExamples" }] : /* istanbul ignore next */ []);
43239
43281
  this.namePlaceholder = input("e.g. Follow-Up — Friendly", ...ngDevMode ? [{ debugName: "namePlaceholder" }] : /* istanbul ignore next */ []);
43240
43282
  this.subjectPlaceholder = input("e.g. Following up on {{property_address}}", ...ngDevMode ? [{ debugName: "subjectPlaceholder" }] : /* istanbul ignore next */ []);
43241
- this.backLabel = input("Email Messages", ...ngDevMode ? [{ debugName: "backLabel" }] : /* istanbul ignore next */ []);
43242
- this.createLabel = input("Create Template", ...ngDevMode ? [{ debugName: "createLabel" }] : /* istanbul ignore next */ []);
43243
- this.editLabel = input("Edit Template", ...ngDevMode ? [{ debugName: "editLabel" }] : /* istanbul ignore next */ []);
43244
43283
  this.systemNote = input("This is a built-in system template, so it can be viewed but not changed.", ...ngDevMode ? [{ debugName: "systemNote" }] : /* istanbul ignore next */ []);
43245
43284
  this.readOnlyNote = input("You have read-only access to email templates, so this template can be viewed but not saved.", ...ngDevMode ? [{ debugName: "readOnlyNote" }] : /* istanbul ignore next */ []);
43246
43285
  this.idPrefix = input("tpl", ...ngDevMode ? [{ debugName: "idPrefix" }] : /* istanbul ignore next */ []);
@@ -43248,21 +43287,19 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
43248
43287
  this.maxTextLength = input(255, ...ngDevMode ? [{ debugName: "maxTextLength" }] : /* istanbul ignore next */ []);
43249
43288
  this.fullAccess = input(true, ...ngDevMode ? [{ debugName: "fullAccess" }] : /* istanbul ignore next */ []);
43250
43289
  this.systemTemplate = input(false, ...ngDevMode ? [{ debugName: "systemTemplate" }] : /* istanbul ignore next */ []);
43251
- this.aiEnabled = input(true, ...ngDevMode ? [{ debugName: "aiEnabled" }] : /* istanbul ignore next */ []);
43252
43290
  this.testSendEnabled = input(true, ...ngDevMode ? [{ debugName: "testSendEnabled" }] : /* istanbul ignore next */ []);
43253
- this.videosEnabled = input(true, ...ngDevMode ? [{ debugName: "videosEnabled" }] : /* istanbul ignore next */ []);
43254
43291
  this.saving = input(false, ...ngDevMode ? [{ debugName: "saving" }] : /* istanbul ignore next */ []);
43255
43292
  this.testSending = input(false, ...ngDevMode ? [{ debugName: "testSending" }] : /* istanbul ignore next */ []);
43256
- this.aiGenerating = input(false, ...ngDevMode ? [{ debugName: "aiGenerating" }] : /* istanbul ignore next */ []);
43257
- this.videos = input([], ...ngDevMode ? [{ debugName: "videos" }] : /* istanbul ignore next */ []);
43293
+ this.videos = input(null, ...ngDevMode ? [{ debugName: "videos" }] : /* istanbul ignore next */ []);
43294
+ this.hideVideos = input(false, ...ngDevMode ? [{ debugName: "hideVideos" }] : /* istanbul ignore next */ []);
43295
+ this.videosEnabled = computed(() => this.videos() !== null && !this.hideVideos(), ...ngDevMode ? [{ debugName: "videosEnabled" }] : /* istanbul ignore next */ []);
43296
+ this.videoList = computed(() => this.videos() ?? [], ...ngDevMode ? [{ debugName: "videoList" }] : /* istanbul ignore next */ []);
43258
43297
  this.videosLoading = input(false, ...ngDevMode ? [{ debugName: "videosLoading" }] : /* istanbul ignore next */ []);
43259
43298
  this.videoDefaults = input(EMPTY_VIDEO_DEFAULTS, ...ngDevMode ? [{ debugName: "videoDefaults" }] : /* istanbul ignore next */ []);
43260
43299
  this.videoLink = input(DEFAULT_VIDEO_LINK, ...ngDevMode ? [{ debugName: "videoLink" }] : /* istanbul ignore next */ []);
43261
43300
  this.noVideosHint = input("Upload videos on the Video Messages page.", ...ngDevMode ? [{ debugName: "noVideosHint" }] : /* istanbul ignore next */ []);
43262
- this.back = output();
43263
43301
  this.save = output();
43264
43302
  this.testSend = output();
43265
- this.aiGenerate = output();
43266
43303
  this.videosRequested = output();
43267
43304
  this.useAsMine = output();
43268
43305
  this.editingId = signal(null, ...ngDevMode ? [{ debugName: "editingId" }] : /* istanbul ignore next */ []);
@@ -43311,8 +43348,6 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
43311
43348
  this.imageAlt = signal("", ...ngDevMode ? [{ debugName: "imageAlt" }] : /* istanbul ignore next */ []);
43312
43349
  this.showTestSendDialog = signal(false, ...ngDevMode ? [{ debugName: "showTestSendDialog" }] : /* istanbul ignore next */ []);
43313
43350
  this.testSendEmail = signal("", ...ngDevMode ? [{ debugName: "testSendEmail" }] : /* istanbul ignore next */ []);
43314
- this.showAiPanel = signal(false, ...ngDevMode ? [{ debugName: "showAiPanel" }] : /* istanbul ignore next */ []);
43315
- this.aiPrompt = signal("", ...ngDevMode ? [{ debugName: "aiPrompt" }] : /* istanbul ignore next */ []);
43316
43351
  this.showAssignmentConfig = signal(false, ...ngDevMode ? [{ debugName: "showAssignmentConfig" }] : /* istanbul ignore next */ []);
43317
43352
  this.configTarget = signal(null, ...ngDevMode ? [{ debugName: "configTarget" }] : /* istanbul ignore next */ []);
43318
43353
  this.configEmail = signal(false, ...ngDevMode ? [{ debugName: "configEmail" }] : /* istanbul ignore next */ []);
@@ -43371,8 +43406,14 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
43371
43406
  if (this.useAllYear() || !this.activeFrom() || !this.activeTo()) return "";
43372
43407
  return this.activeTo() < this.activeFrom() ? "Active To must be on or after Active From." : "";
43373
43408
  }, ...ngDevMode ? [{ debugName: "datesError" }] : /* istanbul ignore next */ []);
43409
+ this.submitAttempted = signal(false, ...ngDevMode ? [{ debugName: "submitAttempted" }] : /* istanbul ignore next */ []);
43410
+ this.nameTouched = signal(false, ...ngDevMode ? [{ debugName: "nameTouched" }] : /* istanbul ignore next */ []);
43411
+ this.subjectTouched = signal(false, ...ngDevMode ? [{ debugName: "subjectTouched" }] : /* istanbul ignore next */ []);
43412
+ this.nameErrorShown = computed(() => this.nameTouched() || this.submitAttempted() ? this.nameError() : "", ...ngDevMode ? [{ debugName: "nameErrorShown" }] : /* istanbul ignore next */ []);
43413
+ this.subjectErrorShown = computed(() => this.subjectTouched() || this.submitAttempted() ? this.subjectError() : "", ...ngDevMode ? [{ debugName: "subjectErrorShown" }] : /* istanbul ignore next */ []);
43414
+ this.bodyErrorShown = computed(() => this.bodyEdited() || this.submitAttempted() ? this.bodyError() : "", ...ngDevMode ? [{ debugName: "bodyErrorShown" }] : /* istanbul ignore next */ []);
43374
43415
  this.canSave = computed(() => !this.nameError() && !this.subjectError() && !this.bodyError() && !this.datesError(), ...ngDevMode ? [{ debugName: "canSave" }] : /* istanbul ignore next */ []);
43375
- this.saveDisabled = computed(() => !this.canWrite() || !this.canSave(), ...ngDevMode ? [{ debugName: "saveDisabled" }] : /* istanbul ignore next */ []);
43416
+ this.saveDisabled = computed(() => !this.canWrite(), ...ngDevMode ? [{ debugName: "saveDisabled" }] : /* istanbul ignore next */ []);
43376
43417
  this.normalizedLink = computed(() => {
43377
43418
  const url = this.linkUrl().trim();
43378
43419
  if (!url) return "";
@@ -43396,7 +43437,6 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
43396
43437
  }, ...ngDevMode ? [{ debugName: "testEmailError" }] : /* istanbul ignore next */ []);
43397
43438
  this.canSendTest = computed(() => this.canWrite() && !!this.editingId() && !!this.testSendEmail().trim() && !this.testEmailError() && !this.testSending(), ...ngDevMode ? [{ debugName: "canSendTest" }] : /* istanbul ignore next */ []);
43398
43439
  this.hasUnsavedChanges = computed(() => !!this.editingId() && this.savedSnapshot() !== null && this.savedSnapshot() !== this.snapshot(), ...ngDevMode ? [{ debugName: "hasUnsavedChanges" }] : /* istanbul ignore next */ []);
43399
- this.canGenerate = computed(() => !!this.aiPrompt().trim() && !this.aiGenerating(), ...ngDevMode ? [{ debugName: "canGenerate" }] : /* istanbul ignore next */ []);
43400
43440
  effect(() => {
43401
43441
  const t = this.template();
43402
43442
  untracked(() => this.applyTemplate(t));
@@ -43412,6 +43452,9 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
43412
43452
  this.videoHideReactions.set(d.hideReactions);
43413
43453
  });
43414
43454
  });
43455
+ effect(() => {
43456
+ if (!this.videosEnabled() && this.activeRightTab() === "video") untracked(() => this.activeRightTab.set("blocks"));
43457
+ });
43415
43458
  effect(() => {
43416
43459
  if (this.showLinkDialog() || this.showImageDialog()) afterNextRender(() => this.host.nativeElement.querySelector(".link-dialog input")?.focus(), { injector: this.injector });
43417
43460
  });
@@ -43439,17 +43482,6 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
43439
43482
  closeTestSend() {
43440
43483
  this.showTestSendDialog.set(false);
43441
43484
  }
43442
- addGeneratedHtml(html) {
43443
- const block = {
43444
- id: this.genId(),
43445
- html: this.stripBlockWrappers(html)
43446
- };
43447
- this.blocks.update((b) => [...b, block]);
43448
- this.bodyEdited.set(true);
43449
- this.selectedBlockId.set(block.id);
43450
- this.showAiPanel.set(false);
43451
- this.toast.show("AI content added to your email");
43452
- }
43453
43485
  applyTemplate(t) {
43454
43486
  this.initializedBlockIds = /* @__PURE__ */ new Set();
43455
43487
  this.editingId.set(t?.id ?? null);
@@ -43469,6 +43501,9 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
43469
43501
  this.blockSpacing.set("");
43470
43502
  this.loadedBody.set(t?.id ? t.body ?? "" : null);
43471
43503
  this.bodyEdited.set(false);
43504
+ this.submitAttempted.set(false);
43505
+ this.nameTouched.set(false);
43506
+ this.subjectTouched.set(false);
43472
43507
  this.assignmentChannels.set(Object.fromEntries((t?.assignments ?? []).map((c) => [c.key, {
43473
43508
  email: !!c.email,
43474
43509
  text: !!c.text
@@ -43476,7 +43511,11 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
43476
43511
  this.savedSnapshot.set(t?.id ? this.snapshot() : null);
43477
43512
  }
43478
43513
  onSave() {
43479
- if (this.saving() || !this.canSave() || !this.canWrite()) return;
43514
+ if (this.saving() || !this.canWrite()) return;
43515
+ if (!this.canSave()) {
43516
+ this.submitAttempted.set(true);
43517
+ return;
43518
+ }
43480
43519
  const keepStoredBody = this.bodyUnchanged() && this.bodyLength() > this.maxBodyLength();
43481
43520
  this.syncActiveBlockHtml();
43482
43521
  this.save.emit({
@@ -43538,10 +43577,6 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
43538
43577
  html
43539
43578
  }];
43540
43579
  }
43541
- stripBlockWrappers(html) {
43542
- if (!html || !html.includes("data-block")) return html;
43543
- return html.replace(/<\/div>\s*(?=<div[^>]*data-block)/g, "").replace(/<div[^>]*data-block[^>]*>/g, "").replace(/<\/div>\s*$/, "");
43544
- }
43545
43580
  genId() {
43546
43581
  return Math.random().toString(36).slice(2, 10);
43547
43582
  }
@@ -43893,15 +43928,6 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
43893
43928
  if (!this.canSendTest()) return;
43894
43929
  this.testSend.emit(this.testSendEmail().trim());
43895
43930
  }
43896
- openAiPanel() {
43897
- if (!this.canWrite() || !this.aiEnabled()) return;
43898
- this.aiPrompt.set("");
43899
- this.showAiPanel.set(true);
43900
- }
43901
- onAiGenerate() {
43902
- if (!this.canWrite() || !this.canGenerate()) return;
43903
- this.aiGenerate.emit(this.aiPrompt());
43904
- }
43905
43931
  openVideoTab() {
43906
43932
  this.activeRightTab.set("video");
43907
43933
  this.videosRequested.emit();
@@ -44060,13 +44086,6 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44060
44086
  isRequired: false,
44061
44087
  transformFunction: null
44062
44088
  },
44063
- aiExamples: {
44064
- classPropertyName: "aiExamples",
44065
- publicName: "aiExamples",
44066
- isSignal: true,
44067
- isRequired: false,
44068
- transformFunction: null
44069
- },
44070
44089
  namePlaceholder: {
44071
44090
  classPropertyName: "namePlaceholder",
44072
44091
  publicName: "namePlaceholder",
@@ -44081,27 +44100,6 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44081
44100
  isRequired: false,
44082
44101
  transformFunction: null
44083
44102
  },
44084
- backLabel: {
44085
- classPropertyName: "backLabel",
44086
- publicName: "backLabel",
44087
- isSignal: true,
44088
- isRequired: false,
44089
- transformFunction: null
44090
- },
44091
- createLabel: {
44092
- classPropertyName: "createLabel",
44093
- publicName: "createLabel",
44094
- isSignal: true,
44095
- isRequired: false,
44096
- transformFunction: null
44097
- },
44098
- editLabel: {
44099
- classPropertyName: "editLabel",
44100
- publicName: "editLabel",
44101
- isSignal: true,
44102
- isRequired: false,
44103
- transformFunction: null
44104
- },
44105
44103
  systemNote: {
44106
44104
  classPropertyName: "systemNote",
44107
44105
  publicName: "systemNote",
@@ -44151,13 +44149,6 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44151
44149
  isRequired: false,
44152
44150
  transformFunction: null
44153
44151
  },
44154
- aiEnabled: {
44155
- classPropertyName: "aiEnabled",
44156
- publicName: "aiEnabled",
44157
- isSignal: true,
44158
- isRequired: false,
44159
- transformFunction: null
44160
- },
44161
44152
  testSendEnabled: {
44162
44153
  classPropertyName: "testSendEnabled",
44163
44154
  publicName: "testSendEnabled",
@@ -44165,13 +44156,6 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44165
44156
  isRequired: false,
44166
44157
  transformFunction: null
44167
44158
  },
44168
- videosEnabled: {
44169
- classPropertyName: "videosEnabled",
44170
- publicName: "videosEnabled",
44171
- isSignal: true,
44172
- isRequired: false,
44173
- transformFunction: null
44174
- },
44175
44159
  saving: {
44176
44160
  classPropertyName: "saving",
44177
44161
  publicName: "saving",
@@ -44186,16 +44170,16 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44186
44170
  isRequired: false,
44187
44171
  transformFunction: null
44188
44172
  },
44189
- aiGenerating: {
44190
- classPropertyName: "aiGenerating",
44191
- publicName: "aiGenerating",
44173
+ videos: {
44174
+ classPropertyName: "videos",
44175
+ publicName: "videos",
44192
44176
  isSignal: true,
44193
44177
  isRequired: false,
44194
44178
  transformFunction: null
44195
44179
  },
44196
- videos: {
44197
- classPropertyName: "videos",
44198
- publicName: "videos",
44180
+ hideVideos: {
44181
+ classPropertyName: "hideVideos",
44182
+ publicName: "hideVideos",
44199
44183
  isSignal: true,
44200
44184
  isRequired: false,
44201
44185
  transformFunction: null
@@ -44230,10 +44214,8 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44230
44214
  }
44231
44215
  },
44232
44216
  outputs: {
44233
- back: "back",
44234
44217
  save: "save",
44235
44218
  testSend: "testSend",
44236
- aiGenerate: "aiGenerate",
44237
44219
  videosRequested: "videosRequested",
44238
44220
  useAsMine: "useAsMine"
44239
44221
  },
@@ -44252,31 +44234,20 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44252
44234
  ngImport: i0,
44253
44235
  template: `
44254
44236
  <div class="editor-page">
44255
- <!-- Top Bar -->
44256
- <div class="editor-topbar">
44257
- <div class="topbar-left">
44258
- <ui-button variant="ghost" size="sm" ariaLabel="Go back" (click)="back.emit()">
44259
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M15 18l-6-6 6-6"/></svg>
44260
- </ui-button>
44261
- <nav class="breadcrumb" aria-label="Breadcrumb">
44262
- <a href="#" (click)="$event.preventDefault(); back.emit()">{{ backLabel() }}</a>
44263
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M9 18l6-6-6-6"/></svg>
44264
- <span>{{ isNew() ? createLabel() : editLabel() }}</span>
44265
- </nav>
44266
- </div>
44267
- <div class="topbar-right">
44268
- @if (canWrite() && testSendEnabled()) {
44269
- <ui-button variant="secondary" size="sm" (click)="openTestSendDialog()">
44270
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
44271
- Test Send
44272
- </ui-button>
44273
- }
44274
- <ui-button variant="primary" size="sm" [loading]="saving()" [disabled]="saveDisabled()" (click)="onSave()">
44275
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg>
44276
- Save Template
44237
+ <!-- Actions (outside the white panels) -->
44238
+ <div class="editor-actions">
44239
+ @if (canWrite() && testSendEnabled()) {
44240
+ <ui-button variant="secondary" size="sm" (click)="openTestSendDialog()">
44241
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
44242
+ Test Send
44277
44243
  </ui-button>
44278
- </div>
44244
+ }
44245
+ <ui-button variant="primary" size="sm" [loading]="saving()" [disabled]="saveDisabled()" (click)="onSave()">
44246
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg>
44247
+ Save Template
44248
+ </ui-button>
44279
44249
  </div>
44250
+ <ui-divider />
44280
44251
 
44281
44252
  @if (systemTemplate()) {
44282
44253
  <div class="readonly-note system-note" role="note" data-testid="editor-system-note">
@@ -44297,15 +44268,12 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44297
44268
 
44298
44269
  <div class="form-field">
44299
44270
  <ui-text-input label="Name" [required]="true" [(ngModel)]="name" [readonly]="!canWrite()" [maxlength]="maxTextLength()"
44300
- [placeholder]="namePlaceholder()" [error]="nameError()" />
44271
+ [placeholder]="namePlaceholder()" [error]="nameErrorShown()" (blurred)="nameTouched.set(true)" />
44301
44272
  </div>
44302
44273
 
44303
44274
  <div class="form-field">
44304
44275
  <ui-text-input label="Subject" [required]="true" [(ngModel)]="subject" [readonly]="!canWrite()" [maxlength]="maxTextLength()"
44305
- [placeholder]="subjectPlaceholder()" [error]="subjectError()">
44306
- @if (canWrite()) {
44307
- <span uiLabelEnd><ng-content select="[uiSubjectAction]" /></span>
44308
- }
44276
+ [placeholder]="subjectPlaceholder()" [error]="subjectErrorShown()" (blurred)="subjectTouched.set(true)">
44309
44277
  </ui-text-input>
44310
44278
  </div>
44311
44279
 
@@ -44328,7 +44296,10 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44328
44296
  <h4 class="section-title">Assignments</h4>
44329
44297
  <p class="section-desc">{{ assignmentsDescription() }}</p>
44330
44298
  <ui-search-input placeholder="Search..." ariaLabel="Search assignments" [(value)]="assignmentSearch" />
44331
- <div class="assignment-list">
44299
+ @if (filteredAssignments().length === 0) {
44300
+ <ui-empty-state iconType="search" title="No assignments found" message="No assignments match your search." />
44301
+ }
44302
+ <div class="assignment-list" [hidden]="filteredAssignments().length === 0">
44332
44303
  @for (item of filteredAssignments(); track item.key) {
44333
44304
  <div class="assignment-item" [class.assignment-readonly]="!canWrite()" [attr.role]="canWrite() ? 'button' : null" [attr.tabindex]="canWrite() ? 0 : null"
44334
44305
  [attr.aria-label]="canWrite() ? 'Configure ' + item.name : null"
@@ -44374,9 +44345,9 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44374
44345
  <!-- Toolbar row 1: mousedown preventDefault keeps focus (and the selection) in the editor -->
44375
44346
  <div class="editor-toolbar" role="toolbar" aria-label="Text formatting" (mousedown)="preventFocusLoss($event)">
44376
44347
  <div class="toolbar-group">
44377
- <ui-button variant="icon" size="sm" ariaLabel="Bold" uiTooltip="Bold" (click)="execCommand('bold')"><strong>B</strong></ui-button>
44378
- <ui-button variant="icon" size="sm" ariaLabel="Italic" uiTooltip="Italic" (click)="execCommand('italic')"><em>I</em></ui-button>
44379
- <ui-button variant="icon" size="sm" ariaLabel="Underline" uiTooltip="Underline" (click)="execCommand('underline')"><u>U</u></ui-button>
44348
+ <ui-button variant="ghost" size="sm" ariaLabel="Bold" uiTooltip="Bold" (click)="execCommand('bold')"><strong>B</strong></ui-button>
44349
+ <ui-button variant="ghost" size="sm" ariaLabel="Italic" uiTooltip="Italic" (click)="execCommand('italic')"><em>I</em></ui-button>
44350
+ <ui-button variant="ghost" size="sm" ariaLabel="Underline" uiTooltip="Underline" (click)="execCommand('underline')"><u>U</u></ui-button>
44380
44351
  </div>
44381
44352
  <div class="toolbar-group">
44382
44353
  @for (k of [headingKey()]; track k) {
@@ -44391,28 +44362,28 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44391
44362
  }
44392
44363
  </div>
44393
44364
  <div class="toolbar-group">
44394
- <ui-button variant="icon" size="sm" ariaLabel="Align left" uiTooltip="Align Left" (click)="execCommand('justifyLeft')">
44365
+ <ui-button variant="ghost" size="sm" ariaLabel="Align left" uiTooltip="Align Left" (click)="execCommand('justifyLeft')">
44395
44366
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="17" y1="10" x2="3" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="17" y1="18" x2="3" y2="18"/></svg>
44396
44367
  </ui-button>
44397
- <ui-button variant="icon" size="sm" ariaLabel="Align center" uiTooltip="Align Center" (click)="execCommand('justifyCenter')">
44368
+ <ui-button variant="ghost" size="sm" ariaLabel="Align center" uiTooltip="Align Center" (click)="execCommand('justifyCenter')">
44398
44369
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="18" y1="10" x2="6" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="18" y1="18" x2="6" y2="18"/></svg>
44399
44370
  </ui-button>
44400
- <ui-button variant="icon" size="sm" ariaLabel="Align right" uiTooltip="Align Right" (click)="execCommand('justifyRight')">
44371
+ <ui-button variant="ghost" size="sm" ariaLabel="Align right" uiTooltip="Align Right" (click)="execCommand('justifyRight')">
44401
44372
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="21" y1="10" x2="7" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="21" y1="18" x2="7" y2="18"/></svg>
44402
44373
  </ui-button>
44403
44374
  </div>
44404
44375
  <div class="toolbar-group">
44405
- <ui-button variant="icon" size="sm" ariaLabel="Bulleted list" uiTooltip="Bulleted List" (click)="execCommand('insertUnorderedList')">
44376
+ <ui-button variant="ghost" size="sm" ariaLabel="Bulleted list" uiTooltip="Bulleted List" (click)="execCommand('insertUnorderedList')">
44406
44377
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>
44407
44378
  </ui-button>
44408
- <ui-button variant="icon" size="sm" ariaLabel="Numbered list" uiTooltip="Numbered List" (click)="execCommand('insertOrderedList')">
44379
+ <ui-button variant="ghost" size="sm" ariaLabel="Numbered list" uiTooltip="Numbered List" (click)="execCommand('insertOrderedList')">
44409
44380
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/></svg>
44410
44381
  </ui-button>
44411
44382
  </div>
44412
44383
  <div class="toolbar-group">
44413
44384
  <!-- The browser's own colour dialog is the picker; a button opens it so the toolbar keeps one look. -->
44414
44385
  <input #colorInput type="color" class="hidden-color-input" aria-label="Text color" tabindex="-1" [value]="currentColor()" (change)="applyTextColor($any($event.target).value)" (mousedown)="$event.stopPropagation()" />
44415
- <ui-button variant="icon" size="sm" ariaLabel="Text color" uiTooltip="Text Color" (mousedown)="openColorPicker()">
44386
+ <ui-button variant="ghost" size="sm" ariaLabel="Text color" uiTooltip="Text Color" (mousedown)="openColorPicker()">
44416
44387
  <span class="color-indicator">
44417
44388
  <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><text y="20" font-size="20" font-weight="700">A</text></svg>
44418
44389
  <span class="color-bar" [style.background]="currentColor()"></span>
@@ -44420,35 +44391,29 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44420
44391
  </ui-button>
44421
44392
  </div>
44422
44393
  <div class="toolbar-group">
44423
- <ui-button variant="icon" size="sm" ariaLabel="Insert link" uiTooltip="Insert Link" (mousedown)="saveSelection()" (click)="openLinkDialog()">
44394
+ <ui-button variant="ghost" size="sm" ariaLabel="Insert link" uiTooltip="Insert Link" (mousedown)="saveSelection()" (click)="openLinkDialog()">
44424
44395
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>
44425
44396
  </ui-button>
44426
- <ui-button variant="icon" size="sm" ariaLabel="Insert image" uiTooltip="Insert Image" (mousedown)="saveSelection()" (click)="openImageDialog()">
44397
+ <ui-button variant="ghost" size="sm" ariaLabel="Insert image" uiTooltip="Insert Image" (mousedown)="saveSelection()" (click)="openImageDialog()">
44427
44398
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>
44428
44399
  </ui-button>
44429
44400
  </div>
44430
44401
  <div class="toolbar-group">
44431
- <ui-button variant="icon" size="sm" ariaLabel="Undo" uiTooltip="Undo" (click)="execCommand('undo')">
44402
+ <ui-button variant="ghost" size="sm" ariaLabel="Undo" uiTooltip="Undo" (click)="execCommand('undo')">
44432
44403
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M3 7v6h6"/><path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6.69 3L3 13"/></svg>
44433
44404
  </ui-button>
44434
- <ui-button variant="icon" size="sm" ariaLabel="Redo" uiTooltip="Redo" (click)="execCommand('redo')">
44405
+ <ui-button variant="ghost" size="sm" ariaLabel="Redo" uiTooltip="Redo" (click)="execCommand('redo')">
44435
44406
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 7v6h-6"/><path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6.69 3L21 13"/></svg>
44436
44407
  </ui-button>
44437
44408
  </div>
44438
44409
  </div>
44439
44410
 
44440
- <!-- Toolbar row 2: block spacing + AI -->
44411
+ <!-- Toolbar row 2: block spacing -->
44441
44412
  <div class="toolbar-row-2">
44442
44413
  <div class="toolbar-group" (mousedown)="preventFocusLoss($event)">
44443
44414
  <span class="toolbar-label" id="tpl-spacing-label">Block spacing</span>
44444
44415
  <ui-select class="toolbar-select" size="sm" ariaLabel="Block spacing" [options]="spacingOptions" [ngModel]="blockSpacing()" (ngModelChange)="applySpacing($event)" />
44445
44416
  </div>
44446
- @if (aiEnabled()) {
44447
- <ui-button variant="secondary" size="sm" (click)="openAiPanel()">
44448
- <span class="ai-dot" aria-hidden="true"></span>
44449
- Generate with AI
44450
- </ui-button>
44451
- }
44452
44417
  </div>
44453
44418
  }
44454
44419
 
@@ -44484,7 +44449,7 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44484
44449
  </div>
44485
44450
  }
44486
44451
 
44487
- <ui-error [errorId]="idPrefix() + '-body-error'" [message]="bodyError()" />
44452
+ <ui-error [errorId]="idPrefix() + '-body-error'" [message]="bodyErrorShown()" />
44488
44453
 
44489
44454
  <!-- Block Canvas with DnD -->
44490
44455
  <div class="blocks-canvas" (dragover)="onCanvasDragOver($event)" (drop)="onDropZoneDrop($event, blocks().length)">
@@ -44509,16 +44474,16 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44509
44474
 
44510
44475
  @if (canWrite()) {
44511
44476
  <div class="block-controls">
44512
- <ui-button variant="icon" size="xs" ariaLabel="Move block up" uiTooltip="Move up" [disabled]="i === 0" (mousedown)="preventFocusLoss($event)" (click)="moveBlock(i, -1)">
44477
+ <ui-button variant="ghost" size="xs" ariaLabel="Move block up" uiTooltip="Move up" [disabled]="i === 0" (mousedown)="preventFocusLoss($event)" (click)="moveBlock(i, -1)">
44513
44478
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M18 15l-6-6-6 6"/></svg>
44514
44479
  </ui-button>
44515
- <ui-button variant="icon" size="xs" ariaLabel="Move block down" uiTooltip="Move down" [disabled]="i === blocks().length - 1" (mousedown)="preventFocusLoss($event)" (click)="moveBlock(i, 1)">
44480
+ <ui-button variant="ghost" size="xs" ariaLabel="Move block down" uiTooltip="Move down" [disabled]="i === blocks().length - 1" (mousedown)="preventFocusLoss($event)" (click)="moveBlock(i, 1)">
44516
44481
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
44517
44482
  </ui-button>
44518
- <ui-button variant="icon" size="xs" ariaLabel="Duplicate block" uiTooltip="Duplicate" (mousedown)="preventFocusLoss($event)" (click)="duplicateBlock(i)">
44483
+ <ui-button variant="ghost" size="xs" ariaLabel="Duplicate block" uiTooltip="Duplicate" (mousedown)="preventFocusLoss($event)" (click)="duplicateBlock(i)">
44519
44484
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
44520
44485
  </ui-button>
44521
- <ui-button variant="icon-danger" size="xs" ariaLabel="Delete block" uiTooltip="Delete block" (mousedown)="preventFocusLoss($event)" (click)="deleteBlock(i)">
44486
+ <ui-button variant="ghost" size="xs" ariaLabel="Delete block" uiTooltip="Delete block" (mousedown)="preventFocusLoss($event)" (click)="deleteBlock(i)">
44522
44487
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6M14 11v6"/></svg>
44523
44488
  </ui-button>
44524
44489
  </div>
@@ -44586,6 +44551,9 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44586
44551
  <p class="right-section-desc">Click to insert or drag into the editor.</p>
44587
44552
  <ui-search-input placeholder="Search blocks..." ariaLabel="Search blocks" [(value)]="blockSearch" />
44588
44553
 
44554
+ @if (filteredBlockGroups().length === 0) {
44555
+ <ui-empty-state iconType="search" title="No blocks found" message="No blocks match your search." />
44556
+ }
44589
44557
  @for (group of filteredBlockGroups(); track group.name) {
44590
44558
  <div class="block-group">
44591
44559
  <button type="button" class="block-group-header" [attr.aria-expanded]="isOpen('b:' + group.name)" (click)="toggleGroup('b:' + group.name)">
@@ -44670,15 +44638,11 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44670
44638
  </div>
44671
44639
  }
44672
44640
  </div>
44673
- } @else if (videos().length === 0) {
44674
- <div class="video-lib-empty">
44675
- <svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" stroke-width="1.5" aria-hidden="true"><polygon points="23 7 16 12 23 17 23 7"/><rect x="1" y="5" width="15" height="14" rx="2" ry="2"/></svg>
44676
- <p>No videos yet</p>
44677
- <span>{{ noVideosHint() }}</span>
44678
- </div>
44641
+ } @else if (videoList().length === 0) {
44642
+ <ui-empty-state iconType="video" title="No videos created" [message]="noVideosHint()" />
44679
44643
  } @else {
44680
44644
  <div class="video-lib-list">
44681
- @for (video of videos(); track video.id) {
44645
+ @for (video of videoList(); track video.id) {
44682
44646
  <button type="button" class="video-lib-item" [class.selected]="video.id === videoId()" [attr.aria-pressed]="video.id === videoId()" (click)="insertVideo(video)">
44683
44647
  <span class="vli-thumb">
44684
44648
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" stroke-width="1.5" aria-hidden="true"><polygon points="5 3 19 12 5 21 5 3"/></svg>
@@ -44724,20 +44688,6 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44724
44688
  }
44725
44689
  </ui-side-panel>
44726
44690
 
44727
- <!-- AI Generate -->
44728
- <ui-side-panel [open]="showAiPanel()" title="Generate with AI" primaryLabel="Generate" [primaryLoading]="aiGenerating()" [primaryDisabled]="!canGenerate()"
44729
- (closed)="showAiPanel.set(false)" (primaryClick)="onAiGenerate()">
44730
- <p class="config-desc">Describe the email you want to write. The AI will generate professional content and add it as a new block.</p>
44731
- <div class="ai-prompt-examples">
44732
- <span class="ai-example-label">Try:</span>
44733
- @for (ex of aiExamples(); track ex) {
44734
- <ui-chip [label]="ex" size="sm" (select)="aiPrompt.set(ex)" />
44735
- }
44736
- </div>
44737
- <div class="config-field config-field-mt">
44738
- <ui-textarea-input label="What do you want to write?" [rows]="5" placeholder="e.g. A friendly follow-up email for a buyer who attended an open house last weekend" [(ngModel)]="aiPrompt" />
44739
- </div>
44740
- </ui-side-panel>
44741
44691
 
44742
44692
  <!-- Assignment config -->
44743
44693
  <ui-side-panel [wide]="true" [open]="showAssignmentConfig()" [title]="configTarget()?.name || 'Configure Automation'" primaryLabel="Save Configuration"
@@ -44763,7 +44713,7 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44763
44713
  </ui-side-panel>
44764
44714
  `,
44765
44715
  isInline: true,
44766
- styles: [":host{display:block}.required{color:#ef4444;font-weight:400}.editor-page{display:flex;flex-direction:column;height:100vh;height:100dvh;background:#f8fafc;overflow:hidden}.editor-topbar{display:flex;justify-content:space-between;align-items:center;gap:8px;flex-wrap:wrap;padding:12px 24px;background:#fff;border-bottom:1px solid #e2e8f0;flex-shrink:0}.topbar-left{display:flex;align-items:center;gap:8px;min-width:0}.topbar-right{display:flex;align-items:center;gap:8px}.breadcrumb{display:flex;align-items:center;gap:6px;font-size:.9375rem;font-weight:700;color:#1e293b;min-width:0}.breadcrumb a{color:#1e293b;text-decoration:none;cursor:pointer}.breadcrumb a:hover{color:#3b82f6}.breadcrumb svg{color:#94a3b8;flex-shrink:0}.breadcrumb span{color:#64748b;font-weight:500}.readonly-note{margin:0;padding:8px 16px;font-size:.8125rem;color:#92400e;background:#fffbeb;border-bottom:1px solid #fde68a}.readonly-note.system-note{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.editor-body{display:grid;grid-template-columns:340px minmax(0,1fr) 300px;flex:1;min-height:0;overflow:hidden}.panel-left{background:#fff;border-right:1px solid #e2e8f0;padding:24px;overflow-y:auto}.panel-title{font-size:1.0625rem;font-weight:700;color:#1e293b;margin:0 0 20px}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.form-row-dates{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:16px}.assignments-section{border-top:1px solid #e2e8f0;padding-top:20px;margin-top:16px}.section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 6px}.section-desc{font-size:.8125rem;color:#64748b;line-height:1.5;margin:0 0 12px}.assignment-list{max-height:340px;overflow-y:auto;margin-top:12px;border:1px solid #e2e8f0;border-radius:8px}.assignment-item{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 14px;cursor:pointer;border-bottom:1px solid #f1f5f9;transition:background .1s}.assignment-item:last-child{border-bottom:none}.assignment-item:hover{background:#f8fafc}.assignment-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.assignment-item.assignment-readonly{cursor:default}.assignment-item.assignment-readonly:hover{background:transparent}.assignment-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.assignment-text strong{font-size:.8125rem;color:#1e293b}.assignment-text span{font-size:.75rem;color:#64748b}.assignment-channels{display:flex;gap:4px;flex-shrink:0}.channel-badge{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:4px;background:#f1f5f9;color:#94a3b8;transition:all .15s}.channel-badge.active{background:#3b82f6;color:#fff}.channel-badge.disabled{opacity:.4;cursor:not-allowed}.config-desc{font-size:.875rem;color:#64748b;line-height:1.5;margin:0}.config-divider{border:none;border-top:1px solid #e2e8f0;margin:20px 0}.config-section{display:flex;flex-direction:column;gap:12px}.config-section-label{font-size:.6875rem;font-weight:700;color:#3b82f6;text-transform:uppercase;letter-spacing:.04em}.config-field{display:flex;flex-direction:column;gap:6px}.config-field-mt{margin-top:16px}.config-label{font-size:.8125rem;font-weight:600;color:#1e293b}.config-readonly{padding:9px 12px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc;font-size:.875rem;color:#1e293b}.config-hint{font-size:.75rem;color:#64748b}.test-save-note{display:flex;align-items:center;gap:8px;padding:10px 14px;background:#fef3c7;border:1px solid #fcd34d;border-radius:8px;font-size:.8125rem;color:#92400e;margin-top:12px}.test-save-note svg{flex-shrink:0}.ai-prompt-examples{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:12px}.ai-example-label{font-size:.75rem;color:#64748b;font-weight:600}.panel-center{display:flex;flex-direction:column;min-height:0;min-width:0;overflow:hidden}.editor-tabs{display:flex;gap:2px;padding:12px 20px 0;background:#fff;border-bottom:1px solid #e2e8f0;overflow-x:auto;-webkit-overflow-scrolling:touch}.editor-tab{display:flex;align-items:center;gap:6px;padding:10px 16px;border:1px solid #e2e8f0;border-bottom:none;border-radius:8px 8px 0 0;background:#f8fafc;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;white-space:nowrap}.editor-tab:hover{background:#fff;color:#1e293b}.editor-tab.active{background:#eff6ff;color:#3b82f6;border-color:#93c5fd}.editor-tab:focus-visible,.right-tab:focus-visible,.block-group-header:focus-visible,.variable-item:focus-visible,.add-block-btn:focus-visible,.block-item:focus-visible,.video-lib-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.editor-toolbar{display:flex;align-items:center;gap:8px;padding:10px 20px;background:#fff;border-bottom:1px solid #e2e8f0;flex-wrap:wrap}.toolbar-row-2{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 20px;background:#fff;border-bottom:1px solid #e2e8f0}.toolbar-group{display:flex;align-items:center;gap:2px;padding-right:8px;border-right:1px solid #e2e8f0}.toolbar-group:last-child{border-right:none;padding-right:0}.toolbar-select{display:block;min-width:96px}.toolbar-label{font-size:.75rem;font-weight:600;color:#64748b;white-space:nowrap;margin-right:6px}.ai-dot{width:8px;height:8px;border-radius:50%;background:#3b82f6;display:inline-block;margin-right:6px}.hidden-color-input{position:absolute;width:0;height:0;opacity:0;pointer-events:none;border:none;padding:0}.color-indicator{display:flex;flex-direction:column;align-items:center;gap:2px;color:#475569}.color-bar{display:block;width:16px;height:3px;border-radius:2px;border:1px solid rgba(0,0,0,.1)}.link-dialog{background:#fff;border-bottom:1px solid #e2e8f0;padding:12px 20px}.link-dialog-inner{display:flex;align-items:flex-start;gap:8px;flex-wrap:wrap}.link-dialog-title{font-size:.8125rem;font-weight:700;color:#1e293b;white-space:nowrap;padding-top:10px}.link-dialog-input{display:block;width:240px;max-width:100%}.link-dialog-actions{display:flex;gap:6px}.preview-frame{flex:1;display:flex;justify-content:center;padding:24px;overflow-y:auto;background:#f1f5f9}.preview-frame.mobile{align-items:flex-start}.preview-content{max-width:600px;width:100%;box-sizing:border-box;background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:32px;min-height:400px;font-size:.9375rem;line-height:1.6;color:#1e293b;overflow-wrap:anywhere}.preview-content p{margin:0 0 8px}.mobile-shell{width:375px;max-width:100%;box-sizing:border-box;min-height:600px;border:2px solid #1e293b;border-radius:24px;padding:40px 12px 24px;background:#fff;box-shadow:0 8px 32px #0000001f}.mobile-shell .preview-content{border:none;border-radius:0;padding:16px;max-width:100%}.blocks-canvas{flex:1;padding:16px 20px 24px;overflow-y:auto;background:#f1f5f9;display:flex;flex-direction:column}.block-wrapper{position:relative;display:flex;align-items:flex-start;background:#fff;border:2px solid transparent;border-radius:8px;transition:border-color .15s,box-shadow .15s}.block-wrapper:hover,.block-wrapper.selected,.block-wrapper:focus-within{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a}.block-wrapper:hover .block-drag-handle,.block-wrapper.selected .block-drag-handle,.block-wrapper:focus-within .block-drag-handle{opacity:1}.block-wrapper:hover .block-controls,.block-wrapper.selected .block-controls,.block-wrapper:focus-within .block-controls{opacity:1;pointer-events:all}.block-wrapper.dragging{opacity:.4}.block-drag-handle{flex-shrink:0;width:28px;display:flex;align-items:flex-start;justify-content:center;padding-top:14px;opacity:0;transition:opacity .15s;cursor:grab;color:#94a3b8}.block-drag-handle:active{cursor:grabbing}.block-content{flex:1;min-width:0;padding:12px 16px;outline:none;font-size:.9375rem;color:#1e293b;line-height:1.6;min-height:48px;overflow-wrap:anywhere}.block-content:empty:before{content:\"Click to edit...\";color:#94a3b8;font-style:italic;pointer-events:none}.block-content p{margin:0 0 8px}.block-content p:last-child{margin:0}.block-content h1,.block-content h2,.block-content h3{margin:8px 0 6px;color:#1e293b}.block-content a{color:#3b82f6}.block-content img{max-width:100%;border-radius:6px}.block-content ul,.block-content ol{padding-left:20px;margin:0 0 8px}.block-controls{position:absolute;top:6px;right:6px;display:flex;gap:2px;opacity:0;pointer-events:none;transition:opacity .15s;background:#fff;border:1px solid #e2e8f0;border-radius:6px;padding:3px;box-shadow:0 2px 6px #00000014}@media(hover:none){.block-wrapper.selected .block-controls{opacity:1;pointer-events:all}}.drop-zone{height:8px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:height .15s,background .15s;position:relative}.drop-zone-label{font-size:.75rem;font-weight:600;color:#3b82f6;opacity:0;transition:opacity .1s}.drop-zone.active{height:40px;background:#3b82f614;border:2px dashed #3b82f6}.drop-zone.active .drop-zone-label{opacity:1}.add-block-btn{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;min-height:44px;padding:12px;margin-top:8px;border:2px dashed #e2e8f0;border-radius:8px;background:none;font-size:.875rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;transition:border-color .15s,color .15s,background .15s}.add-block-btn:hover{border-color:#3b82f6;color:#3b82f6;background:#3b82f60a}.panel-right{background:#fff;border-left:1px solid #e2e8f0;display:flex;flex-direction:column;min-height:0;min-width:0}.right-tabs{display:flex;border-bottom:1px solid #e2e8f0}.right-tab{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:12px;min-height:44px;border:none;background:none;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;border-bottom:2px solid transparent}.right-tab:hover{color:#1e293b}.right-tab.active{color:#3b82f6;background:#eff6ff;border-bottom-color:#3b82f6}.right-panel-body{flex:1;padding:20px;overflow-y:auto}.right-section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 12px}.right-section-desc{font-size:.8125rem;color:#64748b;margin:0 0 16px;line-height:1.5}.right-section-hint{font-size:.8125rem;color:#64748b;margin:0 0 12px;line-height:1.5}.block-group{border-bottom:1px solid #f1f5f9}.block-group-header{display:flex;align-items:center;gap:8px;width:100%;min-height:44px;padding:12px 0;border:none;background:none;font-size:.875rem;font-weight:600;color:#1e293b;cursor:pointer;font-family:inherit;text-align:left}.block-group-header .chevron{transition:transform .2s;color:#94a3b8}.block-group-header .chevron.expanded{transform:rotate(90deg)}.block-group-header span:nth-of-type(1){flex:1}.block-count{font-size:.75rem;font-weight:600;color:#64748b;background:#f1f5f9;padding:2px 8px;border-radius:10px;margin-left:auto}.block-list,.variable-list{display:flex;flex-direction:column;gap:2px;padding-bottom:8px}.block-item{display:flex;align-items:center;gap:6px;box-sizing:border-box;width:100%;min-height:44px;padding:8px 12px 8px 28px;font-size:.8125rem;color:#64748b;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit;-webkit-user-select:none;user-select:none}.block-item:hover{background:#f8fafc;color:#1e293b}.block-item-drag{color:#cbd5e1;flex-shrink:0;cursor:grab}.variable-item{display:grid;grid-template-columns:auto 1fr auto;gap:8px;align-items:center;min-height:44px;padding:8px 12px 8px 28px;border:none;background:none;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit}.variable-item:hover{background:#f8fafc}.var-tag{font-size:.75rem;font-weight:600;color:#3b82f6;background:#3b82f614;padding:2px 6px;border-radius:4px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.var-label{font-size:.8125rem;color:#1e293b}.var-example{font-size:.75rem;color:#64748b;overflow-wrap:anywhere}.video-library-panel{padding:0}.video-library-panel .right-section-title,.video-library-panel .right-section-hint{padding:0 16px}.video-library-panel .right-section-title{padding-top:16px}.video-config-section{display:flex;flex-direction:column;gap:8px;padding:12px 16px;border-bottom:1px solid #f1f5f9}.video-config-section:last-of-type{border-bottom:none}.video-lib-list{display:flex;flex-direction:column;gap:2px;padding:8px 8px 16px}.video-lib-item{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;padding:8px;border:1px solid transparent;border-radius:8px;background:none;cursor:pointer;text-align:left;font-family:inherit;transition:background .15s,border-color .15s}.video-lib-item:hover{background:#f8fafc;border-color:#e2e8f0}.video-lib-item.selected{background:#eff6ff;border-color:#93c5fd}.vli-thumb{position:relative;flex-shrink:0;width:56px;height:40px;border-radius:6px;background:linear-gradient(135deg,#f1f5f9,#e2e8f0);display:flex;align-items:center;justify-content:center}.vli-dur{position:absolute;bottom:2px;right:3px;font-size:.625rem;font-weight:600;color:#fff;background:#000000a6;padding:1px 4px;border-radius:3px}.vli-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.vli-title{font-size:.8125rem;font-weight:600;color:#1e293b;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vli-cat{font-size:.75rem;color:#64748b}.vli-check{flex-shrink:0}.video-lib-empty{display:flex;flex-direction:column;align-items:center;padding:32px 16px;text-align:center;gap:8px}.video-lib-empty p{font-size:.875rem;font-weight:500;color:#475569;margin:0}.video-lib-empty span{font-size:.8125rem;color:#64748b}.video-lib-loading{padding:8px}.video-lib-skeleton{display:flex;align-items:center;gap:10px;padding:8px;margin-bottom:4px}.vls-info{flex:1;display:flex;flex-direction:column;gap:6px}@media(max-width:1200px){.editor-body{grid-template-columns:280px minmax(0,1fr) 260px}}@media(max-width:900px){.editor-page{height:auto;min-height:100vh;min-height:100dvh;overflow:visible}.editor-body{display:flex;flex-direction:column;overflow:visible}.editor-topbar{padding:12px 16px}.panel-left{border-right:none;border-bottom:1px solid #e2e8f0;overflow:visible;padding:16px}.panel-center{overflow:visible;min-height:480px}.blocks-canvas{overflow:visible;min-height:320px}.panel-right{border-left:none;border-top:1px solid #e2e8f0}.right-panel-body{overflow:visible}.editor-toolbar,.toolbar-row-2,.link-dialog,.editor-tabs{padding-left:12px;padding-right:12px}.preview-frame{padding:12px}.preview-content{padding:16px}.form-row-dates{grid-template-columns:1fr}}@media(prefers-reduced-motion:reduce){*{transition:none!important}}\n"],
44716
+ styles: [":host{display:block}.required{color:#ef4444;font-weight:400}.editor-page{display:flex;flex-direction:column;height:100vh;height:100dvh;background:#f8fafc;overflow:hidden}.editor-actions{display:flex;justify-content:flex-end;align-items:center;gap:8px;flex-wrap:wrap;padding:0 0 12px;flex-shrink:0}.readonly-note{margin:0;padding:8px 16px;font-size:.8125rem;color:#92400e;background:#fffbeb;border-bottom:1px solid #fde68a}.readonly-note.system-note{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.editor-body{display:grid;grid-template-columns:340px minmax(0,1fr) 300px;flex:1;min-height:0;overflow:hidden}.panel-left{background:#fff;border-right:1px solid #e2e8f0;padding:24px;overflow-y:auto}.panel-title{font-size:1.0625rem;font-weight:700;color:#1e293b;margin:0 0 20px}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.form-row-dates{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:16px}.assignments-section{border-top:1px solid #e2e8f0;padding-top:20px;margin-top:16px}.section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 6px}.section-desc{font-size:.8125rem;color:#64748b;line-height:1.5;margin:0 0 12px}.assignment-list{max-height:340px;overflow-y:auto;margin-top:12px;border:1px solid #e2e8f0;border-radius:8px}.assignment-item{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 14px;cursor:pointer;border-bottom:1px solid #f1f5f9;transition:background .1s}.assignment-item:last-child{border-bottom:none}.assignment-item:hover{background:#f8fafc}.assignment-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.assignment-item.assignment-readonly{cursor:default}.assignment-item.assignment-readonly:hover{background:transparent}.assignment-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.assignment-text strong{font-size:.8125rem;color:#1e293b}.assignment-text span{font-size:.75rem;color:#64748b}.assignment-channels{display:flex;gap:4px;flex-shrink:0}.channel-badge{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:4px;background:#f1f5f9;color:#94a3b8;transition:all .15s}.channel-badge.active{background:#3b82f6;color:#fff}.channel-badge.disabled{opacity:.4;cursor:not-allowed}.config-desc{font-size:.875rem;color:#64748b;line-height:1.5;margin:0}.config-divider{border:none;border-top:1px solid #e2e8f0;margin:20px 0}.config-section{display:flex;flex-direction:column;gap:12px}.config-section-label{font-size:.6875rem;font-weight:700;color:#3b82f6;text-transform:uppercase;letter-spacing:.04em}.config-field{display:flex;flex-direction:column;gap:6px}.config-field-mt{margin-top:16px}.config-label{font-size:.8125rem;font-weight:600;color:#1e293b}.config-readonly{padding:9px 12px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc;font-size:.875rem;color:#1e293b}.config-hint{font-size:.75rem;color:#64748b}.test-save-note{display:flex;align-items:center;gap:8px;padding:10px 14px;background:#fef3c7;border:1px solid #fcd34d;border-radius:8px;font-size:.8125rem;color:#92400e;margin-top:12px}.test-save-note svg{flex-shrink:0}.panel-center{display:flex;flex-direction:column;min-height:0;min-width:0;overflow:hidden}.editor-tabs{display:flex;gap:2px;padding:12px 20px 0;background:#fff;border-bottom:1px solid #e2e8f0;overflow-x:auto;-webkit-overflow-scrolling:touch}.editor-tab{display:flex;align-items:center;gap:6px;padding:10px 16px;border:1px solid #e2e8f0;border-bottom:none;border-radius:8px 8px 0 0;background:#f8fafc;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;white-space:nowrap}.editor-tab:hover{background:#fff;color:#1e293b}.editor-tab.active{background:#eff6ff;color:#3b82f6;border-color:#93c5fd}.editor-tab:focus-visible,.right-tab:focus-visible,.block-group-header:focus-visible,.variable-item:focus-visible,.add-block-btn:focus-visible,.block-item:focus-visible,.video-lib-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.editor-toolbar{display:flex;align-items:center;gap:8px;padding:10px 20px;background:#fff;border-bottom:1px solid #e2e8f0;flex-wrap:wrap}.toolbar-row-2{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 20px;background:#fff;border-bottom:1px solid #e2e8f0}.toolbar-group{display:flex;align-items:center;gap:2px;padding-right:8px;border-right:1px solid #e2e8f0}.toolbar-group:last-child{border-right:none;padding-right:0}.toolbar-select{display:block;min-width:96px}.toolbar-label{font-size:.75rem;font-weight:600;color:#64748b;white-space:nowrap;margin-right:6px}.hidden-color-input{position:absolute;width:0;height:0;opacity:0;pointer-events:none;border:none;padding:0}.color-indicator{display:flex;flex-direction:column;align-items:center;gap:2px;color:#475569}.color-bar{display:block;width:16px;height:3px;border-radius:2px;border:1px solid rgba(0,0,0,.1)}.link-dialog{background:#fff;border-bottom:1px solid #e2e8f0;padding:12px 20px}.link-dialog-inner{display:flex;align-items:flex-start;gap:8px;flex-wrap:wrap}.link-dialog-title{font-size:.8125rem;font-weight:700;color:#1e293b;white-space:nowrap;padding-top:10px}.link-dialog-input{display:block;width:240px;max-width:100%}.link-dialog-actions{display:flex;gap:6px}.preview-frame{flex:1;display:flex;justify-content:center;padding:24px;overflow-y:auto;background:#f1f5f9}.preview-frame.mobile{align-items:flex-start}.preview-content{max-width:600px;width:100%;box-sizing:border-box;background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:32px;min-height:400px;font-size:.9375rem;line-height:1.6;color:#1e293b;overflow-wrap:anywhere}.preview-content p{margin:0 0 8px}.mobile-shell{width:375px;max-width:100%;box-sizing:border-box;min-height:600px;border:2px solid #1e293b;border-radius:24px;padding:40px 12px 24px;background:#fff;box-shadow:0 8px 32px #0000001f}.mobile-shell .preview-content{border:none;border-radius:0;padding:16px;max-width:100%}.blocks-canvas{flex:1;padding:16px 20px 24px;overflow-y:auto;background:#f1f5f9;display:flex;flex-direction:column}.block-wrapper{position:relative;display:flex;align-items:flex-start;background:#fff;border:2px solid transparent;border-radius:8px;transition:border-color .15s,box-shadow .15s}.block-wrapper:hover,.block-wrapper.selected,.block-wrapper:focus-within{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a}.block-wrapper:hover .block-drag-handle,.block-wrapper.selected .block-drag-handle,.block-wrapper:focus-within .block-drag-handle{opacity:1}.block-wrapper:hover .block-controls,.block-wrapper.selected .block-controls,.block-wrapper:focus-within .block-controls{opacity:1;pointer-events:all}.block-wrapper.dragging{opacity:.4}.block-drag-handle{flex-shrink:0;width:28px;display:flex;align-items:flex-start;justify-content:center;padding-top:14px;opacity:0;transition:opacity .15s;cursor:grab;color:#94a3b8}.block-drag-handle:active{cursor:grabbing}.block-content{flex:1;min-width:0;padding:12px 16px;outline:none;font-size:.9375rem;color:#1e293b;line-height:1.6;min-height:48px;overflow-wrap:anywhere}.block-content:empty:before{content:\"Click to edit...\";color:#94a3b8;font-style:italic;pointer-events:none}.block-content p{margin:0 0 8px}.block-content p:last-child{margin:0}.block-content h1,.block-content h2,.block-content h3{margin:8px 0 6px;color:#1e293b}.block-content a{color:#3b82f6}.block-content img{max-width:100%;border-radius:6px}.block-content ul,.block-content ol{padding-left:20px;margin:0 0 8px}.block-controls{position:absolute;top:6px;right:6px;display:flex;gap:2px;opacity:0;pointer-events:none;transition:opacity .15s;background:#fff;border:1px solid #e2e8f0;border-radius:6px;padding:3px;box-shadow:0 2px 6px #00000014}@media(hover:none){.block-wrapper.selected .block-controls{opacity:1;pointer-events:all}}.drop-zone{height:8px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:height .15s,background .15s;position:relative}.drop-zone-label{font-size:.75rem;font-weight:600;color:#3b82f6;opacity:0;transition:opacity .1s}.drop-zone.active{height:40px;background:#3b82f614;border:2px dashed #3b82f6}.drop-zone.active .drop-zone-label{opacity:1}.add-block-btn{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;min-height:44px;padding:12px;margin-top:8px;border:2px dashed #e2e8f0;border-radius:8px;background:none;font-size:.875rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;transition:border-color .15s,color .15s,background .15s}.add-block-btn:hover{border-color:#3b82f6;color:#3b82f6;background:#3b82f60a}.panel-right{background:#fff;border-left:1px solid #e2e8f0;display:flex;flex-direction:column;min-height:0;min-width:0}.right-tabs{display:flex;border-bottom:1px solid #e2e8f0}.right-tab{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:12px;min-height:44px;border:none;background:none;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;border-bottom:2px solid transparent}.right-tab:hover{color:#1e293b}.right-tab.active{color:#3b82f6;background:#eff6ff;border-bottom-color:#3b82f6}.right-panel-body{flex:1;padding:20px;overflow-y:auto}.right-section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 12px}.right-section-desc{font-size:.8125rem;color:#64748b;margin:0 0 16px;line-height:1.5}.right-section-hint{font-size:.8125rem;color:#64748b;margin:0 0 12px;line-height:1.5}.block-group{border-bottom:1px solid #f1f5f9}.block-group-header{display:flex;align-items:center;gap:8px;width:100%;min-height:44px;padding:12px 0;border:none;background:none;font-size:.875rem;font-weight:600;color:#1e293b;cursor:pointer;font-family:inherit;text-align:left}.block-group-header .chevron{transition:transform .2s;color:#94a3b8}.block-group-header .chevron.expanded{transform:rotate(90deg)}.block-group-header span:nth-of-type(1){flex:1}.block-count{font-size:.75rem;font-weight:600;color:#64748b;background:#f1f5f9;padding:2px 8px;border-radius:10px;margin-left:auto}.block-list,.variable-list{display:flex;flex-direction:column;gap:2px;padding-bottom:8px}.block-item{display:flex;align-items:center;gap:6px;box-sizing:border-box;width:100%;min-height:44px;padding:8px 12px 8px 28px;font-size:.8125rem;color:#64748b;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit;-webkit-user-select:none;user-select:none}.block-item:hover{background:#f8fafc;color:#1e293b}.block-item-drag{color:#cbd5e1;flex-shrink:0;cursor:grab}.variable-item{display:grid;grid-template-columns:auto 1fr auto;gap:8px;align-items:center;min-height:44px;padding:8px 12px 8px 28px;border:none;background:none;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit}.variable-item:hover{background:#f8fafc}.var-tag{font-size:.75rem;font-weight:600;color:#3b82f6;background:#3b82f614;padding:2px 6px;border-radius:4px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.var-label{font-size:.8125rem;color:#1e293b}.var-example{font-size:.75rem;color:#64748b;overflow-wrap:anywhere}.video-library-panel{padding:0}.video-library-panel .right-section-title,.video-library-panel .right-section-hint{padding:0 16px}.video-library-panel .right-section-title{padding-top:16px}.video-config-section{display:flex;flex-direction:column;gap:8px;padding:12px 16px;border-bottom:1px solid #f1f5f9}.video-config-section:last-of-type{border-bottom:none}.video-lib-list{display:flex;flex-direction:column;gap:2px;padding:8px 8px 16px}.video-lib-item{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;padding:8px;border:1px solid transparent;border-radius:8px;background:none;cursor:pointer;text-align:left;font-family:inherit;transition:background .15s,border-color .15s}.video-lib-item:hover{background:#f8fafc;border-color:#e2e8f0}.video-lib-item.selected{background:#eff6ff;border-color:#93c5fd}.vli-thumb{position:relative;flex-shrink:0;width:56px;height:40px;border-radius:6px;background:linear-gradient(135deg,#f1f5f9,#e2e8f0);display:flex;align-items:center;justify-content:center}.vli-dur{position:absolute;bottom:2px;right:3px;font-size:.625rem;font-weight:600;color:#fff;background:#000000a6;padding:1px 4px;border-radius:3px}.vli-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.vli-title{font-size:.8125rem;font-weight:600;color:#1e293b;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vli-cat{font-size:.75rem;color:#64748b}.vli-check{flex-shrink:0}.video-lib-loading{padding:8px}.video-lib-skeleton{display:flex;align-items:center;gap:10px;padding:8px;margin-bottom:4px}.vls-info{flex:1;display:flex;flex-direction:column;gap:6px}@media(max-width:1200px){.editor-body{grid-template-columns:280px minmax(0,1fr) 260px}}@media(max-width:900px){.editor-page{height:auto;min-height:100vh;min-height:100dvh;overflow:visible}.editor-body{display:flex;flex-direction:column;overflow:visible}.panel-left{border-right:none;border-bottom:1px solid #e2e8f0;overflow:visible;padding:16px}.panel-center{overflow:visible;min-height:480px}.blocks-canvas{overflow:visible;min-height:320px}.panel-right{border-left:none;border-top:1px solid #e2e8f0}.right-panel-body{overflow:visible}.editor-toolbar,.toolbar-row-2,.link-dialog,.editor-tabs{padding-left:12px;padding-right:12px}.preview-frame{padding:12px}.preview-content{padding:16px}.form-row-dates{grid-template-columns:1fr}}@media(prefers-reduced-motion:reduce){*{transition:none!important}}\n"],
44767
44717
  dependencies: [
44768
44718
  {
44769
44719
  kind: "ngmodule",
@@ -44860,18 +44810,6 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44860
44810
  "invalidChange"
44861
44811
  ]
44862
44812
  },
44863
- {
44864
- kind: "component",
44865
- type: ChipComponent,
44866
- selector: "ui-chip",
44867
- inputs: [
44868
- "label",
44869
- "size",
44870
- "dismissible",
44871
- "active"
44872
- ],
44873
- outputs: ["select", "dismiss"]
44874
- },
44875
44813
  {
44876
44814
  kind: "component",
44877
44815
  type: DateInputComponent,
@@ -44888,6 +44826,26 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
44888
44826
  ],
44889
44827
  outputs: ["invalidChange", "valueChange"]
44890
44828
  },
44829
+ {
44830
+ kind: "component",
44831
+ type: DividerComponent,
44832
+ selector: "ui-divider",
44833
+ inputs: [
44834
+ "spaceAbove",
44835
+ "spaceBelow",
44836
+ "decorative"
44837
+ ]
44838
+ },
44839
+ {
44840
+ kind: "component",
44841
+ type: EmptyStateComponent,
44842
+ selector: "ui-empty-state",
44843
+ inputs: [
44844
+ "message",
44845
+ "title",
44846
+ "iconType"
44847
+ ]
44848
+ },
44891
44849
  {
44892
44850
  kind: "component",
44893
44851
  type: ErrorComponent,
@@ -45020,27 +44978,6 @@ var EmailTemplateEditorComponent = class EmailTemplateEditorComponent {
45020
44978
  "invalidChange"
45021
44979
  ]
45022
44980
  },
45023
- {
45024
- kind: "component",
45025
- type: TextareaInputComponent,
45026
- selector: "ui-textarea-input",
45027
- inputs: [
45028
- "label",
45029
- "ariaLabel",
45030
- "placeholder",
45031
- "rows",
45032
- "maxlength",
45033
- "required",
45034
- "readonly",
45035
- "hint",
45036
- "hintAsDescription",
45037
- "error",
45038
- "monospace",
45039
- "showErrors",
45040
- "disabled"
45041
- ],
45042
- outputs: ["invalidChange"]
45043
- },
45044
44981
  {
45045
44982
  kind: "directive",
45046
44983
  type: TooltipDirective,
@@ -45067,8 +45004,9 @@ i0.ɵɵngDeclareClassMetadata({
45067
45004
  FormsModule,
45068
45005
  ButtonComponent,
45069
45006
  CheckboxComponent,
45070
- ChipComponent,
45071
45007
  DateInputComponent,
45008
+ DividerComponent,
45009
+ EmptyStateComponent,
45072
45010
  ErrorComponent,
45073
45011
  RadioGroupComponent,
45074
45012
  SearchInputComponent,
@@ -45076,36 +45014,24 @@ i0.ɵɵngDeclareClassMetadata({
45076
45014
  SidePanelComponent,
45077
45015
  SkeletonComponent,
45078
45016
  TextInputComponent,
45079
- TextareaInputComponent,
45080
45017
  TooltipDirective
45081
45018
  ],
45082
45019
  template: `
45083
45020
  <div class="editor-page">
45084
- <!-- Top Bar -->
45085
- <div class="editor-topbar">
45086
- <div class="topbar-left">
45087
- <ui-button variant="ghost" size="sm" ariaLabel="Go back" (click)="back.emit()">
45088
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M15 18l-6-6 6-6"/></svg>
45089
- </ui-button>
45090
- <nav class="breadcrumb" aria-label="Breadcrumb">
45091
- <a href="#" (click)="$event.preventDefault(); back.emit()">{{ backLabel() }}</a>
45092
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M9 18l6-6-6-6"/></svg>
45093
- <span>{{ isNew() ? createLabel() : editLabel() }}</span>
45094
- </nav>
45095
- </div>
45096
- <div class="topbar-right">
45097
- @if (canWrite() && testSendEnabled()) {
45098
- <ui-button variant="secondary" size="sm" (click)="openTestSendDialog()">
45099
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
45100
- Test Send
45101
- </ui-button>
45102
- }
45103
- <ui-button variant="primary" size="sm" [loading]="saving()" [disabled]="saveDisabled()" (click)="onSave()">
45104
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg>
45105
- Save Template
45021
+ <!-- Actions (outside the white panels) -->
45022
+ <div class="editor-actions">
45023
+ @if (canWrite() && testSendEnabled()) {
45024
+ <ui-button variant="secondary" size="sm" (click)="openTestSendDialog()">
45025
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
45026
+ Test Send
45106
45027
  </ui-button>
45107
- </div>
45028
+ }
45029
+ <ui-button variant="primary" size="sm" [loading]="saving()" [disabled]="saveDisabled()" (click)="onSave()">
45030
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg>
45031
+ Save Template
45032
+ </ui-button>
45108
45033
  </div>
45034
+ <ui-divider />
45109
45035
 
45110
45036
  @if (systemTemplate()) {
45111
45037
  <div class="readonly-note system-note" role="note" data-testid="editor-system-note">
@@ -45126,15 +45052,12 @@ i0.ɵɵngDeclareClassMetadata({
45126
45052
 
45127
45053
  <div class="form-field">
45128
45054
  <ui-text-input label="Name" [required]="true" [(ngModel)]="name" [readonly]="!canWrite()" [maxlength]="maxTextLength()"
45129
- [placeholder]="namePlaceholder()" [error]="nameError()" />
45055
+ [placeholder]="namePlaceholder()" [error]="nameErrorShown()" (blurred)="nameTouched.set(true)" />
45130
45056
  </div>
45131
45057
 
45132
45058
  <div class="form-field">
45133
45059
  <ui-text-input label="Subject" [required]="true" [(ngModel)]="subject" [readonly]="!canWrite()" [maxlength]="maxTextLength()"
45134
- [placeholder]="subjectPlaceholder()" [error]="subjectError()">
45135
- @if (canWrite()) {
45136
- <span uiLabelEnd><ng-content select="[uiSubjectAction]" /></span>
45137
- }
45060
+ [placeholder]="subjectPlaceholder()" [error]="subjectErrorShown()" (blurred)="subjectTouched.set(true)">
45138
45061
  </ui-text-input>
45139
45062
  </div>
45140
45063
 
@@ -45157,7 +45080,10 @@ i0.ɵɵngDeclareClassMetadata({
45157
45080
  <h4 class="section-title">Assignments</h4>
45158
45081
  <p class="section-desc">{{ assignmentsDescription() }}</p>
45159
45082
  <ui-search-input placeholder="Search..." ariaLabel="Search assignments" [(value)]="assignmentSearch" />
45160
- <div class="assignment-list">
45083
+ @if (filteredAssignments().length === 0) {
45084
+ <ui-empty-state iconType="search" title="No assignments found" message="No assignments match your search." />
45085
+ }
45086
+ <div class="assignment-list" [hidden]="filteredAssignments().length === 0">
45161
45087
  @for (item of filteredAssignments(); track item.key) {
45162
45088
  <div class="assignment-item" [class.assignment-readonly]="!canWrite()" [attr.role]="canWrite() ? 'button' : null" [attr.tabindex]="canWrite() ? 0 : null"
45163
45089
  [attr.aria-label]="canWrite() ? 'Configure ' + item.name : null"
@@ -45203,9 +45129,9 @@ i0.ɵɵngDeclareClassMetadata({
45203
45129
  <!-- Toolbar row 1: mousedown preventDefault keeps focus (and the selection) in the editor -->
45204
45130
  <div class="editor-toolbar" role="toolbar" aria-label="Text formatting" (mousedown)="preventFocusLoss($event)">
45205
45131
  <div class="toolbar-group">
45206
- <ui-button variant="icon" size="sm" ariaLabel="Bold" uiTooltip="Bold" (click)="execCommand('bold')"><strong>B</strong></ui-button>
45207
- <ui-button variant="icon" size="sm" ariaLabel="Italic" uiTooltip="Italic" (click)="execCommand('italic')"><em>I</em></ui-button>
45208
- <ui-button variant="icon" size="sm" ariaLabel="Underline" uiTooltip="Underline" (click)="execCommand('underline')"><u>U</u></ui-button>
45132
+ <ui-button variant="ghost" size="sm" ariaLabel="Bold" uiTooltip="Bold" (click)="execCommand('bold')"><strong>B</strong></ui-button>
45133
+ <ui-button variant="ghost" size="sm" ariaLabel="Italic" uiTooltip="Italic" (click)="execCommand('italic')"><em>I</em></ui-button>
45134
+ <ui-button variant="ghost" size="sm" ariaLabel="Underline" uiTooltip="Underline" (click)="execCommand('underline')"><u>U</u></ui-button>
45209
45135
  </div>
45210
45136
  <div class="toolbar-group">
45211
45137
  @for (k of [headingKey()]; track k) {
@@ -45220,28 +45146,28 @@ i0.ɵɵngDeclareClassMetadata({
45220
45146
  }
45221
45147
  </div>
45222
45148
  <div class="toolbar-group">
45223
- <ui-button variant="icon" size="sm" ariaLabel="Align left" uiTooltip="Align Left" (click)="execCommand('justifyLeft')">
45149
+ <ui-button variant="ghost" size="sm" ariaLabel="Align left" uiTooltip="Align Left" (click)="execCommand('justifyLeft')">
45224
45150
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="17" y1="10" x2="3" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="17" y1="18" x2="3" y2="18"/></svg>
45225
45151
  </ui-button>
45226
- <ui-button variant="icon" size="sm" ariaLabel="Align center" uiTooltip="Align Center" (click)="execCommand('justifyCenter')">
45152
+ <ui-button variant="ghost" size="sm" ariaLabel="Align center" uiTooltip="Align Center" (click)="execCommand('justifyCenter')">
45227
45153
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="18" y1="10" x2="6" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="18" y1="18" x2="6" y2="18"/></svg>
45228
45154
  </ui-button>
45229
- <ui-button variant="icon" size="sm" ariaLabel="Align right" uiTooltip="Align Right" (click)="execCommand('justifyRight')">
45155
+ <ui-button variant="ghost" size="sm" ariaLabel="Align right" uiTooltip="Align Right" (click)="execCommand('justifyRight')">
45230
45156
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="21" y1="10" x2="7" y2="10"/><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="14" x2="3" y2="14"/><line x1="21" y1="18" x2="7" y2="18"/></svg>
45231
45157
  </ui-button>
45232
45158
  </div>
45233
45159
  <div class="toolbar-group">
45234
- <ui-button variant="icon" size="sm" ariaLabel="Bulleted list" uiTooltip="Bulleted List" (click)="execCommand('insertUnorderedList')">
45160
+ <ui-button variant="ghost" size="sm" ariaLabel="Bulleted list" uiTooltip="Bulleted List" (click)="execCommand('insertUnorderedList')">
45235
45161
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>
45236
45162
  </ui-button>
45237
- <ui-button variant="icon" size="sm" ariaLabel="Numbered list" uiTooltip="Numbered List" (click)="execCommand('insertOrderedList')">
45163
+ <ui-button variant="ghost" size="sm" ariaLabel="Numbered list" uiTooltip="Numbered List" (click)="execCommand('insertOrderedList')">
45238
45164
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-1.5-2-1"/></svg>
45239
45165
  </ui-button>
45240
45166
  </div>
45241
45167
  <div class="toolbar-group">
45242
45168
  <!-- The browser's own colour dialog is the picker; a button opens it so the toolbar keeps one look. -->
45243
45169
  <input #colorInput type="color" class="hidden-color-input" aria-label="Text color" tabindex="-1" [value]="currentColor()" (change)="applyTextColor($any($event.target).value)" (mousedown)="$event.stopPropagation()" />
45244
- <ui-button variant="icon" size="sm" ariaLabel="Text color" uiTooltip="Text Color" (mousedown)="openColorPicker()">
45170
+ <ui-button variant="ghost" size="sm" ariaLabel="Text color" uiTooltip="Text Color" (mousedown)="openColorPicker()">
45245
45171
  <span class="color-indicator">
45246
45172
  <svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><text y="20" font-size="20" font-weight="700">A</text></svg>
45247
45173
  <span class="color-bar" [style.background]="currentColor()"></span>
@@ -45249,35 +45175,29 @@ i0.ɵɵngDeclareClassMetadata({
45249
45175
  </ui-button>
45250
45176
  </div>
45251
45177
  <div class="toolbar-group">
45252
- <ui-button variant="icon" size="sm" ariaLabel="Insert link" uiTooltip="Insert Link" (mousedown)="saveSelection()" (click)="openLinkDialog()">
45178
+ <ui-button variant="ghost" size="sm" ariaLabel="Insert link" uiTooltip="Insert Link" (mousedown)="saveSelection()" (click)="openLinkDialog()">
45253
45179
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>
45254
45180
  </ui-button>
45255
- <ui-button variant="icon" size="sm" ariaLabel="Insert image" uiTooltip="Insert Image" (mousedown)="saveSelection()" (click)="openImageDialog()">
45181
+ <ui-button variant="ghost" size="sm" ariaLabel="Insert image" uiTooltip="Insert Image" (mousedown)="saveSelection()" (click)="openImageDialog()">
45256
45182
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>
45257
45183
  </ui-button>
45258
45184
  </div>
45259
45185
  <div class="toolbar-group">
45260
- <ui-button variant="icon" size="sm" ariaLabel="Undo" uiTooltip="Undo" (click)="execCommand('undo')">
45186
+ <ui-button variant="ghost" size="sm" ariaLabel="Undo" uiTooltip="Undo" (click)="execCommand('undo')">
45261
45187
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M3 7v6h6"/><path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6.69 3L3 13"/></svg>
45262
45188
  </ui-button>
45263
- <ui-button variant="icon" size="sm" ariaLabel="Redo" uiTooltip="Redo" (click)="execCommand('redo')">
45189
+ <ui-button variant="ghost" size="sm" ariaLabel="Redo" uiTooltip="Redo" (click)="execCommand('redo')">
45264
45190
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><path d="M21 7v6h-6"/><path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6.69 3L21 13"/></svg>
45265
45191
  </ui-button>
45266
45192
  </div>
45267
45193
  </div>
45268
45194
 
45269
- <!-- Toolbar row 2: block spacing + AI -->
45195
+ <!-- Toolbar row 2: block spacing -->
45270
45196
  <div class="toolbar-row-2">
45271
45197
  <div class="toolbar-group" (mousedown)="preventFocusLoss($event)">
45272
45198
  <span class="toolbar-label" id="tpl-spacing-label">Block spacing</span>
45273
45199
  <ui-select class="toolbar-select" size="sm" ariaLabel="Block spacing" [options]="spacingOptions" [ngModel]="blockSpacing()" (ngModelChange)="applySpacing($event)" />
45274
45200
  </div>
45275
- @if (aiEnabled()) {
45276
- <ui-button variant="secondary" size="sm" (click)="openAiPanel()">
45277
- <span class="ai-dot" aria-hidden="true"></span>
45278
- Generate with AI
45279
- </ui-button>
45280
- }
45281
45201
  </div>
45282
45202
  }
45283
45203
 
@@ -45313,7 +45233,7 @@ i0.ɵɵngDeclareClassMetadata({
45313
45233
  </div>
45314
45234
  }
45315
45235
 
45316
- <ui-error [errorId]="idPrefix() + '-body-error'" [message]="bodyError()" />
45236
+ <ui-error [errorId]="idPrefix() + '-body-error'" [message]="bodyErrorShown()" />
45317
45237
 
45318
45238
  <!-- Block Canvas with DnD -->
45319
45239
  <div class="blocks-canvas" (dragover)="onCanvasDragOver($event)" (drop)="onDropZoneDrop($event, blocks().length)">
@@ -45338,16 +45258,16 @@ i0.ɵɵngDeclareClassMetadata({
45338
45258
 
45339
45259
  @if (canWrite()) {
45340
45260
  <div class="block-controls">
45341
- <ui-button variant="icon" size="xs" ariaLabel="Move block up" uiTooltip="Move up" [disabled]="i === 0" (mousedown)="preventFocusLoss($event)" (click)="moveBlock(i, -1)">
45261
+ <ui-button variant="ghost" size="xs" ariaLabel="Move block up" uiTooltip="Move up" [disabled]="i === 0" (mousedown)="preventFocusLoss($event)" (click)="moveBlock(i, -1)">
45342
45262
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M18 15l-6-6-6 6"/></svg>
45343
45263
  </ui-button>
45344
- <ui-button variant="icon" size="xs" ariaLabel="Move block down" uiTooltip="Move down" [disabled]="i === blocks().length - 1" (mousedown)="preventFocusLoss($event)" (click)="moveBlock(i, 1)">
45264
+ <ui-button variant="ghost" size="xs" ariaLabel="Move block down" uiTooltip="Move down" [disabled]="i === blocks().length - 1" (mousedown)="preventFocusLoss($event)" (click)="moveBlock(i, 1)">
45345
45265
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg>
45346
45266
  </ui-button>
45347
- <ui-button variant="icon" size="xs" ariaLabel="Duplicate block" uiTooltip="Duplicate" (mousedown)="preventFocusLoss($event)" (click)="duplicateBlock(i)">
45267
+ <ui-button variant="ghost" size="xs" ariaLabel="Duplicate block" uiTooltip="Duplicate" (mousedown)="preventFocusLoss($event)" (click)="duplicateBlock(i)">
45348
45268
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
45349
45269
  </ui-button>
45350
- <ui-button variant="icon-danger" size="xs" ariaLabel="Delete block" uiTooltip="Delete block" (mousedown)="preventFocusLoss($event)" (click)="deleteBlock(i)">
45270
+ <ui-button variant="ghost" size="xs" ariaLabel="Delete block" uiTooltip="Delete block" (mousedown)="preventFocusLoss($event)" (click)="deleteBlock(i)">
45351
45271
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6M14 11v6"/></svg>
45352
45272
  </ui-button>
45353
45273
  </div>
@@ -45415,6 +45335,9 @@ i0.ɵɵngDeclareClassMetadata({
45415
45335
  <p class="right-section-desc">Click to insert or drag into the editor.</p>
45416
45336
  <ui-search-input placeholder="Search blocks..." ariaLabel="Search blocks" [(value)]="blockSearch" />
45417
45337
 
45338
+ @if (filteredBlockGroups().length === 0) {
45339
+ <ui-empty-state iconType="search" title="No blocks found" message="No blocks match your search." />
45340
+ }
45418
45341
  @for (group of filteredBlockGroups(); track group.name) {
45419
45342
  <div class="block-group">
45420
45343
  <button type="button" class="block-group-header" [attr.aria-expanded]="isOpen('b:' + group.name)" (click)="toggleGroup('b:' + group.name)">
@@ -45499,15 +45422,11 @@ i0.ɵɵngDeclareClassMetadata({
45499
45422
  </div>
45500
45423
  }
45501
45424
  </div>
45502
- } @else if (videos().length === 0) {
45503
- <div class="video-lib-empty">
45504
- <svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" stroke-width="1.5" aria-hidden="true"><polygon points="23 7 16 12 23 17 23 7"/><rect x="1" y="5" width="15" height="14" rx="2" ry="2"/></svg>
45505
- <p>No videos yet</p>
45506
- <span>{{ noVideosHint() }}</span>
45507
- </div>
45425
+ } @else if (videoList().length === 0) {
45426
+ <ui-empty-state iconType="video" title="No videos created" [message]="noVideosHint()" />
45508
45427
  } @else {
45509
45428
  <div class="video-lib-list">
45510
- @for (video of videos(); track video.id) {
45429
+ @for (video of videoList(); track video.id) {
45511
45430
  <button type="button" class="video-lib-item" [class.selected]="video.id === videoId()" [attr.aria-pressed]="video.id === videoId()" (click)="insertVideo(video)">
45512
45431
  <span class="vli-thumb">
45513
45432
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" stroke-width="1.5" aria-hidden="true"><polygon points="5 3 19 12 5 21 5 3"/></svg>
@@ -45553,20 +45472,6 @@ i0.ɵɵngDeclareClassMetadata({
45553
45472
  }
45554
45473
  </ui-side-panel>
45555
45474
 
45556
- <!-- AI Generate -->
45557
- <ui-side-panel [open]="showAiPanel()" title="Generate with AI" primaryLabel="Generate" [primaryLoading]="aiGenerating()" [primaryDisabled]="!canGenerate()"
45558
- (closed)="showAiPanel.set(false)" (primaryClick)="onAiGenerate()">
45559
- <p class="config-desc">Describe the email you want to write. The AI will generate professional content and add it as a new block.</p>
45560
- <div class="ai-prompt-examples">
45561
- <span class="ai-example-label">Try:</span>
45562
- @for (ex of aiExamples(); track ex) {
45563
- <ui-chip [label]="ex" size="sm" (select)="aiPrompt.set(ex)" />
45564
- }
45565
- </div>
45566
- <div class="config-field config-field-mt">
45567
- <ui-textarea-input label="What do you want to write?" [rows]="5" placeholder="e.g. A friendly follow-up email for a buyer who attended an open house last weekend" [(ngModel)]="aiPrompt" />
45568
- </div>
45569
- </ui-side-panel>
45570
45475
 
45571
45476
  <!-- Assignment config -->
45572
45477
  <ui-side-panel [wide]="true" [open]="showAssignmentConfig()" [title]="configTarget()?.name || 'Configure Automation'" primaryLabel="Save Configuration"
@@ -45591,7 +45496,7 @@ i0.ɵɵngDeclareClassMetadata({
45591
45496
  }
45592
45497
  </ui-side-panel>
45593
45498
  `,
45594
- styles: [":host{display:block}.required{color:#ef4444;font-weight:400}.editor-page{display:flex;flex-direction:column;height:100vh;height:100dvh;background:#f8fafc;overflow:hidden}.editor-topbar{display:flex;justify-content:space-between;align-items:center;gap:8px;flex-wrap:wrap;padding:12px 24px;background:#fff;border-bottom:1px solid #e2e8f0;flex-shrink:0}.topbar-left{display:flex;align-items:center;gap:8px;min-width:0}.topbar-right{display:flex;align-items:center;gap:8px}.breadcrumb{display:flex;align-items:center;gap:6px;font-size:.9375rem;font-weight:700;color:#1e293b;min-width:0}.breadcrumb a{color:#1e293b;text-decoration:none;cursor:pointer}.breadcrumb a:hover{color:#3b82f6}.breadcrumb svg{color:#94a3b8;flex-shrink:0}.breadcrumb span{color:#64748b;font-weight:500}.readonly-note{margin:0;padding:8px 16px;font-size:.8125rem;color:#92400e;background:#fffbeb;border-bottom:1px solid #fde68a}.readonly-note.system-note{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.editor-body{display:grid;grid-template-columns:340px minmax(0,1fr) 300px;flex:1;min-height:0;overflow:hidden}.panel-left{background:#fff;border-right:1px solid #e2e8f0;padding:24px;overflow-y:auto}.panel-title{font-size:1.0625rem;font-weight:700;color:#1e293b;margin:0 0 20px}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.form-row-dates{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:16px}.assignments-section{border-top:1px solid #e2e8f0;padding-top:20px;margin-top:16px}.section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 6px}.section-desc{font-size:.8125rem;color:#64748b;line-height:1.5;margin:0 0 12px}.assignment-list{max-height:340px;overflow-y:auto;margin-top:12px;border:1px solid #e2e8f0;border-radius:8px}.assignment-item{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 14px;cursor:pointer;border-bottom:1px solid #f1f5f9;transition:background .1s}.assignment-item:last-child{border-bottom:none}.assignment-item:hover{background:#f8fafc}.assignment-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.assignment-item.assignment-readonly{cursor:default}.assignment-item.assignment-readonly:hover{background:transparent}.assignment-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.assignment-text strong{font-size:.8125rem;color:#1e293b}.assignment-text span{font-size:.75rem;color:#64748b}.assignment-channels{display:flex;gap:4px;flex-shrink:0}.channel-badge{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:4px;background:#f1f5f9;color:#94a3b8;transition:all .15s}.channel-badge.active{background:#3b82f6;color:#fff}.channel-badge.disabled{opacity:.4;cursor:not-allowed}.config-desc{font-size:.875rem;color:#64748b;line-height:1.5;margin:0}.config-divider{border:none;border-top:1px solid #e2e8f0;margin:20px 0}.config-section{display:flex;flex-direction:column;gap:12px}.config-section-label{font-size:.6875rem;font-weight:700;color:#3b82f6;text-transform:uppercase;letter-spacing:.04em}.config-field{display:flex;flex-direction:column;gap:6px}.config-field-mt{margin-top:16px}.config-label{font-size:.8125rem;font-weight:600;color:#1e293b}.config-readonly{padding:9px 12px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc;font-size:.875rem;color:#1e293b}.config-hint{font-size:.75rem;color:#64748b}.test-save-note{display:flex;align-items:center;gap:8px;padding:10px 14px;background:#fef3c7;border:1px solid #fcd34d;border-radius:8px;font-size:.8125rem;color:#92400e;margin-top:12px}.test-save-note svg{flex-shrink:0}.ai-prompt-examples{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:12px}.ai-example-label{font-size:.75rem;color:#64748b;font-weight:600}.panel-center{display:flex;flex-direction:column;min-height:0;min-width:0;overflow:hidden}.editor-tabs{display:flex;gap:2px;padding:12px 20px 0;background:#fff;border-bottom:1px solid #e2e8f0;overflow-x:auto;-webkit-overflow-scrolling:touch}.editor-tab{display:flex;align-items:center;gap:6px;padding:10px 16px;border:1px solid #e2e8f0;border-bottom:none;border-radius:8px 8px 0 0;background:#f8fafc;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;white-space:nowrap}.editor-tab:hover{background:#fff;color:#1e293b}.editor-tab.active{background:#eff6ff;color:#3b82f6;border-color:#93c5fd}.editor-tab:focus-visible,.right-tab:focus-visible,.block-group-header:focus-visible,.variable-item:focus-visible,.add-block-btn:focus-visible,.block-item:focus-visible,.video-lib-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.editor-toolbar{display:flex;align-items:center;gap:8px;padding:10px 20px;background:#fff;border-bottom:1px solid #e2e8f0;flex-wrap:wrap}.toolbar-row-2{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 20px;background:#fff;border-bottom:1px solid #e2e8f0}.toolbar-group{display:flex;align-items:center;gap:2px;padding-right:8px;border-right:1px solid #e2e8f0}.toolbar-group:last-child{border-right:none;padding-right:0}.toolbar-select{display:block;min-width:96px}.toolbar-label{font-size:.75rem;font-weight:600;color:#64748b;white-space:nowrap;margin-right:6px}.ai-dot{width:8px;height:8px;border-radius:50%;background:#3b82f6;display:inline-block;margin-right:6px}.hidden-color-input{position:absolute;width:0;height:0;opacity:0;pointer-events:none;border:none;padding:0}.color-indicator{display:flex;flex-direction:column;align-items:center;gap:2px;color:#475569}.color-bar{display:block;width:16px;height:3px;border-radius:2px;border:1px solid rgba(0,0,0,.1)}.link-dialog{background:#fff;border-bottom:1px solid #e2e8f0;padding:12px 20px}.link-dialog-inner{display:flex;align-items:flex-start;gap:8px;flex-wrap:wrap}.link-dialog-title{font-size:.8125rem;font-weight:700;color:#1e293b;white-space:nowrap;padding-top:10px}.link-dialog-input{display:block;width:240px;max-width:100%}.link-dialog-actions{display:flex;gap:6px}.preview-frame{flex:1;display:flex;justify-content:center;padding:24px;overflow-y:auto;background:#f1f5f9}.preview-frame.mobile{align-items:flex-start}.preview-content{max-width:600px;width:100%;box-sizing:border-box;background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:32px;min-height:400px;font-size:.9375rem;line-height:1.6;color:#1e293b;overflow-wrap:anywhere}.preview-content p{margin:0 0 8px}.mobile-shell{width:375px;max-width:100%;box-sizing:border-box;min-height:600px;border:2px solid #1e293b;border-radius:24px;padding:40px 12px 24px;background:#fff;box-shadow:0 8px 32px #0000001f}.mobile-shell .preview-content{border:none;border-radius:0;padding:16px;max-width:100%}.blocks-canvas{flex:1;padding:16px 20px 24px;overflow-y:auto;background:#f1f5f9;display:flex;flex-direction:column}.block-wrapper{position:relative;display:flex;align-items:flex-start;background:#fff;border:2px solid transparent;border-radius:8px;transition:border-color .15s,box-shadow .15s}.block-wrapper:hover,.block-wrapper.selected,.block-wrapper:focus-within{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a}.block-wrapper:hover .block-drag-handle,.block-wrapper.selected .block-drag-handle,.block-wrapper:focus-within .block-drag-handle{opacity:1}.block-wrapper:hover .block-controls,.block-wrapper.selected .block-controls,.block-wrapper:focus-within .block-controls{opacity:1;pointer-events:all}.block-wrapper.dragging{opacity:.4}.block-drag-handle{flex-shrink:0;width:28px;display:flex;align-items:flex-start;justify-content:center;padding-top:14px;opacity:0;transition:opacity .15s;cursor:grab;color:#94a3b8}.block-drag-handle:active{cursor:grabbing}.block-content{flex:1;min-width:0;padding:12px 16px;outline:none;font-size:.9375rem;color:#1e293b;line-height:1.6;min-height:48px;overflow-wrap:anywhere}.block-content:empty:before{content:\"Click to edit...\";color:#94a3b8;font-style:italic;pointer-events:none}.block-content p{margin:0 0 8px}.block-content p:last-child{margin:0}.block-content h1,.block-content h2,.block-content h3{margin:8px 0 6px;color:#1e293b}.block-content a{color:#3b82f6}.block-content img{max-width:100%;border-radius:6px}.block-content ul,.block-content ol{padding-left:20px;margin:0 0 8px}.block-controls{position:absolute;top:6px;right:6px;display:flex;gap:2px;opacity:0;pointer-events:none;transition:opacity .15s;background:#fff;border:1px solid #e2e8f0;border-radius:6px;padding:3px;box-shadow:0 2px 6px #00000014}@media(hover:none){.block-wrapper.selected .block-controls{opacity:1;pointer-events:all}}.drop-zone{height:8px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:height .15s,background .15s;position:relative}.drop-zone-label{font-size:.75rem;font-weight:600;color:#3b82f6;opacity:0;transition:opacity .1s}.drop-zone.active{height:40px;background:#3b82f614;border:2px dashed #3b82f6}.drop-zone.active .drop-zone-label{opacity:1}.add-block-btn{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;min-height:44px;padding:12px;margin-top:8px;border:2px dashed #e2e8f0;border-radius:8px;background:none;font-size:.875rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;transition:border-color .15s,color .15s,background .15s}.add-block-btn:hover{border-color:#3b82f6;color:#3b82f6;background:#3b82f60a}.panel-right{background:#fff;border-left:1px solid #e2e8f0;display:flex;flex-direction:column;min-height:0;min-width:0}.right-tabs{display:flex;border-bottom:1px solid #e2e8f0}.right-tab{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:12px;min-height:44px;border:none;background:none;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;border-bottom:2px solid transparent}.right-tab:hover{color:#1e293b}.right-tab.active{color:#3b82f6;background:#eff6ff;border-bottom-color:#3b82f6}.right-panel-body{flex:1;padding:20px;overflow-y:auto}.right-section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 12px}.right-section-desc{font-size:.8125rem;color:#64748b;margin:0 0 16px;line-height:1.5}.right-section-hint{font-size:.8125rem;color:#64748b;margin:0 0 12px;line-height:1.5}.block-group{border-bottom:1px solid #f1f5f9}.block-group-header{display:flex;align-items:center;gap:8px;width:100%;min-height:44px;padding:12px 0;border:none;background:none;font-size:.875rem;font-weight:600;color:#1e293b;cursor:pointer;font-family:inherit;text-align:left}.block-group-header .chevron{transition:transform .2s;color:#94a3b8}.block-group-header .chevron.expanded{transform:rotate(90deg)}.block-group-header span:nth-of-type(1){flex:1}.block-count{font-size:.75rem;font-weight:600;color:#64748b;background:#f1f5f9;padding:2px 8px;border-radius:10px;margin-left:auto}.block-list,.variable-list{display:flex;flex-direction:column;gap:2px;padding-bottom:8px}.block-item{display:flex;align-items:center;gap:6px;box-sizing:border-box;width:100%;min-height:44px;padding:8px 12px 8px 28px;font-size:.8125rem;color:#64748b;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit;-webkit-user-select:none;user-select:none}.block-item:hover{background:#f8fafc;color:#1e293b}.block-item-drag{color:#cbd5e1;flex-shrink:0;cursor:grab}.variable-item{display:grid;grid-template-columns:auto 1fr auto;gap:8px;align-items:center;min-height:44px;padding:8px 12px 8px 28px;border:none;background:none;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit}.variable-item:hover{background:#f8fafc}.var-tag{font-size:.75rem;font-weight:600;color:#3b82f6;background:#3b82f614;padding:2px 6px;border-radius:4px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.var-label{font-size:.8125rem;color:#1e293b}.var-example{font-size:.75rem;color:#64748b;overflow-wrap:anywhere}.video-library-panel{padding:0}.video-library-panel .right-section-title,.video-library-panel .right-section-hint{padding:0 16px}.video-library-panel .right-section-title{padding-top:16px}.video-config-section{display:flex;flex-direction:column;gap:8px;padding:12px 16px;border-bottom:1px solid #f1f5f9}.video-config-section:last-of-type{border-bottom:none}.video-lib-list{display:flex;flex-direction:column;gap:2px;padding:8px 8px 16px}.video-lib-item{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;padding:8px;border:1px solid transparent;border-radius:8px;background:none;cursor:pointer;text-align:left;font-family:inherit;transition:background .15s,border-color .15s}.video-lib-item:hover{background:#f8fafc;border-color:#e2e8f0}.video-lib-item.selected{background:#eff6ff;border-color:#93c5fd}.vli-thumb{position:relative;flex-shrink:0;width:56px;height:40px;border-radius:6px;background:linear-gradient(135deg,#f1f5f9,#e2e8f0);display:flex;align-items:center;justify-content:center}.vli-dur{position:absolute;bottom:2px;right:3px;font-size:.625rem;font-weight:600;color:#fff;background:#000000a6;padding:1px 4px;border-radius:3px}.vli-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.vli-title{font-size:.8125rem;font-weight:600;color:#1e293b;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vli-cat{font-size:.75rem;color:#64748b}.vli-check{flex-shrink:0}.video-lib-empty{display:flex;flex-direction:column;align-items:center;padding:32px 16px;text-align:center;gap:8px}.video-lib-empty p{font-size:.875rem;font-weight:500;color:#475569;margin:0}.video-lib-empty span{font-size:.8125rem;color:#64748b}.video-lib-loading{padding:8px}.video-lib-skeleton{display:flex;align-items:center;gap:10px;padding:8px;margin-bottom:4px}.vls-info{flex:1;display:flex;flex-direction:column;gap:6px}@media(max-width:1200px){.editor-body{grid-template-columns:280px minmax(0,1fr) 260px}}@media(max-width:900px){.editor-page{height:auto;min-height:100vh;min-height:100dvh;overflow:visible}.editor-body{display:flex;flex-direction:column;overflow:visible}.editor-topbar{padding:12px 16px}.panel-left{border-right:none;border-bottom:1px solid #e2e8f0;overflow:visible;padding:16px}.panel-center{overflow:visible;min-height:480px}.blocks-canvas{overflow:visible;min-height:320px}.panel-right{border-left:none;border-top:1px solid #e2e8f0}.right-panel-body{overflow:visible}.editor-toolbar,.toolbar-row-2,.link-dialog,.editor-tabs{padding-left:12px;padding-right:12px}.preview-frame{padding:12px}.preview-content{padding:16px}.form-row-dates{grid-template-columns:1fr}}@media(prefers-reduced-motion:reduce){*{transition:none!important}}\n"]
45499
+ styles: [":host{display:block}.required{color:#ef4444;font-weight:400}.editor-page{display:flex;flex-direction:column;height:100vh;height:100dvh;background:#f8fafc;overflow:hidden}.editor-actions{display:flex;justify-content:flex-end;align-items:center;gap:8px;flex-wrap:wrap;padding:0 0 12px;flex-shrink:0}.readonly-note{margin:0;padding:8px 16px;font-size:.8125rem;color:#92400e;background:#fffbeb;border-bottom:1px solid #fde68a}.readonly-note.system-note{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap}.editor-body{display:grid;grid-template-columns:340px minmax(0,1fr) 300px;flex:1;min-height:0;overflow:hidden}.panel-left{background:#fff;border-right:1px solid #e2e8f0;padding:24px;overflow-y:auto}.panel-title{font-size:1.0625rem;font-weight:700;color:#1e293b;margin:0 0 20px}.form-field{display:flex;flex-direction:column;gap:6px;margin-bottom:16px}.form-row-dates{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:16px}.assignments-section{border-top:1px solid #e2e8f0;padding-top:20px;margin-top:16px}.section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 6px}.section-desc{font-size:.8125rem;color:#64748b;line-height:1.5;margin:0 0 12px}.assignment-list{max-height:340px;overflow-y:auto;margin-top:12px;border:1px solid #e2e8f0;border-radius:8px}.assignment-item{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 14px;cursor:pointer;border-bottom:1px solid #f1f5f9;transition:background .1s}.assignment-item:last-child{border-bottom:none}.assignment-item:hover{background:#f8fafc}.assignment-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.assignment-item.assignment-readonly{cursor:default}.assignment-item.assignment-readonly:hover{background:transparent}.assignment-text{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.assignment-text strong{font-size:.8125rem;color:#1e293b}.assignment-text span{font-size:.75rem;color:#64748b}.assignment-channels{display:flex;gap:4px;flex-shrink:0}.channel-badge{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:4px;background:#f1f5f9;color:#94a3b8;transition:all .15s}.channel-badge.active{background:#3b82f6;color:#fff}.channel-badge.disabled{opacity:.4;cursor:not-allowed}.config-desc{font-size:.875rem;color:#64748b;line-height:1.5;margin:0}.config-divider{border:none;border-top:1px solid #e2e8f0;margin:20px 0}.config-section{display:flex;flex-direction:column;gap:12px}.config-section-label{font-size:.6875rem;font-weight:700;color:#3b82f6;text-transform:uppercase;letter-spacing:.04em}.config-field{display:flex;flex-direction:column;gap:6px}.config-field-mt{margin-top:16px}.config-label{font-size:.8125rem;font-weight:600;color:#1e293b}.config-readonly{padding:9px 12px;border:1px solid #e2e8f0;border-radius:8px;background:#f8fafc;font-size:.875rem;color:#1e293b}.config-hint{font-size:.75rem;color:#64748b}.test-save-note{display:flex;align-items:center;gap:8px;padding:10px 14px;background:#fef3c7;border:1px solid #fcd34d;border-radius:8px;font-size:.8125rem;color:#92400e;margin-top:12px}.test-save-note svg{flex-shrink:0}.panel-center{display:flex;flex-direction:column;min-height:0;min-width:0;overflow:hidden}.editor-tabs{display:flex;gap:2px;padding:12px 20px 0;background:#fff;border-bottom:1px solid #e2e8f0;overflow-x:auto;-webkit-overflow-scrolling:touch}.editor-tab{display:flex;align-items:center;gap:6px;padding:10px 16px;border:1px solid #e2e8f0;border-bottom:none;border-radius:8px 8px 0 0;background:#f8fafc;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;white-space:nowrap}.editor-tab:hover{background:#fff;color:#1e293b}.editor-tab.active{background:#eff6ff;color:#3b82f6;border-color:#93c5fd}.editor-tab:focus-visible,.right-tab:focus-visible,.block-group-header:focus-visible,.variable-item:focus-visible,.add-block-btn:focus-visible,.block-item:focus-visible,.video-lib-item:focus-visible{outline:2px solid #3b82f6;outline-offset:-2px}.editor-toolbar{display:flex;align-items:center;gap:8px;padding:10px 20px;background:#fff;border-bottom:1px solid #e2e8f0;flex-wrap:wrap}.toolbar-row-2{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 20px;background:#fff;border-bottom:1px solid #e2e8f0}.toolbar-group{display:flex;align-items:center;gap:2px;padding-right:8px;border-right:1px solid #e2e8f0}.toolbar-group:last-child{border-right:none;padding-right:0}.toolbar-select{display:block;min-width:96px}.toolbar-label{font-size:.75rem;font-weight:600;color:#64748b;white-space:nowrap;margin-right:6px}.hidden-color-input{position:absolute;width:0;height:0;opacity:0;pointer-events:none;border:none;padding:0}.color-indicator{display:flex;flex-direction:column;align-items:center;gap:2px;color:#475569}.color-bar{display:block;width:16px;height:3px;border-radius:2px;border:1px solid rgba(0,0,0,.1)}.link-dialog{background:#fff;border-bottom:1px solid #e2e8f0;padding:12px 20px}.link-dialog-inner{display:flex;align-items:flex-start;gap:8px;flex-wrap:wrap}.link-dialog-title{font-size:.8125rem;font-weight:700;color:#1e293b;white-space:nowrap;padding-top:10px}.link-dialog-input{display:block;width:240px;max-width:100%}.link-dialog-actions{display:flex;gap:6px}.preview-frame{flex:1;display:flex;justify-content:center;padding:24px;overflow-y:auto;background:#f1f5f9}.preview-frame.mobile{align-items:flex-start}.preview-content{max-width:600px;width:100%;box-sizing:border-box;background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:32px;min-height:400px;font-size:.9375rem;line-height:1.6;color:#1e293b;overflow-wrap:anywhere}.preview-content p{margin:0 0 8px}.mobile-shell{width:375px;max-width:100%;box-sizing:border-box;min-height:600px;border:2px solid #1e293b;border-radius:24px;padding:40px 12px 24px;background:#fff;box-shadow:0 8px 32px #0000001f}.mobile-shell .preview-content{border:none;border-radius:0;padding:16px;max-width:100%}.blocks-canvas{flex:1;padding:16px 20px 24px;overflow-y:auto;background:#f1f5f9;display:flex;flex-direction:column}.block-wrapper{position:relative;display:flex;align-items:flex-start;background:#fff;border:2px solid transparent;border-radius:8px;transition:border-color .15s,box-shadow .15s}.block-wrapper:hover,.block-wrapper.selected,.block-wrapper:focus-within{border-color:#3b82f6;box-shadow:0 0 0 3px #3b82f61a}.block-wrapper:hover .block-drag-handle,.block-wrapper.selected .block-drag-handle,.block-wrapper:focus-within .block-drag-handle{opacity:1}.block-wrapper:hover .block-controls,.block-wrapper.selected .block-controls,.block-wrapper:focus-within .block-controls{opacity:1;pointer-events:all}.block-wrapper.dragging{opacity:.4}.block-drag-handle{flex-shrink:0;width:28px;display:flex;align-items:flex-start;justify-content:center;padding-top:14px;opacity:0;transition:opacity .15s;cursor:grab;color:#94a3b8}.block-drag-handle:active{cursor:grabbing}.block-content{flex:1;min-width:0;padding:12px 16px;outline:none;font-size:.9375rem;color:#1e293b;line-height:1.6;min-height:48px;overflow-wrap:anywhere}.block-content:empty:before{content:\"Click to edit...\";color:#94a3b8;font-style:italic;pointer-events:none}.block-content p{margin:0 0 8px}.block-content p:last-child{margin:0}.block-content h1,.block-content h2,.block-content h3{margin:8px 0 6px;color:#1e293b}.block-content a{color:#3b82f6}.block-content img{max-width:100%;border-radius:6px}.block-content ul,.block-content ol{padding-left:20px;margin:0 0 8px}.block-controls{position:absolute;top:6px;right:6px;display:flex;gap:2px;opacity:0;pointer-events:none;transition:opacity .15s;background:#fff;border:1px solid #e2e8f0;border-radius:6px;padding:3px;box-shadow:0 2px 6px #00000014}@media(hover:none){.block-wrapper.selected .block-controls{opacity:1;pointer-events:all}}.drop-zone{height:8px;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:height .15s,background .15s;position:relative}.drop-zone-label{font-size:.75rem;font-weight:600;color:#3b82f6;opacity:0;transition:opacity .1s}.drop-zone.active{height:40px;background:#3b82f614;border:2px dashed #3b82f6}.drop-zone.active .drop-zone-label{opacity:1}.add-block-btn{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;min-height:44px;padding:12px;margin-top:8px;border:2px dashed #e2e8f0;border-radius:8px;background:none;font-size:.875rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;transition:border-color .15s,color .15s,background .15s}.add-block-btn:hover{border-color:#3b82f6;color:#3b82f6;background:#3b82f60a}.panel-right{background:#fff;border-left:1px solid #e2e8f0;display:flex;flex-direction:column;min-height:0;min-width:0}.right-tabs{display:flex;border-bottom:1px solid #e2e8f0}.right-tab{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:12px;min-height:44px;border:none;background:none;font-size:.8125rem;font-weight:600;color:#64748b;cursor:pointer;font-family:inherit;border-bottom:2px solid transparent}.right-tab:hover{color:#1e293b}.right-tab.active{color:#3b82f6;background:#eff6ff;border-bottom-color:#3b82f6}.right-panel-body{flex:1;padding:20px;overflow-y:auto}.right-section-title{font-size:.9375rem;font-weight:700;color:#1e293b;margin:0 0 12px}.right-section-desc{font-size:.8125rem;color:#64748b;margin:0 0 16px;line-height:1.5}.right-section-hint{font-size:.8125rem;color:#64748b;margin:0 0 12px;line-height:1.5}.block-group{border-bottom:1px solid #f1f5f9}.block-group-header{display:flex;align-items:center;gap:8px;width:100%;min-height:44px;padding:12px 0;border:none;background:none;font-size:.875rem;font-weight:600;color:#1e293b;cursor:pointer;font-family:inherit;text-align:left}.block-group-header .chevron{transition:transform .2s;color:#94a3b8}.block-group-header .chevron.expanded{transform:rotate(90deg)}.block-group-header span:nth-of-type(1){flex:1}.block-count{font-size:.75rem;font-weight:600;color:#64748b;background:#f1f5f9;padding:2px 8px;border-radius:10px;margin-left:auto}.block-list,.variable-list{display:flex;flex-direction:column;gap:2px;padding-bottom:8px}.block-item{display:flex;align-items:center;gap:6px;box-sizing:border-box;width:100%;min-height:44px;padding:8px 12px 8px 28px;font-size:.8125rem;color:#64748b;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit;-webkit-user-select:none;user-select:none}.block-item:hover{background:#f8fafc;color:#1e293b}.block-item-drag{color:#cbd5e1;flex-shrink:0;cursor:grab}.variable-item{display:grid;grid-template-columns:auto 1fr auto;gap:8px;align-items:center;min-height:44px;padding:8px 12px 8px 28px;border:none;background:none;cursor:pointer;text-align:left;border-radius:4px;font-family:inherit}.variable-item:hover{background:#f8fafc}.var-tag{font-size:.75rem;font-weight:600;color:#3b82f6;background:#3b82f614;padding:2px 6px;border-radius:4px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}.var-label{font-size:.8125rem;color:#1e293b}.var-example{font-size:.75rem;color:#64748b;overflow-wrap:anywhere}.video-library-panel{padding:0}.video-library-panel .right-section-title,.video-library-panel .right-section-hint{padding:0 16px}.video-library-panel .right-section-title{padding-top:16px}.video-config-section{display:flex;flex-direction:column;gap:8px;padding:12px 16px;border-bottom:1px solid #f1f5f9}.video-config-section:last-of-type{border-bottom:none}.video-lib-list{display:flex;flex-direction:column;gap:2px;padding:8px 8px 16px}.video-lib-item{display:flex;align-items:center;gap:10px;width:100%;min-height:44px;padding:8px;border:1px solid transparent;border-radius:8px;background:none;cursor:pointer;text-align:left;font-family:inherit;transition:background .15s,border-color .15s}.video-lib-item:hover{background:#f8fafc;border-color:#e2e8f0}.video-lib-item.selected{background:#eff6ff;border-color:#93c5fd}.vli-thumb{position:relative;flex-shrink:0;width:56px;height:40px;border-radius:6px;background:linear-gradient(135deg,#f1f5f9,#e2e8f0);display:flex;align-items:center;justify-content:center}.vli-dur{position:absolute;bottom:2px;right:3px;font-size:.625rem;font-weight:600;color:#fff;background:#000000a6;padding:1px 4px;border-radius:3px}.vli-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.vli-title{font-size:.8125rem;font-weight:600;color:#1e293b;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.vli-cat{font-size:.75rem;color:#64748b}.vli-check{flex-shrink:0}.video-lib-loading{padding:8px}.video-lib-skeleton{display:flex;align-items:center;gap:10px;padding:8px;margin-bottom:4px}.vls-info{flex:1;display:flex;flex-direction:column;gap:6px}@media(max-width:1200px){.editor-body{grid-template-columns:280px minmax(0,1fr) 260px}}@media(max-width:900px){.editor-page{height:auto;min-height:100vh;min-height:100dvh;overflow:visible}.editor-body{display:flex;flex-direction:column;overflow:visible}.panel-left{border-right:none;border-bottom:1px solid #e2e8f0;overflow:visible;padding:16px}.panel-center{overflow:visible;min-height:480px}.blocks-canvas{overflow:visible;min-height:320px}.panel-right{border-left:none;border-top:1px solid #e2e8f0}.right-panel-body{overflow:visible}.editor-toolbar,.toolbar-row-2,.link-dialog,.editor-tabs{padding-left:12px;padding-right:12px}.preview-frame{padding:12px}.preview-content{padding:16px}.form-row-dates{grid-template-columns:1fr}}@media(prefers-reduced-motion:reduce){*{transition:none!important}}\n"]
45595
45500
  }]
45596
45501
  }],
45597
45502
  ctorParameters: () => [],
@@ -45668,14 +45573,6 @@ i0.ɵɵngDeclareClassMetadata({
45668
45573
  required: false
45669
45574
  }]
45670
45575
  }],
45671
- aiExamples: [{
45672
- type: i0.Input,
45673
- args: [{
45674
- isSignal: true,
45675
- alias: "aiExamples",
45676
- required: false
45677
- }]
45678
- }],
45679
45576
  namePlaceholder: [{
45680
45577
  type: i0.Input,
45681
45578
  args: [{
@@ -45692,30 +45589,6 @@ i0.ɵɵngDeclareClassMetadata({
45692
45589
  required: false
45693
45590
  }]
45694
45591
  }],
45695
- backLabel: [{
45696
- type: i0.Input,
45697
- args: [{
45698
- isSignal: true,
45699
- alias: "backLabel",
45700
- required: false
45701
- }]
45702
- }],
45703
- createLabel: [{
45704
- type: i0.Input,
45705
- args: [{
45706
- isSignal: true,
45707
- alias: "createLabel",
45708
- required: false
45709
- }]
45710
- }],
45711
- editLabel: [{
45712
- type: i0.Input,
45713
- args: [{
45714
- isSignal: true,
45715
- alias: "editLabel",
45716
- required: false
45717
- }]
45718
- }],
45719
45592
  systemNote: [{
45720
45593
  type: i0.Input,
45721
45594
  args: [{
@@ -45772,14 +45645,6 @@ i0.ɵɵngDeclareClassMetadata({
45772
45645
  required: false
45773
45646
  }]
45774
45647
  }],
45775
- aiEnabled: [{
45776
- type: i0.Input,
45777
- args: [{
45778
- isSignal: true,
45779
- alias: "aiEnabled",
45780
- required: false
45781
- }]
45782
- }],
45783
45648
  testSendEnabled: [{
45784
45649
  type: i0.Input,
45785
45650
  args: [{
@@ -45788,14 +45653,6 @@ i0.ɵɵngDeclareClassMetadata({
45788
45653
  required: false
45789
45654
  }]
45790
45655
  }],
45791
- videosEnabled: [{
45792
- type: i0.Input,
45793
- args: [{
45794
- isSignal: true,
45795
- alias: "videosEnabled",
45796
- required: false
45797
- }]
45798
- }],
45799
45656
  saving: [{
45800
45657
  type: i0.Input,
45801
45658
  args: [{
@@ -45812,19 +45669,19 @@ i0.ɵɵngDeclareClassMetadata({
45812
45669
  required: false
45813
45670
  }]
45814
45671
  }],
45815
- aiGenerating: [{
45672
+ videos: [{
45816
45673
  type: i0.Input,
45817
45674
  args: [{
45818
45675
  isSignal: true,
45819
- alias: "aiGenerating",
45676
+ alias: "videos",
45820
45677
  required: false
45821
45678
  }]
45822
45679
  }],
45823
- videos: [{
45680
+ hideVideos: [{
45824
45681
  type: i0.Input,
45825
45682
  args: [{
45826
45683
  isSignal: true,
45827
- alias: "videos",
45684
+ alias: "hideVideos",
45828
45685
  required: false
45829
45686
  }]
45830
45687
  }],
@@ -45860,10 +45717,6 @@ i0.ɵɵngDeclareClassMetadata({
45860
45717
  required: false
45861
45718
  }]
45862
45719
  }],
45863
- back: [{
45864
- type: i0.Output,
45865
- args: ["back"]
45866
- }],
45867
45720
  save: [{
45868
45721
  type: i0.Output,
45869
45722
  args: ["save"]
@@ -45872,10 +45725,6 @@ i0.ɵɵngDeclareClassMetadata({
45872
45725
  type: i0.Output,
45873
45726
  args: ["testSend"]
45874
45727
  }],
45875
- aiGenerate: [{
45876
- type: i0.Output,
45877
- args: ["aiGenerate"]
45878
- }],
45879
45728
  videosRequested: [{
45880
45729
  type: i0.Output,
45881
45730
  args: ["videosRequested"]
@@ -45894,6 +45743,6 @@ i0.ɵɵngDeclareClassMetadata({
45894
45743
  }]
45895
45744
  }
45896
45745
  });
45897
- export { ActionBarComponent, AlertComponent, AppShellComponent, AudioPlayerComponent, AvatarComponent, BADGE_VARIANT_STYLES, BadgeComponent, BarRowComponent, BoardCardDirective, BoardComponent, BulkMessagePanelComponent, BusinessHoursComponent, ButtonComponent, CalendarComponent, CardListItemComponent, CheckboxComponent, CheckboxTrailingDirective, ChipComponent, ChipGroupComponent, ColorInputComponent, ColumnFilterComponent, ColumnsComponent, ComboboxComponent, ConfirmOutletComponent, ConfirmService, ContactPickerComponent, DEFAULT_EMAIL_TEMPLATE_BLOCK_GROUPS, DEFAULT_EMAIL_TEMPLATE_VARIABLE_GROUPS, DEFAULT_PASSWORD_RULES, DROPDOWN_GROUP, DataTableComponent, DateInputComponent, DateRangePickerComponent, DatetimeInputComponent, DetailCardComponent, DiscountSelectorComponent, DividerComponent, DropdownComponent, EMAIL_BLOCK_DRAG_TYPE, EMAIL_TEMPLATE_MAX_BODY, EMAIL_TEMPLATE_MAX_TEXT, EMAIL_TEMPLATE_START_TEXT, EmailTemplateEditorComponent, EmptyStateComponent, ErrorComponent, ErrorStateComponent, FORGEROUTE_CONFIG, FadeComponent, FileInputComponent, FormColSpanDirective, FormComponent, FormRowComponent, FormSectionComponent, HintComponent, IDX_BEHAVIOR_SIGNALS, INTEGRATION_CATALOG, INTEGRATION_FIELD_DEFS, INTEGRATION_GROUP_ORDER, INTEGRATION_OPTION_DEFS, IconComponent, ImageComponent, ImageGalleryComponent, ImageGalleryDialogComponent, ImagePreviewComponent, ImageRepositionComponent, ImportExportComponent, KpiCardComponent, LAYOUT_GAP_PX, ListComponent, ListItemComponent, LiveRegionComponent, MAX_EMAIL_ADDRESS_LENGTH, ModalComponent, MoreMenuComponent, MultiSelectComponent, NOTES_MAX_LENGTH, NotesComponent, PHONE_NUMBER_AREA_CODE_LENGTH, PHONE_NUMBER_ZIP_LENGTH, PageComponent, PaginationComponent, PanelInfoListComponent, PasswordRequirementsComponent, PdfHotspotComponent, PhoneNumberPickerComponent, PillTabsComponent, ProgressBarComponent, ProgressRingComponent, QrCodeComponent, QuickFilterTabsComponent, RICH_TEXT_OPTIONS, RadioComponent, RadioGroupComponent, RadioMatrixComponent, RadioOptionContentDirective, ReadonlyFieldsetComponent, RichTextEditorComponent, SEMANTIC_BADGE_MAP, SETUP_DONE_KEY, SETUP_INTEGRATIONS, SearchInputComponent, SectionHeaderComponent, SelectComponent, SetupWizardComponent, SetupWizardStepDirective, ShowComponent, SidePanelComponent, SidebarLayoutComponent, SignaturePadComponent, SkeletonComponent, StackComponent, StarComponent, StepperComponent, TableToolbarComponent, TextComponent, TextInputComponent, TextareaInputComponent, TimeInputComponent, TimelineComponent, ToastComponent, ToastService, ToggleBadgeComponent, ToggleComponent, TooltipDirective, US_STATES, UiFieldValidity, acceptLabel, appShellGroupsStorageKey, autoVariant, blockHasContent, buildDefaultSchedule, buildVideoBlockHtml, builtInActionIcon, businessTimeOptions, createFieldReveal, decodeFilterValues, digitsOnly, downloadBlob, encodeFilterValue, encodeFilterValues, errorContextInterceptor, escapeHtml, fileMatchesAccept, formatAddress, formatCategoryLabel, formatCurrency, formatFileSize, formatIsoDate, formatIsoDateTime, formatTime, formatVideoDuration, getEligibleIds, getEligibleOptions, getErrorMessage, humanReadableMessage, iconPath, insideEditorBlock, integrationPlainText, integrationsForApp, integrationsOnlyFor, isBlockDrag, isValidEmailAddress, isWebUrl, isoKey, issueToErrors, maxLengthIssue, normalizeHexColor, parseBizHours, parseIso, parseTime, passwordMeetsRules, pluralize, provideForgerouteToast, reorderItems, requiredIssue, resolveLayoutGap, resolvePreset, serializeBizHours, setupIntegrations };
45746
+ export { ActionBarComponent, AlertComponent, AppShellComponent, AudioPlayerComponent, AvatarComponent, BADGE_VARIANT_STYLES, BadgeComponent, BarRowComponent, BoardCardDirective, BoardComponent, BulkMessagePanelComponent, BusinessHoursComponent, ButtonComponent, CalendarComponent, CardListItemComponent, CheckboxComponent, CheckboxTrailingDirective, ChipComponent, ChipGroupComponent, ColorInputComponent, ColumnFilterComponent, ColumnsComponent, ComboboxComponent, ConfirmOutletComponent, ConfirmService, ContactPickerComponent, DEFAULT_EMAIL_TEMPLATE_BLOCK_GROUPS, DEFAULT_EMAIL_TEMPLATE_VARIABLE_GROUPS, DEFAULT_PASSWORD_RULES, DROPDOWN_GROUP, DataTableComponent, DateInputComponent, DateRangePickerComponent, DatetimeInputComponent, DetailCardComponent, DiscountSelectorComponent, DividerComponent, DropdownComponent, EMAIL_BLOCK_DRAG_TYPE, EMAIL_TEMPLATE_MAX_BODY, EMAIL_TEMPLATE_MAX_TEXT, EMAIL_TEMPLATE_START_TEXT, EmailTemplateEditorComponent, EmptyStateComponent, ErrorComponent, ErrorStateComponent, FORGEROUTE_CONFIG, FadeComponent, FileInputComponent, FormColSpanDirective, FormComponent, FormRowComponent, FormSectionComponent, HintComponent, IDX_BEHAVIOR_SIGNALS, INTEGRATION_CATALOG, INTEGRATION_FIELD_DEFS, INTEGRATION_GROUP_ORDER, INTEGRATION_OPTION_DEFS, IconComponent, ImageComponent, ImageGalleryComponent, ImageGalleryDialogComponent, ImagePreviewComponent, ImageRepositionComponent, ImportExportComponent, KpiCardComponent, LAYOUT_GAP_PX, ListComponent, ListItemComponent, LiveRegionComponent, MAX_EMAIL_ADDRESS_LENGTH, ModalComponent, MoreMenuComponent, MultiSelectComponent, NOTES_MAX_LENGTH, NotesComponent, PHONE_NUMBER_AREA_CODE_LENGTH, PHONE_NUMBER_ZIP_LENGTH, PageComponent, PaginationComponent, PanelInfoListComponent, PasswordRequirementsComponent, PdfHotspotComponent, PhoneNumberPickerComponent, PillTabsComponent, ProgressBarComponent, ProgressRingComponent, QrCodeComponent, QuickFilterTabsComponent, RICH_TEXT_OPTIONS, RadioComponent, RadioGroupComponent, RadioMatrixComponent, RadioOptionContentDirective, ReadonlyFieldsetComponent, RichTextEditorComponent, SEMANTIC_BADGE_MAP, SETUP_DONE_KEY, SETUP_INTEGRATIONS, SearchInputComponent, SectionHeaderComponent, SelectComponent, SetupWizardComponent, SetupWizardStepDirective, ShowComponent, SidePanelComponent, SidebarLayoutComponent, SignaturePadComponent, SkeletonComponent, StackComponent, StarComponent, StepperComponent, TableToolbarComponent, TextComponent, TextInputComponent, TextareaInputComponent, TimeInputComponent, TimelineComponent, ToastComponent, ToastService, ToggleBadgeComponent, ToggleComponent, TooltipDirective, US_STATES, UiFieldValidity, acceptLabel, appShellGroupsStorageKey, autoVariant, blockHasContent, buildDefaultSchedule, buildVideoBlockHtml, builtInActionIcon, businessTimeOptions, createFieldReveal, decodeFilterValues, digitsOnly, downloadBlob, encodeFilterValue, encodeFilterValues, errorContextInterceptor, escapeHtml, fileMatchesAccept, formatAddress, formatCategoryLabel, formatCurrency, formatFileSize, formatIsoDate, formatIsoDateTime, formatTime, formatVideoDuration, getEligibleIds, getEligibleOptions, getErrorMessage, humanReadableMessage, iconPath, insideEditorBlock, integrationPlainText, integrationsForApp, integrationsOnlyFor, isBlockDrag, isValidEmailAddress, isWebUrl, isoKey, issueToErrors, maxLengthIssue, normalizeHexColor, parseBizHours, parseIso, parseTime, passwordMeetsRules, pluralize, provideForgerouteToast, reorderItems, requiredIssue, resolveLayoutGap, resolvePreset, serializeBizHours, setupIntegrations, splitIntro };
45898
45747
 
45899
45748
  //# sourceMappingURL=forgeroute-ui.mjs.map