'@mirohq/miro-api':
specifier: ^2.2.2
version: 2.2.2
+ canvas:
+ specifier: ^3.0.1
+ version: 3.0.1
cookie:
specifier: ^0.5.0
version: 0.5.0
devDependencies:
'@mirohq/websdk-types':
specifier: latest
- version: 2.16.1(@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@4.9.5))(eslint@9.18.0)(typescript@4.9.5))(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@4.9.5))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@4.9.5))(eslint-import-resolver-typescript@3.7.0)(eslint@9.18.0))(eslint@9.18.0)
+ version: 2.16.1(@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@4.9.5))(eslint@9.18.0)(typescript@4.9.5))(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@4.9.5))(eslint-plugin-import@2.31.0)(eslint@9.18.0)
'@types/cookie':
specifier: ^0.5.4
version: 0.5.4
specifier: 19.0.2
version: 19.0.2(@types/react@19.0.4)
eslint:
- specifier: ^9
+ specifier: ^9.18.0
version: 9.18.0
eslint-config-next:
specifier: 15.1.4
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ base64-js@1.5.1:
+ resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+
+ bl@4.1.0:
+ resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
+
brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
+ buffer@5.7.1:
+ resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
+
busboy@1.6.0:
resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
engines: {node: '>=10.16.0'}
caniuse-lite@1.0.30001692:
resolution: {integrity: sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==}
+ canvas@3.0.1:
+ resolution: {integrity: sha512-PcpVF4f8RubAeN/jCQQ/UymDKzOiLmRPph8fOTzDnlsUihkO/AUlxuhaa7wGRc3vMcCbV1fzuvyu5cWZlIcn1w==}
+ engines: {node: ^18.12.0 || >= 20.9.0}
+
chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
+ chownr@1.1.4:
+ resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
+
client-only@0.0.1:
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
supports-color:
optional: true
+ decompress-response@4.2.1:
+ resolution: {integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==}
+ engines: {node: '>=8'}
+
+ decompress-response@6.0.0:
+ resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
+ engines: {node: '>=10'}
+
+ deep-extend@0.6.0:
+ resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
+ engines: {node: '>=4.0.0'}
+
deep-is@0.1.4:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+ end-of-stream@1.4.4:
+ resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
+
enhanced-resolve@5.18.0:
resolution: {integrity: sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==}
engines: {node: '>=10.13.0'}
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
+ expand-template@2.0.3:
+ resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
+ engines: {node: '>=6'}
+
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==}
engines: {node: '>= 6'}
+ fs-constants@1.0.0:
+ resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
+
function-bind@1.1.2:
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
get-tsconfig@4.8.1:
resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==}
+ github-from-package@0.0.0:
+ resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
+
glob-parent@5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
html-entities@2.5.2:
resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==}
+ ieee754@1.2.1:
+ resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+
ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+ ini@1.3.8:
+ resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
+
internal-slot@1.1.0:
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
engines: {node: '>= 0.6'}
+ mimic-response@2.1.0:
+ resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==}
+ engines: {node: '>=8'}
+
+ mimic-response@3.1.0:
+ resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
+ engines: {node: '>=10'}
+
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
mirotone@5.3.0:
resolution: {integrity: sha512-PsAMyy48OwGleHWtOCGscjcqt2U5tFbFvTKdUeamv9+bGvt7lQHHkpccQLCqdKfMJeAIySRAJggMDmm7fls+kQ==}
+ mkdirp-classic@0.5.3:
+ resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
+
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
+ napi-build-utils@1.0.2:
+ resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==}
+
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
sass:
optional: true
+ node-abi@3.71.0:
+ resolution: {integrity: sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==}
+ engines: {node: '>=10'}
+
node-addon-api@7.1.1:
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
engines: {node: '>= 0.4'}
+ once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
optionator@0.9.4:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'}
resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
engines: {node: ^10 || ^12 || >=14}
+ prebuild-install@7.1.2:
+ resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==}
+ engines: {node: '>=10'}
+ hasBin: true
+
prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+ pump@3.0.2:
+ resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==}
+
punycode@2.3.1:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
resolution: {integrity: sha512-fhNEG0vGi7bESitNNqNBAfYPdl2efB+1paFlI8BQDCNkruERKuuhG8LkQClDIVqUJLkrmKuOSPQ3xZHqVnVo3Q==}
engines: {node: '>=14.18.0'}
+ rc@1.2.8:
+ resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
+ hasBin: true
+
react-dom@19.0.0:
resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==}
peerDependencies:
readable-stream@2.3.8:
resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
- readdirp@4.0.2:
- resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==}
- engines: {node: '>= 14.16.0'}
+ readable-stream@3.6.2:
+ resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
+ engines: {node: '>= 6'}
+
+ readdirp@4.1.1:
+ resolution: {integrity: sha512-h80JrZu/MHUZCyHu5ciuoI0+WxsCxzxJTILn6Fs8rxSnFPh+UVHYfeIxK1nVGugMqkfC4vJcBOYbkfkwYK0+gw==}
+ engines: {node: '>= 14.18.0'}
reflect.getprototypeof@1.0.10:
resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
engines: {node: '>= 0.4'}
+ simple-concat@1.0.1:
+ resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
+
+ simple-get@3.1.1:
+ resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==}
+
+ simple-get@4.0.1:
+ resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
+
simple-swizzle@0.2.2:
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
engines: {node: '>=4'}
+ strip-json-comments@2.0.1:
+ resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
+ engines: {node: '>=0.10.0'}
+
strip-json-comments@3.1.1:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
engines: {node: '>=6'}
+ tar-fs@2.1.2:
+ resolution: {integrity: sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==}
+
+ tar-stream@2.2.0:
+ resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
+ engines: {node: '>=6'}
+
through2@0.4.2:
resolution: {integrity: sha512-45Llu+EwHKtAZYTPPVn3XZHBgakWMN3rokhEv5hu596XP+cNgplMg+Gj+1nmAvj+L0K7+N49zBKx5rah5u0QIQ==}
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+ tunnel-agent@0.6.0:
+ resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
+
type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'}
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
xtend@2.1.2:
resolution: {integrity: sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ==}
engines: {node: '>=0.4'}
transitivePeerDependencies:
- encoding
- '@mirohq/websdk-types@2.16.1(@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@4.9.5))(eslint@9.18.0)(typescript@4.9.5))(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@4.9.5))(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@4.9.5))(eslint-import-resolver-typescript@3.7.0)(eslint@9.18.0))(eslint@9.18.0)':
+ '@mirohq/websdk-types@2.16.1(@typescript-eslint/eslint-plugin@8.19.1(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@4.9.5))(eslint@9.18.0)(typescript@4.9.5))(@typescript-eslint/parser@8.19.1(eslint@9.18.0)(typescript@4.9.5))(eslint-plugin-import@2.31.0)(eslint@9.18.0)':
dependencies:
typescript: 4.9.5
optionalDependencies:
balanced-match@1.0.2: {}
+ base64-js@1.5.1: {}
+
+ bl@4.1.0:
+ dependencies:
+ buffer: 5.7.1
+ inherits: 2.0.4
+ readable-stream: 3.6.2
+
brace-expansion@1.1.11:
dependencies:
balanced-match: 1.0.2
dependencies:
fill-range: 7.1.1
+ buffer@5.7.1:
+ dependencies:
+ base64-js: 1.5.1
+ ieee754: 1.2.1
+
busboy@1.6.0:
dependencies:
streamsearch: 1.1.0
caniuse-lite@1.0.30001692: {}
+ canvas@3.0.1:
+ dependencies:
+ node-addon-api: 7.1.1
+ prebuild-install: 7.1.2
+ simple-get: 3.1.1
+
chalk@4.1.2:
dependencies:
ansi-styles: 4.3.0
chokidar@4.0.3:
dependencies:
- readdirp: 4.0.2
+ readdirp: 4.1.1
+
+ chownr@1.1.4: {}
client-only@0.0.1: {}
dependencies:
ms: 2.1.3
+ decompress-response@4.2.1:
+ dependencies:
+ mimic-response: 2.1.0
+
+ decompress-response@6.0.0:
+ dependencies:
+ mimic-response: 3.1.0
+
+ deep-extend@0.6.0: {}
+
deep-is@0.1.4: {}
define-data-property@1.1.4:
detect-libc@1.0.3:
optional: true
- detect-libc@2.0.3:
- optional: true
+ detect-libc@2.0.3: {}
doctrine@2.1.0:
dependencies:
emoji-regex@9.2.2: {}
+ end-of-stream@1.4.4:
+ dependencies:
+ once: 1.4.0
+
enhanced-resolve@5.18.0:
dependencies:
graceful-fs: 4.2.11
esutils@2.0.3: {}
+ expand-template@2.0.3: {}
+
fast-deep-equal@3.1.3: {}
fast-glob@3.3.1:
combined-stream: 1.0.8
mime-types: 2.1.35
+ fs-constants@1.0.0: {}
+
function-bind@1.1.2: {}
function.prototype.name@1.1.8:
dependencies:
resolve-pkg-maps: 1.0.0
+ github-from-package@0.0.0: {}
+
glob-parent@5.1.2:
dependencies:
is-glob: 4.0.3
html-entities@2.5.2: {}
+ ieee754@1.2.1: {}
+
ignore@5.3.2: {}
immutable@5.0.3: {}
inherits@2.0.4: {}
+ ini@1.3.8: {}
+
internal-slot@1.1.0:
dependencies:
es-errors: 1.3.0
dependencies:
mime-db: 1.52.0
+ mimic-response@2.1.0: {}
+
+ mimic-response@3.1.0: {}
+
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.11
'@mirohq/design-tokens': 5.1.1
gulp-file: 0.4.0
+ mkdirp-classic@0.5.3: {}
+
ms@2.1.3: {}
nanoid@3.3.8: {}
+ napi-build-utils@1.0.2: {}
+
natural-compare@1.4.0: {}
next@15.1.4(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(sass@1.83.1):
- '@babel/core'
- babel-plugin-macros
- node-addon-api@7.1.1:
- optional: true
+ node-abi@3.71.0:
+ dependencies:
+ semver: 7.6.3
+
+ node-addon-api@7.1.1: {}
node-fetch@2.7.0:
dependencies:
define-properties: 1.2.1
es-object-atoms: 1.0.0
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
optionator@0.9.4:
dependencies:
deep-is: 0.1.4
picocolors: 1.1.1
source-map-js: 1.2.1
+ prebuild-install@7.1.2:
+ dependencies:
+ detect-libc: 2.0.3
+ expand-template: 2.0.3
+ github-from-package: 0.0.0
+ minimist: 1.2.8
+ mkdirp-classic: 0.5.3
+ napi-build-utils: 1.0.2
+ node-abi: 3.71.0
+ pump: 3.0.2
+ rc: 1.2.8
+ simple-get: 4.0.1
+ tar-fs: 2.1.2
+ tunnel-agent: 0.6.0
+
prelude-ls@1.2.1: {}
process-nextick-args@2.0.1: {}
object-assign: 4.1.1
react-is: 16.13.1
+ pump@3.0.2:
+ dependencies:
+ end-of-stream: 1.4.4
+ once: 1.4.0
+
punycode@2.3.1: {}
queue-microtask@1.2.3: {}
ranges-sort@6.0.11: {}
+ rc@1.2.8:
+ dependencies:
+ deep-extend: 0.6.0
+ ini: 1.3.8
+ minimist: 1.2.8
+ strip-json-comments: 2.0.1
+
react-dom@19.0.0(react@19.0.0):
dependencies:
react: 19.0.0
string_decoder: 1.1.1
util-deprecate: 1.0.2
- readdirp@4.0.2: {}
+ readable-stream@3.6.2:
+ dependencies:
+ inherits: 2.0.4
+ string_decoder: 1.1.1
+ util-deprecate: 1.0.2
+
+ readdirp@4.1.1: {}
reflect.getprototypeof@1.0.10:
dependencies:
side-channel-map: 1.0.1
side-channel-weakmap: 1.0.2
+ simple-concat@1.0.1: {}
+
+ simple-get@3.1.1:
+ dependencies:
+ decompress-response: 4.2.1
+ once: 1.4.0
+ simple-concat: 1.0.1
+
+ simple-get@4.0.1:
+ dependencies:
+ decompress-response: 6.0.0
+ once: 1.4.0
+ simple-concat: 1.0.1
+
simple-swizzle@0.2.2:
dependencies:
is-arrayish: 0.3.2
strip-bom@3.0.0: {}
+ strip-json-comments@2.0.1: {}
+
strip-json-comments@3.1.1: {}
styled-jsx@5.1.6(react@19.0.0):
tapable@2.2.1: {}
+ tar-fs@2.1.2:
+ dependencies:
+ chownr: 1.1.4
+ mkdirp-classic: 0.5.3
+ pump: 3.0.2
+ tar-stream: 2.2.0
+
+ tar-stream@2.2.0:
+ dependencies:
+ bl: 4.1.0
+ end-of-stream: 1.4.4
+ fs-constants: 1.0.0
+ inherits: 2.0.4
+ readable-stream: 3.6.2
+
through2@0.4.2:
dependencies:
readable-stream: 1.0.34
tslib@2.8.1: {}
+ tunnel-agent@0.6.0:
+ dependencies:
+ safe-buffer: 5.1.2
+
type-check@0.4.0:
dependencies:
prelude-ls: 1.2.1
word-wrap@1.2.5: {}
+ wrappy@1.0.2: {}
+
xtend@2.1.2:
dependencies:
object-keys: 0.4.0
import { Path, Shape, Slide, Whiteboard, Image, neoboardWhiteboardWidth, neoboardWhiteboardHeight } from './neoboardTypes';
import { stripHtml } from 'string-strip-html';
import { GenericItemCursorPaged } from '@mirohq/miro-api/dist/api';
+import { createCanvas } from 'canvas';
export type FormState = {
neoboards: {
}
];
- console.log('points', points);
-
const path: Path = {
type: 'path',
let maxY = Number.MIN_VALUE;
for (const item of slide.elements) {
- if (item.type === 'shape' || item.type === 'image') {
+ // @ts-expect-error - Internal type for scaling used for text shapes
+ if (item.type === 'shape' || item.type === 'image' || item.type === 'textshape') {
const shape = item as Shape;
// Make sure that we deal with x and y being in the center of the shape and not the corner.
// This means the bounds of the shape itself are x - width / 2, y - height / 2, x + width / 2, y + height / 2
for (const item of slide.elements) {
if (item.type === 'shape' || item.type === 'image') {
const shape = item;
+
+ // Scale the font size as well
+ if (shape.type === 'shape') {
+ if (shape.textSize) {
+ shape.textSize = shape.textSize * scale;
+ }
+ }
+
// Ensure we account for the fact that our coordinates are in the center of the shape currently but we require them to be at the top left
// This means we need to substract half of the width from the x and substract half of the height to the y
const transformedShape = {
};
transformedSlide.elements.push(transformedPath);
+ // @ts-expect-error - Internal type for scaling used for text shapes
+ } else if (item.type === 'textshape') {
+ const shape = item as Shape;
+ if (shape.textSize) {
+ shape.textSize = shape.textSize * scale;
+ }
+
+ const newWidth = shape.width * scale;
+
+ // Recalculate the bounding box of the text as the font and width are changed
+ const textBounds = calculateTextBoundingBox(shape.text, shape.textSize ?? 16, "Inter", newWidth);
+
+ const transformedShape = {
+ ...shape,
+ type: 'shape' as const,
+ position: {
+ x: (shape.position.x - minX - shape.width / 2) * scale + neoboardPadding,
+ y: (shape.position.y - minY - shape.height / 2) * scale + neoboardPadding,
+ },
+ width: textBounds.width,
+ height: textBounds.height,
+ };
+
+ transformedSlide.elements.push(transformedShape);
}
}
}
function hexToRGB(hex: string, alpha?: number): string {
- var r = parseInt(hex.slice(1, 3), 16),
+ const r = parseInt(hex.slice(1, 3), 16),
g = parseInt(hex.slice(3, 5), 16),
b = parseInt(hex.slice(5, 7), 16);
text: stripHtml(item.data?.content ?? "").result,
textAlignment: (item.style?.textAlign ?? "left") as "left" | "center" | "right",
textColor: item.style?.color,
+ textSize: parseInt(item.style?.fontSize ?? "16"),
// TODO: Revisit this when neoboard can do html or inline styles
textBold: false,
textItalic: false,
};
}
+// Calculate the bounding box of the text where only font size and one side of the box is known.
+// We expect to see multiline text here.
+// Use canvas to calculate the bounding box of the text
+// We use node-canvas as this is a server-side function
+function calculateTextBoundingBox(text: string, fontSize: number, fontFamily: string, width: number): { width: number, height: number } {
+ const canvas = createCanvas(1, 1);
+ const context = canvas.getContext('2d');
+ if (!context) {
+ throw new Error('Failed to get 2D context');
+ }
+
+ const neoboardPadding = 10;
+ const maxWidth = width - neoboardPadding * 2;
+
+ context.font = `${fontSize}px ${fontFamily}`;
+ const words = text.split(' ');
+ let line = '';
+ let totalHeight = 0;
+ const lineHeight = fontSize * 1.2; // Assuming line height is 1.2 times the font size
+
+ for (let n = 0; n < words.length; n++) {
+ const testLine = line + words[n] + ' ';
+ const metrics = context.measureText(testLine);
+ const testWidth = metrics.width;
+ if (testWidth > maxWidth && n > 0) {
+ totalHeight += lineHeight;
+ line = words[n] + ' ';
+ } else {
+ line = testLine;
+ }
+ }
+ totalHeight += lineHeight; // Add height for the last line
+ // Add padding to the height
+ totalHeight += neoboardPadding * 2;
+
+ return { width, height: totalHeight };
+}
+
function convertText(item: TextItem): Shape {
+ const text = stripHtml(item.data?.content ?? "").result;
+ const textBounds = calculateTextBoundingBox(text, parseInt(item.style?.fontSize ?? "16"), "Inter", item.geometry?.width ?? 16);
+
+ const neoboardPadding = 5;
+
+ const fillOpacity = parseFloat(item.style?.fillOpacity ?? "1.0");
+ const fillColor = fillOpacity > 0 ? hexToRGB(mapColorNameToHex(item.style?.fillColor ?? '#ffffff'), fillOpacity) : "transparent";
+
return {
- type: 'shape',
+ // @ts-expect-error - Internal type for scaling
+ type: 'textshape',
kind: 'rectangle',
position: {
x: item.position?.x ?? 0,
y: item.position?.y ?? 0,
},
- width: item.geometry?.width ?? 1,
- height: item.geometry?.height ?? 1,
- fillColor: "transparent",
+ width: textBounds.width + neoboardPadding,
+ height: textBounds.height + neoboardPadding,
+ fillColor: fillColor,
+ fillOpacity: fillOpacity,
strokeColor: "transparent",
strokeWidth: 0,
borderRadius: 0,
- text: stripHtml(item.data?.content ?? "").result,
+ text: text,
textAlignment: (item.style?.textAlign ?? "left") as "left" | "center" | "right",
textColor: item.style?.color,
+ textSize: parseInt(item.style?.fontSize ?? "16"),
// TODO: Revisit this when neoboard can do html or inline styles
textBold: false,
textItalic: false,