@signature.digital/catalog 1.6.1 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
- import { DeesElement, state, html, customElement, type TemplateResult, css } from '@design.estate/dees-element';
2
- import { actionButton, demoFields, demoRecipients, fakeDocument, icon, pill, topBar, workspaceBaseStyles, workspaceDemoFrame, type IFieldPlacement, type IRecipient, type TRecipientRole } from './sdig-workspace.shared.js';
1
+ import { DeesElement, property, state, html, customElement, type TemplateResult, css } from '@design.estate/dees-element';
2
+ import { actionButton, demoDocuments, demoFields, demoRecipients, fakeDocument, icon, pill, topBar, workspaceBaseStyles, workspaceDemoFrame, type IDocumentRow, type IFieldPlacement, type IRecipient, type TRecipientRole } from './sdig-workspace.shared.js';
3
3
  import '../sdig-contextmenu/index.js';
4
4
  import { type ISdigContextMenuAction, type ISdigContextMenuActionEventDetail } from '../sdig-contextmenu/index.js';
5
5
 
@@ -71,8 +71,9 @@ export class SdigWorkspaceCompose extends DeesElement {
71
71
  @state() private accessor step: number = 2;
72
72
  @state() private accessor activeRecipient: number = 0;
73
73
  @state() private accessor selectedFieldId: string | null = null;
74
- @state() private accessor recipients: IRecipient[] = [...demoRecipients];
75
- @state() private accessor fields: IFieldPlacement[] = [...demoFields];
74
+ @property({ attribute: false }) public accessor document: IDocumentRow = demoDocuments[0];
75
+ @property({ attribute: false }) public accessor recipients: IRecipient[] = [...demoRecipients];
76
+ @property({ attribute: false }) public accessor fields: IFieldPlacement[] = [...demoFields];
76
77
  @state() private accessor signingOrderDrag: TSigningOrderDrag | null = null;
77
78
  @state() private accessor recipientContextMenu: TRecipientContextMenu | null = null;
78
79
  private draggedFieldDefinition: TFieldDefinition | null = null;
@@ -169,8 +170,36 @@ export class SdigWorkspaceCompose extends DeesElement {
169
170
  return Math.max(min, Math.min(max, value));
170
171
  }
171
172
 
173
+ private emitFieldsChange() {
174
+ this.dispatchEvent(new CustomEvent('fields-change', {
175
+ detail: { fields: this.fields },
176
+ bubbles: true,
177
+ composed: true,
178
+ }));
179
+ }
180
+
181
+ private emitRecipientsChange() {
182
+ this.dispatchEvent(new CustomEvent('recipients-change', {
183
+ detail: { recipients: this.recipients },
184
+ bubbles: true,
185
+ composed: true,
186
+ }));
187
+ this.dispatchEvent(new CustomEvent('routing-change', {
188
+ detail: { recipients: this.recipients },
189
+ bubbles: true,
190
+ composed: true,
191
+ }));
192
+ }
193
+
172
194
  private updateField(fieldId: string, patch: Partial<IFieldPlacement>) {
173
195
  this.fields = this.fields.map((field) => field.id === fieldId ? { ...field, ...patch } : field);
196
+ const field = this.fields.find((currentField) => currentField.id === fieldId);
197
+ this.dispatchEvent(new CustomEvent('field-update', {
198
+ detail: { fieldId, field, patch, fields: this.fields },
199
+ bubbles: true,
200
+ composed: true,
201
+ }));
202
+ this.emitFieldsChange();
174
203
  }
175
204
 
176
205
  private updateSelectedField(patch: Partial<IFieldPlacement>) {
@@ -192,8 +221,15 @@ export class SdigWorkspaceCompose extends DeesElement {
192
221
 
193
222
  private removeSelectedField() {
194
223
  if (!this.selectedFieldId) return;
224
+ const field = this.fields.find((currentField) => currentField.id === this.selectedFieldId);
195
225
  this.fields = this.fields.filter((field) => field.id !== this.selectedFieldId);
226
+ this.dispatchEvent(new CustomEvent('field-delete', {
227
+ detail: { fieldId: this.selectedFieldId, field, fields: this.fields },
228
+ bubbles: true,
229
+ composed: true,
230
+ }));
196
231
  this.selectedFieldId = null;
232
+ this.emitFieldsChange();
197
233
  }
198
234
 
199
235
  private updateRecipientRole(recipientId: number, role: TRecipientRole) {
@@ -220,6 +256,7 @@ export class SdigWorkspaceCompose extends DeesElement {
220
256
  targetMembers.splice(insertIndex, 0, { ...recipient, role: nextRole });
221
257
  nextByRole.set(nextRole, targetMembers);
222
258
  this.recipients = recipientRoleDefinitions.flatMap((roleDefinition) => nextByRole.get(roleDefinition.role) || []).map((currentRecipient, index) => ({ ...currentRecipient, order: index + 1 }));
259
+ this.emitRecipientsChange();
223
260
 
224
261
  const nextSigners = this.recipients.filter((currentRecipient) => currentRecipient.role === 'signer');
225
262
  const fallbackSigner = nextSigners[0];
@@ -229,6 +266,7 @@ export class SdigWorkspaceCompose extends DeesElement {
229
266
  if (this.activeRecipient === recipientId) {
230
267
  this.activeRecipient = fallbackSigner.id;
231
268
  }
269
+ this.emitFieldsChange();
232
270
  }
233
271
  }
234
272
 
@@ -454,6 +492,12 @@ export class SdigWorkspaceCompose extends DeesElement {
454
492
  this.selectedFieldId = nextField.id;
455
493
  this.draggedFieldDefinition = null;
456
494
  this.draggedFieldGrabOffset = null;
495
+ this.dispatchEvent(new CustomEvent('field-create', {
496
+ detail: { field: nextField, fields: this.fields },
497
+ bubbles: true,
498
+ composed: true,
499
+ }));
500
+ this.emitFieldsChange();
457
501
  }
458
502
 
459
503
  private startFieldToolDrag(event: DragEvent, fieldType: TFieldDefinition) {
@@ -567,10 +611,11 @@ export class SdigWorkspaceCompose extends DeesElement {
567
611
  }
568
612
 
569
613
  public render(): TemplateResult {
614
+ const document = this.document || demoDocuments[0];
570
615
  const selectedField = this.fields.find((field) => field.id === this.selectedFieldId);
571
616
 
572
617
  return html`
573
- ${topBar({ breadcrumb: ['signature.digital', 'Inbox', 'Compose'], title: 'Master Services Agreement', subtitle: pill('Draft · auto-saved'), actions: html`${actionButton('Save draft', 'ghost')}${actionButton('Preview', 'outline', 'eye')}${actionButton('Send for signature', 'primary', 'send')}` })}
618
+ ${topBar({ breadcrumb: ['signature.digital', 'Inbox', 'Compose'], title: document.title, subtitle: pill('Draft · auto-saved'), actions: html`${actionButton('Save draft', 'ghost')}${actionButton('Preview', 'outline', 'eye')}${actionButton('Send for signature', 'primary', 'send')}` })}
574
619
  ${this.renderStepper()}
575
620
  <div class="compose-workspace">
576
621
  ${this.renderRecipientContextMenu()}
@@ -585,9 +630,9 @@ export class SdigWorkspaceCompose extends DeesElement {
585
630
  <div class="document-page page-drop-target" @click=${this.handleDocumentClick} @dragover=${(event: DragEvent) => { event.preventDefault(); if (event.dataTransfer) event.dataTransfer.dropEffect = 'copy'; (event.currentTarget as HTMLElement).classList.add('drag-over'); }} @dragleave=${(event: DragEvent) => (event.currentTarget as HTMLElement).classList.remove('drag-over')} @drop=${(event: DragEvent) => this.addFieldFromDrop(event)}>
586
631
  ${fakeDocument()}
587
632
  ${this.fields.map((field) => html`<div class="field-box ${this.selectedFieldId === field.id ? 'selected' : ''}" style="--x: ${field.x}px; --y: ${field.y}px; --w: ${field.w}px; --h: ${field.h}px; --field-color: ${this.recipientColor(field.recipient)};" @click=${() => this.selectedFieldId = field.id} @pointerdown=${(event: PointerEvent) => this.startFieldMove(event, field)}><div class="field-content">${icon(this.fieldIcon(field.type), 12)}<span>${field.label}</span></div>${this.selectedFieldId === field.id ? this.renderResizeHandles(field) : ''}</div>`)}
588
- <div class="mono" style="position: absolute; bottom: 12px; right: 16px; font-size: 9px; color: hsl(0 0% 60%);">Page 1 of 14</div>
633
+ <div class="mono" style="position: absolute; bottom: 12px; right: 16px; font-size: 9px; color: hsl(0 0% 60%);">Page 1 of ${document.pages}</div>
589
634
  </div>
590
- <div style="display: flex; align-items: center; gap: 10px; font-size: 11px; color: var(--text-muted);">${actionButton('Prev', 'outline')}${html`<span class="mono">1 / 14</span>`}${actionButton('Next', 'outline')}</div>
635
+ <div style="display: flex; align-items: center; gap: 10px; font-size: 11px; color: var(--text-muted);">${actionButton('Prev', 'outline')}${html`<span class="mono">1 / ${document.pages}</span>`}${actionButton('Next', 'outline')}</div>
591
636
  </div>
592
637
  <div class="right-panel">
593
638
  <div class="label-upper">Routing order · drag to reorder</div>
@@ -13,6 +13,7 @@ export class SdigWorkspaceSign extends DeesElement {
13
13
  public static demoGroups = ['Signature Digital Workspace'];
14
14
 
15
15
  @property({ attribute: false }) public accessor document: IDocumentRow = demoDocuments[0];
16
+ @property({ attribute: false }) public accessor fields: IFieldPlacement[] = demoFields;
16
17
  @state() private accessor activeFieldId: string = 'f1';
17
18
  @state() private accessor signedFieldIds: string[] = [];
18
19
 
@@ -28,7 +29,7 @@ export class SdigWorkspaceSign extends DeesElement {
28
29
  `];
29
30
 
30
31
  private get signFields() {
31
- return demoFields.slice(0, 3);
32
+ return this.fields.slice(0, 3);
32
33
  }
33
34
 
34
35
  private fieldIcon(type: IFieldPlacement['type']): string {
@@ -1,5 +1,5 @@
1
1
  import { DeesElement, property, html, customElement, type TemplateResult, css } from '@design.estate/dees-element';
2
- import { demoDocuments, icon, type IDocumentRow, type TDensity, type TWorkspaceTheme, type TWorkspaceView } from './sdig-workspace.shared.js';
2
+ import { demoDocuments, demoFields, demoRecipients, icon, type IDocumentRow, type IFieldPlacement, type IRecipient, type TDensity, type TWorkspaceTheme, type TWorkspaceView } from './sdig-workspace.shared.js';
3
3
  import './sdig-workspace-inbox.js';
4
4
  import './sdig-workspace-compose.js';
5
5
  import './sdig-workspace-sign.js';
@@ -25,6 +25,8 @@ export class SdigWorkspace extends DeesElement {
25
25
  @property({ type: String, reflect: true }) public accessor view: TWorkspaceView = 'inbox';
26
26
  @property({ attribute: false }) public accessor documents: IDocumentRow[] = demoDocuments;
27
27
  @property({ type: String }) public accessor activeDocumentId: string = '';
28
+ @property({ attribute: false }) public accessor recipients: IRecipient[] = demoRecipients;
29
+ @property({ attribute: false }) public accessor fields: IFieldPlacement[] = demoFields;
28
30
 
29
31
  public connectedCallback = async () => {
30
32
  await super.connectedCallback();
@@ -163,8 +165,8 @@ export class SdigWorkspace extends DeesElement {
163
165
  const activeDocument = this.documents.find((document) => document.id === this.activeDocumentId) || this.documents[0] || demoDocuments[0];
164
166
  switch (this.view) {
165
167
  case 'inbox': return html`<sdig-workspace-inbox class="view-host" .density=${this.density} .documents=${this.documents}></sdig-workspace-inbox>`;
166
- case 'compose': return html`<sdig-workspace-compose class="view-host"></sdig-workspace-compose>`;
167
- case 'sign': return html`<sdig-workspace-sign class="view-host" .document=${activeDocument}></sdig-workspace-sign>`;
168
+ case 'compose': return html`<sdig-workspace-compose class="view-host" .document=${activeDocument} .recipients=${this.recipients} .fields=${this.fields}></sdig-workspace-compose>`;
169
+ case 'sign': return html`<sdig-workspace-sign class="view-host" .document=${activeDocument} .fields=${this.fields}></sdig-workspace-sign>`;
168
170
  case 'audit': return html`<sdig-workspace-audit class="view-host" .document=${activeDocument}></sdig-workspace-audit>`;
169
171
  case 'developers': return html`<sdig-workspace-developers class="view-host"></sdig-workspace-developers>`;
170
172
  case 'templates': return html`<sdig-workspace-placeholder class="view-host" label="Templates" subtitle="Reusable agreement templates"></sdig-workspace-placeholder>`;