Merge remote-tracking branch 'origin/staging'

This commit is contained in:
Alejandro Alonso 2023-02-02 18:07:20 +01:00
commit 3cfc432c23
51 changed files with 793 additions and 523 deletions

View file

@ -4,7 +4,13 @@
### :bug: Bugs fixed ### :bug: Bugs fixed
- Fix components groups items show the component name in list mode [Taiga #4770](https://tree.taiga.io/project/penpot/issue/4770) - Fix components groups items show the component name in list mode [Taiga #4770](https://tree.taiga.io/project/penpot/issue/4770)
- Fix typing CMD+Z on MacOS turns the cursor into a Zoom cursor [Taiga #4778](https://tree.taiga.io/project/penpot/issue/4778)
- Fix white space on small screens [Taiga #4774](https://tree.taiga.io/project/penpot/issue/4774)
- Fix button spacing on delete acount modal [Taiga #4762](https://tree.taiga.io/project/penpot/issue/4762)
- Fix invitations input on team management and onboarding modal [Taiga #4760](https://tree.taiga.io/project/penpot/issue/4760)
- Fix weird numeration creating new elements in dashboard [Taiga #4755](https://tree.taiga.io/project/penpot/issue/4755)
- Fix can move shape with lens zoom active [Taiga #4787](https://tree.taiga.io/project/penpot/issue/4787)
- Fix social links broken [Taiga #4759](https://tree.taiga.io/project/penpot/issue/4759)
## 1.17.0 ## 1.17.0

View file

@ -50,7 +50,7 @@ Being web based, Penpot is not dependent on operating systems or local installat
Using SVG as no other design and prototyping tool does, Penpot files sport compatibility with most of the vectorial tools, are tech friendly and extremely easy to use on the web. We make sure you will always own your work. Using SVG as no other design and prototyping tool does, Penpot files sport compatibility with most of the vectorial tools, are tech friendly and extremely easy to use on the web. We make sure you will always own your work.
<p align="center"> <p align="center">
<img src="https://penpot.app/images/open-source.png" alt="Open Source"> <img src="https://penpot.app/images/readme/open-source.png" alt="Open Source">
</p> </p>
@ -93,7 +93,7 @@ You will find the following categories:
- [Penpot in your language](https://community.penpot.app/c/penpot-in-your-language/12) - [Penpot in your language](https://community.penpot.app/c/penpot-in-your-language/12)
<p align="center"> <p align="center">
<img src="https://penpot.app/images/cross-teams.webp" alt="Community"> <img src="https://penpot.app/images/readme/cross-teams.webp" alt="Community">
</p> </p>
## Contributing ## ## Contributing ##

View file

@ -48,8 +48,8 @@
<mj-social-element src="{{ public-uri }}/images/email/logo-uxbox.png" href="https://penpot.app/" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-uxbox.png" href="https://penpot.app/" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-twitter.png" href="https://twitter.com/penpotapp" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-twitter.png" href="https://twitter.com/penpotapp" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-github.png" href="https://github.com/penpot/" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-github.png" href="https://github.com/penpot/" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-instagram.png" href="https://instagram.com/penpotapp/" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-instagram.png" href="https://www.instagram.com/penpot.app/" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-taiga.png" href="https://tree.taiga.io/project/uxbox" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-taiga.png" href="https://tree.taiga.io/project/penpot" padding="0 8px" />
</mj-social> </mj-social>
</mj-column> </mj-column>
</mj-section> </mj-section>

View file

@ -41,8 +41,8 @@
<mj-social-element src="{{ public-uri }}/images/email/logo-uxbox.png" href="https://penpot.app/" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-uxbox.png" href="https://penpot.app/" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-twitter.png" href="https://twitter.com/penpotapp" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-twitter.png" href="https://twitter.com/penpotapp" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-github.png" href="https://github.com/penpot/" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-github.png" href="https://github.com/penpot/" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-instagram.png" href="https://instagram.com/penpotapp/" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-instagram.png" href="https://www.instagram.com/penpot.app/" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-taiga.png" href="https://tree.taiga.io/project/uxbox" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-taiga.png" href="https://tree.taiga.io/project/penpot" padding="0 8px" />
</mj-social> </mj-social>
</mj-column> </mj-column>
</mj-section> </mj-section>

View file

@ -50,8 +50,8 @@
<mj-social-element src="{{ public-uri }}/images/email/logo-uxbox.png" href="https://penpot.app/" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-uxbox.png" href="https://penpot.app/" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-twitter.png" href="https://twitter.com/penpotapp" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-twitter.png" href="https://twitter.com/penpotapp" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-github.png" href="https://github.com/penpot/" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-github.png" href="https://github.com/penpot/" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-instagram.png" href="https://instagram.com/penpotapp/" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-instagram.png" href="https://www.instagram.com/penpot.app/" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-taiga.png" href="https://tree.taiga.io/project/uxbox" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-taiga.png" href="https://tree.taiga.io/project/penpot" padding="0 8px" />
</mj-social> </mj-social>
</mj-column> </mj-column>
</mj-section> </mj-section>

View file

@ -47,8 +47,8 @@
<mj-social-element src="{{ public-uri }}/images/email/logo-uxbox.png" href="https://penpot.app/" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-uxbox.png" href="https://penpot.app/" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-twitter.png" href="https://twitter.com/penpotapp" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-twitter.png" href="https://twitter.com/penpotapp" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-github.png" href="https://github.com/penpot/" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-github.png" href="https://github.com/penpot/" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-instagram.png" href="https://instagram.com/penpotapp/" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-instagram.png" href="https://www.instagram.com/penpot.app/" padding="0 8px" />
<mj-social-element src="{{ public-uri }}/images/email/logo-taiga.png" href="https://tree.taiga.io/project/uxbox" padding="0 8px" /> <mj-social-element src="{{ public-uri }}/images/email/logo-taiga.png" href="https://tree.taiga.io/project/penpot" padding="0 8px" />
</mj-social> </mj-social>
</mj-column> </mj-column>
</mj-section> </mj-section>

View file

@ -103,9 +103,9 @@
<td style="direction:ltr;font-size:0px;padding:0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -129,9 +129,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -143,7 +143,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -157,9 +157,9 @@
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -211,9 +211,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -225,7 +225,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -239,9 +239,9 @@
<td style="direction:ltr;font-size:0px;padding:24px 0 0 0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:24px 0 0 0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:425px;" class="" style="vertical-align:top;width:425px;"
> >
@ -257,9 +257,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -271,7 +271,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -285,9 +285,9 @@
<td style="direction:ltr;font-size:0px;padding:0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -301,7 +301,7 @@
align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation"
> >
<tr> <tr>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -321,7 +321,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -341,7 +341,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -361,7 +361,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -370,7 +370,7 @@
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;"> <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;">
<tr> <tr>
<td style="font-size:0;height:24px;vertical-align:middle;width:24px;"> <td style="font-size:0;height:24px;vertical-align:middle;width:24px;">
<a href="https://instagram.com/penpotapp/" target="_blank"> <a href="https://www.instagram.com/penpot.app/" target="_blank">
<img height="24" src="{{ public-uri }}/images/email/logo-instagram.png" style="border-radius:3px;display:block;" width="24" /> <img height="24" src="{{ public-uri }}/images/email/logo-instagram.png" style="border-radius:3px;display:block;" width="24" />
</a> </a>
</td> </td>
@ -381,7 +381,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -390,7 +390,7 @@
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;"> <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;">
<tr> <tr>
<td style="font-size:0;height:24px;vertical-align:middle;width:24px;"> <td style="font-size:0;height:24px;vertical-align:middle;width:24px;">
<a href="https://tree.taiga.io/project/uxbox" target="_blank"> <a href="https://tree.taiga.io/project/penpot" target="_blank">
<img height="24" src="{{ public-uri }}/images/email/logo-taiga.png" style="border-radius:3px;display:block;" width="24" /> <img height="24" src="{{ public-uri }}/images/email/logo-taiga.png" style="border-radius:3px;display:block;" width="24" />
</a> </a>
</td> </td>
@ -401,7 +401,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
@ -411,9 +411,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -425,7 +425,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -439,9 +439,9 @@
<td style="direction:ltr;font-size:0px;padding:0 0 24px 0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:0 0 24px 0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -457,9 +457,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>

View file

@ -103,9 +103,9 @@
<td style="direction:ltr;font-size:0px;padding:0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -129,9 +129,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -143,7 +143,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -157,9 +157,9 @@
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -201,9 +201,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -215,7 +215,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -229,9 +229,9 @@
<td style="direction:ltr;font-size:0px;padding:24px 0 0 0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:24px 0 0 0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:425px;" class="" style="vertical-align:top;width:425px;"
> >
@ -247,9 +247,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -261,7 +261,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -275,9 +275,9 @@
<td style="direction:ltr;font-size:0px;padding:0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -291,7 +291,7 @@
align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation"
> >
<tr> <tr>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -311,7 +311,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -331,7 +331,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -351,7 +351,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -360,7 +360,7 @@
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;"> <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;">
<tr> <tr>
<td style="font-size:0;height:24px;vertical-align:middle;width:24px;"> <td style="font-size:0;height:24px;vertical-align:middle;width:24px;">
<a href="https://instagram.com/penpotapp/" target="_blank"> <a href="https://www.instagram.com/penpot.app/" target="_blank">
<img height="24" src="{{ public-uri }}/images/email/logo-instagram.png" style="border-radius:3px;display:block;" width="24" /> <img height="24" src="{{ public-uri }}/images/email/logo-instagram.png" style="border-radius:3px;display:block;" width="24" />
</a> </a>
</td> </td>
@ -371,7 +371,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -380,7 +380,7 @@
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;"> <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;">
<tr> <tr>
<td style="font-size:0;height:24px;vertical-align:middle;width:24px;"> <td style="font-size:0;height:24px;vertical-align:middle;width:24px;">
<a href="https://tree.taiga.io/project/uxbox" target="_blank"> <a href="https://tree.taiga.io/project/penpot" target="_blank">
<img height="24" src="{{ public-uri }}/images/email/logo-taiga.png" style="border-radius:3px;display:block;" width="24" /> <img height="24" src="{{ public-uri }}/images/email/logo-taiga.png" style="border-radius:3px;display:block;" width="24" />
</a> </a>
</td> </td>
@ -391,7 +391,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
@ -401,9 +401,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -415,7 +415,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -429,9 +429,9 @@
<td style="direction:ltr;font-size:0px;padding:0 0 24px 0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:0 0 24px 0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -447,9 +447,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>

View file

@ -103,9 +103,9 @@
<td style="direction:ltr;font-size:0px;padding:0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -129,9 +129,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -143,7 +143,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -157,9 +157,9 @@
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -206,9 +206,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -220,7 +220,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -234,9 +234,9 @@
<td style="direction:ltr;font-size:0px;padding:24px 0 0 0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:24px 0 0 0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:425px;" class="" style="vertical-align:top;width:425px;"
> >
@ -252,9 +252,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -266,7 +266,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -280,9 +280,9 @@
<td style="direction:ltr;font-size:0px;padding:0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -296,7 +296,7 @@
align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation"
> >
<tr> <tr>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -316,7 +316,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -336,7 +336,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -356,7 +356,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -365,7 +365,7 @@
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;"> <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;">
<tr> <tr>
<td style="font-size:0;height:24px;vertical-align:middle;width:24px;"> <td style="font-size:0;height:24px;vertical-align:middle;width:24px;">
<a href="https://instagram.com/penpotapp/" target="_blank"> <a href="https://www.instagram.com/penpot.app/" target="_blank">
<img height="24" src="{{ public-uri }}/images/email/logo-instagram.png" style="border-radius:3px;display:block;" width="24" /> <img height="24" src="{{ public-uri }}/images/email/logo-instagram.png" style="border-radius:3px;display:block;" width="24" />
</a> </a>
</td> </td>
@ -376,7 +376,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -385,7 +385,7 @@
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;"> <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;">
<tr> <tr>
<td style="font-size:0;height:24px;vertical-align:middle;width:24px;"> <td style="font-size:0;height:24px;vertical-align:middle;width:24px;">
<a href="https://tree.taiga.io/project/uxbox" target="_blank"> <a href="https://tree.taiga.io/project/penpot" target="_blank">
<img height="24" src="{{ public-uri }}/images/email/logo-taiga.png" style="border-radius:3px;display:block;" width="24" /> <img height="24" src="{{ public-uri }}/images/email/logo-taiga.png" style="border-radius:3px;display:block;" width="24" />
</a> </a>
</td> </td>
@ -396,7 +396,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
@ -406,9 +406,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -420,7 +420,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -434,9 +434,9 @@
<td style="direction:ltr;font-size:0px;padding:0 0 24px 0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:0 0 24px 0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -452,9 +452,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>

View file

@ -103,9 +103,9 @@
<td style="direction:ltr;font-size:0px;padding:0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -129,9 +129,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -143,7 +143,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -157,9 +157,9 @@
<td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -201,9 +201,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -215,7 +215,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -229,9 +229,9 @@
<td style="direction:ltr;font-size:0px;padding:24px 0 0 0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:24px 0 0 0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:425px;" class="" style="vertical-align:top;width:425px;"
> >
@ -247,9 +247,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -261,7 +261,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -275,9 +275,9 @@
<td style="direction:ltr;font-size:0px;padding:0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -291,7 +291,7 @@
align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" align="center" border="0" cellpadding="0" cellspacing="0" role="presentation"
> >
<tr> <tr>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -311,7 +311,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -331,7 +331,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -351,7 +351,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -360,7 +360,7 @@
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;"> <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;">
<tr> <tr>
<td style="font-size:0;height:24px;vertical-align:middle;width:24px;"> <td style="font-size:0;height:24px;vertical-align:middle;width:24px;">
<a href="https://instagram.com/penpotapp/" target="_blank"> <a href="https://www.instagram.com/penpot.app/" target="_blank">
<img height="24" src="{{ public-uri }}/images/email/logo-instagram.png" style="border-radius:3px;display:block;" width="24" /> <img height="24" src="{{ public-uri }}/images/email/logo-instagram.png" style="border-radius:3px;display:block;" width="24" />
</a> </a>
</td> </td>
@ -371,7 +371,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
<td> <td>
<![endif]--> <![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;"> <table align="center" border="0" cellpadding="0" cellspacing="0" role="presentation" style="float:none;display:inline-table;">
@ -380,7 +380,7 @@
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;"> <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-radius:3px;width:24px;">
<tr> <tr>
<td style="font-size:0;height:24px;vertical-align:middle;width:24px;"> <td style="font-size:0;height:24px;vertical-align:middle;width:24px;">
<a href="https://tree.taiga.io/project/uxbox" target="_blank"> <a href="https://tree.taiga.io/project/penpot" target="_blank">
<img height="24" src="{{ public-uri }}/images/email/logo-taiga.png" style="border-radius:3px;display:block;" width="24" /> <img height="24" src="{{ public-uri }}/images/email/logo-taiga.png" style="border-radius:3px;display:block;" width="24" />
</a> </a>
</td> </td>
@ -391,7 +391,7 @@
</table> </table>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
@ -401,9 +401,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>
@ -415,7 +415,7 @@
</td> </td>
</tr> </tr>
</table> </table>
<table <table
align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600" align="center" border="0" cellpadding="0" cellspacing="0" class="" style="width:600px;" width="600"
> >
@ -429,9 +429,9 @@
<td style="direction:ltr;font-size:0px;padding:0 0 24px 0;text-align:center;"> <td style="direction:ltr;font-size:0px;padding:0 0 24px 0;text-align:center;">
<!--[if mso | IE]> <!--[if mso | IE]>
<table role="presentation" border="0" cellpadding="0" cellspacing="0"> <table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr> <tr>
<td <td
class="" style="vertical-align:top;width:600px;" class="" style="vertical-align:top;width:600px;"
> >
@ -447,9 +447,9 @@
</div> </div>
<!--[if mso | IE]> <!--[if mso | IE]>
</td> </td>
</tr> </tr>
</table> </table>
<![endif]--> <![endif]-->
</td> </td>

View file

@ -473,7 +473,7 @@
(s/def ::team-id ::us/uuid) (s/def ::team-id ::us/uuid)
(s/def ::member-id ::us/uuid) (s/def ::member-id ::us/uuid)
;; Temporarily disabled viewer role ;; Temporarily disabled viewer role
;; https://tree.taiga.io/project/uxboxproject/issue/1083 ;; https://tree.taiga.io/project/penpot/issue/1083
;; (s/def ::role #{:owner :admin :editor :viewer}) ;; (s/def ::role #{:owner :admin :editor :viewer})
(s/def ::role #{:owner :admin :editor}) (s/def ::role #{:owner :admin :editor})

View file

@ -154,7 +154,7 @@
(t/is (th/success? out)) (t/is (th/success? out))
(let [[thread :as result] (:result out)] (let [[thread :as result] (:result out)]
(t/is (= 1 (count result))) (t/is (= 1 (count result)))
(t/is (= "Page-1" (:page-name thread))) (t/is (= "Page 1" (:page-name thread)))
(t/is (= "hello world" (:content thread))) (t/is (= "hello world" (:content thread)))
(t/is (= 2 (:count-comments thread))) (t/is (= 2 (:count-comments thread)))
(t/is (true? (:is-resolved thread)))))) (t/is (true? (:is-resolved thread))))))

View file

@ -200,7 +200,7 @@
(assert (nil? (:current-component-id file))) (assert (nil? (:current-component-id file)))
(let [page-id (or (:id data) (uuid/next)) (let [page-id (or (:id data) (uuid/next))
page (-> (ctp/make-empty-page page-id "Page-1") page (-> (ctp/make-empty-page page-id "Page 1")
(d/deep-merge data))] (d/deep-merge data))]
(-> file (-> file
(commit-change (commit-change

View file

@ -43,13 +43,13 @@
(defn bounding-box (defn bounding-box
"Returns a rect that wraps the shape after all transformations applied." "Returns a rect that wraps the shape after all transformations applied."
[shape] [shape]
; TODO: perhaps we need to store this calculation in a shape attribute ;; TODO: perhaps we need to store this calculation in a shape attribute
(gpr/points->rect (:points shape))) (gpr/points->rect (:points shape)))
(defn left-bound (defn left-bound
"Returns the lowest x coord of the shape BEFORE applying transformations." "Returns the lowest x coord of the shape BEFORE applying transformations."
; TODO: perhaps some day we want after transformations, but for the ;; TODO: perhaps some day we want after transformations, but for the
; moment it's enough as is now. ;; moment it's enough as is now.
[shape] [shape]
(or (:x shape) (:x (:selrect shape)))) ; Paths don't have :x attribute (or (:x shape) (:x (:selrect shape)))) ; Paths don't have :x attribute
@ -106,8 +106,8 @@
([attr val1 val2 precision] ([attr val1 val2 precision]
(let [close-val? (fn [num1 num2] (let [close-val? (fn [num1 num2]
(when (and (number? num1) (number? num2)) (when (and (number? num1) (number? num2))
(< (mth/abs (- num1 num2)) precision)))] (< (mth/abs (- num1 num2)) precision)))]
(cond (cond
(and (number? val1) (number? val2)) (and (number? val1) (number? val2))
(close-val? val1 val2) (close-val? val1 val2)

View file

@ -210,7 +210,7 @@
;; after-vec will contain the side length of the grown side ;; after-vec will contain the side length of the grown side
;; we scale the shape by the diference and translate it by the start ;; we scale the shape by the diference and translate it by the start
;; displacement (so its left+top position is constant) ;; displacement (so its left+top position is constant)
scale (/ (gpt/length after-vec) (gpt/length before-vec)) scale (/ (gpt/length after-vec) (max 0.01 (gpt/length before-vec)))
resize-origin (gpo/origin child-points-after) resize-origin (gpo/origin child-points-after)
@ -268,11 +268,11 @@
scale-x (if (= :scale constraints-h) scale-x (if (= :scale constraints-h)
1 1
(/ (gpo/width-points child-bb-before) (gpo/width-points child-bb-after))) (/ (gpo/width-points child-bb-before) (max 0.01 (gpo/width-points child-bb-after))))
scale-y (if (= :scale constraints-v) scale-y (if (= :scale constraints-v)
1 1
(/ (gpo/height-points child-bb-before) (gpo/height-points child-bb-after))) (/ (gpo/height-points child-bb-before) (max 0.01 (gpo/height-points child-bb-after))))
resize-vector (gpt/point scale-x scale-y) resize-vector (gpt/point scale-x scale-y)
resize-origin (gpo/origin transformed-child-bounds) resize-origin (gpo/origin transformed-child-bounds)

View file

@ -238,6 +238,30 @@
(and col? (< total-min-width rest-layout-width total-max-width) (not (ctl/auto-width? parent))) (and col? (< total-min-width rest-layout-width total-max-width) (not (ctl/auto-width? parent)))
(distribute-space :line-width :line-min-width :line-max-width total-min-width rest-layout-width)) (distribute-space :line-width :line-min-width :line-max-width total-min-width rest-layout-width))
;; Add information to limit the growth of width: 100% shapes to the bounds of the layout
layout-lines
(cond
row?
(->> layout-lines
(reduce
(fn [[result rest-layout-height] {:keys [line-height] :as line}]
[(conj result (assoc line :to-bound-height rest-layout-height))
(- rest-layout-height line-height layout-gap-row)])
[[] layout-height])
(first))
col?
(->> layout-lines
(reduce
(fn [[result rest-layout-width] {:keys [line-width] :as line}]
[(conj result (assoc line :to-bound-width rest-layout-width))
(- rest-layout-width line-width layout-gap-col)])
[[] layout-width])
(first))
:else
layout-lines)
[total-width total-height] (->> layout-lines (reduce add-lines [0 0])) [total-width total-height] (->> layout-lines (reduce add-lines [0 0]))
base-p (flp/get-base-line parent layout-bounds total-width total-height num-lines)] base-p (flp/get-base-line parent layout-bounds total-width total-height num-lines)]

View file

@ -20,7 +20,7 @@
transform-inverse transform-inverse
child child
child-origin child-width child-origin child-width
{:keys [children-data line-width] :as layout-data}] {:keys [children-data line-width to-bound-width] :as layout-data}]
(cond (cond
(ctl/row? parent) (ctl/row? parent)
@ -30,8 +30,9 @@
:modifiers (ctm/resize-modifiers (gpt/point fill-scale 1) child-origin transform transform-inverse)}) :modifiers (ctm/resize-modifiers (gpt/point fill-scale 1) child-origin transform transform-inverse)})
(ctl/col? parent) (ctl/col? parent)
(let [target-width (max (- line-width (ctl/child-width-margin child)) 0.01) (let [line-width (min line-width (or to-bound-width line-width))
max-width (ctl/child-max-width child) target-width (max (- line-width (ctl/child-width-margin child)) 0.01)
max-width (max (ctl/child-max-width child) 0.01)
target-width (min max-width target-width) target-width (min max-width target-width)
fill-scale (/ target-width child-width)] fill-scale (/ target-width child-width)]
{:width target-width {:width target-width
@ -43,7 +44,7 @@
transform transform-inverse transform transform-inverse
child child
child-origin child-height child-origin child-height
{:keys [children-data line-height] :as layout-data}] {:keys [children-data line-height to-bound-height] :as layout-data}]
(cond (cond
(ctl/col? parent) (ctl/col? parent)
@ -53,8 +54,9 @@
:modifiers (ctm/resize-modifiers (gpt/point 1 fill-scale) child-origin transform transform-inverse)}) :modifiers (ctm/resize-modifiers (gpt/point 1 fill-scale) child-origin transform transform-inverse)})
(ctl/row? parent) (ctl/row? parent)
(let [target-height (max (- line-height (ctl/child-height-margin child)) 0.01) (let [line-height (min line-height (or to-bound-height line-height))
max-height (ctl/child-max-height child) target-height (max (- line-height (ctl/child-height-margin child)) 0.01)
max-height (max (ctl/child-max-height child) 0.01)
target-height (min max-height target-height) target-height (min max-height target-height)
fill-scale (/ target-height child-height)] fill-scale (/ target-height child-height)]
{:height target-height {:height target-height
@ -71,8 +73,13 @@
(when (or (ctl/fill-width? child) (ctl/fill-height? child)) (when (or (ctl/fill-width? child) (ctl/fill-height? child))
(gtr/calculate-geometry @parent-bounds)) (gtr/calculate-geometry @parent-bounds))
fill-width (when (ctl/fill-width? child) (calc-fill-width-data parent transform transform-inverse child child-origin child-width layout-line)) fill-width
fill-height (when (ctl/fill-height? child) (calc-fill-height-data parent transform transform-inverse child child-origin child-height layout-line)) (when (ctl/fill-width? child)
(calc-fill-width-data parent transform transform-inverse child child-origin child-width layout-line))
fill-height
(when (ctl/fill-height? child)
(calc-fill-height-data parent transform transform-inverse child child-origin child-height layout-line))
child-width (or (:width fill-width) child-width) child-width (or (:width fill-width) child-width)
child-height (or (:height fill-height) child-height) child-height (or (:height fill-height) child-height)

View file

@ -20,9 +20,13 @@
hv (partial gpo/start-hv layout-bounds) hv (partial gpo/start-hv layout-bounds)
vv (partial gpo/start-vv layout-bounds) vv (partial gpo/start-vv layout-bounds)
end? (ctl/content-end? parent) wrap? (ctl/wrap? parent)
center? (ctl/content-center? parent)
around? (ctl/content-around? parent) end? (or (and wrap? (ctl/content-end? parent))
(and (not wrap?) (ctl/align-items-end? parent)))
center? (or (and wrap? (ctl/content-center? parent))
(and (not wrap?) (ctl/align-items-center? parent)))
around? (and wrap? (ctl/content-around? parent))
;; Adjust the totals so it takes into account the gaps ;; Adjust the totals so it takes into account the gaps
[layout-gap-row layout-gap-col] (ctl/gaps parent) [layout-gap-row layout-gap-col] (ctl/gaps parent)

View file

@ -54,11 +54,11 @@
(defn width-points (defn width-points
[[p0 p1 _ _]] [[p0 p1 _ _]]
(gpt/length (gpt/to-vec p0 p1))) (max 0.01 (gpt/length (gpt/to-vec p0 p1))))
(defn height-points (defn height-points
[[p0 _ _ p3]] [[p0 _ _ p3]]
(gpt/length (gpt/to-vec p0 p3))) (max 0.01 (gpt/length (gpt/to-vec p0 p3))))
(defn pad-points (defn pad-points
[[p0 p1 p2 p3 :as points] pad-top pad-right pad-bottom pad-left] [[p0 p1 p2 p3 :as points] pad-top pad-right pad-bottom pad-left]

View file

@ -34,7 +34,7 @@
(defn abs (defn abs
[v] [v]
#?(:cljs (js/Math.abs v) #?(:cljs (js/Math.abs v)
:clj (Math/abs v))) :clj (Math/abs (double v))))
(defn sin (defn sin
"Returns the sine of a number" "Returns the sine of a number"

View file

@ -19,6 +19,8 @@
(dm/export common/file-version) (dm/export common/file-version)
(dm/export common/default-color) (dm/export common/default-color)
(dm/export common/component-sync-attrs) (dm/export common/component-sync-attrs)
(dm/export common/retrieve-used-names)
(dm/export common/generate-unique-name)
;; Focus ;; Focus
(dm/export focus/focus-objects) (dm/export focus/focus-objects)

View file

@ -7,7 +7,10 @@
(ns app.common.pages.common (ns app.common.pages.common
(:require (:require
[app.common.colors :as clr] [app.common.colors :as clr]
[app.common.uuid :as uuid])) [app.common.data :as d]
[app.common.spec :as us]
[app.common.uuid :as uuid]
[clojure.spec.alpha :as s]))
(def file-version 20) (def file-version 20)
(def default-color clr/gray-20) (def default-color clr/gray-20)
@ -580,3 +583,31 @@
:layout-item-min-w :layout-item-min-w
:layout-item-align-self}}) :layout-item-align-self}})
(defn retrieve-used-names
"Return a set with the all unique names used in the
elements (any entity thas has a :name)"
[elements]
(into #{} (comp (map :name) (remove nil?)) (vals elements)))
(defn- extract-numeric-suffix
[basename]
(if-let [[_ p1 p2] (re-find #"(.*) ([0-9]+)$" basename)]
[p1 (+ 1 (d/parse-integer p2))]
[basename 1]))
(s/def ::set-of-strings
(s/every ::us/string :kind set?))
(defn generate-unique-name
"A unique name generator"
[used basename]
(us/assert! ::set-of-strings used)
(us/assert! ::us/string basename)
(if-not (contains? used basename)
basename
(let [[prefix initial] (extract-numeric-suffix basename)]
(loop [counter initial]
(let [candidate (str prefix " " counter)]
(if (contains? used candidate)
(recur (inc counter))
candidate))))))

View file

@ -109,6 +109,20 @@
(recur (conj result parent-id) parent-id) (recur (conj result parent-id) parent-id)
result)))) result))))
(defn get-parent-ids-with-index
"Returns a tuple with the list of parents and a map with the position within each parent"
[objects shape-id]
(loop [parent-list []
parent-indices {}
current shape-id]
(let [parent-id (dm/get-in objects [current :parent-id])
parent (get objects parent-id)]
(if (and (some? parent) (not= parent-id current))
(let [parent-list (conj parent-list parent-id)
parent-indices (assoc parent-indices parent-id (d/index-of (:shapes parent) current))]
(recur parent-list parent-indices parent-id))
[parent-list parent-indices]))))
(defn get-siblings-ids (defn get-siblings-ids
[objects id] [objects id]
(let [parent (get-parent objects id)] (let [parent (get-parent objects id)]

View file

@ -9,6 +9,7 @@
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.pages.common :as common]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.types.shape-tree :as ctst] [app.common.types.shape-tree :as ctst]
[clojure.spec.alpha :as s])) [clojure.spec.alpha :as s]))
@ -130,7 +131,7 @@
delta (gpt/subtract position orig-pos) delta (gpt/subtract position orig-pos)
objects (:objects container) objects (:objects container)
unames (volatile! (ctst/retrieve-used-names objects)) unames (volatile! (common/retrieve-used-names objects))
frame-id (ctst/frame-id-by-position objects (gpt/add orig-pos delta)) frame-id (ctst/frame-id-by-position objects (gpt/add orig-pos delta))
frame-ids-map (volatile! {}) frame-ids-map (volatile! {})

View file

@ -73,7 +73,7 @@
([file-id page-id] ([file-id page-id]
(let [page (when (some? page-id) (let [page (when (some? page-id)
(ctp/make-empty-page page-id "Page-1"))] (ctp/make-empty-page page-id "Page 1"))]
(cond-> (-> empty-file-data (cond-> (-> empty-file-data
(assoc :id file-id)) (assoc :id file-id))

View file

@ -275,6 +275,21 @@
(or (= :stretch layout-align-content) (or (= :stretch layout-align-content)
(nil? layout-align-content))) (nil? layout-align-content)))
(defn align-items-center?
[{:keys [layout-align-items]}]
(= layout-align-items :center))
(defn align-items-start?
[{:keys [layout-align-items]}]
(= layout-align-items :start))
(defn align-items-end?
[{:keys [layout-align-items]}]
(= layout-align-items :end))
(defn align-items-stretch?
[{:keys [layout-align-items]}]
(= layout-align-items :stretch))
(defn reverse? (defn reverse?
[{:keys [layout-flex-dir]}] [{:keys [layout-flex-dir]}]

View file

@ -132,43 +132,34 @@
(defn get-base (defn get-base
[objects id-a id-b] [objects id-a id-b]
(let [parents-a (reverse (cons id-a (cph/get-parent-ids objects id-a))) (let [[parents-a parents-a-index] (cph/get-parent-ids-with-index objects id-a)
parents-b (reverse (cons id-b (cph/get-parent-ids objects id-b))) [parents-b parents-b-index] (cph/get-parent-ids-with-index objects id-b)
[base base-child-a base-child-b] parents-a (cons id-a parents-a)
(loop [parents-a (rest parents-a) parents-b (into #{id-b} parents-b)
parents-b (rest parents-b)
base uuid/zero]
(cond
(not= (first parents-a) (first parents-b))
[base (first parents-a) (first parents-b)]
(or (empty? parents-a) (empty? parents-b)) ;; Search for the common frame in order
[uuid/zero (first parents-a) (first parents-b)] base (or (d/seek parents-b parents-a) uuid/zero)
:else idx-a (get parents-a-index base)
(recur (rest parents-a) (rest parents-b) (first parents-a)))) idx-b (get parents-b-index base)]
index-base-a (when base-child-a (cph/get-position-on-parent objects base-child-a)) [base idx-a idx-b]))
index-base-b (when base-child-b (cph/get-position-on-parent objects base-child-b))]
[base index-base-a index-base-b]))
(defn is-shape-over-shape? (defn is-shape-over-shape?
[objects base-shape-id over-shape-id] [objects base-shape-id over-shape-id]
(let [[base index-a index-b] (get-base objects base-shape-id over-shape-id)] (let [[base index-a index-b] (get-base objects base-shape-id over-shape-id)]
(cond (cond
;; The base the base shape, so the other item is bellow
(= base base-shape-id) (= base base-shape-id)
(let [object (get objects base-shape-id)] false
(or (cph/frame-shape? object)
(cph/root-frame? object)))
;; The base is the testing over, so it's over
(= base over-shape-id) (= base over-shape-id)
(let [object (get objects over-shape-id)] true
(or (not (cph/frame-shape? object))
(not (cph/root-frame? object))))
;; Check which index is lower
:else :else
(< index-a index-b)))) (< index-a index-b))))
@ -284,35 +275,6 @@
[frame] [frame]
(not (mth/almost-zero? (:rotation frame 0)))) (not (mth/almost-zero? (:rotation frame 0))))
(defn retrieve-used-names
[objects]
(into #{} (comp (map :name) (remove nil?)) (vals objects)))
(defn- extract-numeric-suffix
[basename]
(if-let [[_ p1 p2] (re-find #"(.*)-([0-9]+)$" basename)]
[p1 (+ 1 (d/parse-integer p2))]
[basename 1]))
(s/def ::set-of-strings
(s/every ::us/string :kind set?))
(defn generate-unique-name
"A unique name generator"
[used basename]
(us/assert! ::set-of-strings used)
(us/assert! ::us/string basename)
;; We have add a condition because UX doesn't want numbers on
;; layer names.
(if-not (contains? used basename)
basename
(let [[prefix initial] (extract-numeric-suffix basename)]
(loop [counter initial]
(let [candidate (str prefix "-" counter)]
(if (contains? used candidate)
(recur (inc counter))
candidate))))))
(defn clone-object (defn clone-object
"Gets a copy of the object and all its children, with new ids "Gets a copy of the object and all its children, with new ids
and with the parent-children links correctly set. Admits functions and with the parent-children links correctly set. Admits functions

View file

@ -126,7 +126,7 @@
(fn [file-data] (fn [file-data]
(let [id (uuid/next) (let [id (uuid/next)
props (merge {:id id props (merge {:id id
:name "Color-1" :name "Color 1"
:color "#000000" :color "#000000"
:opacity 1} :opacity 1}
props)] props)]
@ -140,7 +140,7 @@
(fn [file-data] (fn [file-data]
(let [id (uuid/next) (let [id (uuid/next)
props (merge {:id id props (merge {:id id
:name "Typography-1" :name "Typography 1"
:font-id "sourcesanspro" :font-id "sourcesanspro"
:font-family "sourcesanspro" :font-family "sourcesanspro"
:font-size "14" :font-size "14"

View file

@ -101,7 +101,7 @@
;; false) ;; false)
(t/is (= (count pages) 2)) (t/is (= (count pages) 2))
(t/is (= (:name (first pages)) "Page-1")) (t/is (= (:name (first pages)) "Page 1"))
(t/is (= (:name (second pages)) "Library backup")) (t/is (= (:name (second pages)) "Library backup"))
(t/is (= (count components) 1)) (t/is (= (count components) 1))

View file

@ -29,7 +29,35 @@
.custom-input { .custom-input {
width: 100%; width: 100%;
height: 115px; min-height: 116px;
max-height: 176px;
overflow-y: hidden;
input {
&.no-padding {
padding-top: 12px;
}
min-height: 40px;
}
.selected-items {
gap: 8px;
padding: 8px;
max-height: 132px;
overflow-y: scroll;
.selected-item {
.around {
height: 24px;
display: flex;
align-items: center;
justify-content: flex-start;
width: fit-content;
.icon {
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
} }
.custom-select { .custom-select {

View file

@ -184,6 +184,7 @@
.modal-footer .action-buttons { .modal-footer .action-buttons {
justify-content: space-around; justify-content: space-around;
gap: 15px;
} }
.fields-container { .fields-container {
@ -1541,8 +1542,52 @@
.onboarding-team-members { .onboarding-team-members {
.team-left { .team-left {
padding: 42px 64px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: auto;
form { form {
margin-top: 32px; margin-top: 5px;
.invite-row {
.custom-input {
width: 100%;
min-height: 80px;
height: fit-content;
max-height: 176px;
overflow-y: hidden;
input {
&.no-padding {
padding-top: 12px;
}
min-height: 40px;
}
.selected-items {
gap: 7px;
padding: 7px;
max-height: 132px;
overflow-y: scroll;
.selected-item {
.around {
height: 24px;
display: flex;
align-items: center;
justify-content: flex-start;
width: fit-content;
.icon {
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
}
}
.buttons {
margin-top: 12px;
}
} }
} }
} }

View file

@ -17,7 +17,7 @@ $height-palette-max: 80px;
#workspace { #workspace {
width: 100vw; width: 100vw;
height: 100vh; height: 100%;
user-select: none; user-select: none;
background-color: $color-canvas; background-color: $color-canvas;
display: grid; display: grid;
@ -37,6 +37,8 @@ $height-palette-max: 80px;
.left-toolbar { .left-toolbar {
grid-area: toolbar; grid-area: toolbar;
width: $width-left-toolbar; width: $width-left-toolbar;
overflow-y: scroll;
overflow-x: hidden;
} }
.settings-bar.settings-bar-left { .settings-bar.settings-bar-left {

View file

@ -7,6 +7,7 @@
(ns app.main.data.dashboard (ns app.main.data.dashboard
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.pages :as cp]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.config :as cf] [app.config :as cf]
@ -664,10 +665,12 @@
(ptk/reify ::create-project (ptk/reify ::create-project
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [name (name (gensym (str (tr "dashboard.new-project-prefix") " "))) (let [projects (get state :dashboard-projects)
team-id (:current-team-id state) unames (cp/retrieve-used-names projects)
params {:name name name (cp/generate-unique-name unames (str (tr "dashboard.new-project-prefix") " 1"))
:team-id team-id} team-id (:current-team-id state)
params {:name name
:team-id team-id}
{:keys [on-success on-error] {:keys [on-success on-error]
:or {on-success identity :or {on-success identity
on-error rx/throw}} (meta params)] on-error rx/throw}} (meta params)]
@ -875,7 +878,9 @@
:or {on-success identity :or {on-success identity
on-error rx/throw}} (meta params) on-error rx/throw}} (meta params)
name (name (gensym (str (tr "dashboard.new-file-prefix") " "))) files (get state :dashboard-files)
unames (cp/retrieve-used-names files)
name (cp/generate-unique-name unames (str (tr "dashboard.new-file-prefix") " 1"))
features (cond-> #{} features (cond-> #{}
(features/active-feature? state :components-v2) (features/active-feature? state :components-v2)
(conj "components/v2")) (conj "components/v2"))
@ -1067,8 +1072,12 @@
pparams (:path-params route) pparams (:path-params route)
in-project? (contains? pparams :project-id) in-project? (contains? pparams :project-id)
name (if in-project? name (if in-project?
(name (gensym (str (tr "dashboard.new-file-prefix") " "))) (let [files (get state :dashboard-files)
(name (gensym (str (tr "dashboard.new-project-prefix") " ")))) unames (cp/retrieve-used-names files)]
(cp/generate-unique-name unames (str (tr "dashboard.new-file-prefix") " 1")))
(let [projects (get state :dashboard-projects)
unames (cp/retrieve-used-names projects)]
(cp/generate-unique-name unames (str (tr "dashboard.new-project-prefix") " 1"))))
params (if in-project? params (if in-project?
{:project-id (:project-id pparams) {:project-id (:project-id pparams)
:name name} :name name}

View file

@ -15,6 +15,7 @@
[app.common.geom.proportions :as gpp] [app.common.geom.proportions :as gpp]
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.logging :as log] [app.common.logging :as log]
[app.common.pages :as cp]
[app.common.pages.changes-builder :as pcb] [app.common.pages.changes-builder :as pcb]
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.spec :as us] [app.common.spec :as us]
@ -408,8 +409,8 @@
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (watch [it state _]
(let [pages (get-in state [:workspace-data :pages-index]) (let [pages (get-in state [:workspace-data :pages-index])
unames (ctst/retrieve-used-names pages) unames (cp/retrieve-used-names pages)
name (ctst/generate-unique-name unames "Page-1") name (cp/generate-unique-name unames "Page 1")
changes (-> (pcb/empty-changes it) changes (-> (pcb/empty-changes it)
(pcb/add-empty-page id name))] (pcb/add-empty-page id name))]
@ -423,9 +424,9 @@
(watch [it state _] (watch [it state _]
(let [id (uuid/next) (let [id (uuid/next)
pages (get-in state [:workspace-data :pages-index]) pages (get-in state [:workspace-data :pages-index])
unames (ctst/retrieve-used-names pages) unames (cp/retrieve-used-names pages)
page (get-in state [:workspace-data :pages-index page-id]) page (get-in state [:workspace-data :pages-index page-id])
name (ctst/generate-unique-name unames (:name page)) name (cp/generate-unique-name unames (:name page))
no_thumbnails_objects (->> (:objects page) no_thumbnails_objects (->> (:objects page)
(d/mapm (fn [_ val] (dissoc val :use-for-thumbnail?)))) (d/mapm (fn [_ val] (dissoc val :use-for-thumbnail?))))

View file

@ -8,6 +8,7 @@
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.pages :as cp]
[app.common.pages.changes-builder :as pcb] [app.common.pages.changes-builder :as pcb]
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.spec :as us] [app.common.spec :as us]
@ -33,7 +34,7 @@
flows (get-in page [:options :flows] []) flows (get-in page [:options :flows] [])
unames (into #{} (map :name flows)) unames (into #{} (map :name flows))
name (ctst/generate-unique-name unames "Flow-1") name (cp/generate-unique-name unames "Flow 1")
new-flow {:id (uuid/next) new-flow {:id (uuid/next)
:name name :name name

View file

@ -73,7 +73,7 @@
(pcb/with-objects objects))] (pcb/with-objects objects))]
(let [group-name (if (= 1 (count shapes)) (let [group-name (if (= 1 (count shapes))
(:name (first shapes)) (:name (first shapes))
"Component-1")] "Component 1")]
(dwg/prepare-create-group it (dwg/prepare-create-group it
objects objects
page-id page-id

View file

@ -15,7 +15,6 @@
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.types.page :as ctp] [app.common.types.page :as ctp]
[app.common.types.shape-tree :as ctt]
[app.common.types.shape.interactions :as ctsi] [app.common.types.shape.interactions :as ctsi]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.main.data.modal :as md] [app.main.data.modal :as md]
@ -290,7 +289,7 @@
move to the desired position, and recalculate parents and frames as needed." move to the desired position, and recalculate parents and frames as needed."
[all-objects page ids delta it] [all-objects page ids delta it]
(let [shapes (map (d/getf all-objects) ids) (let [shapes (map (d/getf all-objects) ids)
unames (volatile! (ctt/retrieve-used-names (:objects page))) unames (volatile! (cp/retrieve-used-names (:objects page)))
update-unames! (fn [new-name] (vswap! unames conj new-name)) update-unames! (fn [new-name] (vswap! unames conj new-name))
all-ids (reduce #(into %1 (cons %2 (cph/get-children-ids all-objects %2))) (d/ordered-set) ids) all-ids (reduce #(into %1 (cons %2 (cph/get-children-ids all-objects %2))) (d/ordered-set) ids)
ids-map (into {} (map #(vector % (uuid/next))) all-ids) ids-map (into {} (map #(vector % (uuid/next))) all-ids)
@ -367,7 +366,7 @@
(let [update-flows (fn [flows] (let [update-flows (fn [flows]
(reduce (reduce
(fn [flows frame] (fn [flows frame]
(let [name (ctt/generate-unique-name @unames "Flow-1") (let [name (cp/generate-unique-name @unames "Flow 1")
_ (vswap! unames conj name) _ (vswap! unames conj name)
new-flow {:id (uuid/next) new-flow {:id (uuid/next)
:name name :name name

View file

@ -271,16 +271,89 @@
(ptk/data-event :layout/update ids) (ptk/data-event :layout/update ids)
(dwu/commit-undo-transaction undo-id)))))) (dwu/commit-undo-transaction undo-id))))))
(defn fix-child-sizing
[objects parent-changes shape]
(let [parent (-> (cph/get-parent objects (:id shape))
(d/deep-merge parent-changes))
auto-width? (ctl/auto-width? parent)
auto-height? (ctl/auto-height? parent)
col? (ctl/col? parent)
row? (ctl/row? parent)
all-children (->> parent :shapes (map (d/getf objects)))]
(cond-> shape
;; If the parent is hug width and the direction column
;; change to fixed when ALL children are fill
(and col? auto-width? (every? ctl/fill-width? all-children))
(assoc :layout-item-h-sizing :fix)
;; If the parent is hug height and the direction is column
;; change to fixed when ANY children is fill
(and col? auto-height? (ctl/fill-height? shape))
(assoc :layout-item-v-sizing :fix)
;; If the parent is hug width and the direction row
;; change to fixed when ANY children is fill
(and row? auto-width? (ctl/fill-width? shape))
(assoc :layout-item-h-sizing :fix)
;; If the parent is hug height and the direction row
;; change to fixed when ALL children are fill
(and row? auto-height? (every? ctl/fill-height? all-children))
(assoc :layout-item-v-sizing :fix))))
(defn fix-parent-sizing
[objects ids-set changes parent]
(let [auto-width? (ctl/auto-width? parent)
auto-height? (ctl/auto-height? parent)
col? (ctl/col? parent)
row? (ctl/row? parent)
all-children
(->> parent :shapes
(map (d/getf objects))
(map (fn [shape]
(if (contains? ids-set (:id shape))
(d/deep-merge shape changes)
shape))))]
(cond-> parent
;; Col layout and parent is hug-width if all children are fill-width
;; change parent to fixed
(and col? auto-width? (every? ctl/fill-width? all-children))
(assoc :layout-item-h-sizing :fix)
;; Col layout and parent is hug-height if any children is fill-height
;; change parent to fixed
(and col? auto-height? (some ctl/fill-height? all-children))
(assoc :layout-item-v-sizing :fix)
;; Row layout and parent is hug-width if any children is fill-width
;; change parent to fixed
(and row? auto-width? (some ctl/fill-width? all-children))
(assoc :layout-item-h-sizing :fix)
;; Row layout and parent is hug-height if all children are fill-height
;; change parent to fixed
(and row? auto-height? (every? ctl/fill-height? all-children))
(assoc :layout-item-v-sizing :fix))))
(defn update-layout-child (defn update-layout-child
[ids changes] [ids changes]
(ptk/reify ::update-layout-child (ptk/reify ::update-layout-child
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [objects (wsh/lookup-page-objects state) (let [objects (wsh/lookup-page-objects state)
children-ids (->> ids (mapcat #(cph/get-children-ids objects %)))
parent-ids (->> ids (map #(cph/get-parent-id objects %))) parent-ids (->> ids (map #(cph/get-parent-id objects %)))
layout-ids (->> ids (filter (comp ctl/layout? (d/getf objects))))
undo-id (js/Symbol)] undo-id (js/Symbol)]
(rx/of (dwu/start-undo-transaction undo-id) (rx/of (dwu/start-undo-transaction undo-id)
(dwc/update-shapes ids #(d/deep-merge (or % {}) changes)) (dwc/update-shapes ids #(d/deep-merge (or % {}) changes))
(ptk/data-event :layout/update (d/concat-vec layout-ids parent-ids)) (dwc/update-shapes children-ids (partial fix-child-sizing objects changes))
(dwc/update-shapes parent-ids (partial fix-parent-sizing objects (set ids) changes))
(ptk/data-event :layout/update ids)
(dwu/commit-undo-transaction undo-id)))))) (dwu/commit-undo-transaction undo-id))))))

View file

@ -12,6 +12,7 @@
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.math :as mth] [app.common.math :as mth]
[app.common.pages :as cp]
[app.common.pages.changes-builder :as pcb] [app.common.pages.changes-builder :as pcb]
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.spec :as us :refer [max-safe-int min-safe-int]] [app.common.spec :as us :refer [max-safe-int min-safe-int]]
@ -493,7 +494,7 @@
(- y vb-y (/ vb-height 2)) (- y vb-y (/ vb-height 2))
y)) y))
unames (ctst/retrieve-used-names objects) unames (cp/retrieve-used-names objects)
svg-name (str/replace (:name svg-data) ".svg" "") svg-name (str/replace (:name svg-data) ".svg" "")

View file

@ -77,6 +77,11 @@
;; Delete the thumbnail first so if we interrupt we can regenerate after ;; Delete the thumbnail first so if we interrupt we can regenerate after
(->> (rp/cmd! :upsert-file-object-thumbnail params) (->> (rp/cmd! :upsert-file-object-thumbnail params)
(rx/catch #(rx/empty))) (rx/catch #(rx/empty)))
;; Remove the thumbnail temporary. If the user changes pages the thumbnail is regenerated
(rx/of #(update % :workspace-thumbnails assoc object-id nil))
;; Send the update to the back-end
(->> blob-result (->> blob-result
(rx/merge-map (rx/merge-map
(fn [blob] (fn [blob]

View file

@ -484,6 +484,15 @@
(some (partial ctl/layout-immediate-child? objects)))) (some (partial ctl/layout-immediate-child? objects))))
workspace-page-objects)) workspace-page-objects))
(defn all-layout-child?
[ids]
(l/derived
(fn [objects]
(->> ids
(map (d/getf objects))
(every? (partial ctl/layout-immediate-child? objects))))
workspace-page-objects))
(defn get-flex-child-viewer (defn get-flex-child-viewer
[ids page-id] [ids page-id]
(l/derived (l/derived

View file

@ -130,7 +130,7 @@
(cond (cond
(and touched? (:message error)) (and touched? (:message error))
[:span.error {:id (dm/str "error-" input-name) [:span.error {:id (dm/str "error-" input-name)
:data-test (clojure.string/join [data-test "-error"]) }(tr (:message error))] :data-test (clojure.string/join [data-test "-error"])} (tr (:message error))]
(string? hint) (string? hint)
[:span.hint hint])]])) [:span.hint hint])]]))
@ -328,7 +328,13 @@
remove-item! remove-item!
(mf/use-fn (mf/use-fn
(fn [item] (fn [item]
(swap! items #(into [] (remove (fn [x] (= x item))) %))))] (swap! items #(into [] (remove (fn [x] (= x item))) %))))
manage-key-down
(mf/use-fn
(fn [item event]
(when (kbd/enter? event)
(remove-item! item))))]
(mf/with-effect [result @value] (mf/with-effect [result @value]
(let [val (cond-> @value trim str/trim) (let [val (cond-> @value trim str/trim)
@ -337,14 +343,6 @@
(update-form! values))) (update-form! values)))
[:div {:class klass} [:div {:class klass}
(when-let [items (seq @items)]
[:div.selected-items
(for [item items]
[:div.selected-item {:key (:text item)}
[:span.around {:class (when-not (:valid item) "invalid")}
[:span.text (:text item)]
[:span.icon {:on-click #(remove-item! item)} i/cross]]])])
[:input {:id (name input-name) [:input {:id (name input-name)
:class in-klass :class in-klass
:type "text" :type "text"
@ -355,4 +353,14 @@
:value @value :value @value
:on-change on-change :on-change on-change
:placeholder (when empty? label)}] :placeholder (when empty? label)}]
[:label {:for (name input-name)} label]])) [:label {:for (name input-name)} label]
(when-let [items (seq @items)]
[:div.selected-items
(for [item items]
[:div.selected-item {:key (:text item)
:tab-index "0"
:on-key-down (partial manage-key-down item)}
[:span.around {:class (when-not (:valid item) "invalid")}
[:span.text (:text item)]
[:span.icon {:on-click #(remove-item! item)} i/cross]]])])]))

View file

@ -82,7 +82,7 @@
(when (:is-admin permissions) (when (:is-admin permissions)
{:value "admin" :label (tr "labels.admin")}) {:value "admin" :label (tr "labels.admin")})
;; Temporarily disabled viewer roles ;; Temporarily disabled viewer roles
;; https://tree.taiga.io/project/uxboxproject/issue/1083 ;; https://tree.taiga.io/project/penpot/issue/1083
;; {:value "viewer" :label (tr "labels.viewer")} ;; {:value "viewer" :label (tr "labels.viewer")}
] ]
(filterv identity))) (filterv identity)))
@ -209,7 +209,7 @@
[:li {:on-click set-admin} (tr "labels.admin")] [:li {:on-click set-admin} (tr "labels.admin")]
[:li {:on-click set-editor} (tr "labels.editor")] [:li {:on-click set-editor} (tr "labels.editor")]
;; Temporarily disabled viewer role ;; Temporarily disabled viewer role
;; https://tree.taiga.io/project/uxboxproject/issue/1083 ;; https://tree.taiga.io/project/penpot/issue/1083
;; [:li {:on-click set-viewer} (tr "labels.viewer")] ;; [:li {:on-click set-viewer} (tr "labels.viewer")]
(when you-owner? (when you-owner?
[:li {:on-click (partial set-owner member)} (tr "labels.owner")])]]])) [:li {:on-click (partial set-owner member)} (tr "labels.owner")])]]]))

View file

@ -27,23 +27,21 @@
(defn- draw-thumbnail-canvas! (defn- draw-thumbnail-canvas!
[canvas-node img-node] [canvas-node img-node]
(ts/raf (try
(fn [] (when (and (some? canvas-node) (some? img-node))
(try (let [canvas-context (.getContext canvas-node "2d")
(when (and (some? canvas-node) (some? img-node)) canvas-width (.-width canvas-node)
(let [canvas-context (.getContext canvas-node "2d") canvas-height (.-height canvas-node)]
canvas-width (.-width canvas-node) (.clearRect canvas-context 0 0 canvas-width canvas-height)
canvas-height (.-height canvas-node)] (.drawImage canvas-context img-node 0 0 canvas-width canvas-height)
(.clearRect canvas-context 0 0 canvas-width canvas-height)
(.drawImage canvas-context img-node 0 0 canvas-width canvas-height)
;; Set a true on the next animation frame, we make sure the drawImage is completed ;; Set a true on the next animation frame, we make sure the drawImage is completed
(ts/raf (ts/raf
#(dom/set-data! canvas-node "ready" "true")) #(dom/set-data! canvas-node "ready" "true"))
true)) true))
(catch :default err (catch :default err
(.error js/console err) (.error js/console err)
false))))) false)))
(defn- remove-image-loading (defn- remove-image-loading
"Remove the changes related to change a url for its embed value. This is necessary "Remove the changes related to change a url for its embed value. This is necessary
@ -78,8 +76,12 @@
(gsh/selection-rect (concat [shape] all-children)) (gsh/selection-rect (concat [shape] all-children))
(-> shape :points gsh/points->selrect)) (-> shape :points gsh/points->selrect))
fixed-width (mth/clamp width 250 2000) [fixed-width fixed-height]
fixed-height (/ (* height fixed-width) width) (if (> width height)
[(mth/clamp width 250 2000)
(/ (* height (mth/clamp width 250 2000)) width)]
[(/ (* width (mth/clamp height 250 2000)) height)
(mth/clamp height 250 2000)])
image-url (mf/use-state nil) image-url (mf/use-state nil)
observer-ref (mf/use-var nil) observer-ref (mf/use-var nil)
@ -91,6 +93,10 @@
thumbnail-data-ref (mf/use-memo (mf/deps page-id id) #(refs/thumbnail-frame-data page-id id)) thumbnail-data-ref (mf/use-memo (mf/deps page-id id) #(refs/thumbnail-frame-data page-id id))
thumbnail-data (mf/deref thumbnail-data-ref) thumbnail-data (mf/deref thumbnail-data-ref)
;; We only need the zoom level in Safari. For other browsers we don't want to activate this because
;; will render for every zoom change
zoom (when (cf/check-browser? :safari) (mf/deref refs/selected-zoom))
prev-thumbnail-data (hooks/use-previous thumbnail-data) prev-thumbnail-data (hooks/use-previous thumbnail-data)
;; State to indicate to the parent that should render the frame ;; State to indicate to the parent that should render the frame
@ -108,7 +114,9 @@
(let [canvas-node (mf/ref-val frame-canvas-ref) (let [canvas-node (mf/ref-val frame-canvas-ref)
img-node (mf/ref-val frame-image-ref)] img-node (mf/ref-val frame-image-ref)]
(when (draw-thumbnail-canvas! canvas-node img-node) (when (draw-thumbnail-canvas! canvas-node img-node)
(reset! image-url nil) (when-not (cf/check-browser? :safari)
(reset! image-url nil))
(when @show-frame-thumbnail (when @show-frame-thumbnail
(reset! show-frame-thumbnail false)) (reset! show-frame-thumbnail false))
;; If we don't have the thumbnail data saved (normally the first load) we update the data ;; If we don't have the thumbnail data saved (normally the first load) we update the data
@ -266,12 +274,16 @@
{:key (dm/str "thumbnail-canvas-" (:id shape)) {:key (dm/str "thumbnail-canvas-" (:id shape))
:ref frame-canvas-ref :ref frame-canvas-ref
:data-object-id (dm/str page-id (:id shape)) :data-object-id (dm/str page-id (:id shape))
:width fixed-width :width width
:height fixed-height :height height
;; DEBUG :style {;; Safari has a problem with the positioning of the canvas. All this is to fix Safari behavior
:style {:filter (when (and (not (cf/check-browser? :safari)) (debug? :thumbnails)) "invert(1)") ;; https://bugs.webkit.org/show_bug.cgi?id=23113
:width "100%" :display (when (cf/check-browser? :safari) "none")
:height "100%"}}]] :position "fixed"
:transform-origin "top left"
:transform (when (cf/check-browser? :safari) (dm/fmt "scale(%)" zoom))
;; DEBUG
:filter (when (debug? :thumbnails) "invert(1)")}}]]
;; Safari don't support filters so instead we add a rectangle around the thumbnail ;; Safari don't support filters so instead we add a rectangle around the thumbnail
(when (and (cf/check-browser? :safari) (debug? :thumbnails)) (when (and (cf/check-browser? :safari) (debug? :thumbnails))
@ -285,10 +297,10 @@
(when (some? @image-url) (when (some? @image-url)
[:foreignObject {:x x [:foreignObject {:x x
:y y :y y
:width width :width fixed-width
:height height} :height fixed-height}
[:img {:ref frame-image-ref [:img {:ref frame-image-ref
:src @image-url :src @image-url
:width width :width fixed-width
:height height :height fixed-height
:on-load on-image-load}]])])])) :on-load on-image-load}]])])]))

View file

@ -11,6 +11,7 @@
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.pages.common :as cpc] [app.common.pages.common :as cpc]
[app.common.text :as txt] [app.common.text :as txt]
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace.texts :as dwt] [app.main.data.workspace.texts :as dwt]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
@ -26,7 +27,7 @@
[app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-attrs shadow-menu]] [app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-attrs shadow-menu]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu]] [app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu]]
[app.main.ui.workspace.sidebar.options.menus.text :as ot] [app.main.ui.workspace.sidebar.options.menus.text :as ot]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
;; Define how to read each kind of attribute depending on the shape type: ;; Define how to read each kind of attribute depending on the shape type:
;; - shape: read the attribute directly from the shape. ;; - shape: read the attribute directly from the shape.
@ -298,6 +299,13 @@
has-text? (contains? all-types :text) has-text? (contains? all-types :text)
has-layout-container? (->> shapes (some ctl/layout?))
all-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/all-layout-child? ids))
all-layout-child? (mf/deref all-layout-child-ref)
all-layout-container? (->> shapes (every? ctl/layout?))
[measure-ids measure-values] (get-attrs shapes objects :measure) [measure-ids measure-values] (get-attrs shapes objects :measure)
[layer-ids layer-values [layer-ids layer-values
@ -332,14 +340,15 @@
(when-not (empty? measure-ids) (when-not (empty? measure-ids)
[:& measures-menu {:type type :all-types all-types :ids measure-ids :values measure-values :shape shapes}]) [:& measures-menu {:type type :all-types all-types :ids measure-ids :values measure-values :shape shapes}])
[:& layout-container-menu {:type type :ids layout-container-ids :values layout-container-values :multiple true}] (when has-layout-container?
[:& layout-container-menu {:type type :ids layout-container-ids :values layout-container-values :multiple true}])
(when is-layout-child? (when (or is-layout-child? has-layout-container?)
[:& layout-item-menu [:& layout-item-menu
{:type type {:type type
:ids layout-item-ids :ids layout-item-ids
:is-layout-child? true :is-layout-child? all-layout-child?
:is-layout-container? true :is-layout-container? all-layout-container?
:values layout-item-values}]) :values layout-item-values}])
(when-not (or (empty? constraint-ids) is-layout-child?) (when-not (or (empty? constraint-ids) is-layout-child?)

View file

@ -162,14 +162,14 @@
on-drag-over (actions/on-drag-over) on-drag-over (actions/on-drag-over)
on-drop (actions/on-drop file) on-drop (actions/on-drop file)
on-mouse-down (actions/on-mouse-down @hover selected edition drawing-tool text-editing? node-editing? on-mouse-down (actions/on-mouse-down @hover selected edition drawing-tool text-editing? node-editing?
drawing-path? create-comment? space? panning workspace-read-only?) drawing-path? create-comment? space? panning z? workspace-read-only?)
on-mouse-up (actions/on-mouse-up disable-paste) on-mouse-up (actions/on-mouse-up disable-paste)
on-pointer-down (actions/on-pointer-down) on-pointer-down (actions/on-pointer-down)
on-pointer-enter (actions/on-pointer-enter in-viewport?) on-pointer-enter (actions/on-pointer-enter in-viewport?)
on-pointer-leave (actions/on-pointer-leave in-viewport?) on-pointer-leave (actions/on-pointer-leave in-viewport?)
on-pointer-move (actions/on-pointer-move move-stream) on-pointer-move (actions/on-pointer-move move-stream)
on-pointer-up (actions/on-pointer-up) on-pointer-up (actions/on-pointer-up)
on-move-selected (actions/on-move-selected hover hover-ids selected space? workspace-read-only?) on-move-selected (actions/on-move-selected hover hover-ids selected space? z? workspace-read-only?)
on-menu-selected (actions/on-menu-selected hover hover-ids selected workspace-read-only?) on-menu-selected (actions/on-menu-selected hover hover-ids selected workspace-read-only?)
on-frame-enter (actions/on-frame-enter frame-hover) on-frame-enter (actions/on-frame-enter frame-hover)

View file

@ -34,70 +34,71 @@
(defn on-mouse-down (defn on-mouse-down
[{:keys [id blocked hidden type]} selected edition drawing-tool text-editing? [{:keys [id blocked hidden type]} selected edition drawing-tool text-editing?
node-editing? drawing-path? create-comment? space? panning workspace-read-only?] node-editing? drawing-path? create-comment? space? panning z? workspace-read-only?]
(mf/use-callback (mf/use-callback
(mf/deps id blocked hidden type selected edition drawing-tool text-editing? (mf/deps id blocked hidden type selected edition drawing-tool text-editing?
node-editing? drawing-path? create-comment? @space? node-editing? drawing-path? create-comment? @z? @space?
panning workspace-read-only?) panning workspace-read-only?)
(fn [bevent] (fn [bevent]
(when (or (dom/class? (dom/get-target bevent) "viewport-controls") (when (or (dom/class? (dom/get-target bevent) "viewport-controls")
(dom/class? (dom/get-target bevent) "viewport-selrect")) (dom/class? (dom/get-target bevent) "viewport-selrect"))
(dom/stop-propagation bevent) (dom/stop-propagation bevent)
(let [event (.-nativeEvent bevent) (when-not @z?
ctrl? (kbd/ctrl? event) (let [event (.-nativeEvent bevent)
meta? (kbd/meta? event) ctrl? (kbd/ctrl? event)
shift? (kbd/shift? event) meta? (kbd/meta? event)
alt? (kbd/alt? event) shift? (kbd/shift? event)
mod? (kbd/mod? event) alt? (kbd/alt? event)
mod? (kbd/mod? event)
left-click? (and (not panning) (= 1 (.-which event))) left-click? (and (not panning) (= 1 (.-which event)))
middle-click? (and (not panning) (= 2 (.-which event)))] middle-click? (and (not panning) (= 2 (.-which event)))]
(cond (cond
(or middle-click? (and left-click? @space?)) (or middle-click? (and left-click? @space?))
(do (do
(dom/prevent-default bevent) (dom/prevent-default bevent)
(if mod? (if mod?
(let [raw-pt (dom/get-client-position event) (let [raw-pt (dom/get-client-position event)
pt (uwvv/point->viewport raw-pt)] pt (uwvv/point->viewport raw-pt)]
(st/emit! (dw/start-zooming pt))) (st/emit! (dw/start-zooming pt)))
(st/emit! (dw/start-panning)))) (st/emit! (dw/start-panning))))
left-click? left-click?
(do (do
(st/emit! (ms/->MouseEvent :down ctrl? shift? alt? meta?)) (st/emit! (ms/->MouseEvent :down ctrl? shift? alt? meta?))
(when (and (not= edition id) text-editing?) (when (and (not= edition id) text-editing?)
(st/emit! dw/clear-edition-mode)) (st/emit! dw/clear-edition-mode))
(when (and (not text-editing?) (when (and (not text-editing?)
(not blocked) (not blocked)
(not hidden) (not hidden)
(not create-comment?) (not create-comment?)
(not drawing-path?)) (not drawing-path?))
(cond (cond
node-editing? node-editing?
;; Handle path node area selection ;; Handle path node area selection
(when-not workspace-read-only? (when-not workspace-read-only?
(st/emit! (dwdp/handle-area-selection shift?))) (st/emit! (dwdp/handle-area-selection shift?)))
drawing-tool drawing-tool
(when-not workspace-read-only? (when-not workspace-read-only?
(st/emit! (dd/start-drawing drawing-tool))) (st/emit! (dd/start-drawing drawing-tool)))
(or (not id) mod?) (or (not id) mod?)
(st/emit! (dw/handle-area-selection shift? mod?)) (st/emit! (dw/handle-area-selection shift? mod?))
(not drawing-tool) (not drawing-tool)
(when-not workspace-read-only? (when-not workspace-read-only?
(st/emit! (dw/start-move-selected id shift?)))))))))))) (st/emit! (dw/start-move-selected id shift?)))))))))))))
(defn on-move-selected (defn on-move-selected
[hover hover-ids selected space? workspace-read-only?] [hover hover-ids selected space? z? workspace-read-only?]
(mf/use-callback (mf/use-callback
(mf/deps @hover @hover-ids selected @space? workspace-read-only?) (mf/deps @hover @hover-ids selected @space? @z? workspace-read-only?)
(fn [bevent] (fn [bevent]
(let [event (.-nativeEvent bevent) (let [event (.-nativeEvent bevent)
shift? (kbd/shift? event) shift? (kbd/shift? event)
@ -110,7 +111,7 @@
(not @space?)) (not @space?))
(dom/prevent-default bevent) (dom/prevent-default bevent)
(dom/stop-propagation bevent) (dom/stop-propagation bevent)
(when-not workspace-read-only? (when-not (or workspace-read-only? @z?)
(st/emit! (dw/start-move-selected)))))))) (st/emit! (dw/start-move-selected))))))))
(defn on-frame-select (defn on-frame-select

View file

@ -109,7 +109,8 @@
(defn setup-keyboard [alt? mod? space? z?] (defn setup-keyboard [alt? mod? space? z?]
(hooks/use-stream ms/keyboard-alt #(reset! alt? %)) (hooks/use-stream ms/keyboard-alt #(reset! alt? %))
(hooks/use-stream ms/keyboard-mod #(reset! mod? %)) (hooks/use-stream ms/keyboard-mod #((reset! mod? %)
(when-not % (reset! z? false)))) ;; In mac after command+z there is no event for the release of the z key
(hooks/use-stream ms/keyboard-space #(reset! space? %)) (hooks/use-stream ms/keyboard-space #(reset! space? %))
(hooks/use-stream ms/keyboard-z #(reset! z? %))) (hooks/use-stream ms/keyboard-z #(reset! z? %)))

View file

@ -166,12 +166,12 @@
; ;
; [Page] ; [Page]
; Root Frame ; Root Frame
; Component-1* #--> Component-1 ; Component 1* #--> Component 1
; #{:shapes-group} ; #{:shapes-group}
; Rect 2 ---> Rect 2 ; Rect 2 ---> Rect 2
; ;
; [Component-1] ; [Component 1]
; Component-1 ; Component 1
; Rect 1 ; Rect 1
; Rect 2 ; Rect 2
; ;
@ -180,14 +180,14 @@
new-state new-state
(thp/id :instance1))] (thp/id :instance1))]
(t/is (= (:name group) "Component-1")) (t/is (= (:name group) "Component 1"))
(t/is (= (:touched group) #{:shapes-group})) (t/is (= (:touched group) #{:shapes-group}))
(t/is (not= (:shape-ref group) nil)) (t/is (not= (:shape-ref group) nil))
(t/is (= (:name shape2) "Rect 2")) (t/is (= (:name shape2) "Rect 2"))
(t/is (= (:touched shape2) nil)) (t/is (= (:touched shape2) nil))
(t/is (not= (:shape-ref shape2) nil)) (t/is (not= (:shape-ref shape2) nil))
(t/is (= (:name c-group) "Component-1")) (t/is (= (:name c-group) "Component 1"))
(t/is (= (:touched c-group) nil)) (t/is (= (:touched c-group) nil))
(t/is (= (:shape-ref c-group) nil)) (t/is (= (:shape-ref c-group) nil))
(t/is (= (:name c-shape2) "Rect 1")) (t/is (= (:name c-shape2) "Rect 1"))
@ -227,14 +227,14 @@
; ;
; [Page] ; [Page]
; Root Frame ; Root Frame
; Component-1* #--> Component-1 ; Component 1* #--> Component 1
; #{:shapes-group} ; #{:shapes-group}
; Rect 2 ---> Rect 2 ; Rect 2 ---> Rect 2
; Rect 1 ---> Rect 1 ; Rect 1 ---> Rect 1
; Rect 3 ---> Rect 3 ; Rect 3 ---> Rect 3
; ;
; [Component-1] ; [Component 1]
; Component-1 ; Component 1
; Rect 1 ; Rect 1
; Rect 2 ; Rect 2
; Rect 3 ; Rect 3
@ -245,7 +245,7 @@
new-state new-state
(thp/id :instance1))] (thp/id :instance1))]
(t/is (= (:name group) "Component-1")) (t/is (= (:name group) "Component 1"))
(t/is (= (:touched group) #{:shapes-group})) (t/is (= (:touched group) #{:shapes-group}))
(t/is (= (:name shape1) "Rect 2")) (t/is (= (:name shape1) "Rect 2"))
(t/is (= (:touched shape1) nil)) (t/is (= (:touched shape1) nil))
@ -257,7 +257,7 @@
(t/is (= (:touched shape3) nil)) (t/is (= (:touched shape3) nil))
(t/is (not= (:shape-ref shape3) nil)) (t/is (not= (:shape-ref shape3) nil))
(t/is (= (:name c-group) "Component-1")) (t/is (= (:name c-group) "Component 1"))
(t/is (= (:touched c-group) nil)) (t/is (= (:touched c-group) nil))
(t/is (= (:shape-ref c-group) nil)) (t/is (= (:shape-ref c-group) nil))
(t/is (= (:name c-shape1) "Rect 1")) (t/is (= (:name c-shape1) "Rect 1"))
@ -389,7 +389,7 @@
new-state new-state
(thp/id :instance2))] (thp/id :instance2))]
; TODO: get and check the instance inside component [Group-1] ; TODO: get and check the instance inside component [Group 1]
(t/is (= (:name instance2) "Group")) (t/is (= (:name instance2) "Group"))
(t/is (= (:touched instance2) nil)) (t/is (= (:touched instance2) nil))
@ -478,7 +478,7 @@
new-state new-state
(thp/id :instance2))] (thp/id :instance2))]
; TODO: get and check the instance inside component [Group-1] ; TODO: get and check the instance inside component [Group 1]
(t/is (= (:name instance2) "Group")) (t/is (= (:name instance2) "Group"))
(t/is (= (:touched instance2) nil)) (t/is (= (:touched instance2) nil))
@ -567,7 +567,7 @@
new-state new-state
(thp/id :instance2))] (thp/id :instance2))]
; TODO: get and check the instance inside component [Group-1] ; TODO: get and check the instance inside component [Group 1]
(t/is (= (:name instance2) "Group")) (t/is (= (:name instance2) "Group"))
(t/is (= (:touched instance2) nil)) (t/is (= (:touched instance2) nil))
@ -737,12 +737,12 @@
; ;
; [Page] ; [Page]
; Root Frame ; Root Frame
; Component-1 #--> Component-1 ; Component 1 #--> Component 1
; Rect 1 ---> Rect 1 ; Rect 1 ---> Rect 1
; Rect 2 ---> Rect 2 ; Rect 2 ---> Rect 2
; ;
; [Component-1] ; [Component 1]
; Component-1 ; Component 1
; Rect 1 ; Rect 1
; Rect 2 ; Rect 2
; ;
@ -752,7 +752,7 @@
new-state new-state
(thp/id :instance1))] (thp/id :instance1))]
(t/is (= (:name group) "Component-1")) (t/is (= (:name group) "Component 1"))
(t/is (= (:touched group) nil)) (t/is (= (:touched group) nil))
(t/is (not= (:shape-ref group) nil)) (t/is (not= (:shape-ref group) nil))
(t/is (= (:name shape1) "Rect 1")) (t/is (= (:name shape1) "Rect 1"))
@ -762,7 +762,7 @@
(t/is (= (:touched shape2) nil)) (t/is (= (:touched shape2) nil))
(t/is (not= (:shape-ref shape2) nil)) (t/is (not= (:shape-ref shape2) nil))
(t/is (= (:name c-group) "Component-1")) (t/is (= (:name c-group) "Component 1"))
(t/is (= (:touched c-group) nil)) (t/is (= (:touched c-group) nil))
(t/is (= (:shape-ref c-group) nil)) (t/is (= (:shape-ref c-group) nil))
(t/is (= (:name c-shape1) "Rect 1")) (t/is (= (:name c-shape1) "Rect 1"))
@ -803,13 +803,13 @@
; ;
; [Page] ; [Page]
; Root Frame ; Root Frame
; Component-1 #--> Component-1 ; Component 1 #--> Component 1
; Rect 1 ---> Rect 1 ; Rect 1 ---> Rect 1
; Rect 2 ---> Rect 2 ; Rect 2 ---> Rect 2
; Rect 3 ---> Rect 3 ; Rect 3 ---> Rect 3
; ;
; [Component-1] ; [Component 1]
; Component-1 ; Component 1
; Rect 1 ; Rect 1
; Rect 2 ; Rect 2
; Rect 3 ; Rect 3
@ -819,7 +819,7 @@
new-state new-state
(thp/id :instance1))] (thp/id :instance1))]
(t/is (= (:name group) "Component-1")) (t/is (= (:name group) "Component 1"))
(t/is (= (:touched group) nil)) (t/is (= (:touched group) nil))
(t/is (not= (:shape-ref group) nil)) (t/is (not= (:shape-ref group) nil))
(t/is (= (:name shape1) "Rect 1")) (t/is (= (:name shape1) "Rect 1"))
@ -832,7 +832,7 @@
(t/is (= (:touched shape3) nil)) (t/is (= (:touched shape3) nil))
(t/is (not= (:shape-ref shape3) nil)) (t/is (not= (:shape-ref shape3) nil))
(t/is (= (:name c-group) "Component-1")) (t/is (= (:name c-group) "Component 1"))
(t/is (= (:touched c-group) nil)) (t/is (= (:touched c-group) nil))
(t/is (= (:shape-ref c-group) nil)) (t/is (= (:shape-ref c-group) nil))
(t/is (= (:name c-shape1) "Rect 1")) (t/is (= (:name c-shape1) "Rect 1"))
@ -1144,7 +1144,7 @@
new-state new-state
(thp/id :instance2))] (thp/id :instance2))]
; TODO: get and check the instance inside component [Group-1] ; TODO: get and check the instance inside component [Group 1]
(t/is (= (:name instance2) "Group")) (t/is (= (:name instance2) "Group"))
(t/is (= (:touched instance2) nil)) (t/is (= (:touched instance2) nil))
@ -1517,11 +1517,11 @@
; ;
; [Page] ; [Page]
; Root Frame ; Root Frame
; Component-1 #--> Component-1 ; Component 1 #--> Component 1
; Rect 2 ---> Rect 2 ; Rect 2 ---> Rect 2
; ;
; [Component-1] ; [Component 1]
; Component-1 ; Component 1
; Rect 2 ; Rect 2
; ;
(let [[[group shape2] [c-group c-shape2] component] (let [[[group shape2] [c-group c-shape2] component]
@ -1529,14 +1529,14 @@
new-state new-state
(thp/id :instance1))] (thp/id :instance1))]
(t/is (= (:name group) "Component-1")) (t/is (= (:name group) "Component 1"))
(t/is (= (:touched group) nil)) (t/is (= (:touched group) nil))
(t/is (not= (:shape-ref group) nil)) (t/is (not= (:shape-ref group) nil))
(t/is (= (:name shape2) "Rect 2")) (t/is (= (:name shape2) "Rect 2"))
(t/is (= (:touched shape2) nil)) (t/is (= (:touched shape2) nil))
(t/is (not= (:shape-ref shape2) nil)) (t/is (not= (:shape-ref shape2) nil))
(t/is (= (:name c-group) "Component-1")) (t/is (= (:name c-group) "Component 1"))
(t/is (= (:touched c-group) nil)) (t/is (= (:touched c-group) nil))
(t/is (= (:shape-ref c-group) nil)) (t/is (= (:shape-ref c-group) nil))
(t/is (= (:name c-shape2) "Rect 2")) (t/is (= (:name c-shape2) "Rect 2"))
@ -1576,13 +1576,13 @@
; ;
; [Page] ; [Page]
; Root Frame ; Root Frame
; Component-1 #--> Component-1 ; Component 1 #--> Component 1
; Rect 2 ---> Rect 2 ; Rect 2 ---> Rect 2
; Rect 1 ---> Rect 1 ; Rect 1 ---> Rect 1
; Rect 3 ---> Rect 3 ; Rect 3 ---> Rect 3
; ;
; [Component-1] ; [Component 1]
; Component-1 ; Component 1
; Rect 2 ; Rect 2
; Rect 1 ; Rect 1
; Rect 3 ; Rect 3
@ -1592,7 +1592,7 @@
new-state new-state
(thp/id :instance1))] (thp/id :instance1))]
(t/is (= (:name group) "Component-1")) (t/is (= (:name group) "Component 1"))
(t/is (= (:touched group) nil)) (t/is (= (:touched group) nil))
(t/is (not= (:shape-ref group) nil)) (t/is (not= (:shape-ref group) nil))
(t/is (= (:touched shape1) nil)) (t/is (= (:touched shape1) nil))
@ -1605,7 +1605,7 @@
(t/is (not= (:shape-ref shape3) nil)) (t/is (not= (:shape-ref shape3) nil))
(t/is (= (:name shape3) "Rect 3")) (t/is (= (:name shape3) "Rect 3"))
(t/is (= (:name c-group) "Component-1")) (t/is (= (:name c-group) "Component 1"))
(t/is (= (:touched c-group) nil)) (t/is (= (:touched c-group) nil))
(t/is (= (:shape-ref c-group) nil)) (t/is (= (:shape-ref c-group) nil))
(t/is (= (:name c-shape1) "Rect 2")) (t/is (= (:name c-shape1) "Rect 2"))
@ -1737,7 +1737,7 @@
new-state new-state
(thp/id :instance2))] (thp/id :instance2))]
; TODO: get and check the instance inside component [Group-1] ; TODO: get and check the instance inside component [Group 1]
(t/is (= (:name instance2) "Group")) (t/is (= (:name instance2) "Group"))
(t/is (= (:touched instance2) nil)) (t/is (= (:touched instance2) nil))
@ -1826,7 +1826,7 @@
new-state new-state
(thp/id :instance2))] (thp/id :instance2))]
; TODO: get and check the instance inside component [Group-1] ; TODO: get and check the instance inside component [Group 1]
(t/is (= (:name instance2) "Group")) (t/is (= (:name instance2) "Group"))
(t/is (= (:touched instance2) nil)) (t/is (= (:touched instance2) nil))
@ -1916,7 +1916,7 @@
new-state new-state
(thp/id :instance2))] (thp/id :instance2))]
; TODO: get and check the instance inside component [Group-1] ; TODO: get and check the instance inside component [Group 1]
(t/is (= (:name instance2) "Group")) (t/is (= (:name instance2) "Group"))
(t/is (= (:touched instance2) nil)) (t/is (= (:touched instance2) nil))

View file

@ -30,7 +30,7 @@
(let [state (-> thp/initial-state (let [state (-> thp/initial-state
(thp/sample-page) (thp/sample-page)
(thp/sample-shape :shape1 :rect (thp/sample-shape :shape1 :rect
{:name "Rect-1"})) {:name "Rect 1"}))
store (the/prepare-store state done store (the/prepare-store state done
(fn [new-state] (fn [new-state]
@ -43,12 +43,12 @@
; ;
; [Page] ; [Page]
; Root Frame ; Root Frame
; Rect-1 #--> Rect-1 ; Rect 1 #--> Rect 1
; Rect-1 ---> Rect-1 ; Rect 1 ---> Rect 1
; ;
; [Rect-1] ; [Rect 1]
; Rect-1 ; Rect 1
; Rect-1 ; Rect 1
; ;
(let [shape1 (thp/get-shape new-state :shape1) (let [shape1 (thp/get-shape new-state :shape1)
@ -59,11 +59,11 @@
file (wsh/get-local-file new-state)] file (wsh/get-local-file new-state)]
(t/is (= (:name shape1) "Rect-1")) (t/is (= (:name shape1) "Rect 1"))
(t/is (= (:name group) "Rect-1")) (t/is (= (:name group) "Rect 1"))
(t/is (= (:name component) "Rect-1")) (t/is (= (:name component) "Rect 1"))
(t/is (= (:name c-shape1) "Rect-1")) (t/is (= (:name c-shape1) "Rect 1"))
(t/is (= (:name c-group) "Rect-1")) (t/is (= (:name c-group) "Rect 1"))
(thl/is-from-file group file))))] (thl/is-from-file group file))))]
@ -81,7 +81,7 @@
(let [state (-> thp/initial-state (let [state (-> thp/initial-state
(thp/sample-page) (thp/sample-page)
(thp/sample-shape :shape1 :rect (thp/sample-shape :shape1 :rect
{:name "Rect-1"}))] {:name "Rect 1"}))]
(->> state (->> state
(the/do-update (dw/select-shape (thp/id :shape1))) (the/do-update (dw/select-shape (thp/id :shape1)))
@ -97,11 +97,11 @@
file (wsh/get-local-file new-state)] file (wsh/get-local-file new-state)]
(t/is (= (:name shape1) "Rect-1")) (t/is (= (:name shape1) "Rect 1"))
(t/is (= (:name group) "Component-1")) (t/is (= (:name group) "Component 1"))
(t/is (= (:name component) "Component-1")) (t/is (= (:name component) "Component 1"))
(t/is (= (:name c-shape1) "Rect-1")) (t/is (= (:name c-shape1) "Rect 1"))
(t/is (= (:name c-group) "Component-1")) (t/is (= (:name c-group) "Component 1"))
(thl/is-from-file group file)))) (thl/is-from-file group file))))
@ -113,7 +113,7 @@
(let [state (-> thp/initial-state (let [state (-> thp/initial-state
(thp/sample-page) (thp/sample-page)
(thp/sample-shape :shape1 :rect (thp/sample-shape :shape1 :rect
{:name "Rect-1"}) {:name "Rect 1"})
(thp/sample-shape :shape2 :rect (thp/sample-shape :shape2 :rect
{:name "Rect-2"})) {:name "Rect-2"}))
@ -123,13 +123,13 @@
; ;
; [Page] ; [Page]
; Root Frame ; Root Frame
; Component-1 #--> Component-1 ; Component 1 #--> Component 1
; Rect-1 ---> Rect-1 ; Rect 1 ---> Rect 1
; Rect-2 ---> Rect-2 ; Rect-2 ---> Rect-2
; ;
; [Component-1] ; [Component 1]
; Component-1 ; Component 1
; Rect-1 ; Rect 1
; Rect-2 ; Rect-2
; ;
(let [shape1 (thp/get-shape new-state :shape1) (let [shape1 (thp/get-shape new-state :shape1)
@ -143,12 +143,12 @@
file (wsh/get-local-file new-state)] file (wsh/get-local-file new-state)]
(t/is (= (:name group) "Component-1")) (t/is (= (:name group) "Component 1"))
(t/is (= (:name shape1) "Rect-1")) (t/is (= (:name shape1) "Rect 1"))
(t/is (= (:name shape2) "Rect-2")) (t/is (= (:name shape2) "Rect-2"))
(t/is (= (:name component) "Component-1")) (t/is (= (:name component) "Component 1"))
(t/is (= (:name c-group) "Component-1")) (t/is (= (:name c-group) "Component 1"))
(t/is (= (:name c-shape1) "Rect-1")) (t/is (= (:name c-shape1) "Rect 1"))
(t/is (= (:name c-shape2) "Rect-2")) (t/is (= (:name c-shape2) "Rect-2"))
(thl/is-from-file group file))))] (thl/is-from-file group file))))]
@ -166,7 +166,7 @@
(let [state (-> thp/initial-state (let [state (-> thp/initial-state
(thp/sample-page) (thp/sample-page)
(thp/sample-shape :shape1 :rect (thp/sample-shape :shape1 :rect
{:name "Rect-1"}) {:name "Rect 1"})
(thp/sample-shape :shape2 :rect (thp/sample-shape :shape2 :rect
{:name "Rect-2"}) {:name "Rect-2"})
(thp/group-shapes :group1 (thp/group-shapes :group1
@ -180,12 +180,12 @@
; [Page] ; [Page]
; Root Frame ; Root Frame
; Group #--> Group ; Group #--> Group
; Rect-1 ---> Rect-1 ; Rect 1 ---> Rect 1
; Rect-2 ---> Rect-2 ; Rect-2 ---> Rect-2
; ;
; [Group] ; [Group]
; Group ; Group
; Rect-1 ; Rect 1
; Rect-2 ; Rect-2
; ;
(let [[[group shape1 shape2] (let [[[group shape1 shape2]
@ -197,11 +197,11 @@
file (wsh/get-local-file new-state)] file (wsh/get-local-file new-state)]
(t/is (= (:name shape1) "Rect-1")) (t/is (= (:name shape1) "Rect 1"))
(t/is (= (:name shape2) "Rect-2")) (t/is (= (:name shape2) "Rect-2"))
(t/is (= (:name group) "Group")) (t/is (= (:name group) "Group"))
(t/is (= (:name component) "Group")) (t/is (= (:name component) "Group"))
(t/is (= (:name c-shape1) "Rect-1")) (t/is (= (:name c-shape1) "Rect 1"))
(t/is (= (:name c-shape2) "Rect-2")) (t/is (= (:name c-shape2) "Rect-2"))
(t/is (= (:name c-group) "Group")) (t/is (= (:name c-group) "Group"))
@ -219,7 +219,7 @@
(let [state (-> thp/initial-state (let [state (-> thp/initial-state
(thp/sample-page) (thp/sample-page)
(thp/sample-shape :shape1 :rect (thp/sample-shape :shape1 :rect
{:name "Rect-1"}) {:name "Rect 1"})
(thp/make-component :instance1 :component1 (thp/make-component :instance1 :component1
[(thp/id :shape1)])) [(thp/id :shape1)]))
@ -229,18 +229,18 @@
; ;
; [Page] ; [Page]
; Root Frame ; Root Frame
; Rect-1 #--> Rect-1 ; Rect 1 #--> Rect 1
; Rect-1 @--> Rect-1 ; Rect 1 @--> Rect 1
; Rect-1 ---> Rect-1 ; Rect 1 ---> Rect 1
; ;
; [Rect-1] ; [Rect 1]
; Rect-1 ; Rect 1
; Rect-1 ; Rect 1
; ;
; [Rect-1] ; [Rect 1]
; Rect-1 ; Rect 1
; Rect-1 @--> Rect-1 ; Rect 1 @--> Rect 1
; Rect-1 ---> Rect-1 ; Rect 1 ---> Rect 1
; ;
(let [[[instance1 shape1] (let [[[instance1 shape1]
[c-instance1 c-shape1] [c-instance1 c-shape1]
@ -257,19 +257,19 @@
new-state new-state
(:parent-id instance1))] (:parent-id instance1))]
(t/is (= (:name shape1) "Rect-1")) (t/is (= (:name shape1) "Rect 1"))
(t/is (= (:name instance1) "Rect-1")) (t/is (= (:name instance1) "Rect 1"))
(t/is (= (:name component1) "Rect-1")) (t/is (= (:name component1) "Rect 1"))
(t/is (= (:name c-shape1) "Rect-1")) (t/is (= (:name c-shape1) "Rect 1"))
(t/is (= (:name c-instance1) "Rect-1")) (t/is (= (:name c-instance1) "Rect 1"))
(t/is (= (:name shape1') "Rect-1")) (t/is (= (:name shape1') "Rect 1"))
(t/is (= (:name instance1') "Rect-1")) (t/is (= (:name instance1') "Rect 1"))
(t/is (= (:name instance2) "Rect-1")) (t/is (= (:name instance2) "Rect 1"))
(t/is (= (:name component2) "Rect-1")) (t/is (= (:name component2) "Rect 1"))
(t/is (= (:name c-shape1') "Rect-1")) (t/is (= (:name c-shape1') "Rect 1"))
(t/is (= (:name c-instance1') "Rect-1")) (t/is (= (:name c-instance1') "Rect 1"))
(t/is (= (:name c-instance2) "Rect-1")))))] (t/is (= (:name c-instance2) "Rect 1")))))]
(ptk/emit! (ptk/emit!
store store
@ -283,7 +283,7 @@
(let [state (-> thp/initial-state (let [state (-> thp/initial-state
(thp/sample-page) (thp/sample-page)
(thp/sample-shape :shape1 :rect (thp/sample-shape :shape1 :rect
{:name "Rect-1"}) {:name "Rect 1"})
(thp/make-component :instance1 :component-1 (thp/make-component :instance1 :component-1
[(thp/id :shape1)])) [(thp/id :shape1)]))
@ -296,11 +296,11 @@
; [Page] ; [Page]
; Root Frame ; Root Frame
; Rect-2 #--> Renamed component ; Rect-2 #--> Renamed component
; Rect-1 ---> Rect-1 ; Rect 1 ---> Rect 1
; ;
; [Renamed] ; [Renamed]
; Renamed component ; Renamed component
; Rect-1 ; Rect 1
(let [libs (wsh/get-libraries new-state) (let [libs (wsh/get-libraries new-state)
component (cph/get-component libs component (cph/get-component libs
(:component-file instance1) (:component-file instance1)
@ -319,7 +319,7 @@
(let [state (-> thp/initial-state (let [state (-> thp/initial-state
(thp/sample-page) (thp/sample-page)
(thp/sample-shape :shape1 :rect (thp/sample-shape :shape1 :rect
{:name "Rect-1"}) {:name "Rect 1"})
(thp/make-component :instance1 :component-1 (thp/make-component :instance1 :component-1
[(thp/id :shape1)])) [(thp/id :shape1)]))
@ -332,16 +332,16 @@
; ;
; [Page] ; [Page]
; Root Frame ; Root Frame
; Rect-1 #--> Rect-1 ; Rect 1 #--> Rect 1
; Rect-1 ---> Rect-1 ; Rect 1 ---> Rect 1
; ;
; [Rect-1] ; [Rect 1]
; Rect-1 ; Rect 1
; Rect-1 ; Rect 1
; ;
; [Rect-1] ; [Rect 1]
; Rect-1 ; Rect 1
; Rect-1 ; Rect 1
; ;
(let [new-component-id (->> (get-in new-state (let [new-component-id (->> (get-in new-state
[:workspace-data [:workspace-data
@ -363,7 +363,7 @@
new-state new-state
new-component-id)] new-component-id)]
(t/is (= (:name component2) "Rect-1")))))] (t/is (= (:name component2) "Rect 1")))))]
(ptk/emit! (ptk/emit!
store store
@ -376,7 +376,7 @@
(let [state (-> thp/initial-state (let [state (-> thp/initial-state
(thp/sample-page) (thp/sample-page)
(thp/sample-shape :shape1 :rect (thp/sample-shape :shape1 :rect
{:name "Rect-1"}) {:name "Rect 1"})
(thp/make-component :instance1 :component-1 (thp/make-component :instance1 :component-1
[(thp/id :shape1)])) [(thp/id :shape1)]))
@ -392,7 +392,7 @@
; [Page] ; [Page]
; Root Frame ; Root Frame
; Rect-2 ; Rect-2
; Rect-1 ; Rect 1
; ;
(let [[instance1 shape1] (let [[instance1 shape1]
(thl/resolve-noninstance (thl/resolve-noninstance
@ -420,7 +420,7 @@
(let [state (-> thp/initial-state (let [state (-> thp/initial-state
(thp/sample-page) (thp/sample-page)
(thp/sample-shape :shape1 :rect (thp/sample-shape :shape1 :rect
{:name "Rect-1"}) {:name "Rect 1"})
(thp/make-component :instance1 :component-1 (thp/make-component :instance1 :component-1
[(thp/id :shape1)])) [(thp/id :shape1)]))
@ -434,14 +434,14 @@
; ;
; [Page] ; [Page]
; Root Frame ; Root Frame
; Rect-1 #--> Rect-1 ; Rect 1 #--> Rect 1
; Rect-1 ---> Rect-1 ; Rect 1 ---> Rect 1
; Rect-1 #--> Rect-1 ; Rect 1 #--> Rect 1
; Rect-1 ---> Rect-1 ; Rect 1 ---> Rect 1
; ;
; [Rect-1] ; [Rect 1]
; Rect-1 ; Rect 1
; Rect-1 ; Rect 1
; ;
(let [new-instance-id (-> new-state (let [new-instance-id (-> new-state
wsh/lookup-selected wsh/lookup-selected
@ -456,10 +456,10 @@
(t/is (not= (:id instance1) (:id instance2))) (t/is (not= (:id instance1) (:id instance2)))
(t/is (= (:id component) component-id)) (t/is (= (:id component) component-id))
(t/is (= (:name instance2) "Rect-1")) (t/is (= (:name instance2) "Rect 1"))
(t/is (= (:name shape2) "Rect-1")) (t/is (= (:name shape2) "Rect 1"))
(t/is (= (:name c-instance2) "Rect-1")) (t/is (= (:name c-instance2) "Rect 1"))
(t/is (= (:name c-shape2) "Rect-1")) (t/is (= (:name c-shape2) "Rect 1"))
(t/is (= (:component-file instance2) (t/is (= (:component-file instance2)
thp/current-file-id)))))] thp/current-file-id)))))]
@ -476,7 +476,7 @@
(let [state (-> thp/initial-state (let [state (-> thp/initial-state
(thp/sample-page) (thp/sample-page)
(thp/sample-shape :shape1 :rect (thp/sample-shape :shape1 :rect
{:name "Rect-1"}) {:name "Rect 1"})
(thp/make-component :instance1 :component-1 (thp/make-component :instance1 :component-1
[(thp/id :shape1)]) [(thp/id :shape1)])
(thp/move-to-library :lib1 "Library 1") (thp/move-to-library :lib1 "Library 1")
@ -491,8 +491,8 @@
; ;
; [Page] ; [Page]
; Root Frame ; Root Frame
; Rect-1 #--> <Library 1> Rect-1 ; Rect 1 #--> <Library 1> Rect 1
; Rect-1 ---> <Library 1> Rect-1 ; Rect 1 ---> <Library 1> Rect 1
; ;
(let [new-instance-id (-> new-state (let [new-instance-id (-> new-state
wsh/lookup-selected wsh/lookup-selected
@ -506,10 +506,10 @@
new-instance-id)] new-instance-id)]
(t/is (= (:id component) component-id)) (t/is (= (:id component) component-id))
(t/is (= (:name instance2) "Rect-1")) (t/is (= (:name instance2) "Rect 1"))
(t/is (= (:name shape2) "Rect-1")) (t/is (= (:name shape2) "Rect 1"))
(t/is (= (:name c-instance2) "Rect-1")) (t/is (= (:name c-instance2) "Rect 1"))
(t/is (= (:name c-shape2) "Rect-1")) (t/is (= (:name c-shape2) "Rect 1"))
(t/is (= (:component-file instance2) library-id)))))] (t/is (= (:component-file instance2) library-id)))))]
(ptk/emit! (ptk/emit!
@ -525,7 +525,7 @@
(let [state (-> thp/initial-state (let [state (-> thp/initial-state
(thp/sample-page) (thp/sample-page)
(thp/sample-shape :shape1 :rect (thp/sample-shape :shape1 :rect
{:name "Rect-1"}) {:name "Rect 1"})
(thp/make-component :instance1 :component-1 (thp/make-component :instance1 :component-1
[(thp/id :shape1)])) [(thp/id :shape1)]))
@ -539,11 +539,11 @@
; [Page] ; [Page]
; Root Frame ; Root Frame
; Rect-2 ; Rect-2
; Rect-1 ; Rect 1
; ;
; [Rect-2] ; [Rect-2]
; Rect-2 ; Rect-2
; Rect-1 ; Rect 1
; ;
(let [[instance1 shape1] (let [[instance1 shape1]
(thl/resolve-noninstance (thl/resolve-noninstance
@ -564,7 +564,7 @@
(let [state (-> thp/initial-state (let [state (-> thp/initial-state
(thp/sample-page) (thp/sample-page)
(thp/sample-shape :shape1 :rect (thp/sample-shape :shape1 :rect
{:name "Rect-1"})) {:name "Rect 1"}))
file (wsh/get-local-file state) file (wsh/get-local-file state)
instance1 (thp/get-shape state :instance1) instance1 (thp/get-shape state :instance1)
@ -577,17 +577,17 @@
; [Page] ; [Page]
; Root Frame ; Root Frame
; Group #--> Group ; Group #--> Group
; Rect-1 @--> Rect-1 ; Rect 1 @--> Rect 1
; Rect-1 ---> Rect-1 ; Rect 1 ---> Rect 1
; ;
; [Rect-1] ; [Rect 1]
; Rect-1 ; Rect 1
; Rect-1 ; Rect 1
; ;
; [Group] ; [Group]
; Group ; Group
; Rect-1 @--> Rect-1 ; Rect 1 @--> Rect 1
; Rect-1 ---> Rect-1 ; Rect 1 ---> Rect 1
; ;
(let [page (thp/current-page new-state) (let [page (thp/current-page new-state)
shape1 (thp/get-shape new-state :shape1) shape1 (thp/get-shape new-state :shape1)
@ -601,12 +601,12 @@
(:parent-id parent1))] (:parent-id parent1))]
(t/is (= (:name group) "Group")) (t/is (= (:name group) "Group"))
(t/is (= (:name shape1) "Rect-1")) (t/is (= (:name shape1) "Rect 1"))
(t/is (= (:name shape2) "Rect-1")) (t/is (= (:name shape2) "Rect 1"))
(t/is (= (:name component) "Group")) (t/is (= (:name component) "Group"))
(t/is (= (:name c-group) "Group")) (t/is (= (:name c-group) "Group"))
(t/is (= (:name c-shape1) "Rect-1")) (t/is (= (:name c-shape1) "Rect 1"))
(t/is (= (:name c-shape2) "Rect-1")))))] (t/is (= (:name c-shape2) "Rect 1")))))]
(ptk/emit! (ptk/emit!
store store
@ -622,7 +622,7 @@
(let [state (-> thp/initial-state (let [state (-> thp/initial-state
(thp/sample-page) (thp/sample-page)
(thp/sample-shape :shape1 :rect (thp/sample-shape :shape1 :rect
{:name "Rect-1"}) {:name "Rect 1"})
(thp/make-component :instance1 :component-1 (thp/make-component :instance1 :component-1
[(thp/id :shape1)]) [(thp/id :shape1)])
(thp/group-shapes :group1 (thp/group-shapes :group1
@ -641,21 +641,21 @@
; ;
; [Page] ; [Page]
; Root Frame ; Root Frame
; Rect-1 #--> Rect-1 ; Rect 1 #--> Rect 1
; Rect-1 @--> Rect-1 ; Rect 1 @--> Rect 1
; Rect-1 ---> Rect-1 ; Rect 1 ---> Rect 1
; Rect-1 #--> Rect-1 ; Rect 1 #--> Rect 1
; Rect-1 @--> Rect-1 ; Rect 1 @--> Rect 1
; Rect-1 ---> Rect-1 ; Rect 1 ---> Rect 1
; ;
; [Rect-1] ; [Rect 1]
; Rect-1 ; Rect 1
; Rect-1 ; Rect 1
; ;
; [Rect-1] ; [Rect 1]
; Rect-1 ; Rect 1
; Rect-1 @--> Rect-1 ; Rect 1 @--> Rect 1
; Rect-1 ---> Rect-1 ; Rect 1 ---> Rect 1
; ;
(let [new-instance-id (-> new-state (let [new-instance-id (-> new-state
wsh/lookup-selected wsh/lookup-selected
@ -672,12 +672,12 @@
(t/is (not= (:id instance1) (:id instance3))) (t/is (not= (:id instance1) (:id instance3)))
(t/is (= (:id component) component-id)) (t/is (= (:id component) component-id))
(t/is (= (:name instance3) "Rect-1")) (t/is (= (:name instance3) "Rect 1"))
(t/is (= (:name shape3) "Rect-1")) (t/is (= (:name shape3) "Rect 1"))
(t/is (= (:name shape4) "Rect-1")) (t/is (= (:name shape4) "Rect 1"))
(t/is (= (:name c-instance3) "Rect-1")) (t/is (= (:name c-instance3) "Rect 1"))
(t/is (= (:name c-shape3) "Rect-1")) (t/is (= (:name c-shape3) "Rect 1"))
(t/is (= (:name c-shape4) "Rect-1")))))] (t/is (= (:name c-shape4) "Rect 1")))))]
(ptk/emit! (ptk/emit!
store store
@ -692,7 +692,7 @@
(let [state (-> thp/initial-state (let [state (-> thp/initial-state
(thp/sample-page) (thp/sample-page)
(thp/sample-shape :shape1 :rect (thp/sample-shape :shape1 :rect
{:name "Rect-1"}) {:name "Rect 1"})
(thp/make-component :instance1 :component-1 (thp/make-component :instance1 :component-1
[(thp/id :shape1)]) [(thp/id :shape1)])
(thp/move-to-library :lib1 "Library 1") (thp/move-to-library :lib1 "Library 1")
@ -711,13 +711,13 @@
; [Page] ; [Page]
; Root Frame ; Root Frame
; Group #--> Group ; Group #--> Group
; Rect-1 @--> <Library 1> Rect-1 ; Rect 1 @--> <Library 1> Rect 1
; Rect-1 ---> <Library 1> Rect-1 ; Rect 1 ---> <Library 1> Rect 1
; ;
; [Group] ; [Group]
; Group ; Group
; Rect-1 @--> <Library 1> Rect-1 ; Rect 1 @--> <Library 1> Rect 1
; Rect-1 ---> <Library 1> Rect-1 ; Rect 1 ---> <Library 1> Rect 1
; ;
(let [instance2 (thp/get-shape new-state :instance2) (let [instance2 (thp/get-shape new-state :instance2)
@ -727,11 +727,11 @@
(:parent-id instance2))] (:parent-id instance2))]
(t/is (= (:name group1) "Group")) (t/is (= (:name group1) "Group"))
(t/is (= (:name shape1) "Rect-1")) (t/is (= (:name shape1) "Rect 1"))
(t/is (= (:name shape2) "Rect-1")) (t/is (= (:name shape2) "Rect 1"))
(t/is (= (:name c-group1) "Group")) (t/is (= (:name c-group1) "Group"))
(t/is (= (:name c-shape1) "Rect-1")) (t/is (= (:name c-shape1) "Rect 1"))
(t/is (= (:name c-shape2) "Rect-1")) (t/is (= (:name c-shape2) "Rect 1"))
(t/is (= (:component-file group1) thp/current-file-id)) (t/is (= (:component-file group1) thp/current-file-id))
(t/is (= (:component-file shape1) library-id)) (t/is (= (:component-file shape1) library-id))
(t/is (= (:component-file shape2) nil)) (t/is (= (:component-file shape2) nil))

View file

@ -19,7 +19,7 @@
(t/testing "Add empty page (only root-frame)" (t/testing "Add empty page (only root-frame)"
(let [page (-> (fb/create-file "Test") (let [page (-> (fb/create-file "Test")
(fb/add-page {:name "Page-1"}) (fb/add-page {:name "Page 1"})
(fb/get-current-page)) (fb/get-current-page))
data (-> (sd/make-snap-data) data (-> (sd/make-snap-data)
@ -28,7 +28,7 @@
(t/testing "Create simple shape on root" (t/testing "Create simple shape on root"
(let [file (-> (fb/create-file "Test") (let [file (-> (fb/create-file "Test")
(fb/add-page {:name "Page-1"}) (fb/add-page {:name "Page 1"})
(fb/create-rect (fb/create-rect
{:x 0 {:x 0
:y 0 :y 0
@ -57,7 +57,7 @@
(t/testing "Add page with single empty frame" (t/testing "Add page with single empty frame"
(let [file (-> (fb/create-file "Test") (let [file (-> (fb/create-file "Test")
(fb/add-page {:name "Page-1"}) (fb/add-page {:name "Page 1"})
(fb/add-artboard (fb/add-artboard
{:x 0 {:x 0
:y 0 :y 0
@ -81,7 +81,7 @@
(t/testing "Add page with some shapes inside frames" (t/testing "Add page with some shapes inside frames"
(let [file (-> (fb/create-file "Test") (let [file (-> (fb/create-file "Test")
(fb/add-page {:name "Page-1"}) (fb/add-page {:name "Page 1"})
(fb/add-artboard (fb/add-artboard
{:x 0 {:x 0
:y 0 :y 0
@ -112,7 +112,7 @@
(t/testing "Add a global guide" (t/testing "Add a global guide"
(let [file (-> (fb/create-file "Test") (let [file (-> (fb/create-file "Test")
(fb/add-page {:name "Page-1"}) (fb/add-page {:name "Page 1"})
(fb/add-guide {:position 50 :axis :x}) (fb/add-guide {:position 50 :axis :x})
(fb/add-artboard {:x 200 :y 200 :width 100 :height 100}) (fb/add-artboard {:x 200 :y 200 :width 100 :height 100})
(fb/close-artboard)) (fb/close-artboard))
@ -140,7 +140,7 @@
(t/testing "Add a frame guide" (t/testing "Add a frame guide"
(let [file (-> (fb/create-file "Test") (let [file (-> (fb/create-file "Test")
(fb/add-page {:name "Page-1"}) (fb/add-page {:name "Page 1"})
(fb/add-artboard {:x 200 :y 200 :width 100 :height 100}) (fb/add-artboard {:x 200 :y 200 :width 100 :height 100})
(fb/close-artboard)) (fb/close-artboard))
@ -171,7 +171,7 @@
(t/deftest test-update-index (t/deftest test-update-index
(t/testing "Create frame on root and then remove it." (t/testing "Create frame on root and then remove it."
(let [file (-> (fb/create-file "Test") (let [file (-> (fb/create-file "Test")
(fb/add-page {:name "Page-1"}) (fb/add-page {:name "Page 1"})
(fb/add-artboard (fb/add-artboard
{:x 0 {:x 0
:y 0 :y 0
@ -201,7 +201,7 @@
(t/testing "Create simple shape on root. Then remove it" (t/testing "Create simple shape on root. Then remove it"
(let [file (-> (fb/create-file "Test") (let [file (-> (fb/create-file "Test")
(fb/add-page {:name "Page-1"}) (fb/add-page {:name "Page 1"})
(fb/create-rect (fb/create-rect
{:x 0 {:x 0
:y 0 :y 0
@ -229,7 +229,7 @@
(t/testing "Create shape inside frame, then remove it" (t/testing "Create shape inside frame, then remove it"
(let [file (-> (fb/create-file "Test") (let [file (-> (fb/create-file "Test")
(fb/add-page {:name "Page-1"}) (fb/add-page {:name "Page 1"})
(fb/add-artboard (fb/add-artboard
{:x 0 {:x 0
:y 0 :y 0
@ -260,7 +260,7 @@
(t/testing "Create global guide then remove it" (t/testing "Create global guide then remove it"
(let [file (-> (fb/create-file "Test") (let [file (-> (fb/create-file "Test")
(fb/add-page {:name "Page-1"}) (fb/add-page {:name "Page 1"})
(fb/add-guide {:position 50 :axis :x})) (fb/add-guide {:position 50 :axis :x}))
guide-id (:last-id file) guide-id (:last-id file)
@ -293,7 +293,7 @@
(t/testing "Create frame guide then remove it" (t/testing "Create frame guide then remove it"
(let [file (-> (fb/create-file "Test") (let [file (-> (fb/create-file "Test")
(fb/add-page {:name "Page-1"}) (fb/add-page {:name "Page 1"})
(fb/add-artboard {:x 200 :y 200 :width 100 :height 100}) (fb/add-artboard {:x 200 :y 200 :width 100 :height 100})
(fb/close-artboard)) (fb/close-artboard))
@ -324,7 +324,7 @@
(t/testing "Update frame coordinates" (t/testing "Update frame coordinates"
(let [file (-> (fb/create-file "Test") (let [file (-> (fb/create-file "Test")
(fb/add-page {:name "Page-1"}) (fb/add-page {:name "Page 1"})
(fb/add-artboard (fb/add-artboard
{:x 0 {:x 0
:y 0 :y 0
@ -358,7 +358,7 @@
(t/testing "Update shape coordinates" (t/testing "Update shape coordinates"
(let [file (-> (fb/create-file "Test") (let [file (-> (fb/create-file "Test")
(fb/add-page {:name "Page-1"}) (fb/add-page {:name "Page 1"})
(fb/create-rect (fb/create-rect
{:x 0 {:x 0
:y 0 :y 0
@ -388,7 +388,7 @@
(t/testing "Update global guide" (t/testing "Update global guide"
(let [guide {:position 50 :axis :x} (let [guide {:position 50 :axis :x}
file (-> (fb/create-file "Test") file (-> (fb/create-file "Test")
(fb/add-page {:name "Page-1"}) (fb/add-page {:name "Page 1"})
(fb/add-guide guide)) (fb/add-guide guide))
guide-id (:last-id file) guide-id (:last-id file)