@signature.digital/catalog 1.7.0 → 1.9.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.
- package/dist_ts_web/00_commitinfo_data.js +3 -3
- package/dist_ts_web/elements/index.d.ts +1 -0
- package/dist_ts_web/elements/index.js +3 -1
- package/dist_ts_web/elements/sdig-app-shell/index.d.ts +1 -0
- package/dist_ts_web/elements/sdig-app-shell/index.js +2 -0
- package/dist_ts_web/elements/sdig-app-shell/sdig-app-shell.d.ts +38 -0
- package/dist_ts_web/elements/sdig-app-shell/sdig-app-shell.js +309 -0
- package/dist_ts_web/elements/sdig-signbox/sdig-signbox.d.ts +1 -0
- package/dist_ts_web/elements/sdig-signbox/sdig-signbox.js +28 -9
- package/dist_ts_web/elements/sdig-signpad/sdig-signpad.d.ts +9 -2
- package/dist_ts_web/elements/sdig-signpad/sdig-signpad.js +23 -5
- package/dist_ts_web/elements/sdig-workspace/sdig-workspace-audit.js +5 -5
- package/dist_ts_web/elements/sdig-workspace/sdig-workspace-compose.d.ts +1 -0
- package/dist_ts_web/elements/sdig-workspace/sdig-workspace-compose.js +18 -6
- package/dist_ts_web/elements/sdig-workspace/sdig-workspace-developers.js +13 -15
- package/dist_ts_web/elements/sdig-workspace/sdig-workspace-inbox.js +14 -13
- package/dist_ts_web/elements/sdig-workspace/sdig-workspace-sign.d.ts +3 -0
- package/dist_ts_web/elements/sdig-workspace/sdig-workspace-sign.js +55 -18
- package/dist_ts_web/elements/sdig-workspace/sdig-workspace.js +28 -28
- package/dist_ts_web/elements/sdig-workspace/sdig-workspace.shared.js +44 -42
- package/dist_ts_web/plugins.d.ts +3 -3
- package/dist_ts_web/plugins.js +3 -4
- package/package.json +15 -21
- package/readme.md +54 -2
- package/ts_web/00_commitinfo_data.ts +2 -2
- package/ts_web/elements/index.ts +3 -0
- package/ts_web/elements/sdig-app-shell/index.ts +1 -0
- package/ts_web/elements/sdig-app-shell/sdig-app-shell.ts +200 -0
- package/ts_web/elements/sdig-signbox/sdig-signbox.ts +26 -8
- package/ts_web/elements/sdig-signpad/sdig-signpad.ts +27 -6
- package/ts_web/elements/sdig-workspace/sdig-workspace-audit.ts +4 -4
- package/ts_web/elements/sdig-workspace/sdig-workspace-compose.ts +16 -5
- package/ts_web/elements/sdig-workspace/sdig-workspace-developers.ts +12 -14
- package/ts_web/elements/sdig-workspace/sdig-workspace-inbox.ts +13 -12
- package/ts_web/elements/sdig-workspace/sdig-workspace-sign.ts +53 -17
- package/ts_web/elements/sdig-workspace/sdig-workspace.shared.ts +44 -41
- package/ts_web/elements/sdig-workspace/sdig-workspace.ts +27 -27
- package/ts_web/plugins.ts +3 -4
- package/.smartconfig.json +0 -82
- package/dist_bundle/bundle.js +0 -6214
- package/dist_bundle/bundle.js.map +0 -7
- package/dist_bundle/index.html +0 -28
- package/dist_watch/bundle.js +0 -135739
- package/dist_watch/bundle.js.map +0 -7
- package/dist_watch/index.html +0 -28
|
@@ -20,10 +20,10 @@ export class SdigWorkspaceInbox extends DeesElement {
|
|
|
20
20
|
|
|
21
21
|
public static styles = [workspaceBaseStyles, css`
|
|
22
22
|
.filterbar { padding: 14px 24px; border-bottom: 1px solid var(--border-subtle); display: flex; align-items: center; gap: 8px; }
|
|
23
|
-
.searchbox { display: flex; align-items: center; gap: 8px; padding: 0 10px; height: 32px; width: 280px; background: var(--bg-input); border: 1px solid var(--border); border-radius:
|
|
23
|
+
.searchbox { display: flex; align-items: center; gap: 8px; padding: 0 10px; height: 32px; width: 280px; background: var(--bg-input); border: 1px solid var(--border); border-radius: 8px; }
|
|
24
24
|
.searchbox input { flex: 1; min-width: 0; background: transparent; border: none; outline: none; color: var(--text); font-size: 12px; }
|
|
25
|
-
.segmented { display: flex; gap: 2px; padding: 2px; background: var(--bg-el); border-radius:
|
|
26
|
-
.segmented button { padding: 4px 10px; font-size:
|
|
25
|
+
.segmented { display: flex; gap: 2px; padding: 2px; background: var(--bg-el); border-radius: 8px; border: 1px solid var(--border-subtle); }
|
|
26
|
+
.segmented button { padding: 4px 10px; font-size: 11.5px; font-weight: 510; border-radius: 6px; background: transparent; color: var(--text-muted); display: inline-flex; align-items: center; gap: 5px; }
|
|
27
27
|
.segmented button.active { background: var(--bg-card); color: var(--text); box-shadow: inset 0 0 0 1px var(--border); }
|
|
28
28
|
.doc-table { min-width: 880px; }
|
|
29
29
|
.doc-head, .doc-row { display: grid; grid-template-columns: 32px minmax(220px,2.4fr) 150px 160px 90px 60px 32px; align-items: center; gap: 14px; padding: 0 16px; }
|
|
@@ -32,7 +32,7 @@ export class SdigWorkspaceInbox extends DeesElement {
|
|
|
32
32
|
.doc-row.compact { height: 48px; }
|
|
33
33
|
.doc-row:last-child { border-bottom: 0; }
|
|
34
34
|
.doc-row:hover { background: var(--row-hover); }
|
|
35
|
-
.doc-icon { width: 28px; height: 32px; border-radius:
|
|
35
|
+
.doc-icon { width: 28px; height: 32px; border-radius: 6px; background: var(--bg-input); border: 1px solid var(--border); display: flex; align-items: center; justify-content: center; }
|
|
36
36
|
.doc-title { font-size: 13px; color: var(--text); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
37
37
|
.doc-meta { margin-top: 2px; font-size: 11px; color: var(--text-muted); }
|
|
38
38
|
.recipient-stack { display: flex; align-items: center; }
|
|
@@ -68,7 +68,8 @@ export class SdigWorkspaceInbox extends DeesElement {
|
|
|
68
68
|
bubbles: true,
|
|
69
69
|
composed: true,
|
|
70
70
|
}));
|
|
71
|
-
|
|
71
|
+
const view = doc.status === 'draft' ? 'compose' : doc.status === 'signed' || doc.status === 'declined' ? 'audit' : 'sign';
|
|
72
|
+
requestWorkspaceView(this, view);
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
public render(): TemplateResult {
|
|
@@ -84,10 +85,10 @@ export class SdigWorkspaceInbox extends DeesElement {
|
|
|
84
85
|
|
|
85
86
|
return html`
|
|
86
87
|
${topBar({
|
|
87
|
-
breadcrumb: ['signature.digital', '
|
|
88
|
+
breadcrumb: ['signature.digital', 'Example workspace', 'Inbox'],
|
|
88
89
|
title: 'Inbox',
|
|
89
90
|
subtitle: pill(`${attentionCount} need attention`, 'info'),
|
|
90
|
-
actions: html`${actionButton('Import', 'outline', 'upload')}${actionButton('New document', 'primary', 'plus', () => requestWorkspaceView(this, 'compose'))}`,
|
|
91
|
+
actions: html`${actionButton('Import', 'outline', 'upload', () => this.dispatchEvent(new CustomEvent('import-request', { bubbles: true, composed: true })))}${actionButton('New document', 'primary', 'plus', () => requestWorkspaceView(this, 'compose'))}`,
|
|
91
92
|
})}
|
|
92
93
|
<div class="filterbar">
|
|
93
94
|
<div class="searchbox">${icon('search', 13)}<input .value=${this.search} @input=${(event: Event) => this.search = (event.target as HTMLInputElement).value} placeholder="Search documents, recipients, IDs..." /><span class="mono" style="font-size: 10px; color: var(--text-dim); border: 1px solid var(--border); border-radius: 3px; padding: 1px 5px;">⌘K</span></div>
|
|
@@ -113,11 +114,11 @@ export class SdigWorkspaceInbox extends DeesElement {
|
|
|
113
114
|
</div>
|
|
114
115
|
<div class="stats-grid">
|
|
115
116
|
${[
|
|
116
|
-
{ label: '
|
|
117
|
-
{ label: '
|
|
118
|
-
{ label: '
|
|
119
|
-
{ label: '
|
|
120
|
-
].map((metric) => html`<div class="card metric-card"><div style="display: flex; justify-content: space-between; margin-bottom: 12px;">${icon(metric.icon, 14)}<span class="mono" style="font-size: 10px; color: var(--
|
|
117
|
+
{ label: 'Documents', value: documents.length, icon: 'file' },
|
|
118
|
+
{ label: 'Awaiting signatures', value: attentionCount, icon: 'clock' },
|
|
119
|
+
{ label: 'Completed', value: documents.filter((document) => document.status === 'signed').length, icon: 'check' },
|
|
120
|
+
{ label: 'Drafts', value: documents.filter((document) => document.status === 'draft').length, icon: 'code' },
|
|
121
|
+
].map((metric) => html`<div class="card metric-card"><div style="display: flex; justify-content: space-between; margin-bottom: 12px;">${icon(metric.icon, 14)}<span class="mono" style="font-size: 10px; color: var(--text-muted);">current</span></div><div class="metric-value">${metric.value}</div><div style="font-size: 11px; color: var(--text-muted); margin-top: 2px;">${metric.label}</div></div>`)}
|
|
121
122
|
</div>
|
|
122
123
|
</div>
|
|
123
124
|
`;
|
|
@@ -29,7 +29,13 @@ export class SdigWorkspaceSign extends DeesElement {
|
|
|
29
29
|
`];
|
|
30
30
|
|
|
31
31
|
private get signFields() {
|
|
32
|
-
return this.fields
|
|
32
|
+
return this.fields;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private get activeField(): IFieldPlacement | undefined {
|
|
36
|
+
return this.signFields.find((field) => field.id === this.activeFieldId && !this.signedFieldIds.includes(field.id))
|
|
37
|
+
|| this.signFields.find((field) => !this.signedFieldIds.includes(field.id))
|
|
38
|
+
|| this.signFields[0];
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
private fieldIcon(type: IFieldPlacement['type']): string {
|
|
@@ -39,29 +45,59 @@ export class SdigWorkspaceSign extends DeesElement {
|
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
private signField(fieldId: string) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
const field = this.signFields.find((currentField) => currentField.id === fieldId);
|
|
49
|
+
if (!field || this.signedFieldIds.includes(fieldId)) return;
|
|
50
|
+
this.signedFieldIds = [...this.signedFieldIds, fieldId];
|
|
51
|
+
this.dispatchEvent(new CustomEvent('field-signed', {
|
|
52
|
+
detail: { document: this.document, field, signedFieldIds: this.signedFieldIds },
|
|
53
|
+
bubbles: true,
|
|
54
|
+
composed: true,
|
|
55
|
+
}));
|
|
56
|
+
const next = this.signFields.find((currentField) => !this.signedFieldIds.includes(currentField.id));
|
|
46
57
|
if (next) this.activeFieldId = next.id;
|
|
47
58
|
}
|
|
48
59
|
|
|
60
|
+
private emitSigningComplete() {
|
|
61
|
+
if (this.signedFieldIds.length !== this.signFields.length) return;
|
|
62
|
+
this.dispatchEvent(new CustomEvent('signing-complete', {
|
|
63
|
+
detail: {
|
|
64
|
+
document: this.document,
|
|
65
|
+
fields: this.signFields,
|
|
66
|
+
signedFieldIds: this.signedFieldIds,
|
|
67
|
+
completedAt: Date.now(),
|
|
68
|
+
},
|
|
69
|
+
bubbles: true,
|
|
70
|
+
composed: true,
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private handlePrimaryAction() {
|
|
75
|
+
if (!this.signFields.length) return;
|
|
76
|
+
if (this.signedFieldIds.length === this.signFields.length) {
|
|
77
|
+
this.emitSigningComplete();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const activeField = this.activeField;
|
|
81
|
+
if (activeField) this.signField(activeField.id);
|
|
82
|
+
}
|
|
83
|
+
|
|
49
84
|
private renderSignedValue(field: IFieldPlacement): TemplateResult {
|
|
50
|
-
if (field.type === 'signature') return html`<span style="font-
|
|
51
|
-
if (field.type === 'date') return html`<span class="mono" style="font-size: 12px; color: hsl(0 0% 18%);">
|
|
52
|
-
return html`<span style="font-size: 12px; color: hsl(0 0% 18%);">
|
|
85
|
+
if (field.type === 'signature') return html`<span style="font-size: 12px; font-weight: 600; color: hsl(220 50% 30%);">Signature captured</span>`;
|
|
86
|
+
if (field.type === 'date') return html`<span class="mono" style="font-size: 12px; color: hsl(0 0% 18%);">Date captured</span>`;
|
|
87
|
+
return html`<span style="font-size: 12px; color: hsl(0 0% 18%);">Completed</span>`;
|
|
53
88
|
}
|
|
54
89
|
|
|
55
90
|
public render(): TemplateResult {
|
|
56
91
|
const document = this.document || demoDocuments[0];
|
|
57
92
|
const completed = this.signedFieldIds.length;
|
|
58
|
-
const
|
|
59
|
-
const
|
|
93
|
+
const total = this.signFields.length;
|
|
94
|
+
const progress = total ? Math.round((completed / total) * 100) : 0;
|
|
95
|
+
const activeField = this.activeField;
|
|
60
96
|
|
|
61
97
|
return html`
|
|
62
98
|
<div class="recipient-header">
|
|
63
99
|
<div style="display: flex; align-items: center; gap: 12px;"><span class="logomark">s</span><div><div style="font-size: 12px; font-weight: 600;">${document.title}</div><div class="mono" style="font-size: 10px; color: var(--text-muted);">From ${document.sender} · ${document.id} · ${document.pages} pages</div></div></div>
|
|
64
|
-
<div class="actions"><span class="pill
|
|
100
|
+
<div class="actions"><span class="pill info">${icon('shield', 12)} Sender details supplied by host</span>${actionButton('Decline', 'outline')}${actionButton('PDF', 'outline', 'download')}</div>
|
|
65
101
|
</div>
|
|
66
102
|
<div class="progress-track"><div class="progress-fill" style="width: ${progress}%"></div></div>
|
|
67
103
|
<div class="sign-layout">
|
|
@@ -70,23 +106,23 @@ export class SdigWorkspaceSign extends DeesElement {
|
|
|
70
106
|
${fakeDocument()}
|
|
71
107
|
${this.signFields.map((field) => {
|
|
72
108
|
const filled = this.signedFieldIds.includes(field.id);
|
|
73
|
-
const active =
|
|
109
|
+
const active = activeField?.id === field.id && !filled;
|
|
74
110
|
return html`<div class="field-box ${active ? 'selected' : ''}" style="--x: ${field.x}px; --y: ${field.y}px; --w: ${field.w}px; --h: ${field.h}px; --field-color: ${filled ? 'transparent' : 'var(--accent)'}; color: ${filled ? 'hsl(220 50% 30%)' : 'var(--accent)'}; background: ${filled ? 'transparent' : 'color-mix(in srgb, var(--accent) 12%, transparent)'};" @click=${() => !filled ? this.signField(field.id) : undefined}>${filled ? this.renderSignedValue(field) : html`${icon(this.fieldIcon(field.type), 12)}<span>${active ? html`<span style="display: inline-block; width: 5px; height: 5px; border-radius: 50%; background: var(--accent); animation: pulse 1.4s infinite;"></span>` : ''}${field.label}</span>`}</div>`;
|
|
75
111
|
})}
|
|
76
112
|
<div class="mono" style="position: absolute; bottom: 14px; right: 18px; font-size: 9px; color: hsl(0 0% 60%);">Page 1 of ${document.pages}</div>
|
|
77
113
|
</div>
|
|
78
114
|
</div>
|
|
79
115
|
<div class="sign-panel">
|
|
80
|
-
<div style="display: flex; align-items: center; gap: 8px;"><span class="avatar" style="background: #60a5fa;">
|
|
81
|
-
<div class="card" style="padding: 14px; margin-top: 16px;"><div class="label-upper">Your progress</div><div style="font-size: 24px; font-weight: 700;">${completed} <span style="color: var(--text-muted); font-weight: 400;">/ ${
|
|
116
|
+
<div style="display: flex; align-items: center; gap: 8px;"><span class="avatar" style="background: #60a5fa;">SG</span><div><div style="font-size: 13px; font-weight: 600;">Signing session</div><div class="mono" style="font-size: 10px; color: var(--text-muted);">${document.id}</div></div></div>
|
|
117
|
+
<div class="card" style="padding: 14px; margin-top: 16px;"><div class="label-upper">Your progress</div><div style="font-size: 24px; font-weight: 700;">${completed} <span style="color: var(--text-muted); font-weight: 400;">/ ${total}</span></div><div style="font-size: 11px; color: var(--text-muted); margin-top: 2px;">${total === 0 ? 'No fields assigned' : total - completed === 0 ? 'All fields complete' : `${total - completed} fields remaining`}</div><div class="progress-track" style="margin-top: 12px;"><div class="progress-fill" style="width: ${progress}%"></div></div></div>
|
|
82
118
|
<div style="margin-top: 20px;" class="label-upper">Step by step</div>
|
|
83
119
|
${this.signFields.map((field, index) => {
|
|
84
120
|
const filled = this.signedFieldIds.includes(field.id);
|
|
85
|
-
const active =
|
|
121
|
+
const active = activeField?.id === field.id && !filled;
|
|
86
122
|
return html`<div class="recipient-line ${active ? 'active' : ''}" @click=${() => !filled ? this.activeFieldId = field.id : undefined}><span class="avatar" style="width: 22px; height: 22px; background: ${filled ? 'var(--success)' : active ? 'var(--accent)' : 'var(--bg-input)'}; color: ${filled || active ? 'white' : 'var(--text-muted)'};">${filled ? '✓' : index + 1}</span><div style="flex: 1;"><div style="font-size: 12px; font-weight: 500; text-decoration: ${filled ? 'line-through' : 'none'};">${field.label}</div><div class="mono" style="font-size: 10px; color: var(--text-muted);">${field.type} · page ${field.page}</div></div>${active ? icon('chevronRight', 12) : ''}</div>`;
|
|
87
123
|
})}
|
|
88
|
-
<button class="btn primary" style="width: 100%; height: 44px; margin-top: 20px;" @click=${() => this.
|
|
89
|
-
<div style="margin-top: 12px; padding: 10px; font-size: 10px; color: var(--text-muted); line-height: 1.5; text-align: center; border-radius: 6px; background: var(--bg-el);">
|
|
124
|
+
<button class="btn primary" style="width: 100%; height: 44px; margin-top: 20px;" ?disabled=${total === 0} @click=${() => this.handlePrimaryAction()}>${total === 0 ? 'No fields to sign' : completed === total ? 'Finish & submit' : `Continue - ${activeField?.label || 'next field'}`}</button>
|
|
125
|
+
<div style="margin-top: 12px; padding: 10px; font-size: 10px; color: var(--text-muted); line-height: 1.5; text-align: center; border-radius: 6px; background: var(--bg-el);">Field completion is captured locally until the host application submits it through a signing API.</div>
|
|
90
126
|
</div>
|
|
91
127
|
</div>
|
|
92
128
|
`;
|
|
@@ -59,7 +59,7 @@ export const demoDocuments: IDocumentRow[] = [
|
|
|
59
59
|
export const demoRecipients: IRecipient[] = [
|
|
60
60
|
{ id: 0, name: 'Sarah Chen', email: 'sarah@acme.com', color: '#60a5fa', order: 1, role: 'signer' },
|
|
61
61
|
{ id: 1, name: 'David Park', email: 'd.park@acme.com', color: '#fbbf24', order: 2, role: 'signer' },
|
|
62
|
-
{ id: 2, name: '
|
|
62
|
+
{ id: 2, name: 'Alex Example', email: 'alex@example.test', color: '#007aff', order: 3, role: 'copy' },
|
|
63
63
|
];
|
|
64
64
|
|
|
65
65
|
export const demoFields: IFieldPlacement[] = [
|
|
@@ -77,13 +77,14 @@ export const workspaceBaseStyles = css`
|
|
|
77
77
|
min-height: 0;
|
|
78
78
|
color: var(--text);
|
|
79
79
|
background: var(--bg);
|
|
80
|
-
font-family:
|
|
80
|
+
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", Arial, sans-serif;
|
|
81
81
|
font-feature-settings: 'cv11', 'tnum', 'cv05' 1;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
* { box-sizing: border-box; }
|
|
85
85
|
button, input, textarea { font: inherit; }
|
|
86
86
|
button { border: 0; cursor: pointer; }
|
|
87
|
+
button:disabled { cursor: not-allowed; opacity: 0.52; }
|
|
87
88
|
dees-icon { flex-shrink: 0; }
|
|
88
89
|
|
|
89
90
|
.mono {
|
|
@@ -99,7 +100,8 @@ export const workspaceBaseStyles = css`
|
|
|
99
100
|
align-items: center;
|
|
100
101
|
justify-content: space-between;
|
|
101
102
|
border-bottom: 1px solid var(--border-subtle);
|
|
102
|
-
background: var(--bg);
|
|
103
|
+
background: color-mix(in srgb, var(--bg) 72%, transparent);
|
|
104
|
+
backdrop-filter: saturate(180%) blur(20px);
|
|
103
105
|
gap: 12px;
|
|
104
106
|
}
|
|
105
107
|
|
|
@@ -122,10 +124,10 @@ export const workspaceBaseStyles = css`
|
|
|
122
124
|
}
|
|
123
125
|
|
|
124
126
|
.top-title > span:first-child {
|
|
125
|
-
font-family:
|
|
126
|
-
font-size:
|
|
127
|
-
font-weight:
|
|
128
|
-
letter-spacing: -0.
|
|
127
|
+
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Helvetica Neue", Arial, sans-serif;
|
|
128
|
+
font-size: 19px;
|
|
129
|
+
font-weight: 640;
|
|
130
|
+
letter-spacing: -0.022em;
|
|
129
131
|
white-space: nowrap;
|
|
130
132
|
overflow: hidden;
|
|
131
133
|
text-overflow: ellipsis;
|
|
@@ -141,7 +143,7 @@ export const workspaceBaseStyles = css`
|
|
|
141
143
|
.btn {
|
|
142
144
|
height: 34px;
|
|
143
145
|
padding: 0 14px;
|
|
144
|
-
border-radius:
|
|
146
|
+
border-radius: 7px;
|
|
145
147
|
font-size: 13px;
|
|
146
148
|
font-weight: 500;
|
|
147
149
|
letter-spacing: -0.01em;
|
|
@@ -216,7 +218,7 @@ export const workspaceBaseStyles = css`
|
|
|
216
218
|
.card {
|
|
217
219
|
background: var(--bg-card);
|
|
218
220
|
border: 1px solid var(--border);
|
|
219
|
-
border-radius:
|
|
221
|
+
border-radius: 12px;
|
|
220
222
|
overflow: hidden;
|
|
221
223
|
}
|
|
222
224
|
|
|
@@ -341,23 +343,24 @@ export const workspaceBaseStyles = css`
|
|
|
341
343
|
`;
|
|
342
344
|
|
|
343
345
|
export function icon(name: string, size = 14): TemplateResult {
|
|
344
|
-
|
|
345
|
-
inbox: 'lucide:Inbox', plus: 'lucide:Plus', folder: 'lucide:Folder', shield: 'lucide:Shield', code: 'lucide:Code2',
|
|
346
|
-
user: 'lucide:User', settings: 'lucide:Settings', upload: 'lucide:Upload', file: 'lucide:FileText', sign: 'lucide:PenTool',
|
|
347
|
-
clock: 'lucide:Clock', search: 'lucide:Search', more: 'lucide:MoreHorizontal', send: 'lucide:Send', check: 'lucide:Check',
|
|
348
|
-
eye: 'lucide:Eye', calendar: 'lucide:Calendar', type: 'lucide:Type', download: 'lucide:Download', hash: 'lucide:Hash',
|
|
349
|
-
github: 'lucide:GitBranch', git: 'lucide:GitBranch', server: 'lucide:Server', star: 'lucide:Star', sparkle: 'lucide:Sparkles',
|
|
350
|
-
chevronRight: 'lucide:ChevronRight', chevronDown: 'lucide:ChevronDown', x: 'lucide:X', activity: 'lucide:Activity',
|
|
351
|
-
};
|
|
352
|
-
return html`<dees-icon .icon=${iconMap[name] || iconMap.file} style="font-size: ${size}px;"></dees-icon>`;
|
|
346
|
+
return html`<dees-icon .icon=${iconMap[name] || iconMap.file} .iconSize=${size}></dees-icon>`;
|
|
353
347
|
}
|
|
354
348
|
|
|
349
|
+
const iconMap: Record<string, string> = {
|
|
350
|
+
inbox: 'lucide:Inbox', plus: 'lucide:Plus', folder: 'lucide:Folder', shield: 'lucide:Shield', code: 'lucide:Code2',
|
|
351
|
+
user: 'lucide:User', settings: 'lucide:Settings', upload: 'lucide:Upload', file: 'lucide:FileText', sign: 'lucide:PenTool',
|
|
352
|
+
clock: 'lucide:Clock', search: 'lucide:Search', more: 'lucide:MoreHorizontal', send: 'lucide:Send', check: 'lucide:Check',
|
|
353
|
+
eye: 'lucide:Eye', calendar: 'lucide:Calendar', type: 'lucide:Type', download: 'lucide:Download', hash: 'lucide:Hash',
|
|
354
|
+
github: 'lucide:Github', git: 'lucide:GitBranch', server: 'lucide:Server', star: 'lucide:Star', sparkle: 'lucide:Sparkles',
|
|
355
|
+
chevronRight: 'lucide:ChevronRight', chevronDown: 'lucide:ChevronDown', x: 'lucide:X', activity: 'lucide:Activity',
|
|
356
|
+
};
|
|
357
|
+
|
|
355
358
|
export function pill(label: string, tone: 'default' | 'success' | 'warning' | 'error' | 'info' = 'default', dot = false): TemplateResult {
|
|
356
359
|
return html`<span class="pill ${tone} ${dot ? 'dot' : ''}">${label}</span>`;
|
|
357
360
|
}
|
|
358
361
|
|
|
359
362
|
export function actionButton(label: string, variant: 'primary' | 'outline' | 'ghost' = 'outline', iconName?: string, onClick?: () => void): TemplateResult {
|
|
360
|
-
return html`<button class="btn ${variant}"
|
|
363
|
+
return html`<button class="btn ${variant}" ?disabled=${!onClick} title=${onClick ? '' : 'This action must be wired by the host application.'} @click=${onClick}>${iconName ? icon(iconName, 13) : ''}${label}</button>`;
|
|
361
364
|
}
|
|
362
365
|
|
|
363
366
|
export function topBar(config: { breadcrumb: string[]; title: string; subtitle?: TemplateResult; actions?: TemplateResult }): TemplateResult {
|
|
@@ -374,9 +377,9 @@ export function topBar(config: { breadcrumb: string[]; title: string; subtitle?:
|
|
|
374
377
|
`;
|
|
375
378
|
}
|
|
376
379
|
|
|
377
|
-
export function workspaceDemoFrame(content: TemplateResult, theme: TWorkspaceTheme = '
|
|
380
|
+
export function workspaceDemoFrame(content: TemplateResult, theme: TWorkspaceTheme = 'light'): TemplateResult {
|
|
378
381
|
const darkVars = `
|
|
379
|
-
--accent: #
|
|
382
|
+
--accent: #007aff;
|
|
380
383
|
--bg: hsl(0 0% 3.9%);
|
|
381
384
|
--bg-el: hsl(0 0% 6%);
|
|
382
385
|
--bg-card: hsl(0 0% 7%);
|
|
@@ -396,39 +399,39 @@ export function workspaceDemoFrame(content: TemplateResult, theme: TWorkspaceThe
|
|
|
396
399
|
--error: #ef4444;
|
|
397
400
|
`;
|
|
398
401
|
const lightVars = `
|
|
399
|
-
--accent: #
|
|
400
|
-
--bg: hsl(0 0%
|
|
401
|
-
--bg-el: hsl(
|
|
402
|
+
--accent: #007aff;
|
|
403
|
+
--bg: hsl(0 0% 100%);
|
|
404
|
+
--bg-el: hsl(240 9% 96.5%);
|
|
402
405
|
--bg-card: hsl(0 0% 100%);
|
|
403
|
-
--bg-input: hsl(0 0%
|
|
404
|
-
--border: hsl(
|
|
405
|
-
--border-subtle: hsl(
|
|
406
|
-
--border-strong: hsl(
|
|
407
|
-
--text: hsl(
|
|
408
|
-
--text-sec: hsl(
|
|
409
|
-
--text-muted: hsl(
|
|
410
|
-
--text-dim: hsl(
|
|
411
|
-
--hover: rgba(0,0,0,0.
|
|
412
|
-
--hover-subtle: rgba(0,0,0,0.
|
|
413
|
-
--row-hover: rgba(0,0,0,0.
|
|
414
|
-
--success: #
|
|
415
|
-
--warning: #
|
|
416
|
-
--error: #
|
|
406
|
+
--bg-input: hsl(0 0% 100%);
|
|
407
|
+
--border: hsl(240 6% 89%);
|
|
408
|
+
--border-subtle: hsl(240 6% 92.5%);
|
|
409
|
+
--border-strong: hsl(240 6% 80%);
|
|
410
|
+
--text: hsl(240 6% 11%);
|
|
411
|
+
--text-sec: hsl(240 4% 34%);
|
|
412
|
+
--text-muted: hsl(240 3% 52%);
|
|
413
|
+
--text-dim: hsl(240 3% 66%);
|
|
414
|
+
--hover: rgba(0,0,0,0.05);
|
|
415
|
+
--hover-subtle: rgba(0,0,0,0.028);
|
|
416
|
+
--row-hover: rgba(0,0,0,0.028);
|
|
417
|
+
--success: #34c759;
|
|
418
|
+
--warning: #ff9500;
|
|
419
|
+
--error: #ff3b30;
|
|
417
420
|
`;
|
|
418
421
|
|
|
419
|
-
return html`<div style="${theme === 'dark' ? darkVars : lightVars} height: 720px; min-height: 720px; background: var(--bg); color: var(--text); overflow: hidden; font-family:
|
|
422
|
+
return html`<div style="${theme === 'dark' ? darkVars : lightVars} height: 720px; min-height: 720px; background: var(--bg); color: var(--text); overflow: hidden; font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Helvetica Neue', Arial, sans-serif;">${content}</div>`;
|
|
420
423
|
}
|
|
421
424
|
|
|
422
425
|
export function fakeDocument(): TemplateResult {
|
|
423
426
|
return html`
|
|
424
427
|
<div class="fake-document">
|
|
425
428
|
<div class="fake-title">Master Services Agreement</div>
|
|
426
|
-
<div class="mono" style="font-size: 10px; color: hsl(0 0% 45%); margin-bottom: 24px;">Effective: May 2, 2026 · Acme Corp ↔
|
|
429
|
+
<div class="mono" style="font-size: 10px; color: hsl(0 0% 45%); margin-bottom: 24px;">Effective: May 2, 2026 · Acme Corp ↔ Example Company</div>
|
|
427
430
|
${Array.from({ length: 18 }).map((_, index) => html`<div class="fake-line ${index % 5 === 0 ? 'heavy' : ''} ${index % 4 === 3 ? 'short' : ''}"></div>`)}
|
|
428
431
|
<div style="height: 16px;"></div>
|
|
429
432
|
${Array.from({ length: 8 }).map((_, index) => html`<div class="fake-line ${index % 3 === 2 ? 'short' : ''}"></div>`)}
|
|
430
433
|
<div style="margin-top: 60px; font-size: 10px; font-weight: 600; color: hsl(0 0% 35%);">SIGNED ON BEHALF OF ACME CORP</div>
|
|
431
|
-
<div style="margin-top: 70px; font-size: 10px; font-weight: 600; color: hsl(0 0% 35%);">SIGNED ON BEHALF OF
|
|
434
|
+
<div style="margin-top: 70px; font-size: 10px; font-weight: 600; color: hsl(0 0% 35%);">SIGNED ON BEHALF OF EXAMPLE COMPANY</div>
|
|
432
435
|
</div>
|
|
433
436
|
`;
|
|
434
437
|
}
|
|
@@ -15,7 +15,7 @@ declare global {
|
|
|
15
15
|
|
|
16
16
|
@customElement('sdig-workspace')
|
|
17
17
|
export class SdigWorkspace extends DeesElement {
|
|
18
|
-
public static demo = () => html`<sdig-workspace></sdig-workspace>`;
|
|
18
|
+
public static demo = () => html`<sdig-workspace theme="light" accent="#007aff"></sdig-workspace>`;
|
|
19
19
|
public static demoGroups = ['Signature Digital Workspace'];
|
|
20
20
|
|
|
21
21
|
@property({ type: String }) public accessor accent: string = '#3b82f6';
|
|
@@ -69,29 +69,29 @@ export class SdigWorkspace extends DeesElement {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
:host([theme='light']) {
|
|
72
|
-
--bg: hsl(0 0%
|
|
73
|
-
--bg-el: hsl(
|
|
72
|
+
--bg: hsl(0 0% 100%);
|
|
73
|
+
--bg-el: hsl(240 9% 96.5%);
|
|
74
74
|
--bg-card: hsl(0 0% 100%);
|
|
75
|
-
--bg-input: hsl(0 0%
|
|
76
|
-
--border: hsl(
|
|
77
|
-
--border-subtle: hsl(
|
|
78
|
-
--border-strong: hsl(
|
|
79
|
-
--text: hsl(
|
|
80
|
-
--text-sec: hsl(
|
|
81
|
-
--text-muted: hsl(
|
|
82
|
-
--text-dim: hsl(
|
|
83
|
-
--hover: rgba(0,0,0,0.
|
|
84
|
-
--hover-subtle: rgba(0,0,0,0.
|
|
85
|
-
--row-hover: rgba(0,0,0,0.
|
|
86
|
-
--success: #
|
|
87
|
-
--warning: #
|
|
88
|
-
--error: #
|
|
75
|
+
--bg-input: hsl(0 0% 100%);
|
|
76
|
+
--border: hsl(240 6% 89%);
|
|
77
|
+
--border-subtle: hsl(240 6% 92.5%);
|
|
78
|
+
--border-strong: hsl(240 6% 80%);
|
|
79
|
+
--text: hsl(240 6% 11%);
|
|
80
|
+
--text-sec: hsl(240 4% 34%);
|
|
81
|
+
--text-muted: hsl(240 3% 52%);
|
|
82
|
+
--text-dim: hsl(240 3% 66%);
|
|
83
|
+
--hover: rgba(0,0,0,0.05);
|
|
84
|
+
--hover-subtle: rgba(0,0,0,0.028);
|
|
85
|
+
--row-hover: rgba(0,0,0,0.028);
|
|
86
|
+
--success: #34c759;
|
|
87
|
+
--warning: #ff9500;
|
|
88
|
+
--error: #ff3b30;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
* { box-sizing: border-box; }
|
|
92
92
|
button { font: inherit; border: 0; cursor: pointer; }
|
|
93
93
|
.workspace { display: flex; height: 100%; min-height: 720px; background: var(--bg); color: var(--text); overflow: hidden; }
|
|
94
|
-
.sidebar { width:
|
|
94
|
+
.sidebar { width: 224px; background: color-mix(in srgb, var(--bg-el) 94%, transparent); border-right: 1px solid var(--border-subtle); display: flex; flex-direction: column; flex-shrink: 0; height: 100%; backdrop-filter: saturate(180%) blur(20px); }
|
|
95
95
|
.brand { padding: 14px 16px 12px; display: flex; align-items: center; gap: 8px; }
|
|
96
96
|
.logomark { width: 26px; height: 26px; border-radius: 6px; background: var(--bg-el); border: 1px solid var(--border-strong); display: inline-flex; align-items: center; justify-content: center; font-family: 'Plus Jakarta Sans', Inter, sans-serif; font-size: 13px; font-weight: 700; position: relative; }
|
|
97
97
|
.logomark::after, .wordmark::after { content: ''; display: inline-block; border-radius: 50%; background: var(--accent); }
|
|
@@ -99,18 +99,18 @@ export class SdigWorkspace extends DeesElement {
|
|
|
99
99
|
.wordmark { font-size: 13px; font-weight: 500; letter-spacing: -0.02em; white-space: nowrap; }
|
|
100
100
|
.wordmark .dot { color: var(--text-muted); }
|
|
101
101
|
.wordmark::after { width: 4px; height: 4px; margin-left: 3px; transform: translateY(-1px); }
|
|
102
|
-
.workspace-card { margin: 0 12px 8px; padding: 7px 10px; background: var(--bg-
|
|
102
|
+
.workspace-card { margin: 0 12px 8px; padding: 7px 10px; background: var(--bg-card); border: 1px solid var(--border); border-radius: 9px; display: flex; align-items: center; gap: 8px; }
|
|
103
103
|
.workspace-badge { width: 18px; height: 18px; border-radius: 4px; background: linear-gradient(135deg, var(--accent), hsl(280 70% 60%)); color: white; font-size: 10px; font-weight: 700; display: flex; align-items: center; justify-content: center; }
|
|
104
104
|
.workspace-name { font-size: 12px; font-weight: 500; line-height: 1.2; }
|
|
105
105
|
.workspace-plan { font-size: 10px; color: var(--text-muted); }
|
|
106
106
|
.nav-block { padding: 4px 0; }
|
|
107
|
-
.nav-item { display: flex; align-items: center; gap:
|
|
107
|
+
.nav-item { display: flex; align-items: center; gap: 9px; padding: 6px 9px; margin: 1px 9px; border-radius: 7px; color: var(--text-sec); background: transparent; transition: all 0.1s ease; font-size: 13px; position: relative; width: calc(100% - 18px); text-align: left; }
|
|
108
108
|
.compact .nav-item { padding: 5px 10px; }
|
|
109
109
|
.nav-item:hover { background: var(--hover-subtle); color: var(--text-sec); }
|
|
110
|
-
.nav-item.active { background: var(--
|
|
111
|
-
.nav-item.active::before {
|
|
110
|
+
.nav-item.active { background: var(--accent); color: white; font-weight: 510; box-shadow: 0 1px 2px color-mix(in srgb, var(--accent) 42%, transparent); }
|
|
111
|
+
.nav-item.active::before { display: none; }
|
|
112
112
|
.nav-count { margin-left: auto; min-width: 18px; padding: 1px 6px; border-radius: 999px; background: var(--bg-el); color: var(--text-muted); font-size: 10px; text-align: center; }
|
|
113
|
-
.github-card { margin: 8px 12px; padding: 10px; border: 1px solid var(--border
|
|
113
|
+
.github-card { margin: 8px 12px; padding: 10px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg-card); }
|
|
114
114
|
.sparkline { margin-top: 8px; display: flex; gap: 2px; align-items: flex-end; height: 18px; }
|
|
115
115
|
.sparkline span { flex: 1; background: var(--border-strong); border-radius: 1px; }
|
|
116
116
|
.sparkline span:nth-last-child(-n+4) { background: var(--accent); }
|
|
@@ -151,12 +151,12 @@ export class SdigWorkspace extends DeesElement {
|
|
|
151
151
|
return html`
|
|
152
152
|
<aside class="sidebar">
|
|
153
153
|
<div class="brand"><span class="logomark">s</span><span class="wordmark">signature<span class="dot">.</span>digital</span></div>
|
|
154
|
-
<div class="workspace-card"><span class="workspace-badge">
|
|
154
|
+
<div class="workspace-card"><span class="workspace-badge">E</span><div style="flex: 1; min-width: 0;"><div class="workspace-name">Example workspace</div><div class="workspace-plan">Component preview</div></div></div>
|
|
155
155
|
<div class="nav-block">${navItems.map((item) => this.navButton(item))}</div>
|
|
156
156
|
<div style="flex: 1;"></div>
|
|
157
|
-
<div class="github-card"><div style="display: flex; align-items: center; gap: 6px; margin-bottom:
|
|
157
|
+
<div class="github-card"><div style="display: flex; align-items: center; gap: 6px; margin-bottom: 6px; font-size: 11px; color: var(--text-sec); font-family: 'Intel One Mono', ui-monospace;">${icon('code', 13)} host controlled</div><div style="font-size: 10px; line-height: 1.45; color: var(--text-muted);">Demo data is replaceable through component properties and intent events.</div></div>
|
|
158
158
|
<div class="nav-block" style="border-top: 1px solid var(--border-subtle); padding-top: 8px;">${lowerItems.map((item) => this.navButton(item))}</div>
|
|
159
|
-
<div class="user-card"><span class="avatar">
|
|
159
|
+
<div class="user-card"><span class="avatar">DE</span><div style="flex: 1; min-width: 0;"><div style="font-size: 12px; font-weight: 500;">Demo owner</div><div style="font-family: 'Intel One Mono', ui-monospace; font-size: 10px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis;">owner@example.test</div></div>${icon('more', 14)}</div>
|
|
160
160
|
</aside>
|
|
161
161
|
`;
|
|
162
162
|
}
|
|
@@ -177,6 +177,6 @@ export class SdigWorkspace extends DeesElement {
|
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
public render(): TemplateResult {
|
|
180
|
-
return html`<div class="workspace ${this.density === 'compact' ? 'compact' : ''}" style="--accent: ${this.accent};" data-screen-label=${this.view}>${this.renderSidebar()}<main class="main">${this.renderView()}<div class="statusbar"><span style="display: inline-flex; align-items: center; gap: 5px;"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--success);"></span>
|
|
180
|
+
return html`<div class="workspace ${this.density === 'compact' ? 'compact' : ''}" style="--accent: ${this.accent};" data-screen-label=${this.view}>${this.renderSidebar()}<main class="main">${this.renderView()}<div class="statusbar"><span style="display: inline-flex; align-items: center; gap: 5px;"><span style="width: 6px; height: 6px; border-radius: 50%; background: var(--success);"></span>component preview</span><span>${this.documents.length} documents</span><div style="flex: 1;"></div><span style="color: var(--accent);">Open Source · MIT</span><span>host controlled</span></div></main></div>`;
|
|
181
181
|
}
|
|
182
182
|
}
|
package/ts_web/plugins.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
// third party
|
|
2
|
-
import
|
|
3
|
-
type
|
|
4
|
-
const signaturePad = signaturePadMod as any as signaturePadType;
|
|
2
|
+
import SignaturePad from 'signature_pad';
|
|
3
|
+
export type { PointGroup as TSignaturePadPointGroup } from 'signature_pad';
|
|
5
4
|
|
|
6
5
|
export {
|
|
7
|
-
signaturePad,
|
|
6
|
+
SignaturePad as signaturePad,
|
|
8
7
|
}
|
package/.smartconfig.json
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"@git.zone/cli": {
|
|
3
|
-
"projectType": "wcc",
|
|
4
|
-
"module": {
|
|
5
|
-
"githost": "gitlab.com",
|
|
6
|
-
"gitscope": "signature.digital",
|
|
7
|
-
"gitrepo": "catalog",
|
|
8
|
-
"description": "A comprehensive catalog of customizable web components designed for building and managing e-signature applications.",
|
|
9
|
-
"npmPackagename": "@signature.digital/catalog",
|
|
10
|
-
"license": "MIT",
|
|
11
|
-
"projectDomain": "signature.digital",
|
|
12
|
-
"keywords": [
|
|
13
|
-
"e-signature",
|
|
14
|
-
"web components",
|
|
15
|
-
"digital signature",
|
|
16
|
-
"signature capture",
|
|
17
|
-
"ECMAScript Modules",
|
|
18
|
-
"typescript",
|
|
19
|
-
"component library",
|
|
20
|
-
"contract management",
|
|
21
|
-
"frontend development",
|
|
22
|
-
"signature pad",
|
|
23
|
-
"custom elements",
|
|
24
|
-
"electronic signing",
|
|
25
|
-
"npm package"
|
|
26
|
-
]
|
|
27
|
-
},
|
|
28
|
-
"release": {
|
|
29
|
-
"registries": [
|
|
30
|
-
"https://verdaccio.lossless.digital",
|
|
31
|
-
"https://registry.npmjs.org"
|
|
32
|
-
],
|
|
33
|
-
"accessLevel": "public"
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
"@git.zone/tsbundle": {
|
|
37
|
-
"bundles": [
|
|
38
|
-
{
|
|
39
|
-
"from": "./html/index.ts",
|
|
40
|
-
"to": "./dist_bundle/bundle.js",
|
|
41
|
-
"outputMode": "bundle",
|
|
42
|
-
"bundler": "esbuild",
|
|
43
|
-
"production": true,
|
|
44
|
-
"includeFiles": [
|
|
45
|
-
"./html/index.html"
|
|
46
|
-
]
|
|
47
|
-
}
|
|
48
|
-
]
|
|
49
|
-
},
|
|
50
|
-
"@git.zone/tswatch": {
|
|
51
|
-
"server": {
|
|
52
|
-
"enabled": true,
|
|
53
|
-
"port": 3002,
|
|
54
|
-
"serveDir": "./dist_watch/",
|
|
55
|
-
"liveReload": true
|
|
56
|
-
},
|
|
57
|
-
"bundles": [
|
|
58
|
-
{
|
|
59
|
-
"name": "element-bundle",
|
|
60
|
-
"from": "./html/index.ts",
|
|
61
|
-
"to": "./dist_watch/bundle.js",
|
|
62
|
-
"watchPatterns": [
|
|
63
|
-
"./ts_web/**/*",
|
|
64
|
-
"./html/index.ts"
|
|
65
|
-
],
|
|
66
|
-
"triggerReload": true,
|
|
67
|
-
"bundler": "esbuild",
|
|
68
|
-
"production": false
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
"name": "html",
|
|
72
|
-
"from": "./html/index.html",
|
|
73
|
-
"to": "./dist_watch/index.html",
|
|
74
|
-
"watchPatterns": [
|
|
75
|
-
"./html/**/*"
|
|
76
|
-
],
|
|
77
|
-
"triggerReload": true
|
|
78
|
-
}
|
|
79
|
-
]
|
|
80
|
-
},
|
|
81
|
-
"@ship.zone/szci": {}
|
|
82
|
-
}
|