diff --git a/package.json b/package.json
index dd867c8..6cb472e 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,9 @@
"bcryptjs": "^3.0.3",
"clsx": "^2.1.1",
"drizzle-orm": "^0.45.1",
+ "html2canvas": "^1.4.1",
"jose": "^6.1.3",
+ "jspdf": "^3.0.4",
"lucide-react": "^0.561.0",
"mammoth": "^1.11.0",
"nanoid": "^5.1.6",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index eabd7da..7a57117 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -20,9 +20,15 @@ importers:
drizzle-orm:
specifier: ^0.45.1
version: 0.45.1(@types/pg@8.16.0)(pg@8.16.3)
+ html2canvas:
+ specifier: ^1.4.1
+ version: 1.4.1
jose:
specifier: ^6.1.3
version: 6.1.3
+ jspdf:
+ specifier: ^3.0.4
+ version: 3.0.4
lucide-react:
specifier: ^0.561.0
version: 0.561.0(react@19.2.1)
@@ -299,6 +305,10 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
+ '@babel/runtime@7.28.4':
+ resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==}
+ engines: {node: '>=6.9.0'}
+
'@babel/template@7.27.2':
resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==}
engines: {node: '>=6.9.0'}
@@ -1358,12 +1368,18 @@ packages:
'@types/nodemailer@7.0.4':
resolution: {integrity: sha512-ee8fxWqOchH+Hv6MDDNNy028kwvVnLplrStm4Zf/3uHWw5zzo8FoYYeffpJtGs2wWysEumMH0ZIdMGMY1eMAow==}
+ '@types/pako@2.0.4':
+ resolution: {integrity: sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==}
+
'@types/pg@8.16.0':
resolution: {integrity: sha512-RmhMd/wD+CF8Dfo+cVIy3RR5cl8CyfXQ0tGgW6XBL8L4LM/UTEbNXYRbLwU6w+CgrKBNbrQWt4FUtTfaU5jSYQ==}
'@types/prismjs@1.26.5':
resolution: {integrity: sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==}
+ '@types/raf@3.4.3':
+ resolution: {integrity: sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==}
+
'@types/react-dom@19.2.3':
resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
peerDependencies:
@@ -1372,6 +1388,9 @@ packages:
'@types/react@19.2.7':
resolution: {integrity: sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==}
+ '@types/trusted-types@2.0.7':
+ resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
+
'@types/unist@2.0.11':
resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
@@ -1627,6 +1646,10 @@ packages:
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ base64-arraybuffer@1.0.2:
+ resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==}
+ engines: {node: '>= 0.6.0'}
+
base64-js@1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
@@ -1684,6 +1707,10 @@ packages:
caniuse-lite@1.0.30001760:
resolution: {integrity: sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==}
+ canvg@3.0.11:
+ resolution: {integrity: sha512-5ON+q7jCTgMp9cjpu4Jo6XbvfYwSB2Ow3kzHKfIyJfaCAOHLbdKPQqGKgfED/R5B+3TFFfe8pegYA+b423SRyA==}
+ engines: {node: '>=10.0.0'}
+
ccount@2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
@@ -1734,6 +1761,9 @@ packages:
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ core-js@3.47.0:
+ resolution: {integrity: sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==}
+
core-util-is@1.0.3:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
@@ -1746,6 +1776,9 @@ packages:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'}
+ css-line-break@2.1.0:
+ resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==}
+
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
@@ -1813,6 +1846,9 @@ packages:
resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
engines: {node: '>=0.10.0'}
+ dompurify@3.3.1:
+ resolution: {integrity: sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==}
+
drizzle-kit@0.31.8:
resolution: {integrity: sha512-O9EC/miwdnRDY10qRxM8P3Pg8hXe3LyU4ZipReKOgTwn4OqANmftj8XJz1UPUAS6NMHf0E2htjsbQujUTkncCg==}
hasBin: true
@@ -2125,6 +2161,9 @@ packages:
fast-levenshtein@2.0.6:
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+ fast-png@6.4.0:
+ resolution: {integrity: sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==}
+
fast-xml-parser@5.2.5:
resolution: {integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==}
hasBin: true
@@ -2144,6 +2183,9 @@ packages:
picomatch:
optional: true
+ fflate@0.8.2:
+ resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
+
file-entry-cache@8.0.0:
resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
engines: {node: '>=16.0.0'}
@@ -2278,6 +2320,10 @@ packages:
html-url-attributes@3.0.1:
resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
+ html2canvas@1.4.1:
+ resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==}
+ engines: {node: '>=8.0.0'}
+
ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
@@ -2307,6 +2353,9 @@ packages:
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
+ iobuffer@5.4.0:
+ resolution: {integrity: sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==}
+
is-alphabetical@2.0.1:
resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
@@ -2476,6 +2525,9 @@ packages:
engines: {node: '>=6'}
hasBin: true
+ jspdf@3.0.4:
+ resolution: {integrity: sha512-dc6oQ8y37rRcHn316s4ngz/nOjayLF/FFxBF4V9zamQKRqXxyiH1zagkCdktdWhtoQId5K20xt1lB90XzkB+hQ==}
+
jsx-ast-utils@3.3.5:
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
engines: {node: '>=4.0'}
@@ -2860,6 +2912,9 @@ packages:
pako@1.0.11:
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
+ pako@2.1.0:
+ resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==}
+
parent-module@1.0.1:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
@@ -2885,6 +2940,9 @@ packages:
pend@1.2.0:
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
+ performance-now@2.1.0:
+ resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==}
+
pg-cloudflare@1.2.7:
resolution: {integrity: sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==}
@@ -2982,6 +3040,9 @@ packages:
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+ raf@3.4.1:
+ resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==}
+
react-dom@19.2.1:
resolution: {integrity: sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==}
peerDependencies:
@@ -3007,6 +3068,9 @@ packages:
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
engines: {node: '>= 0.4'}
+ regenerator-runtime@0.13.11:
+ resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==}
+
regexp.prototype.flags@1.5.4:
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
engines: {node: '>= 0.4'}
@@ -3043,6 +3107,10 @@ packages:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ rgbcolor@1.0.1:
+ resolution: {integrity: sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==}
+ engines: {node: '>= 0.8.15'}
+
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
@@ -3154,6 +3222,10 @@ packages:
stable-hash@0.0.5:
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
+ stackblur-canvas@2.7.0:
+ resolution: {integrity: sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==}
+ engines: {node: '>=0.1.14'}
+
stop-iteration-iterator@1.1.0:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'}
@@ -3225,6 +3297,10 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
+ svg-pathdata@6.0.3:
+ resolution: {integrity: sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==}
+ engines: {node: '>=12.0.0'}
+
tailwindcss@4.1.18:
resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==}
@@ -3232,6 +3308,9 @@ packages:
resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
engines: {node: '>=6'}
+ text-segmentation@1.0.3:
+ resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==}
+
tinyglobby@0.2.15:
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
engines: {node: '>=12.0.0'}
@@ -3338,6 +3417,9 @@ packages:
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+ utrie@1.0.2:
+ resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==}
+
vfile-message@4.0.3:
resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
@@ -3897,6 +3979,8 @@ snapshots:
dependencies:
'@babel/types': 7.28.5
+ '@babel/runtime@7.28.4': {}
+
'@babel/template@7.27.2':
dependencies:
'@babel/code-frame': 7.27.1
@@ -4787,6 +4871,8 @@ snapshots:
transitivePeerDependencies:
- aws-crt
+ '@types/pako@2.0.4': {}
+
'@types/pg@8.16.0':
dependencies:
'@types/node': 20.19.27
@@ -4795,6 +4881,9 @@ snapshots:
'@types/prismjs@1.26.5': {}
+ '@types/raf@3.4.3':
+ optional: true
+
'@types/react-dom@19.2.3(@types/react@19.2.7)':
dependencies:
'@types/react': 19.2.7
@@ -4803,6 +4892,9 @@ snapshots:
dependencies:
csstype: 3.2.3
+ '@types/trusted-types@2.0.7':
+ optional: true
+
'@types/unist@2.0.11': {}
'@types/unist@3.0.3': {}
@@ -5071,6 +5163,8 @@ snapshots:
balanced-match@1.0.2: {}
+ base64-arraybuffer@1.0.2: {}
+
base64-js@1.5.1: {}
baseline-browser-mapping@2.9.9: {}
@@ -5127,6 +5221,18 @@ snapshots:
caniuse-lite@1.0.30001760: {}
+ canvg@3.0.11:
+ dependencies:
+ '@babel/runtime': 7.28.4
+ '@types/raf': 3.4.3
+ core-js: 3.47.0
+ raf: 3.4.1
+ regenerator-runtime: 0.13.11
+ rgbcolor: 1.0.1
+ stackblur-canvas: 2.7.0
+ svg-pathdata: 6.0.3
+ optional: true
+
ccount@2.0.1: {}
cfb@1.2.2:
@@ -5165,6 +5271,9 @@ snapshots:
convert-source-map@2.0.0: {}
+ core-js@3.47.0:
+ optional: true
+
core-util-is@1.0.3: {}
crc-32@1.2.2: {}
@@ -5175,6 +5284,10 @@ snapshots:
shebang-command: 2.0.0
which: 2.0.2
+ css-line-break@2.1.0:
+ dependencies:
+ utrie: 1.0.2
+
csstype@3.2.3: {}
damerau-levenshtein@1.0.8: {}
@@ -5237,6 +5350,11 @@ snapshots:
dependencies:
esutils: 2.0.3
+ dompurify@3.3.1:
+ optionalDependencies:
+ '@types/trusted-types': 2.0.7
+ optional: true
+
drizzle-kit@0.31.8:
dependencies:
'@drizzle-team/brocli': 0.10.2
@@ -5688,6 +5806,12 @@ snapshots:
fast-levenshtein@2.0.6: {}
+ fast-png@6.4.0:
+ dependencies:
+ '@types/pako': 2.0.4
+ iobuffer: 5.4.0
+ pako: 2.1.0
+
fast-xml-parser@5.2.5:
dependencies:
strnum: 2.1.2
@@ -5704,6 +5828,8 @@ snapshots:
optionalDependencies:
picomatch: 4.0.3
+ fflate@0.8.2: {}
+
file-entry-cache@8.0.0:
dependencies:
flat-cache: 4.0.1
@@ -5853,6 +5979,11 @@ snapshots:
html-url-attributes@3.0.1: {}
+ html2canvas@1.4.1:
+ dependencies:
+ css-line-break: 2.1.0
+ text-segmentation: 1.0.3
+
ignore@5.3.2: {}
ignore@7.0.5: {}
@@ -5876,6 +6007,8 @@ snapshots:
hasown: 2.0.2
side-channel: 1.1.0
+ iobuffer@5.4.0: {}
+
is-alphabetical@2.0.1: {}
is-alphanumerical@2.0.1:
@@ -6040,6 +6173,17 @@ snapshots:
json5@2.2.3: {}
+ jspdf@3.0.4:
+ dependencies:
+ '@babel/runtime': 7.28.4
+ fast-png: 6.4.0
+ fflate: 0.8.2
+ optionalDependencies:
+ canvg: 3.0.11
+ core-js: 3.47.0
+ dompurify: 3.3.1
+ html2canvas: 1.4.1
+
jsx-ast-utils@3.3.5:
dependencies:
array-includes: 3.1.9
@@ -6636,6 +6780,8 @@ snapshots:
pako@1.0.11: {}
+ pako@2.1.0: {}
+
parent-module@1.0.1:
dependencies:
callsites: 3.1.0
@@ -6660,6 +6806,9 @@ snapshots:
pend@1.2.0: {}
+ performance-now@2.1.0:
+ optional: true
+
pg-cloudflare@1.2.7:
optional: true
@@ -6743,6 +6892,11 @@ snapshots:
queue-microtask@1.2.3: {}
+ raf@3.4.1:
+ dependencies:
+ performance-now: 2.1.0
+ optional: true
+
react-dom@19.2.1(react@19.2.1):
dependencies:
react: 19.2.1
@@ -6791,6 +6945,9 @@ snapshots:
get-proto: 1.0.1
which-builtin-type: 1.2.1
+ regenerator-runtime@0.13.11:
+ optional: true
+
regexp.prototype.flags@1.5.4:
dependencies:
call-bind: 1.0.8
@@ -6852,6 +7009,9 @@ snapshots:
reusify@1.1.0: {}
+ rgbcolor@1.0.1:
+ optional: true
+
run-parallel@1.2.0:
dependencies:
queue-microtask: 1.2.3
@@ -7003,6 +7163,9 @@ snapshots:
stable-hash@0.0.5: {}
+ stackblur-canvas@2.7.0:
+ optional: true
+
stop-iteration-iterator@1.1.0:
dependencies:
es-errors: 1.3.0
@@ -7094,10 +7257,17 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
+ svg-pathdata@6.0.3:
+ optional: true
+
tailwindcss@4.1.18: {}
tapable@2.3.0: {}
+ text-segmentation@1.0.3:
+ dependencies:
+ utrie: 1.0.2
+
tinyglobby@0.2.15:
dependencies:
fdir: 6.5.0(picomatch@4.0.3)
@@ -7261,6 +7431,10 @@ snapshots:
util-deprecate@1.0.2: {}
+ utrie@1.0.2:
+ dependencies:
+ base64-arraybuffer: 1.0.2
+
vfile-message@4.0.3:
dependencies:
'@types/unist': 3.0.3
diff --git a/src/app/chat/[id]/page.tsx b/src/app/chat/[id]/page.tsx
index 856b554..0999c19 100644
--- a/src/app/chat/[id]/page.tsx
+++ b/src/app/chat/[id]/page.tsx
@@ -3,7 +3,7 @@
import { useState, useRef, useEffect, use } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import Link from 'next/link';
-import { Share2, MoreHorizontal, Loader2, Square, Clock, ChevronDown, Pencil, Trash2, Check, X, AlertTriangle, Settings } from 'lucide-react';
+import { Share2, Loader2, Square, Clock, ChevronDown, Pencil, Trash2, Check, X, AlertTriangle, Settings } from 'lucide-react';
import { Sidebar, SidebarToggle } from '@/components/layout/Sidebar';
import { ChatInput } from '@/components/features/ChatInput';
import { MessageBubble } from '@/components/features/MessageBubble';
@@ -11,6 +11,7 @@ import { ChatHeaderInfo } from '@/components/features/ChatHeader';
import { SaveToNoteModal } from '@/components/features/SaveToNoteModal';
import { PromptOptimizer } from '@/components/features/PromptOptimizer';
import { LinkPreviewModal } from '@/components/features/LinkPreviewModal';
+import { ExportDropdown } from '@/components/features/ExportDropdown';
import { cn } from '@/lib/utils';
import { useConversation, useConversations } from '@/hooks/useConversations';
import { useStreamChat, type ChatMessage } from '@/hooks/useStreamChat';
@@ -503,12 +504,11 @@ export default function ChatPage({ params }: PageProps) {
分享
-
+