@unlev/exeq 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,566 @@
1
+ /* src/styles/pdf-builder.css */
2
+ .designer-layout,
3
+ .signer-layout {
4
+ display: flex;
5
+ flex-direction: column;
6
+ height: 100vh;
7
+ font-family:
8
+ system-ui,
9
+ -apple-system,
10
+ sans-serif;
11
+ color: #222;
12
+ background: #fafafa;
13
+ }
14
+ .designer-toolbar {
15
+ display: flex;
16
+ justify-content: space-between;
17
+ align-items: center;
18
+ padding: 0.5rem 1rem;
19
+ border-bottom: 1px solid #e5e5e5;
20
+ background: #fff;
21
+ gap: 1rem;
22
+ flex-wrap: wrap;
23
+ }
24
+ .toolbar-left,
25
+ .toolbar-right {
26
+ display: flex;
27
+ align-items: center;
28
+ gap: 0.5rem;
29
+ }
30
+ .designer-content,
31
+ .signer-content {
32
+ display: flex;
33
+ flex: 1;
34
+ overflow: hidden;
35
+ }
36
+ .designer-pdf-area,
37
+ .signer-pdf-area {
38
+ flex: 1;
39
+ overflow-y: auto;
40
+ padding: 1rem;
41
+ background: #eee;
42
+ }
43
+ .designer-panel,
44
+ .signer-panel {
45
+ width: 320px;
46
+ overflow-y: auto;
47
+ border-left: 1px solid #e5e5e5;
48
+ background: #fff;
49
+ padding: 1rem;
50
+ display: flex;
51
+ flex-direction: column;
52
+ gap: 1rem;
53
+ }
54
+ .pdf-viewer {
55
+ display: flex;
56
+ flex-direction: column;
57
+ gap: 1rem;
58
+ align-items: center;
59
+ }
60
+ .pdf-page {
61
+ position: relative;
62
+ width: 100%;
63
+ max-width: 800px;
64
+ background: #fff;
65
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
66
+ cursor: crosshair;
67
+ }
68
+ .pdf-page-image {
69
+ width: 100%;
70
+ height: 100%;
71
+ display: block;
72
+ pointer-events: none;
73
+ }
74
+ .field-overlay {
75
+ position: absolute;
76
+ border: 1.5px solid;
77
+ border-radius: 2px;
78
+ display: flex;
79
+ align-items: center;
80
+ justify-content: center;
81
+ overflow: hidden;
82
+ transition: box-shadow 0.1s;
83
+ }
84
+ .field-overlay.selected {
85
+ box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.2);
86
+ z-index: 10;
87
+ }
88
+ .field-overlay.editable {
89
+ cursor: text;
90
+ }
91
+ .field-overlay-label {
92
+ position: absolute;
93
+ top: -18px;
94
+ left: -1px;
95
+ font-size: 10px;
96
+ color: #fff;
97
+ padding: 1px 6px;
98
+ border-radius: 2px 2px 0 0;
99
+ white-space: nowrap;
100
+ pointer-events: none;
101
+ }
102
+ .field-overlay-placeholder {
103
+ color: #999;
104
+ font-size: 11px;
105
+ padding: 2px 4px;
106
+ width: 100%;
107
+ text-overflow: ellipsis;
108
+ overflow: hidden;
109
+ white-space: nowrap;
110
+ }
111
+ .field-overlay-placeholder.readonly {
112
+ color: #666;
113
+ }
114
+ .field-overlay-value {
115
+ font-size: 11px;
116
+ padding: 2px 4px;
117
+ width: 100%;
118
+ }
119
+ .field-inline-input {
120
+ width: 100%;
121
+ height: 100%;
122
+ border: none;
123
+ background: transparent;
124
+ padding: 2px 4px;
125
+ outline: none;
126
+ font-family: inherit;
127
+ }
128
+ .field-signature-preview {
129
+ width: 100%;
130
+ height: 100%;
131
+ object-fit: contain;
132
+ }
133
+ .field-signature-filled {
134
+ width: 100%;
135
+ height: 100%;
136
+ cursor: pointer;
137
+ }
138
+ .field-checkbox-display {
139
+ width: 100%;
140
+ height: 100%;
141
+ display: flex;
142
+ align-items: center;
143
+ justify-content: center;
144
+ font-size: 16px;
145
+ font-weight: bold;
146
+ }
147
+ .field-checkbox-display.editable {
148
+ cursor: pointer;
149
+ }
150
+ .field-resize-handle {
151
+ position: absolute;
152
+ bottom: 0;
153
+ right: 0;
154
+ width: 10px;
155
+ height: 10px;
156
+ background: #fff;
157
+ border: 1px solid #999;
158
+ cursor: nwse-resize;
159
+ }
160
+ .upload-btn {
161
+ display: inline-block;
162
+ padding: 0.4rem 1rem;
163
+ background: #111;
164
+ color: #fff;
165
+ border: none;
166
+ border-radius: 4px;
167
+ cursor: pointer;
168
+ font-size: 0.85rem;
169
+ font-weight: 500;
170
+ }
171
+ .upload-btn:hover {
172
+ background: #333;
173
+ }
174
+ .upload-btn-small {
175
+ font-size: 0.8rem;
176
+ padding: 0.3rem 0.75rem;
177
+ background: #555;
178
+ }
179
+ .upload-btn-large {
180
+ font-size: 1rem;
181
+ padding: 0.6rem 1.5rem;
182
+ }
183
+ .export-btn {
184
+ padding: 0.4rem 1rem;
185
+ background: #111;
186
+ color: #fff;
187
+ border: none;
188
+ border-radius: 4px;
189
+ cursor: pointer;
190
+ font-size: 0.85rem;
191
+ font-weight: 500;
192
+ }
193
+ .export-btn:hover {
194
+ background: #333;
195
+ }
196
+ .field-type-selector {
197
+ display: flex;
198
+ gap: 2px;
199
+ }
200
+ .field-type-btn {
201
+ padding: 0.3rem 0.6rem;
202
+ background: #fff;
203
+ border: 1px solid #ddd;
204
+ border-radius: 4px;
205
+ cursor: pointer;
206
+ font-size: 0.8rem;
207
+ color: #555;
208
+ }
209
+ .field-type-btn.active {
210
+ background: #111;
211
+ color: #fff;
212
+ border-color: #111;
213
+ }
214
+ .field-type-btn:hover:not(.active) {
215
+ background: #f5f5f5;
216
+ }
217
+ .signer-role-selector {
218
+ padding: 0.5rem 1rem;
219
+ border-bottom: 1px solid #e5e5e5;
220
+ background: #fff;
221
+ }
222
+ .signer-role-label {
223
+ font-size: 0.75rem;
224
+ color: #888;
225
+ margin-bottom: 0.35rem;
226
+ }
227
+ .signer-role-list {
228
+ display: flex;
229
+ gap: 0.35rem;
230
+ flex-wrap: wrap;
231
+ align-items: center;
232
+ }
233
+ .signer-role-chip {
234
+ padding: 0.2rem 0.6rem;
235
+ border: 1.5px solid;
236
+ border-radius: 4px;
237
+ cursor: pointer;
238
+ font-size: 0.8rem;
239
+ font-weight: 500;
240
+ background: transparent;
241
+ transition: all 0.1s;
242
+ }
243
+ .signer-role-remove {
244
+ margin-left: 0.3rem;
245
+ cursor: pointer;
246
+ font-size: 1rem;
247
+ }
248
+ .signer-role-add-btn {
249
+ padding: 0.2rem 0.5rem;
250
+ border: 1px dashed #ccc;
251
+ border-radius: 4px;
252
+ background: none;
253
+ cursor: pointer;
254
+ font-size: 0.8rem;
255
+ color: #888;
256
+ }
257
+ .signer-role-add-input {
258
+ display: flex;
259
+ gap: 0.25rem;
260
+ align-items: center;
261
+ }
262
+ .signer-role-add-input input {
263
+ padding: 0.2rem 0.4rem;
264
+ border: 1px solid #ccc;
265
+ border-radius: 4px;
266
+ font-size: 0.8rem;
267
+ width: 120px;
268
+ }
269
+ .signer-role-add-input button {
270
+ padding: 0.2rem 0.5rem;
271
+ border: 1px solid #ccc;
272
+ border-radius: 4px;
273
+ background: #fff;
274
+ cursor: pointer;
275
+ font-size: 0.8rem;
276
+ }
277
+ .field-property-panel {
278
+ display: flex;
279
+ flex-direction: column;
280
+ gap: 0.75rem;
281
+ }
282
+ .panel-header {
283
+ display: flex;
284
+ justify-content: space-between;
285
+ align-items: center;
286
+ }
287
+ .panel-header h3 {
288
+ margin: 0;
289
+ font-size: 1rem;
290
+ }
291
+ .panel-delete-btn {
292
+ padding: 0.2rem 0.5rem;
293
+ background: none;
294
+ border: 1px solid #e44;
295
+ color: #e44;
296
+ border-radius: 4px;
297
+ cursor: pointer;
298
+ font-size: 0.8rem;
299
+ }
300
+ .panel-delete-btn:hover {
301
+ background: #e44;
302
+ color: #fff;
303
+ }
304
+ .panel-field label {
305
+ display: block;
306
+ font-size: 0.75rem;
307
+ color: #888;
308
+ margin-bottom: 0.2rem;
309
+ }
310
+ .panel-field input[type=text],
311
+ .panel-field input[type=number],
312
+ .panel-field input[type=email],
313
+ .panel-field input[type=tel],
314
+ .panel-field input[type=date],
315
+ .panel-field select {
316
+ width: 100%;
317
+ padding: 0.35rem 0.5rem;
318
+ border: 1px solid #ddd;
319
+ border-radius: 4px;
320
+ font-size: 0.85rem;
321
+ background: #fff;
322
+ }
323
+ .panel-field-group {
324
+ display: grid;
325
+ grid-template-columns: 1fr 1fr;
326
+ gap: 0.5rem;
327
+ }
328
+ .panel-checkbox-label {
329
+ display: flex;
330
+ align-items: center;
331
+ gap: 0.4rem;
332
+ font-size: 0.85rem;
333
+ cursor: pointer;
334
+ }
335
+ .panel-empty {
336
+ color: #888;
337
+ font-size: 0.85rem;
338
+ padding: 2rem 1rem;
339
+ text-align: center;
340
+ }
341
+ .prefill-section {
342
+ border-top: 1px solid #eee;
343
+ padding-top: 0.75rem;
344
+ }
345
+ .prefill-section h4 {
346
+ margin: 0 0 0.5rem;
347
+ font-size: 0.85rem;
348
+ color: #555;
349
+ }
350
+ .prefill-input {
351
+ width: 100%;
352
+ padding: 0.35rem 0.5rem;
353
+ border: 1px solid #ddd;
354
+ border-radius: 4px;
355
+ font-size: 0.85rem;
356
+ }
357
+ .field-list {
358
+ border-top: 1px solid #eee;
359
+ padding-top: 0.75rem;
360
+ }
361
+ .field-list h4 {
362
+ margin: 0 0 0.5rem;
363
+ font-size: 0.85rem;
364
+ color: #555;
365
+ }
366
+ .field-list-item {
367
+ display: flex;
368
+ align-items: center;
369
+ gap: 0.4rem;
370
+ padding: 0.35rem 0.5rem;
371
+ border-radius: 4px;
372
+ cursor: pointer;
373
+ font-size: 0.8rem;
374
+ }
375
+ .field-list-item:hover {
376
+ background: #f5f5f5;
377
+ }
378
+ .field-list-item.active {
379
+ background: #eee;
380
+ }
381
+ .field-list-dot {
382
+ width: 8px;
383
+ height: 8px;
384
+ border-radius: 50%;
385
+ flex-shrink: 0;
386
+ }
387
+ .field-list-name {
388
+ flex: 1;
389
+ overflow: hidden;
390
+ text-overflow: ellipsis;
391
+ white-space: nowrap;
392
+ }
393
+ .field-list-page {
394
+ color: #aaa;
395
+ font-size: 0.75rem;
396
+ }
397
+ .field-list-required {
398
+ color: #e44;
399
+ font-weight: bold;
400
+ }
401
+ .signer-field-input h3 {
402
+ margin: 0 0 0.5rem;
403
+ font-size: 1rem;
404
+ }
405
+ .required-badge {
406
+ display: inline-block;
407
+ font-size: 0.7rem;
408
+ background: #fee;
409
+ color: #c33;
410
+ padding: 1px 6px;
411
+ border-radius: 3px;
412
+ margin-bottom: 0.5rem;
413
+ }
414
+ .signer-text-input {
415
+ width: 100%;
416
+ padding: 0.4rem 0.5rem;
417
+ border: 1px solid #ddd;
418
+ border-radius: 4px;
419
+ font-size: 0.9rem;
420
+ }
421
+ .signer-checkbox-label {
422
+ display: flex;
423
+ align-items: center;
424
+ gap: 0.5rem;
425
+ font-size: 0.9rem;
426
+ cursor: pointer;
427
+ }
428
+ .signer-date-display {
429
+ font-size: 0.9rem;
430
+ color: #555;
431
+ padding: 0.4rem 0;
432
+ }
433
+ .signer-field-readonly {
434
+ color: #888;
435
+ font-size: 0.85rem;
436
+ }
437
+ .signer-field-readonly h3 {
438
+ margin: 0 0 0.25rem;
439
+ font-size: 1rem;
440
+ color: #555;
441
+ }
442
+ .signature-canvas-wrapper {
443
+ display: flex;
444
+ flex-direction: column;
445
+ gap: 0.35rem;
446
+ }
447
+ .signature-canvas {
448
+ border: 1px solid #ddd;
449
+ border-radius: 4px;
450
+ background: #fff;
451
+ cursor: crosshair;
452
+ }
453
+ .signature-canvas-actions {
454
+ display: flex;
455
+ align-items: center;
456
+ justify-content: space-between;
457
+ }
458
+ .signature-clear-btn {
459
+ padding: 0.2rem 0.5rem;
460
+ background: none;
461
+ border: 1px solid #ccc;
462
+ border-radius: 4px;
463
+ cursor: pointer;
464
+ font-size: 0.8rem;
465
+ color: #888;
466
+ }
467
+ .signature-hint {
468
+ font-size: 0.75rem;
469
+ color: #aaa;
470
+ }
471
+ .field-navigator {
472
+ margin-top: auto;
473
+ border-top: 1px solid #eee;
474
+ padding-top: 0.75rem;
475
+ display: flex;
476
+ flex-direction: column;
477
+ gap: 0.5rem;
478
+ }
479
+ .field-navigator-progress {
480
+ font-size: 0.8rem;
481
+ color: #888;
482
+ text-align: center;
483
+ }
484
+ .field-navigator-controls {
485
+ display: flex;
486
+ align-items: center;
487
+ justify-content: center;
488
+ gap: 1rem;
489
+ }
490
+ .nav-btn {
491
+ padding: 0.35rem 1rem;
492
+ border: 1px solid #ddd;
493
+ border-radius: 4px;
494
+ background: #fff;
495
+ cursor: pointer;
496
+ font-size: 0.85rem;
497
+ }
498
+ .nav-btn:hover:not(:disabled) {
499
+ background: #f5f5f5;
500
+ }
501
+ .nav-btn:disabled {
502
+ opacity: 0.4;
503
+ cursor: default;
504
+ }
505
+ .field-navigator-position {
506
+ font-size: 0.85rem;
507
+ color: #888;
508
+ min-width: 50px;
509
+ text-align: center;
510
+ }
511
+ .submit-btn {
512
+ padding: 0.5rem;
513
+ background: #111;
514
+ color: #fff;
515
+ border: none;
516
+ border-radius: 4px;
517
+ cursor: pointer;
518
+ font-size: 0.9rem;
519
+ font-weight: 500;
520
+ }
521
+ .submit-btn:hover:not(:disabled) {
522
+ background: #333;
523
+ }
524
+ .submit-btn:disabled {
525
+ opacity: 0.4;
526
+ cursor: default;
527
+ }
528
+ .loading-indicator {
529
+ text-align: center;
530
+ padding: 2rem;
531
+ color: #888;
532
+ font-size: 0.9rem;
533
+ }
534
+ .empty-state {
535
+ display: flex;
536
+ flex-direction: column;
537
+ align-items: center;
538
+ justify-content: center;
539
+ height: 100%;
540
+ gap: 0.75rem;
541
+ color: #888;
542
+ }
543
+ .empty-state h2 {
544
+ margin: 0;
545
+ font-size: 1.25rem;
546
+ color: #555;
547
+ }
548
+ .empty-state p {
549
+ margin: 0;
550
+ font-size: 0.9rem;
551
+ }
552
+ .powered-by {
553
+ text-align: center;
554
+ padding: 0.4rem;
555
+ font-size: 0.7rem;
556
+ color: #aaa;
557
+ border-top: 1px solid #eee;
558
+ background: #fff;
559
+ }
560
+ .powered-by a {
561
+ color: #888;
562
+ text-decoration: none;
563
+ }
564
+ .powered-by a:hover {
565
+ text-decoration: underline;
566
+ }
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@unlev/exeq",
3
+ "version": "0.1.0",
4
+ "description": "Embeddable PDF form builder and document signing — client-side, no backend required",
5
+ "license": "MIT",
6
+ "main": "dist/index.js",
7
+ "module": "dist/index.mjs",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.mjs",
13
+ "require": "./dist/index.js"
14
+ },
15
+ "./styles": "./dist/styles.css",
16
+ "./embed": "./dist/embed.global.js"
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "sideEffects": [
22
+ "*.css"
23
+ ],
24
+ "keywords": [
25
+ "pdf",
26
+ "form-builder",
27
+ "document-signing",
28
+ "e-signature",
29
+ "pdf-forms",
30
+ "react",
31
+ "embeddable"
32
+ ],
33
+ "scripts": {
34
+ "dev": "next dev",
35
+ "build": "node scripts/build-embed.mjs && next build",
36
+ "build:lib": "tsup",
37
+ "build:embed": "node scripts/build-embed.mjs",
38
+ "prepublishOnly": "tsup",
39
+ "start": "next start",
40
+ "lint": "next lint"
41
+ },
42
+ "peerDependencies": {
43
+ "react": "^18.0.0 || ^19.0.0",
44
+ "react-dom": "^18.0.0 || ^19.0.0"
45
+ },
46
+ "dependencies": {
47
+ "@dnd-kit/core": "^6.3.1",
48
+ "@dnd-kit/sortable": "^10.0.0",
49
+ "@dnd-kit/utilities": "^3.2.2",
50
+ "pdf-lib": "^1.17.1",
51
+ "pdfjs-dist": "^4.10.38",
52
+ "perfect-freehand": "^1.2.2"
53
+ },
54
+ "devDependencies": {
55
+ "@types/node": "^24.10.1",
56
+ "@types/react": "^19.2.7",
57
+ "@types/react-dom": "^19.2.3",
58
+ "esbuild": "^0.25.0",
59
+ "jspdf": "^4.2.0",
60
+ "marked": "^17.0.3",
61
+ "next": "^15.3.2",
62
+ "react": "^19.2.0",
63
+ "react-dom": "^19.2.0",
64
+ "tsup": "^8.5.1",
65
+ "typescript": "~5.9.3"
66
+ }
67
+ }