mirror of
https://github.com/penpot/penpot.git
synced 2025-04-11 06:21:30 -05:00
💄 Update desing tab phase 2 (#3621)
* 💄 Update constraint component * 💄 Update fill and selected color components * 💄 Update stroke component * 💄 Update text component * 💄 Update frame grid component * 💄 Update export component * 💄 Update shadow and blur components * 💄 Update colorpicker component UI * 💄 Update svg attrs and componets components UI * 💄 Small UI changes * 🐛 Fix shadow functions
This commit is contained in:
parent
95f1a8b9ee
commit
fb36b77bd1
92 changed files with 6014 additions and 2132 deletions
3
frontend/resources/images/icons/hsva-refactor.svg
Normal file
3
frontend/resources/images/icons/hsva-refactor.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12.998 4a2.5 2.5 0 11-5 0m5 0a2.5 2.5 0 10-5 0m5 0h2.5m-7.5 0h-7.5m2.5 8a2.5 2.5 0 015 0m-5 0a2.5 2.5 0 005 0m-5 0h-2.5m7.5 0h7.5"/>
|
||||
</svg>
|
After Width: | Height: | Size: 260 B |
3
frontend/resources/images/icons/picker-refactor.svg
Normal file
3
frontend/resources/images/icons/picker-refactor.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M8.82 5.134L7.756 4.073a1 1 0 011.414-1.415l.707.707L12 1.244a2 2 0 112.828 2.828l-2.12 2.122.706.707A.999.999 0 1112 8.315l-1.06-1.06m0 0L8.818 5.134l-6.91 7.435a.93.93 0 00-.149.208l-.213.398c-.468.872.481 1.822 1.354 1.353l.397-.213a.93.93 0 00.208-.149l7.435-6.911z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 399 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3.5 6a2.5 2.5 0 100-5 2.5 2.5 0 000 5zM10 5a5 5 0 100 10 5 5 0 000-10z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 201 B |
3
frontend/resources/images/icons/rgba-refactor.svg
Normal file
3
frontend/resources/images/icons/rgba-refactor.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12.667 2H3.333C2.597 2 2 2.597 2 3.333v9.334C2 13.403 2.597 14 3.333 14h9.334c.736 0 1.333-.597 1.333-1.333V3.333C14 2.597 13.403 2 12.667 2z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 272 B |
3
frontend/resources/images/icons/switch-refactor.svg
Normal file
3
frontend/resources/images/icons/switch-refactor.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M11 14.556l2.5-2.445m0 0L11 9.556m2.5 2.555H3M5 6.5L2.5 4.056m0 0L5 1.5M2.5 4.056H13"/>
|
||||
</svg>
|
After Width: | Height: | Size: 216 B |
|
@ -4,6 +4,36 @@
|
|||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
// SCROLLBAR
|
||||
.new-scrollbar {
|
||||
::-webkit-scrollbar {
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
height: $s-12;
|
||||
width: $s-12;
|
||||
}
|
||||
::-webkit-scrollbar-track,
|
||||
::-webkit-scrollbar-corner {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(170, 181, 186, 0.3);
|
||||
background-clip: content-box;
|
||||
border: $s-2 solid transparent;
|
||||
border-radius: $br-8;
|
||||
&:hover {
|
||||
background-color: rgba(170, 181, 186, 0.7);
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
::selection {
|
||||
background-color: var(--color-accent-primary-muted);
|
||||
}
|
||||
}
|
||||
|
||||
// BUTTONS
|
||||
.button-primary {
|
||||
@include buttonStyle;
|
||||
@include flexCenter;
|
||||
|
@ -235,14 +265,130 @@
|
|||
stroke-width: 1.33px;
|
||||
}
|
||||
|
||||
.link {
|
||||
background: unset;
|
||||
border: none;
|
||||
color: var(--link-foreground-color);
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
.button-constraint {
|
||||
@include buttonStyle;
|
||||
width: $s-32;
|
||||
height: $s-4;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--button-constraint-background-color-rest);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
&:hover,
|
||||
&:focus {
|
||||
outline: $s-4 solid var(--button-constraint-border-color-hover);
|
||||
background-color: var(--button-constraint-background-color-hover);
|
||||
}
|
||||
}
|
||||
|
||||
// INPUTS
|
||||
|
||||
.input-base {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
@include textEllipsis;
|
||||
height: $s-28;
|
||||
width: 100%;
|
||||
margin: $s-2 0;
|
||||
padding: 0 0 0 $s-4;
|
||||
color: var(--input-foreground-color-active);
|
||||
&:focus-within,
|
||||
&:active {
|
||||
color: var(--input-foreground-color-active);
|
||||
background-color: var(--input-background-color-active);
|
||||
}
|
||||
}
|
||||
|
||||
.input-icon {
|
||||
@include flexCenter;
|
||||
min-width: $s-12;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
|
||||
.input-label {
|
||||
@include tabTitleTipography;
|
||||
@include flexCenter;
|
||||
min-width: $s-12;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
color: var(--input-foreground-color);
|
||||
}
|
||||
|
||||
.input-element {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
padding: 0 $s-4;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--input-background-color);
|
||||
border: $s-1 solid var(--input-background-color);
|
||||
color: var(--input-foreground-color);
|
||||
span {
|
||||
@extend .input-label;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
stroke: var(--input-foreground-color);
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
@extend .input-base;
|
||||
}
|
||||
::placeholder {
|
||||
color: var(--input-placeholder-color);
|
||||
}
|
||||
&:hover {
|
||||
span {
|
||||
color: var(--input-foreground-color);
|
||||
}
|
||||
input {
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
background-color: var(--input-background-color-hover);
|
||||
}
|
||||
|
||||
&:focus-within,
|
||||
&:active {
|
||||
input {
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
background-color: var(--input-background-color-active);
|
||||
border: $s-1 solid var(--input-border-color-active);
|
||||
}
|
||||
}
|
||||
|
||||
.disabled-input {
|
||||
background-color: var(--input-background-color-disabled);
|
||||
border: 1px solid var(--input-border-color-disabled);
|
||||
color: var(--input-foreground-color-disabled);
|
||||
input {
|
||||
pointer-events: none;
|
||||
cursor: default;
|
||||
color: var(--input-foreground-color-disabled);
|
||||
}
|
||||
span svg {
|
||||
stroke: var(--input-foreground-color-disabled);
|
||||
}
|
||||
}
|
||||
|
||||
//MODALS
|
||||
.modal-background {
|
||||
@include menuShadow;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: $s-12;
|
||||
border-radius: $br-8;
|
||||
z-index: $z-index-10;
|
||||
color: var(--color-foreground-primary);
|
||||
background-color: var(--modal-background-color);
|
||||
}
|
||||
|
||||
// UI ELEMENTS
|
||||
.asset-element {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
|
@ -259,89 +405,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.input-element {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--input-background-color);
|
||||
color: var(--input-foreground-color);
|
||||
span {
|
||||
color: var(--input-foreground-color);
|
||||
}
|
||||
input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
color: var(--input-foreground-color);
|
||||
height: $s-32;
|
||||
}
|
||||
::placeholder {
|
||||
color: var(--input-placeholder-color);
|
||||
}
|
||||
&:hover,
|
||||
&:focus-within {
|
||||
span {
|
||||
color: var(--input-foreground-color);
|
||||
}
|
||||
input {
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
background-color: var(--input-background-color-hover);
|
||||
}
|
||||
}
|
||||
.new-scrollbar {
|
||||
::-webkit-scrollbar {
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
height: $s-12;
|
||||
width: $s-12;
|
||||
}
|
||||
::-webkit-scrollbar-track,
|
||||
::-webkit-scrollbar-corner {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(170, 181, 186, 0.3);
|
||||
background-clip: content-box;
|
||||
border: $s-2 solid transparent;
|
||||
border-radius: $br-8;
|
||||
&:hover {
|
||||
background-color: rgba(170, 181, 186, 0.7);
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-dropdown {
|
||||
@include menuShadow;
|
||||
color: var(--title-foreground-color-hover);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
width: $s-192;
|
||||
padding: $s-4;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--menu-background-color);
|
||||
z-index: $z-index-10;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: $s-28;
|
||||
width: 100%;
|
||||
padding: $s-6;
|
||||
border-radius: $br-8;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: var(--menu-background-color-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.shortcut {
|
||||
@include flexCenter;
|
||||
gap: $s-2;
|
||||
|
@ -368,3 +431,114 @@
|
|||
border: $s-2 solid var(--user-count-foreground-color);
|
||||
}
|
||||
}
|
||||
|
||||
.mixed-bar {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
border-radius: $br-8;
|
||||
height: $s-32;
|
||||
padding: $s-8;
|
||||
background-color: var(--input-background-color);
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
|
||||
.link {
|
||||
background: unset;
|
||||
border: none;
|
||||
color: var(--link-foreground-color);
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.colorpicker-handler {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: $s-24;
|
||||
height: $s-24;
|
||||
border: $s-2 solid var(--colorpicker-details-color);
|
||||
border-radius: $br-circle;
|
||||
transform: translate(calc(-1 * $s-12), calc(-1 * $s-12));
|
||||
z-index: $z-index-1;
|
||||
&:hover,
|
||||
&:active {
|
||||
border-color: var(--colorpicker-details-color-selected);
|
||||
}
|
||||
}
|
||||
// SELECTS AND DROPDOWNS
|
||||
|
||||
.menu-dropdown {
|
||||
@include menuShadow;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
padding: $s-4;
|
||||
border-radius: $br-8;
|
||||
z-index: $z-index-10;
|
||||
color: var(--title-foreground-color-hover);
|
||||
background-color: var(--menu-background-color);
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: $s-28;
|
||||
width: 100%;
|
||||
padding: $s-6;
|
||||
border-radius: $br-8;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: var(--menu-background-color-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-element-base {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-8;
|
||||
height: $s-32;
|
||||
padding: 0 $s-8;
|
||||
border-radius: $br-6;
|
||||
cursor: pointer;
|
||||
color: var(--menu-foreground-color-rest);
|
||||
|
||||
span {
|
||||
@include flexCenter;
|
||||
@include textEllipsis;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--menu-background-color-hover);
|
||||
color: var(--menu-foreground-color);
|
||||
span svg {
|
||||
stroke: var(--menu-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-wrapper {
|
||||
@include menuShadow;
|
||||
position: absolute;
|
||||
top: $s-32;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
max-height: $s-300;
|
||||
padding: $s-2;
|
||||
margin: 0;
|
||||
margin-top: $s-4;
|
||||
border-radius: $br-8;
|
||||
z-index: $z-index-3;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
background-color: var(--menu-background-color);
|
||||
color: var(--menu-foreground-color);
|
||||
}
|
||||
|
|
|
@ -77,6 +77,13 @@
|
|||
--button-disabled-border-color-rest: var(--color-background-disabled);
|
||||
--button-disabled-foreground-color-rest: var(--color-foreground-disabled);
|
||||
|
||||
--button-constraint-background-color-rest: var(--color-foreground-secondary);
|
||||
--button-constraint-border-color-rest: var(--color-background-tertiary);
|
||||
--button-constraint-border-color-hover: var(--color-accent-primary-muted);
|
||||
--button-constraint-background-color-hover: var(--color-accent-primary);
|
||||
--constraint-widget-background-color: var(--color-background-tertiary);
|
||||
--constraint-center-area-background-color: var(--color-background-primary);
|
||||
|
||||
--icon-foreground: var(--color-foreground-secondary);
|
||||
--icon-foreground-hover: var(--color-foreground-primary);
|
||||
|
||||
|
@ -111,18 +118,19 @@
|
|||
--search-bar-input-border-color: var(--color-background-tertiary);
|
||||
|
||||
--input-background-color: var(--color-background-tertiary);
|
||||
--input-background-color-active: var(--color-background-primary);
|
||||
--input-foreground-color: var(--color-foreground-secondary);
|
||||
--input-placeholder-color: var(--color-foreground-secondary);
|
||||
--input-background-color-hover: var(--color-background-quaternary);
|
||||
--input-background-color-focus: var(--color-background-tertiary);
|
||||
--input-background-color-disabled: var(--color-background-primary);
|
||||
--input-placeholder-color: var(--color-foreground-secondary);
|
||||
--input-foreground-color: var(--color-foreground-secondary);
|
||||
--input-foreground-color-active: var(--color-foreground-primary);
|
||||
--input-foreground-color-disabled: var(--color-foreground-secondary);
|
||||
--input-border-color-active: var(--color-accent-primary);
|
||||
--input-border-color-disabled: var(--color-background-quaternary);
|
||||
--input-border-outline-color-active: var(--color-accent-primary-muted);
|
||||
--input-border-color-focus: var(--color-accent-primary);
|
||||
--input-background-color-active: var(--color-background-primary);
|
||||
--input-foreground-color-active: var(--color-foreground-primary);
|
||||
--input-border-outline-color-active: var(--color-accent-primary-muted);
|
||||
--input-border-color-active: var(--color-accent-primary);
|
||||
--input-background-color-disabled: var(--color-background-primary);
|
||||
--input-foreground-color-disabled: var(--color-foreground-secondary);
|
||||
--input-border-color-disabled: var(--color-background-quaternary);
|
||||
--input-details-color: var(--color-background-primary);
|
||||
|
||||
--pill-background-color: var(--color-background-tertiary);
|
||||
--pill-foreground-color: var(--color-foreground-primary);
|
||||
|
@ -130,17 +138,20 @@
|
|||
--menu-background-color: var(--color-background-tertiary);
|
||||
--menu-foreground-color: var(--color-foreground-primary);
|
||||
--menu-background-color-selected: var(--color-background-tertiary);
|
||||
--menu-foreground-color-selected: var(--color-foreground-primary);
|
||||
--menu-background-color-hover: var(--color-background-quaternary);
|
||||
--menu-foreground-color-hover: var(--color-foreground-primary);
|
||||
--menu-background-color-focus: var(--color-background-tertiary);
|
||||
--menu-foreground-color-focus: var(--color-foreground-primary);
|
||||
--menu-foreground-color-rest: var(--color-foreground-secondary);
|
||||
--menu-border-color-focus: var(--color-accent-primary);
|
||||
--menu-shortcut-background-color: var(--color-background-primary);
|
||||
--menu-shortcut-foreground-color: var(--color-foreground-secondary);
|
||||
--menu-shortcut-foreground-color-selected: var(--color-foreground-primary);
|
||||
--menu-shortcut-foreground-color-hover: var(--color-foreground-primary);
|
||||
--menu-shadow-color: var(--color-background-subtle);
|
||||
--menu-background-color-disabled: var(--color-background-primary);
|
||||
--menu-foreground-color-disabled: var(--color-foreground-secondary);
|
||||
--menu-border-color-disabled: var(--color-background-quaternary);
|
||||
|
||||
--tag-background-color: var(--color-accent-primary);
|
||||
|
||||
|
@ -210,4 +221,8 @@
|
|||
--modal-background-color: var(--color-background-primary);
|
||||
--modal-foreground-color: var(--color-foreground-primary);
|
||||
--modal-foreground-color-secondary: var(--color-foreground-secondary);
|
||||
|
||||
--colorpicker-details-color: var(--color-background-quaternary);
|
||||
--colorpicker-details-color-selected: var(--color-accent-primary);
|
||||
--colorpicker-handlers-color: var(--color-foreground-primary);
|
||||
}
|
||||
|
|
|
@ -33,11 +33,13 @@ $s-80: calc(var(--s-4) * 20);
|
|||
$s-84: calc(var(--s-4) * 21);
|
||||
$s-92: calc(var(--s-4) * 23);
|
||||
$s-96: calc(var(--s-4) * 24);
|
||||
$s-100: calc(var(--s-4) * 25);
|
||||
$s-104: calc(var(--s-4) * 26);
|
||||
$s-108: calc(var(--s-4) * 27);
|
||||
$s-116: calc(var(--s-4) * 29);
|
||||
$s-120: calc(var(--s-4) * 30);
|
||||
$s-124: calc(var(--s-4) * 31);
|
||||
$s-128: calc(var(--s-4) * 32);
|
||||
$s-136: calc(var(--s-4) * 34);
|
||||
$s-140: calc(var(--s-4) * 35);
|
||||
$s-148: calc(var(--s-4) * 37);
|
||||
|
@ -45,6 +47,7 @@ $s-156: calc(var(--s-4) * 39);
|
|||
$s-152: calc(var(--s-4) * 38);
|
||||
$s-160: calc(var(--s-4) * 40);
|
||||
$s-168: calc(var(--s-4) * 42);
|
||||
$s-172: calc(var(--s-4) * 43);
|
||||
$s-180: calc(var(--s-4) * 45);
|
||||
$s-184: calc(var(--s-4) * 46);
|
||||
$s-188: calc(var(--s-4) * 47);
|
||||
|
@ -53,10 +56,12 @@ $s-196: calc(var(--s-4) * 49);
|
|||
$s-200: calc(var(--s-4) * 50);
|
||||
$s-216: calc(var(--s-4) * 54);
|
||||
$s-220: calc(var(--s-4) * 55);
|
||||
$s-228: calc(var(--s-4) * 57);
|
||||
$s-240: calc(var(--s-4) * 60);
|
||||
$s-248: calc(var(--s-4) * 62);
|
||||
$s-252: calc(var(--s-4) * 63);
|
||||
$s-256: calc(var(--s-4) * 64);
|
||||
$s-260: calc(var(--s-4) * 65);
|
||||
$s-272: calc(var(--s-4) * 68);
|
||||
$s-276: calc(var(--s-4) * 69);
|
||||
$s-280: calc(var(--s-4) * 70);
|
||||
|
|
|
@ -342,6 +342,9 @@
|
|||
margin-right: -8px;
|
||||
max-height: 5.5rem;
|
||||
overflow: auto;
|
||||
div {
|
||||
grid-area: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.selected-colors::after {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
(mf/defc color-bullet
|
||||
{::mf/wrap [mf/memo]
|
||||
::mf/wrap-props false}
|
||||
[{:keys [color on-click mini?]}]
|
||||
[{:keys [color on-click mini? area]}]
|
||||
(let [on-click (mf/use-fn
|
||||
(mf/deps color on-click)
|
||||
(fn [event]
|
||||
|
@ -34,7 +34,9 @@
|
|||
:is-library-color (some? id)
|
||||
:is-not-library-color (nil? id)
|
||||
:is-gradient (some? gradient)
|
||||
:is-transparent (and opacity (> 1 opacity)))
|
||||
:is-transparent (and opacity (> 1 opacity))
|
||||
:grid-area area)
|
||||
|
||||
:on-click on-click}
|
||||
|
||||
(if (some? gradient)
|
||||
|
|
|
@ -12,9 +12,13 @@
|
|||
flex-direction: row;
|
||||
width: var(--bullet-size, $s-24);
|
||||
height: var(--bullet-size, $s-24);
|
||||
margin-top: $s-4;
|
||||
min-width: var(--bullet-size, $s-24);
|
||||
min-height: var(--bullet-size, $s-24);
|
||||
border: $s-2 solid var(--color-bullet-border-color);
|
||||
border-radius: $br-circle;
|
||||
&.grid-area {
|
||||
grid-area: color;
|
||||
}
|
||||
&.mini {
|
||||
width: var(--bullet-size, $s-16);
|
||||
height: var(--bullet-size, $s-16);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
on-blur (obj/get props "onBlur")
|
||||
on-focus (obj/get props "onFocus")
|
||||
select-on-focus? (d/nilv (unchecked-get props "selectOnFocus") true)
|
||||
class (d/nilv (unchecked-get props "className") "color-input")
|
||||
|
||||
;; We need a ref pointing to the input dom element, but the user
|
||||
;; of this component may provide one (that is forwarded here).
|
||||
|
@ -132,6 +133,7 @@
|
|||
(obj/unset! "selectOnFocus")
|
||||
(obj/set! "value" mf/undefined)
|
||||
(obj/set! "onChange" mf/undefined)
|
||||
(obj/set! "className" class)
|
||||
(obj/set! "type" "text")
|
||||
(obj/set! "ref" ref)
|
||||
;; (obj/set! "list" list-id)
|
||||
|
|
|
@ -82,12 +82,12 @@
|
|||
&:hover .context-menu-action {
|
||||
background-color: var(--menu-background-color-hover);
|
||||
text-decoration: none;
|
||||
color: var(--menu-foreground-color-hover);
|
||||
color: var(--menu-foreground-color);
|
||||
&.submenu .submenu-icon svg {
|
||||
stroke: var(--menu-foreground-color-hover);
|
||||
stroke: var(--menu-foreground-color);
|
||||
}
|
||||
&.submenu-back .submenu-icon-back svg {
|
||||
stroke: var(--menu-foreground-color-hover);
|
||||
stroke: var(--menu-foreground-color);
|
||||
}
|
||||
}
|
||||
&:focus {
|
||||
|
|
|
@ -5,12 +5,15 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.components.editable-select
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.math :as mth]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input*]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.keyboard :as kbd]
|
||||
|
@ -18,13 +21,21 @@
|
|||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc editable-select
|
||||
[{:keys [value type options class on-change placeholder on-blur] :as params}]
|
||||
(let [state (mf/use-state {:id (uuid/next)
|
||||
:is-open? false
|
||||
:current-value value
|
||||
:top nil
|
||||
:left nil
|
||||
:bottom nil})
|
||||
[{:keys [value type options class on-change placeholder on-blur input-class] :as params}]
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
state* (mf/use-state {:id (uuid/next)
|
||||
:is-open? false
|
||||
:current-value value
|
||||
:top nil
|
||||
:left nil
|
||||
:bottom nil})
|
||||
state (deref state*)
|
||||
is-open? (:is-open? state)
|
||||
current-value (:current-value state)
|
||||
top-value (:top state)
|
||||
left-value (:left state)
|
||||
bottom-value (:bottom state)
|
||||
element-id (:id state)
|
||||
|
||||
min-val (get params :min)
|
||||
max-val (get params :max)
|
||||
|
@ -35,16 +46,28 @@
|
|||
open-dropdown
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(swap! state assoc :is-open? true))
|
||||
(swap! state* assoc :is-open? true))
|
||||
|
||||
toggle-dropdown
|
||||
(mf/use-fn
|
||||
(mf/deps state)
|
||||
#(swap! state* update :is-open? not))
|
||||
|
||||
close-dropdown
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(swap! state assoc :is-open? false))
|
||||
select-item (fn [value]
|
||||
(fn [_]
|
||||
(swap! state assoc :current-value value)
|
||||
(when on-change (on-change value))
|
||||
(when on-blur (on-blur))))
|
||||
(swap! state* assoc :is-open? false))
|
||||
|
||||
select-item
|
||||
(mf/use-fn
|
||||
(mf/deps on-change on-blur)
|
||||
(fn [event]
|
||||
(let [value (-> (dom/get-current-target event)
|
||||
(dom/get-data "value")
|
||||
(d/read-string))]
|
||||
(swap! state* assoc :current-value value)
|
||||
(when on-change (on-change value))
|
||||
(when on-blur (on-blur)))))
|
||||
|
||||
as-key-value (fn [item] (if (map? item) [(:value item) (:label item)] [item item]))
|
||||
labels-map (into {} (map as-key-value) options)
|
||||
|
@ -52,7 +75,7 @@
|
|||
|
||||
set-value
|
||||
(fn [value]
|
||||
(swap! state assoc :current-value value)
|
||||
(swap! state* assoc :current-value value)
|
||||
(when on-change (on-change value)))
|
||||
|
||||
;; TODO: why this method supposes that all editable select
|
||||
|
@ -75,14 +98,14 @@
|
|||
{:keys [left top height]} bounds
|
||||
bottom (when (< (- window-height top) 300) (- window-height top))
|
||||
top (when (>= (- window-height top) 300) (+ top height))]
|
||||
(swap! state
|
||||
(swap! state*
|
||||
assoc
|
||||
:left left
|
||||
:top top
|
||||
:bottom bottom))))))
|
||||
|
||||
handle-key-down
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(mf/deps set-value)
|
||||
(fn [event]
|
||||
(when (= type "number")
|
||||
|
@ -113,12 +136,12 @@
|
|||
(set-value new-value)))))))
|
||||
|
||||
handle-focus
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(mf/set-ref-val! emit-blur? false)))
|
||||
|
||||
handle-blur
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(mf/set-ref-val! emit-blur? true)
|
||||
(timers/schedule
|
||||
|
@ -127,56 +150,101 @@
|
|||
(when (and on-blur (mf/ref-val emit-blur?)) (on-blur))))))]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps value (:current-value @state))
|
||||
#(when (not= (str value) (:current-value @state))
|
||||
(reset! state {:current-value value})))
|
||||
(mf/deps value current-value)
|
||||
#(when (not= (str value) current-value)
|
||||
(reset! state* {:current-value value})))
|
||||
|
||||
(mf/with-effect [(:is-open? @state)]
|
||||
(mf/with-effect [is-open?]
|
||||
(let [wrapper-node (mf/ref-val font-size-wrapper-ref)
|
||||
node (dom/get-element-by-class "checked-element is-selected" wrapper-node)
|
||||
nodes (dom/get-elements-by-class "checked-element-value" wrapper-node)
|
||||
closest (fn [a b] (first (sort-by #(mth/abs (- % b)) a)))
|
||||
closest-value (str (closest options value))]
|
||||
(when (:is-open? @state)
|
||||
(when is-open?
|
||||
(if (some? node)
|
||||
(dom/scroll-into-view-if-needed! node)
|
||||
(some->> nodes
|
||||
(d/seek #(= closest-value (dom/get-inner-text %)))
|
||||
(dom/scroll-into-view-if-needed!)))))
|
||||
|
||||
(mf/set-ref-val! emit-blur? (not (:is-open? @state))))
|
||||
(mf/set-ref-val! emit-blur? (not is-open?)))
|
||||
|
||||
[:div.editable-select {:class class
|
||||
:ref on-node-load}
|
||||
(if (= type "number")
|
||||
[:> numeric-input* {:value (or (some-> @state :current-value value->label) "")
|
||||
:on-change set-value
|
||||
:on-focus handle-focus
|
||||
:on-blur handle-blur
|
||||
:placeholder placeholder}]
|
||||
[:input.input-text {:value (or (some-> @state :current-value value->label) "")
|
||||
:on-change handle-change-input
|
||||
:on-key-down handle-key-down
|
||||
:on-focus handle-focus
|
||||
:on-blur handle-blur
|
||||
:placeholder placeholder
|
||||
:type type}])
|
||||
[:span.dropdown-button {:on-click open-dropdown} i/arrow-down]
|
||||
|
||||
[:& dropdown {:show (get @state :is-open? false)
|
||||
:on-close close-dropdown}
|
||||
[:ul.custom-select-dropdown {:style {:position "fixed"
|
||||
:top (:top @state)
|
||||
:left (:left @state)
|
||||
:bottom (:bottom @state)
|
||||
:ref font-size-wrapper-ref}}
|
||||
(for [[index item] (map-indexed vector options)]
|
||||
(if (= :separator item)
|
||||
[:hr {:key (str (:id @state) "-" index)}]
|
||||
(let [[value label] (as-key-value item)]
|
||||
[:li.checked-element
|
||||
{:key (str (:id @state) "-" index)
|
||||
:class (when (= (str value) (-> @state :current-value)) "is-selected")
|
||||
:on-click (select-item value)}
|
||||
[:span.check-icon i/tick]
|
||||
[:span.checked-element-value label]])))]]]))
|
||||
(if new-css-system
|
||||
[:div {:class (dm/str class " " (stl/css :editable-select))
|
||||
:ref on-node-load}
|
||||
(if (= type "number")
|
||||
[:> numeric-input* {:value (or (some-> current-value value->label) "")
|
||||
:className input-class
|
||||
:on-change set-value
|
||||
:on-focus handle-focus
|
||||
:on-blur handle-blur
|
||||
:placeholder placeholder}]
|
||||
[:input {:value (or (some-> current-value value->label) "")
|
||||
:class input-class
|
||||
:on-change handle-change-input
|
||||
:on-key-down handle-key-down
|
||||
:on-focus handle-focus
|
||||
:on-blur handle-blur
|
||||
:placeholder placeholder
|
||||
:type type}])
|
||||
|
||||
[:span {:class (stl/css :dropdown-button)
|
||||
:on-click toggle-dropdown}
|
||||
i/arrow-refactor]
|
||||
|
||||
[:& dropdown {:show (or is-open? false)
|
||||
:on-close close-dropdown}
|
||||
[:ul {:class (stl/css :custom-select-dropdown)
|
||||
:ref font-size-wrapper-ref}
|
||||
(for [[index item] (map-indexed vector options)]
|
||||
(if (= :separator item)
|
||||
[:li {:class (stl/css :separator)
|
||||
:key (dm/str element-id "-" index)}]
|
||||
(let [[value label] (as-key-value item)]
|
||||
[:li
|
||||
{:key (str element-id "-" index)
|
||||
:class (stl/css-case :dropdown-element true
|
||||
:is-selected (= value current-value))
|
||||
:data-value value
|
||||
:on-click select-item}
|
||||
[:span {:class (stl/css :label)} label]
|
||||
[:span {:class (stl/css :check-icon)}
|
||||
i/tick-refactor]])))]]]
|
||||
|
||||
|
||||
[:div.editable-select {:class class
|
||||
:ref on-node-load}
|
||||
(if (= type "number")
|
||||
[:> numeric-input* {:value (or (some-> current-value value->label) "")
|
||||
:on-change set-value
|
||||
:on-focus handle-focus
|
||||
:on-blur handle-blur
|
||||
:placeholder placeholder}]
|
||||
[:input.input-text {:value (or (some-> current-value value->label) "")
|
||||
:on-change handle-change-input
|
||||
:on-key-down handle-key-down
|
||||
:on-focus handle-focus
|
||||
:on-blur handle-blur
|
||||
:placeholder placeholder
|
||||
:type type}])
|
||||
[:span.dropdown-button {:on-click open-dropdown} i/arrow-down]
|
||||
|
||||
[:& dropdown {:show (or is-open? false)
|
||||
:on-close close-dropdown}
|
||||
[:ul.custom-select-dropdown {:style {:position "fixed"
|
||||
:top top-value
|
||||
:left left-value
|
||||
:bottom bottom-value}
|
||||
:ref font-size-wrapper-ref}
|
||||
(for [[index item] (map-indexed vector options)]
|
||||
(if (= :separator item)
|
||||
[:hr {:key (str element-id "-" index)}]
|
||||
(let [[value label] (as-key-value item)]
|
||||
[:li.checked-element
|
||||
{:key (str element-id "-" index)
|
||||
:class (when (= (str value) current-value) "is-selected")
|
||||
:data-value value
|
||||
:on-click select-item}
|
||||
[:span.check-icon i/tick]
|
||||
[:span.checked-element-value label]])))]]])))
|
||||
|
|
69
frontend/src/app/main/ui/components/editable_select.scss
Normal file
69
frontend/src/app/main/ui/components/editable_select.scss
Normal file
|
@ -0,0 +1,69 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.editable-select {
|
||||
@extend .asset-element;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: $s-1 solid var(--input-background-color);
|
||||
position: relative;
|
||||
display: flex;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
padding: $s-8;
|
||||
border-radius: $br-8;
|
||||
cursor: pointer;
|
||||
.dropdown-button {
|
||||
@include flexCenter;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
transform: rotate(90deg);
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
.custom-select-dropdown {
|
||||
@extend .dropdown-wrapper;
|
||||
max-height: $s-320;
|
||||
.separator {
|
||||
margin: 0;
|
||||
height: $s-12;
|
||||
}
|
||||
.dropdown-element {
|
||||
@extend .dropdown-element-base;
|
||||
color: var(--menu-foreground-color);
|
||||
.label {
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.check-icon {
|
||||
@include flexCenter;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
visibility: hidden;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
&.is-selected {
|
||||
.check-icon svg {
|
||||
stroke: var(--menu-foreground-color);
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--menu-background-color-hover);
|
||||
color: var(--menu-foreground-color-hover);
|
||||
.check-icon svg {
|
||||
stroke: var(--menu-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -66,6 +66,7 @@
|
|||
icon (unchecked-get props "icon")
|
||||
id (unchecked-get props "id")
|
||||
value (unchecked-get props "value")
|
||||
title (unchecked-get props "title")
|
||||
disabled (unchecked-get props "disabled")
|
||||
unique-key (unchecked-get props "unique-key")
|
||||
icon-class (unchecked-get props "icon-class")
|
||||
|
@ -79,6 +80,7 @@
|
|||
|
||||
[:label {:for id
|
||||
:key unique-key
|
||||
:title title
|
||||
:class (stl/css-case
|
||||
:radio-icon true
|
||||
:disabled disabled
|
||||
|
@ -142,3 +144,6 @@
|
|||
[:div {:class (dm/str class " " (stl/css :radio-btn-wrapper))
|
||||
:style {:width width}}
|
||||
children]]))
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.components.select
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
|
@ -23,7 +23,7 @@
|
|||
[item item]))
|
||||
|
||||
(mf/defc select
|
||||
[{:keys [default-value options class is-open? on-change on-pointer-enter-option on-pointer-leave-option]}]
|
||||
[{:keys [default-value options class is-open? on-change on-pointer-enter-option on-pointer-leave-option disabled]}]
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
label-index (mf/with-memo [options]
|
||||
(into {} (map as-key-value) options))
|
||||
|
@ -39,7 +39,13 @@
|
|||
current-label (get label-index current-value)
|
||||
is-open? (:is-open? state)
|
||||
|
||||
open-dropdown (mf/use-fn #(swap! state* assoc :is-open? true))
|
||||
open-dropdown
|
||||
(mf/use-fn
|
||||
(mf/deps disabled)
|
||||
(fn[]
|
||||
(when-not disabled
|
||||
(swap! state* assoc :is-open? true))))
|
||||
|
||||
close-dropdown (mf/use-fn #(swap! state* assoc :is-open? false))
|
||||
|
||||
select-item
|
||||
|
@ -78,27 +84,29 @@
|
|||
(swap! state* assoc :current-value default-value))
|
||||
(if new-css-system
|
||||
[:div {:on-click open-dropdown
|
||||
:class (dom/classnames (css class) true
|
||||
(css :custom-select) true)}
|
||||
[:span {:class (css :current-label)} current-label]
|
||||
[:span {:class (css :dropdown-button)} i/arrow-refactor]
|
||||
:class (dm/str class " " (stl/css-case :custom-select true
|
||||
:disabled disabled))}
|
||||
[:span {:class (stl/css :current-label)} current-label]
|
||||
[:span {:class (stl/css :dropdown-button)} i/arrow-refactor]
|
||||
[:& dropdown {:show is-open? :on-close close-dropdown}
|
||||
[:ul {:class (css :custom-select-dropdown)}
|
||||
[:ul {:class (stl/css :custom-select-dropdown)}
|
||||
(for [[index item] (d/enumerate options)]
|
||||
(if (= :separator item)
|
||||
[:hr {:key (dm/str current-id "-" index)}]
|
||||
[:li {:class (dom/classnames (stl/css :separator) true)
|
||||
:key (dm/str current-id "-" index)}]
|
||||
(let [[value label] (as-key-value item)]
|
||||
[:li
|
||||
{:key (dm/str current-id "-" index)
|
||||
:class (dom/classnames
|
||||
(css :checked-element) true
|
||||
(css :is-selected) (= value current-value))
|
||||
(stl/css :checked-element) true
|
||||
(stl/css :is-selected) (= value current-value))
|
||||
:data-value (pr-str value)
|
||||
:on-pointer-enter highlight-item
|
||||
:on-pointer-leave unhighlight-item
|
||||
:on-click select-item}
|
||||
[:span {:class (css :label)} label]
|
||||
[:span {:class (css :check-icon)} i/tick-refactor]])))]]]
|
||||
[:span {:class (stl/css :label)} label]
|
||||
[:span {:class (stl/css :check-icon)} i/tick-refactor]])))]]]
|
||||
|
||||
|
||||
[:div.custom-select {:on-click open-dropdown :class class}
|
||||
[:span current-label]
|
||||
|
|
|
@ -7,11 +7,18 @@
|
|||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.custom-select {
|
||||
@include titleTipography;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: $s-8;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--menu-background-color);
|
||||
border: $s-1 solid var(--menu-background-color);
|
||||
color: var(--menu-foreground-color);
|
||||
cursor: pointer;
|
||||
.current-label {
|
||||
width: 100%;
|
||||
|
@ -26,26 +33,15 @@
|
|||
}
|
||||
}
|
||||
.custom-select-dropdown {
|
||||
@include menuShadow;
|
||||
position: absolute;
|
||||
top: $s-32;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
padding: $s-2;
|
||||
margin: 0;
|
||||
margin-top: $s-4;
|
||||
border-radius: $br-8;
|
||||
z-index: $z-index-3;
|
||||
overflow-y: auto;
|
||||
background-color: var(--menu-background-color);
|
||||
@extend .dropdown-wrapper;
|
||||
.separator {
|
||||
margin: 0;
|
||||
height: $s-12;
|
||||
}
|
||||
}
|
||||
.checked-element {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
padding: 0 $s-8;
|
||||
border-radius: $br-6;
|
||||
color: var(--menu-foreground-color);
|
||||
@extend .dropdown-element-base;
|
||||
|
||||
.label {
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
|
@ -61,26 +57,35 @@
|
|||
}
|
||||
|
||||
&.is-selected {
|
||||
color: var(--menu-foreground-color);
|
||||
.check-icon svg {
|
||||
stroke: var(--menu-foreground-color);
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--menu-background-color-hover);
|
||||
color: var(--menu-foreground-color-hover);
|
||||
.check-icon svg {
|
||||
stroke: var(--menu-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--menu-background-color-hover);
|
||||
border: $s-1 solid var(--menu-background-color-hover);
|
||||
.dropdown-button {
|
||||
color: var(--menu-foreground-color-hover);
|
||||
svg {
|
||||
stroke: var(--menu-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
&:focus {
|
||||
background-color: var(--menu-background-color-focus);
|
||||
border: $s-1 solid var(--menu-border-color-focus);
|
||||
}
|
||||
&.disabled {
|
||||
background-color: var(--menu-background-color-disabled);
|
||||
color: var(--menu-foreground-color-disabled);
|
||||
border: $s-1 solid var(--menu-border-color-disabled);
|
||||
pointer-events: none;
|
||||
cursor: default;
|
||||
.dropdown-button svg {
|
||||
stroke: var(--menu-foreground-color-disabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.components.tab-container
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
|
@ -20,9 +21,7 @@
|
|||
[props]
|
||||
(let [children (unchecked-get props "children")
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)]
|
||||
[:div {:class (if new-css-system
|
||||
(dom/classnames (css :tab-element) true)
|
||||
(dom/classnames :tab-element true))}
|
||||
[:div {:class (stl/css new-css-system :tab-element)}
|
||||
children]))
|
||||
|
||||
(mf/defc tab-container
|
||||
|
@ -35,7 +34,7 @@
|
|||
on-change (unchecked-get props "on-change-tab")
|
||||
collapsable? (unchecked-get props "collapsable?")
|
||||
handle-collapse (unchecked-get props "handle-collapse")
|
||||
klass (unchecked-get props "klass")
|
||||
class (unchecked-get props "class")
|
||||
content-class (unchecked-get props "content-class")
|
||||
|
||||
state (mf/use-state #(or selected (-> children first .-props .-id)))
|
||||
|
@ -45,31 +44,32 @@
|
|||
(mf/use-fn
|
||||
(mf/deps on-change)
|
||||
(fn [event]
|
||||
(let [id (d/read-string (.. event -target -dataset -id))]
|
||||
(let [id (-> event
|
||||
(dom/get-current-target)
|
||||
(dom/get-data "id")
|
||||
(keyword))]
|
||||
(reset! state id)
|
||||
(when (fn? on-change) (on-change id)))))]
|
||||
|
||||
[:div {:class (dom/classnames (css :tab-container) true)}
|
||||
[:div {:class (dom/classnames (css :tab-container-tabs) true
|
||||
klass true)}
|
||||
[:div {:class (stl/css :tab-container)}
|
||||
[:div {:class (dm/str class " "(stl/css :tab-container-tabs))}
|
||||
(when collapsable?
|
||||
[:button
|
||||
{:on-click handle-collapse
|
||||
:class (dom/classnames (css :collapse-sidebar) true)
|
||||
:class (stl/css :collapse-sidebar)
|
||||
:aria-label (tr "workspace.sidebar.collapse")}
|
||||
i/arrow-refactor])
|
||||
[:div {:class (dom/classnames (css :tab-container-tab-wrapper) true)}
|
||||
[:div {:class (stl/css :tab-container-tab-wrapper)}
|
||||
(for [tab children]
|
||||
(let [props (.-props tab)
|
||||
id (.-id props)
|
||||
title (.-title props)]
|
||||
[:div
|
||||
{:key (str/concat "tab-" (d/name id))
|
||||
:data-id (pr-str id)
|
||||
:data-id (d/name id)
|
||||
:on-click select-fn
|
||||
:class (dom/classnames (css :tab-container-tab-title) true
|
||||
(css :current) (= selected id))}
|
||||
:class (stl/css-case :tab-container-tab-title true
|
||||
:current (= selected id))}
|
||||
title]))]]
|
||||
[:div {:class (dom/classnames (css :tab-container-content) true
|
||||
content-class (some? content-class))}
|
||||
[:div {:class (dm/str content-class " " (stl/css :tab-container-content ))}
|
||||
(d/seek #(= selected (-> % .-props .-id)) children)]]))
|
||||
|
|
|
@ -48,14 +48,24 @@
|
|||
background-color: transparent;
|
||||
color: var(--tab-foreground-color);
|
||||
white-space: nowrap;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
stroke: var(--tab-foreground-color);
|
||||
}
|
||||
|
||||
&.current,
|
||||
&.current:hover {
|
||||
background: var(--tab-background-color-selected);
|
||||
color: var(--tab-foreground-color-selected);
|
||||
svg {
|
||||
stroke: var(--tab-foreground-color-selected);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
color: var(--tab-foreground-color-hover);
|
||||
svg {
|
||||
stroke: var(--tab-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
(d/name color)]))]]
|
||||
|
||||
[:div {:class (stl/css :components-row)}
|
||||
[:h2 {:class(stl/css :title)} "Components"]
|
||||
[:h2 {:class (stl/css :title)} "Components"]
|
||||
[:div {:class (stl/css :components-wrapper)}
|
||||
[:div {:class (stl/css :components-group)}
|
||||
[:h3 "Titles"]
|
||||
|
@ -167,7 +167,7 @@
|
|||
[:& search-bar {:on-change update-search
|
||||
:value input-value
|
||||
:placeholder "Test value"}
|
||||
[:button {:class (stl/css :test-button)
|
||||
[:button {:class (stl/css :button-secondary)
|
||||
:on-click on-btn-click}
|
||||
"X"]]]]
|
||||
|
||||
|
@ -246,4 +246,25 @@
|
|||
[:& component-wrapper
|
||||
{:title "Button tertiary with icon"}
|
||||
[:button {:class (stl/css :button-tertiary)}
|
||||
i/add-refactor]]]]]]))
|
||||
i/add-refactor]]]
|
||||
|
||||
[:div {:class (stl/css :components-group)}
|
||||
[:h3 "Inputs"]
|
||||
[:& component-wrapper
|
||||
{:title "Only input"}
|
||||
[:div {:class (stl/css :input-wrapper)}
|
||||
[:input {:class (stl/css :basic-input)
|
||||
:placeholder "----"}]]]
|
||||
[:& component-wrapper
|
||||
{:title "Input with label"}
|
||||
[:div {:class (stl/css :input-wrapper)}
|
||||
[:span {:class (stl/css :input-label)} "label"]
|
||||
[:input {:class (stl/css :basic-input)
|
||||
:placeholder "----"}]]]
|
||||
[:& component-wrapper
|
||||
{:title "Input with icon"}
|
||||
[:div {:class (stl/css :input-wrapper)}
|
||||
[:span {:class (stl/css :input-label)}
|
||||
i/add-refactor]
|
||||
[:input {:class (stl/css :basic-input)
|
||||
:placeholder "----"}]]]]]]]))
|
||||
|
|
|
@ -84,11 +84,10 @@
|
|||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: $s-20;
|
||||
.component-group {
|
||||
.components-group {
|
||||
@include flexCenter;
|
||||
justify-content: flex-start;
|
||||
flex-direction: column;
|
||||
// width: $s-256;
|
||||
border-radius: $s-8;
|
||||
h3 {
|
||||
@include titleTipography;
|
||||
|
@ -129,5 +128,8 @@
|
|||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
.input-wrapper {
|
||||
@extend .input-element;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -276,7 +276,6 @@
|
|||
(def align-content-row-between-refactor (icon-xref :align-content-row-between-refactor))
|
||||
(def align-content-row-evenly-refactor (icon-xref :align-content-row-evenly-refactor))
|
||||
(def align-content-row-start-refactor (icon-xref :align-content-row-start-refactor))
|
||||
|
||||
(def align-horizontal-center-refactor (icon-xref :align-horizontal-center-refactor))
|
||||
(def align-vertical-center-refactor (icon-xref :align-vertical-center-refactor))
|
||||
(def align-items-row-center-refactor (icon-xref :align-items-row-center-refactor))
|
||||
|
@ -345,6 +344,7 @@
|
|||
(def gap-vertical-refactor (icon-xref :gap-vertical-refactor))
|
||||
(def hide-refactor (icon-xref :hide-refactor))
|
||||
(def history-refactor (icon-xref :history-refactor))
|
||||
(def hsva-refactor (icon-xref :hsva-refactor))
|
||||
(def hug-content-refactor (icon-xref :hug-content-refactor))
|
||||
(def img-refactor (icon-xref :img-refactor))
|
||||
(def icon-refactor (icon-xref :icon-refactor))
|
||||
|
@ -384,9 +384,12 @@
|
|||
(def padding-extended-refactor (icon-xref :padding-extended-refactor))
|
||||
(def path-refactor (icon-xref :path-refactor))
|
||||
(def pentool-refactor (icon-xref :pentool-refactor))
|
||||
(def picker-refactor (icon-xref :picker-refactor))
|
||||
(def play-refactor (icon-xref :play-refactor))
|
||||
(def rectangle-refactor (icon-xref :rectangle-refactor))
|
||||
(def remove-refactor (icon-xref :remove-refactor))
|
||||
(def rgba-refactor (icon-xref :rgba-refactor))
|
||||
(def rgba-complementary-refactor (icon-xref :rgba-complementary-refactor))
|
||||
(def rotation-refactor (icon-xref :rotation-refactor))
|
||||
(def row-reverse-refactor (icon-xref :row-reverse-refactor))
|
||||
(def search-refactor (icon-xref :search-refactor))
|
||||
|
@ -400,12 +403,13 @@
|
|||
(def stroke-size-refactor (icon-xref :stroke-size-refactor))
|
||||
(def svg-refactor (icon-xref :svg-refactor))
|
||||
(def swatches-refactor (icon-xref :swatches-refactor))
|
||||
(def switch-refactor (icon-xref :switch-refactor))
|
||||
(def text-align-center-refactor (icon-xref :text-align-center-refactor))
|
||||
(def text-align-left-refactor (icon-xref :text-align-left-refactor))
|
||||
(def text-align-right-refactor (icon-xref :text-align-right-refactor))
|
||||
(def text-auto-height-refactor (icon-xref :text-auto-height-refactor))
|
||||
(def text-auto-width-refactor (icon-xref :text-auto-width-refactor))
|
||||
(def text-fixed-refactor (icon-xref :textfixed--refactor))
|
||||
(def text-fixed-refactor (icon-xref :text-fixed-refactor))
|
||||
(def text-justify-refactor (icon-xref :text-justify-refactor))
|
||||
(def text-letterspacing-refactor (icon-xref :text-letterspacing-refactor))
|
||||
(def text-lineheight-refactor (icon-xref :text-lineheight-refactor))
|
||||
|
@ -420,7 +424,7 @@
|
|||
(def text-mixed-refactor (icon-xref :text-mixed-refactor))
|
||||
(def text-stroked-refactor (icon-xref :text-stroked-refactor))
|
||||
(def text-top-refactor (icon-xref :text-top-refactor))
|
||||
(def text-underlined-refactor (icon-xref :text-undelined-refactor))
|
||||
(def text-underlined-refactor (icon-xref :text-underlined-refactor))
|
||||
(def text-uppercase-refactor (icon-xref :text-uppercase-refactor))
|
||||
(def tick-refactor (icon-xref :tick-refactor))
|
||||
(def unlock-refactor (icon-xref :unlock-refactor))
|
||||
|
|
|
@ -825,21 +825,20 @@
|
|||
(map create-cgdd)))]
|
||||
|
||||
[:g.gaps {:pointer-events "visible"}
|
||||
[:*
|
||||
(for [[index display-item] (d/enumerate (concat display-blocks display-children))]
|
||||
(let [gap-type (:gap-type display-item)]
|
||||
[:& gap-display {:key (str frame-id index)
|
||||
:frame-id frame-id
|
||||
:zoom zoom
|
||||
:gap-type gap-type
|
||||
:gap gap
|
||||
:on-pointer-enter (partial on-pointer-enter gap-type (get gap gap-type))
|
||||
:on-pointer-leave on-pointer-leave
|
||||
:rect-data display-item
|
||||
:hover? (= @hover gap-type)
|
||||
:selected? (= gap-selected gap-type)
|
||||
:mouse-pos mouse-pos
|
||||
:hover-value hover-value}]))]
|
||||
(for [[index display-item] (d/enumerate (concat display-blocks display-children))]
|
||||
(let [gap-type (:gap-type display-item)]
|
||||
[:& gap-display {:key (str frame-id index)
|
||||
:frame-id frame-id
|
||||
:zoom zoom
|
||||
:gap-type gap-type
|
||||
:gap gap
|
||||
:on-pointer-enter (partial on-pointer-enter gap-type (get gap gap-type))
|
||||
:on-pointer-leave on-pointer-leave
|
||||
:rect-data display-item
|
||||
:hover? (= @hover gap-type)
|
||||
:selected? (= gap-selected gap-type)
|
||||
:mouse-pos mouse-pos
|
||||
:hover-value hover-value}]))
|
||||
|
||||
(when @hover
|
||||
[:& flex-display-pill {:height pill-height
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
.palette-menu {
|
||||
position: absolute;
|
||||
left: auto;
|
||||
max-width: $s-480;
|
||||
bottom: $s-0;
|
||||
max-width: $s-480;
|
||||
padding: $s-4;
|
||||
margin: 0 0 $s-4 0;
|
||||
z-index: $z-index-3;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.colorpicker
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.main.data.modal :as modal]
|
||||
[app.main.data.workspace.colors :as dc]
|
||||
|
@ -12,6 +13,8 @@
|
|||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.tab-container :refer [tab-container tab-element]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.colorpicker.color-inputs :refer [color-inputs]]
|
||||
[app.main.ui.workspace.colorpicker.gradients :refer [gradients]]
|
||||
|
@ -44,7 +47,8 @@
|
|||
|
||||
(mf/defc colorpicker
|
||||
[{:keys [data disable-gradient disable-opacity on-change on-accept]}]
|
||||
(let [state (mf/deref refs/colorpicker)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
state (mf/deref refs/colorpicker)
|
||||
node-ref (mf/use-ref)
|
||||
|
||||
;; TODO: I think we need to put all this picking state under
|
||||
|
@ -58,15 +62,15 @@
|
|||
|
||||
active-tab (mf/use-state (dc/get-active-color-tab))
|
||||
drag? (mf/use-state false)
|
||||
|
||||
|
||||
set-tab!
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(let [tab (-> (dom/get-current-target event)
|
||||
(dom/get-data "tab")
|
||||
(keyword))]
|
||||
(reset! active-tab tab)
|
||||
(dc/set-active-color-tab! tab))))
|
||||
(fn [event]
|
||||
(let [tab (-> (dom/get-current-target event)
|
||||
(dom/get-data "tab")
|
||||
(keyword))]
|
||||
(reset! active-tab tab)
|
||||
(dc/set-active-color-tab! tab))))
|
||||
|
||||
handle-change-color
|
||||
(mf/use-fn
|
||||
|
@ -86,14 +90,17 @@
|
|||
(fn []
|
||||
(if picking-color?
|
||||
(do (modal/disallow-click-outside!)
|
||||
(st/emit! (dc/stop-picker)))
|
||||
(st/emit! (dc/stop-picker)))
|
||||
(do (modal/allow-click-outside!)
|
||||
(st/emit! (dc/start-picker))))))
|
||||
(st/emit! (dc/start-picker))))))
|
||||
|
||||
handle-change-stop
|
||||
(mf/use-fn
|
||||
(fn [offset]
|
||||
(st/emit! (dc/select-colorpicker-gradient-stop offset))))
|
||||
(fn [event]
|
||||
(let [offset (-> (dom/get-current-target event)
|
||||
(dom/get-data "value")
|
||||
(int))]
|
||||
(st/emit! (dc/select-colorpicker-gradient-stop offset)))))
|
||||
|
||||
on-select-library-color
|
||||
(mf/use-fn
|
||||
|
@ -128,7 +135,7 @@
|
|||
;; Click on a solid color -> This color is applied to the selected offset
|
||||
;; Click on a color with transparency -> The same to solid color will happend
|
||||
;; Click on any kind of gradient -> The color changes completly to new gradient
|
||||
|
||||
|
||||
;; If we have a non gradient color the new color is applied without any change
|
||||
(if (or (= :radial-gradient type-origin) (= :linear-gradient type-origin))
|
||||
(if is-gradient?
|
||||
|
@ -150,15 +157,24 @@
|
|||
|
||||
on-start-drag
|
||||
(mf/use-fn
|
||||
(mf/deps drag? node-ref)
|
||||
(fn []
|
||||
(reset! drag? true)
|
||||
(st/emit! (dwu/start-undo-transaction (mf/ref-val node-ref)))))
|
||||
|
||||
on-finish-drag
|
||||
(mf/use-fn
|
||||
(mf/deps drag? node-ref)
|
||||
(fn []
|
||||
(reset! drag? false)
|
||||
(st/emit! (dwu/commit-undo-transaction (mf/ref-val node-ref)))))]
|
||||
(st/emit! (dwu/commit-undo-transaction (mf/ref-val node-ref)))))
|
||||
|
||||
on-color-accept
|
||||
(mf/use-fn
|
||||
(mf/deps state)
|
||||
(fn []
|
||||
(on-accept (dc/get-color-from-colorpicker-state state))
|
||||
(modal/hide!)))]
|
||||
|
||||
;; Initialize colorpicker state
|
||||
(mf/with-effect []
|
||||
|
@ -199,110 +215,200 @@
|
|||
:h h :s s :v v
|
||||
:alpha (/ alpha 255)}))))
|
||||
|
||||
[:div.colorpicker {:ref node-ref
|
||||
:style {:touch-action "none"}}
|
||||
[:div.colorpicker-content
|
||||
[:div.top-actions
|
||||
[:button.picker-btn
|
||||
{:class (when picking-color? "active")
|
||||
:on-click handle-click-picker}
|
||||
i/picker]
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :colorpicker)
|
||||
:ref node-ref
|
||||
:style {:touch-action "none"}}
|
||||
[:div {:class (stl/css :top-actions)}
|
||||
[:button {:class (stl/css-case :picker-btn true
|
||||
:selected picking-color?)
|
||||
:on-click handle-click-picker}
|
||||
i/picker-refactor]
|
||||
(when (not disable-gradient)
|
||||
[:div {:class (stl/css :gradient-buttons)}
|
||||
[:button
|
||||
{:on-click on-activate-linear-gradient
|
||||
:class (stl/css-case :gradient-btn true
|
||||
:linear-gradient-btn true
|
||||
:selected (= :linear-gradient (:type state)))}]
|
||||
|
||||
(when (not disable-gradient)
|
||||
[:div.gradients-buttons
|
||||
[:button.gradient.linear-gradient
|
||||
{:on-click on-activate-linear-gradient
|
||||
:class (when (= :linear-gradient (:type state)) "active")}]
|
||||
[:button
|
||||
{:on-click on-activate-radial-gradient
|
||||
:class (stl/css-case :gradient-btn true
|
||||
:radial-gradient-btn true
|
||||
:selected (= :radial-gradient (:type state)))}]])]
|
||||
|
||||
[:button.gradient.radial-gradient
|
||||
{:on-click on-activate-radial-gradient
|
||||
:class (when (= :radial-gradient (:type state)) "active")}]])]
|
||||
(when (or (= (:type state) :linear-gradient)
|
||||
(= (:type state) :radial-gradient))
|
||||
[:& gradients
|
||||
{:stops (:stops state)
|
||||
:editing-stop (:editing-stop state)
|
||||
:on-select-stop handle-change-stop}])
|
||||
|
||||
[:div {:class (stl/css :colorpicker-tabs)}
|
||||
[:& tab-container
|
||||
{:on-change-tab set-tab!
|
||||
:selected @active-tab
|
||||
:collapsable? false}
|
||||
|
||||
(when (or (= (:type state) :linear-gradient)
|
||||
(= (:type state) :radial-gradient))
|
||||
[:& gradients
|
||||
{:stops (:stops state)
|
||||
:editing-stop (:editing-stop state)
|
||||
:on-select-stop handle-change-stop}])
|
||||
[:& tab-element {:id :ramp :title i/rgba-refactor}
|
||||
(if picking-color?
|
||||
[:div {:class (stl/css :picker-detail-wrapper)}
|
||||
[:div {:class (stl/css :center-circle)}]
|
||||
[:canvas#picker-detail {:width 256 :height 140}]]
|
||||
[:& ramp-selector
|
||||
{:color current-color
|
||||
:disable-opacity disable-opacity
|
||||
:on-change handle-change-color
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}])]
|
||||
|
||||
[:div.colorpicker-tabs
|
||||
[:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
|
||||
{:class (when (= @active-tab :ramp) "active")
|
||||
:alt (tr "workspace.libraries.colors.rgba")
|
||||
:on-click set-tab!
|
||||
:data-tab "ramp"} i/picker-ramp]
|
||||
[:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
|
||||
{:class (when (= @active-tab :harmony) "active")
|
||||
:alt (tr "workspace.libraries.colors.rgb-complementary")
|
||||
:on-click set-tab!
|
||||
:data-tab "harmony"} i/picker-harmony]
|
||||
[:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
|
||||
{:class (when (= @active-tab :hsva) "active")
|
||||
:alt (tr "workspace.libraries.colors.hsv")
|
||||
:on-click set-tab!
|
||||
:data-tab "hsva"} i/picker-hsv]]
|
||||
[:& tab-element {:id :harmony :title i/rgba-complementary-refactor}
|
||||
(if picking-color?
|
||||
[:div {:class (stl/css :picker-detail-wrapper)}
|
||||
[:div {:class (stl/css :center-circle)}]
|
||||
[:canvas#picker-detail {:width 256 :height 140}]]
|
||||
[:& harmony-selector
|
||||
{:color current-color
|
||||
:disable-opacity disable-opacity
|
||||
:on-change handle-change-color
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}])]
|
||||
|
||||
(if picking-color?
|
||||
[:div.picker-detail-wrapper
|
||||
[:div.center-circle]
|
||||
[:canvas#picker-detail {:width 200 :height 160}]]
|
||||
(case @active-tab
|
||||
:ramp
|
||||
[:& ramp-selector
|
||||
{:color current-color
|
||||
:disable-opacity disable-opacity
|
||||
:on-change handle-change-color
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
:harmony
|
||||
[:& harmony-selector
|
||||
{:color current-color
|
||||
:disable-opacity disable-opacity
|
||||
:on-change handle-change-color
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
:hsva
|
||||
[:& hsva-selector
|
||||
{:color current-color
|
||||
:disable-opacity disable-opacity
|
||||
:on-change handle-change-color
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
nil))
|
||||
[:& tab-element {:id :hsva :title i/hsva-refactor}
|
||||
(if picking-color?
|
||||
[:div {:class (stl/css :picker-detail-wrapper)}
|
||||
[:div {:class (stl/css :center-circle)}]
|
||||
[:canvas#picker-detail {:width 256 :height 140}]]
|
||||
[:& hsva-selector
|
||||
{:color current-color
|
||||
:disable-opacity disable-opacity
|
||||
:on-change handle-change-color
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}])]]]
|
||||
|
||||
[:& color-inputs
|
||||
{:type (if (= @active-tab :hsva) :hsv :rgb)
|
||||
:disable-opacity disable-opacity
|
||||
:color current-color
|
||||
:on-change handle-change-color}]
|
||||
[:& color-inputs
|
||||
{:type (if (= @active-tab :hsva) :hsv :rgb)
|
||||
:disable-opacity disable-opacity
|
||||
:color current-color
|
||||
:on-change handle-change-color}]
|
||||
|
||||
[:& libraries
|
||||
{:state state
|
||||
:current-color current-color
|
||||
:disable-gradient disable-gradient
|
||||
:disable-opacity disable-opacity
|
||||
:on-select-color on-select-library-color
|
||||
:on-add-library-color on-add-library-color}]
|
||||
[:& libraries
|
||||
{:state state
|
||||
:current-color current-color
|
||||
:on-select-color on-select-library-color
|
||||
:on-add-library-color on-add-library-color}]
|
||||
|
||||
(when on-accept
|
||||
[:div.actions
|
||||
[:button.btn-primary.btn-large
|
||||
{:on-click (fn []
|
||||
(on-accept (dc/get-color-from-colorpicker-state state))
|
||||
(modal/hide!))}
|
||||
(tr "workspace.libraries.colors.save-color")]])]]))
|
||||
(when on-accept
|
||||
[:div {:class (stl/css :actions)}
|
||||
[:button {:class (stl/css :accept-color)
|
||||
:on-click on-color-accept}
|
||||
(tr "workspace.libraries.colors.save-color")]])]
|
||||
|
||||
[:div.colorpicker {:ref node-ref
|
||||
:style {:touch-action "none"}}
|
||||
[:div.colorpicker-content
|
||||
[:div.top-actions
|
||||
[:button.picker-btn
|
||||
{:class (when picking-color? "active")
|
||||
:on-click handle-click-picker}
|
||||
i/picker]
|
||||
|
||||
(when (not disable-gradient)
|
||||
[:div.gradients-buttons
|
||||
[:button.gradient.linear-gradient
|
||||
{:on-click on-activate-linear-gradient
|
||||
:class (when (= :linear-gradient (:type state)) "active")}]
|
||||
|
||||
[:button.gradient.radial-gradient
|
||||
{:on-click on-activate-radial-gradient
|
||||
:class (when (= :radial-gradient (:type state)) "active")}]])]
|
||||
|
||||
(when (or (= (:type state) :linear-gradient)
|
||||
(= (:type state) :radial-gradient))
|
||||
|
||||
[:& gradients
|
||||
{:stops (:stops state)
|
||||
:editing-stop (:editing-stop state)
|
||||
:on-select-stop handle-change-stop}])
|
||||
|
||||
[:div.colorpicker-tabs
|
||||
[:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
|
||||
{:class (when (= @active-tab :ramp) "active")
|
||||
:alt (tr "workspace.libraries.colors.rgba")
|
||||
:on-click set-tab!
|
||||
:data-tab "ramp"} i/picker-ramp]
|
||||
[:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
|
||||
{:class (when (= @active-tab :harmony) "active")
|
||||
:alt (tr "workspace.libraries.colors.rgb-complementary")
|
||||
:on-click set-tab!
|
||||
:data-tab "harmony"} i/picker-harmony]
|
||||
[:div.colorpicker-tab.tooltip.tooltip-bottom.tooltip-expand
|
||||
{:class (when (= @active-tab :hsva) "active")
|
||||
:alt (tr "workspace.libraries.colors.hsv")
|
||||
:on-click set-tab!
|
||||
:data-tab "hsva"} i/picker-hsv]]
|
||||
|
||||
(if picking-color?
|
||||
[:div.picker-detail-wrapper
|
||||
[:div.center-circle]
|
||||
[:canvas#picker-detail {:width 200 :height 160}]]
|
||||
(case @active-tab
|
||||
:ramp
|
||||
[:& ramp-selector
|
||||
{:color current-color
|
||||
:disable-opacity disable-opacity
|
||||
:on-change handle-change-color
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
:harmony
|
||||
[:& harmony-selector
|
||||
{:color current-color
|
||||
:disable-opacity disable-opacity
|
||||
:on-change handle-change-color
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
:hsva
|
||||
[:& hsva-selector
|
||||
{:color current-color
|
||||
:disable-opacity disable-opacity
|
||||
:on-change handle-change-color
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
nil))
|
||||
|
||||
[:& color-inputs
|
||||
{:type (if (= @active-tab :hsva) :hsv :rgb)
|
||||
:disable-opacity disable-opacity
|
||||
:color current-color
|
||||
:on-change handle-change-color}]
|
||||
|
||||
[:& libraries
|
||||
{:state state
|
||||
:current-color current-color
|
||||
:disable-gradient disable-gradient
|
||||
:disable-opacity disable-opacity
|
||||
:on-select-color on-select-library-color
|
||||
:on-add-library-color on-add-library-color}]
|
||||
|
||||
(when on-accept
|
||||
[:div.actions
|
||||
[:button.btn-primary.btn-large
|
||||
{:on-click on-color-accept}
|
||||
(tr "workspace.libraries.colors.save-color")]])]])))
|
||||
|
||||
(defn calculate-position
|
||||
"Calculates the style properties for the given coordinates and position"
|
||||
[{vh :height} position x y]
|
||||
[{vh :height} position x y new-css-system]
|
||||
(let [;; picker height in pixels
|
||||
h 430
|
||||
h(if new-css-system 510 430)
|
||||
;; Checks for overflow outside the viewport height
|
||||
overflow-fix (max 0 (+ y (- 50) h (- vh)))]
|
||||
overflow-fix (max 0 (+ y (- 50) h (- vh)))
|
||||
|
||||
x-pos (if new-css-system 325 250)]
|
||||
(cond
|
||||
(or (nil? x) (nil? y)) {:left "auto" :right "16rem" :top "4rem"}
|
||||
(= position :left) {:left (str (- x 250) "px")
|
||||
(= position :left) {:left (str (- x x-pos) "px")
|
||||
:top (str (- y 50 overflow-fix) "px")}
|
||||
:else {:left (str (+ x 80) "px")
|
||||
:top (str (- y 70 overflow-fix) "px")})))
|
||||
|
@ -315,11 +421,12 @@
|
|||
disable-gradient
|
||||
disable-opacity
|
||||
on-change on-close on-accept] :as props}]
|
||||
(let [vport (mf/deref viewport)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
vport (mf/deref viewport)
|
||||
dirty? (mf/use-var false)
|
||||
last-change (mf/use-var nil)
|
||||
position (or position :left)
|
||||
style (calculate-position vport position x y)
|
||||
style (calculate-position vport position x y new-css-system)
|
||||
|
||||
handle-change
|
||||
(fn [new-data]
|
||||
|
@ -333,8 +440,8 @@
|
|||
#(when (and @dirty? @last-change on-close)
|
||||
(on-close @last-change))))
|
||||
|
||||
[:div.colorpicker-tooltip
|
||||
{:style (clj->js style)}
|
||||
[:div {:class (stl/css new-css-system :colorpicker-tooltip)
|
||||
:style (clj->js style)}
|
||||
[:& colorpicker {:data data
|
||||
:disable-gradient disable-gradient
|
||||
:disable-opacity disable-opacity
|
||||
|
|
124
frontend/src/app/main/ui/workspace/colorpicker.scss
Normal file
124
frontend/src/app/main/ui/workspace/colorpicker.scss
Normal file
|
@ -0,0 +1,124 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.colorpicker-tooltip {
|
||||
@extend .modal-background;
|
||||
top: $s-100;
|
||||
left: calc(10 * $s-140);
|
||||
width: auto;
|
||||
.colorpicker {
|
||||
border-radius: $br-8;
|
||||
width: $s-260;
|
||||
& > * {
|
||||
width: $s-260;
|
||||
}
|
||||
.top-actions {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
height: $s-28;
|
||||
.picker-btn {
|
||||
@include buttonStyle;
|
||||
@include flexCenter;
|
||||
border-radius: $br-8;
|
||||
background-color: transparent;
|
||||
border: $s-1 solid transparent;
|
||||
height: $s-20;
|
||||
width: $s-20;
|
||||
border-radius: $br-4;
|
||||
padding: 0;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
stroke: var(--button-tertiary-foreground-color-rest);
|
||||
}
|
||||
&:hover {
|
||||
svg {
|
||||
stroke: var(--button-tertiary-foreground-color-focus);
|
||||
}
|
||||
}
|
||||
&:focus,
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
svg {
|
||||
stroke: var(--button-secondary-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
&:active {
|
||||
outline: none;
|
||||
border: $s-1 solid transparent;
|
||||
svg {
|
||||
stroke: var(--button-tertiary-foreground-color-active);
|
||||
}
|
||||
}
|
||||
&.selected {
|
||||
svg {
|
||||
stroke: var(--button-tertiary-foreground-color-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
.gradient-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-8;
|
||||
.gradient-btn {
|
||||
@extend .button-tertiary;
|
||||
height: $s-20;
|
||||
width: $s-20;
|
||||
border-radius: $br-4;
|
||||
border: $s-2 solid transparent;
|
||||
&:hover {
|
||||
border: $s-2 solid var(--colorpicker-details-color-selected);
|
||||
}
|
||||
}
|
||||
.linear-gradient-btn {
|
||||
background: linear-gradient(180deg, var(--color-foreground-secondary), transparent);
|
||||
&.selected {
|
||||
background: linear-gradient(to bottom, rgba(126, 255, 245, 1) 0%, rgba(126, 255, 245, 0.2) 100%);
|
||||
border: $s-2 solid var(--colorpicker-details-color-selected);
|
||||
}
|
||||
}
|
||||
|
||||
.radial-gradient-btn {
|
||||
background: radial-gradient(transparent, var(--color-foreground-secondary));
|
||||
&.selected {
|
||||
background: radial-gradient(rgba(126, 255, 245, 1) 0%, rgba(126, 255, 245, 0.2) 100%);
|
||||
border: $s-2 solid var(--colorpicker-details-color-selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
.accept-color {
|
||||
@include titleTipography;
|
||||
@extend .button-secondary;
|
||||
width: 100%;
|
||||
height: $s-32;
|
||||
margin-top: $s-8;
|
||||
}
|
||||
}
|
||||
}
|
||||
.colorpicker-tabs {
|
||||
.picker-detail-wrapper {
|
||||
@include flexCenter;
|
||||
position: relative;
|
||||
margin: $s-12 0 $s-8 0;
|
||||
.center-circle {
|
||||
width: $s-24;
|
||||
height: $s-24;
|
||||
border: $s-2 solid var(--colorpicker-details-color);
|
||||
border-radius: $br-circle;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(calc(-1 * $s-12), calc(-1 * $s-12));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,9 +5,11 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.colorpicker.color-inputs
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.math :as mth]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.util.color :as uc]
|
||||
[app.util.dom :as dom]
|
||||
[rumext.v2 :as mf]))
|
||||
|
@ -27,7 +29,8 @@
|
|||
(* (/ val 255) 100))
|
||||
|
||||
(mf/defc color-inputs [{:keys [type color disable-opacity on-change]}]
|
||||
(let [{red :r green :g blue :b
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
{red :r green :g blue :b
|
||||
hue :h saturation :s value :v
|
||||
hex :hex alpha :alpha} color
|
||||
|
||||
|
@ -108,84 +111,169 @@
|
|||
property-val)]
|
||||
(dom/set-value! node new-val))))))))
|
||||
|
||||
[:div.color-values
|
||||
{:class (when disable-opacity "disable-opacity")}
|
||||
[:input {:id "hex-value"
|
||||
:ref (:hex refs)
|
||||
:default-value hex
|
||||
:on-change on-change-hex
|
||||
:on-blur on-blur-hex}]
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css-case :color-values true
|
||||
:disable-opacity disable-opacity)}
|
||||
|
||||
(if (= type :rgb)
|
||||
[:*
|
||||
[:input {:id "red-value"
|
||||
:ref (:r refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 255
|
||||
:default-value red
|
||||
:on-change (on-change-property :r 255)}]
|
||||
[:div {:class (stl/css :colors-row)}
|
||||
(if (= type :rgb)
|
||||
[:*
|
||||
[:div {:class (stl/css :input-wrapper)}
|
||||
[:span {:class (stl/css :input-label)} "R"]
|
||||
[:input {:id "red-value"
|
||||
:ref (:r refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 255
|
||||
:default-value red
|
||||
:on-change (on-change-property :r 255)}]]
|
||||
[:div {:class (stl/css :input-wrapper)}
|
||||
[:span {:class (stl/css :input-label)} "G"]
|
||||
[:input {:id "green-value"
|
||||
:ref (:g refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 255
|
||||
:default-value green
|
||||
:on-change (on-change-property :g 255)}]]
|
||||
[:div {:class (stl/css :input-wrapper)}
|
||||
[:span {:class (stl/css :input-label)} "B"]
|
||||
[:input {:id "blue-value"
|
||||
:ref (:b refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 255
|
||||
:default-value blue
|
||||
:on-change (on-change-property :b 255)}]]]
|
||||
|
||||
[:input {:id "green-value"
|
||||
:ref (:g refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 255
|
||||
:default-value green
|
||||
:on-change (on-change-property :g 255)}]
|
||||
[:*
|
||||
[:div {:class (stl/css :input-wrapper)}
|
||||
[:span {:class (stl/css :input-label)} "H"]
|
||||
[:input {:id "hue-value"
|
||||
:ref (:h refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 360
|
||||
:default-value hue
|
||||
:on-change (on-change-property :h 360)}]]
|
||||
[:div {:class (stl/css :input-wrapper)}
|
||||
[:span {:class (stl/css :input-label)} "S"]
|
||||
[:input {:id "saturation-value"
|
||||
:ref (:s refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 100
|
||||
:step 1
|
||||
:default-value saturation
|
||||
:on-change (on-change-property :s 100)}]]
|
||||
[:div {:class (stl/css :input-wrapper)}
|
||||
[:span {:class (stl/css :input-label)} "V"]
|
||||
[:input {:id "value-value"
|
||||
:ref (:v refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 100
|
||||
:default-value value
|
||||
:on-change (on-change-property :v 100)}]]])]
|
||||
[:div {:class (stl/css :hex-alpha-wrapper)}
|
||||
[:div {:class (stl/css-case :input-wrapper true
|
||||
:hex true)}
|
||||
[:span {:class (stl/css :input-label)} "HEX"]
|
||||
[:input {:id "hex-value"
|
||||
:ref (:hex refs)
|
||||
:default-value hex
|
||||
:on-change on-change-hex
|
||||
:on-blur on-blur-hex}]]
|
||||
(when (not disable-opacity)
|
||||
[:div {:class (stl/css-case :input-wrapper true)}
|
||||
[:span {:class (stl/css :input-label)} "A"]
|
||||
[:input {:id "alpha-value"
|
||||
:ref (:alpha refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:step 1
|
||||
:max 100
|
||||
:default-value (if (= alpha :multiple) "" alpha)
|
||||
:on-change on-change-opacity}]])]]
|
||||
|
||||
[:input {:id "blue-value"
|
||||
:ref (:b refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 255
|
||||
:default-value blue
|
||||
:on-change (on-change-property :b 255)}]]
|
||||
[:*
|
||||
[:input {:id "hue-value"
|
||||
:ref (:h refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 360
|
||||
:default-value hue
|
||||
:on-change (on-change-property :h 360)}]
|
||||
[:div.color-values
|
||||
{:class (when disable-opacity "disable-opacity")}
|
||||
[:input {:id "hex-value"
|
||||
:ref (:hex refs)
|
||||
:default-value hex
|
||||
:on-change on-change-hex
|
||||
:on-blur on-blur-hex}]
|
||||
|
||||
[:input {:id "saturation-value"
|
||||
:ref (:s refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 100
|
||||
:step 1
|
||||
:default-value saturation
|
||||
:on-change (on-change-property :s 100)}]
|
||||
(if (= type :rgb)
|
||||
[:*
|
||||
[:input {:id "red-value"
|
||||
:ref (:r refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 255
|
||||
:default-value red
|
||||
:on-change (on-change-property :r 255)}]
|
||||
|
||||
[:input {:id "value-value"
|
||||
:ref (:v refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 100
|
||||
:default-value value
|
||||
:on-change (on-change-property :v 100)}]])
|
||||
[:input {:id "green-value"
|
||||
:ref (:g refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 255
|
||||
:default-value green
|
||||
:on-change (on-change-property :g 255)}]
|
||||
|
||||
(when (not disable-opacity)
|
||||
[:input.alpha-value {:id "alpha-value"
|
||||
:ref (:alpha refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:step 1
|
||||
:max 100
|
||||
:default-value (if (= alpha :multiple) "" alpha)
|
||||
:on-change on-change-opacity}])
|
||||
[:input {:id "blue-value"
|
||||
:ref (:b refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 255
|
||||
:default-value blue
|
||||
:on-change (on-change-property :b 255)}]]
|
||||
[:*
|
||||
[:input {:id "hue-value"
|
||||
:ref (:h refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 360
|
||||
:default-value hue
|
||||
:on-change (on-change-property :h 360)}]
|
||||
|
||||
[:label.hex-label {:for "hex-value"} "HEX"]
|
||||
(if (= type :rgb)
|
||||
[:*
|
||||
[:label.red-label {:for "red-value"} "R"]
|
||||
[:label.green-label {:for "green-value"} "G"]
|
||||
[:label.blue-label {:for "blue-value"} "B"]]
|
||||
[:*
|
||||
[:label.red-label {:for "hue-value"} "H"]
|
||||
[:label.green-label {:for "saturation-value"} "S"]
|
||||
[:label.blue-label {:for "value-value"} "V"]])
|
||||
(when (not disable-opacity)
|
||||
[:label.alpha-label {:for "alpha-value"} "A"])]))
|
||||
[:input {:id "saturation-value"
|
||||
:ref (:s refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 100
|
||||
:step 1
|
||||
:default-value saturation
|
||||
:on-change (on-change-property :s 100)}]
|
||||
|
||||
[:input {:id "value-value"
|
||||
:ref (:v refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:max 100
|
||||
:default-value value
|
||||
:on-change (on-change-property :v 100)}]])
|
||||
|
||||
(when (not disable-opacity)
|
||||
[:input.alpha-value {:id "alpha-value"
|
||||
:ref (:alpha refs)
|
||||
:type "number"
|
||||
:min 0
|
||||
:step 1
|
||||
:max 100
|
||||
:default-value (if (= alpha :multiple) "" alpha)
|
||||
:on-change on-change-opacity}])
|
||||
|
||||
[:label.hex-label {:for "hex-value"} "HEX"]
|
||||
(if (= type :rgb)
|
||||
[:*
|
||||
[:label.red-label {:for "red-value"} "R"]
|
||||
[:label.green-label {:for "green-value"} "G"]
|
||||
[:label.blue-label {:for "blue-value"} "B"]]
|
||||
[:*
|
||||
[:label.red-label {:for "hue-value"} "H"]
|
||||
[:label.green-label {:for "saturation-value"} "S"]
|
||||
[:label.blue-label {:for "value-value"} "V"]])
|
||||
(when (not disable-opacity)
|
||||
[:label.alpha-label {:for "alpha-value"} "A"])])))
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.color-values {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
&.disable-opacity {
|
||||
grid-template-columns: 3.5rem repeat(3, 1fr);
|
||||
}
|
||||
.colors-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.input-wrapper {
|
||||
@extend .input-element;
|
||||
width: $s-84;
|
||||
}
|
||||
}
|
||||
.hex-alpha-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.input-wrapper {
|
||||
@extend .input-element;
|
||||
width: $s-84;
|
||||
&.hex {
|
||||
width: $s-172;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,8 +5,10 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.colorpicker.gradients
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.ui.context :as ctx]
|
||||
[cuerdas.core :as str]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
|
@ -20,17 +22,40 @@
|
|||
|
||||
(mf/defc gradients
|
||||
[{:keys [stops editing-stop on-select-stop]}]
|
||||
[:div.gradient-stops
|
||||
[:div.gradient-background-wrapper
|
||||
[:div.gradient-background {:style {:background (gradient->string stops)}}]]
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)]
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :gradient-stops)}
|
||||
[:div {:class (stl/css :gradient-background-wrapper)}
|
||||
[:div {:class (stl/css :gradient-background)
|
||||
:style {:background (gradient->string stops)}}]]
|
||||
|
||||
[:div.gradient-stop-wrapper
|
||||
(for [{:keys [offset hex r g b alpha] :as value} stops]
|
||||
[:div.gradient-stop
|
||||
{:class (when (= editing-stop offset) "active")
|
||||
:on-click (partial on-select-stop offset)
|
||||
:style {:left (dm/str (* offset 100) "%")}
|
||||
:key (dm/str offset)}
|
||||
[:div {:class (stl/css :gradient-stop-wrapper)}
|
||||
(for [{:keys [offset hex r g b alpha] :as value} stops]
|
||||
[:button {:class (stl/css-case :gradient-stop true
|
||||
:selected (= editing-stop offset))
|
||||
:data-value offset
|
||||
:on-click on-select-stop
|
||||
:style {:left (dm/str (* offset 100) "%")
|
||||
:backgroundColor hex}
|
||||
:key (dm/str offset)}
|
||||
|
||||
[:div.gradient-stop-color {:style {:background-color hex}}]
|
||||
[:div.gradient-stop-alpha {:style {:background-color (str/ffmt "rgba(%1, %2, %3, %4)" r g b alpha)}}]])]])
|
||||
[:div {:class (stl/css :gradient-stop-color)
|
||||
:style {:background-color hex}}]
|
||||
[:div {:class (stl/css :gradient-stop-alpha)
|
||||
:style {:background-color (str/ffmt "rgba(%1, %2, %3, %4)" r g b alpha)}}]])]]
|
||||
|
||||
[:div.gradient-stops
|
||||
[:div.gradient-background-wrapper
|
||||
[:div.gradient-background {:style {:background (gradient->string stops)}}]]
|
||||
|
||||
[:div.gradient-stop-wrapper
|
||||
(for [{:keys [offset hex r g b alpha] :as value} stops]
|
||||
[:div.gradient-stop
|
||||
{:class (when (= editing-stop offset) "active")
|
||||
:data-value offset
|
||||
:on-click on-select-stop
|
||||
:style {:left (dm/str (* offset 100) "%")}
|
||||
:key (dm/str offset)}
|
||||
|
||||
[:div.gradient-stop-color {:style {:background-color hex}}]
|
||||
[:div.gradient-stop-alpha {:style {:background-color (str/ffmt "rgba(%1, %2, %3, %4)" r g b alpha)}}]])]])))
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.gradient-stops {
|
||||
display: flex;
|
||||
height: $s-20;
|
||||
width: 100%;
|
||||
margin: $s-12 0;
|
||||
background-color: var(--colorpicker-handlers-color);
|
||||
border-radius: $br-6;
|
||||
|
||||
.gradient-background-wrapper {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-radius: $br-6;
|
||||
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=")
|
||||
left center;
|
||||
|
||||
.gradient-background {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-radius: $br-6;
|
||||
border: $s-2 solid var(--colorpicker-details-color);
|
||||
}
|
||||
}
|
||||
.gradient-stop-wrapper {
|
||||
position: absolute;
|
||||
width: calc(100% - 2rem);
|
||||
.gradient-stop {
|
||||
position: absolute;
|
||||
display: grid;
|
||||
grid-template-columns: 50% 50%;
|
||||
width: $s-16;
|
||||
height: $s-24;
|
||||
border-radius: $br-4;
|
||||
margin-top: calc(-1 * $s-2);
|
||||
margin-left: calc(-1 * $s-8);
|
||||
border: $s-2 solid var(--colorpicker-handlers-color);
|
||||
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=")
|
||||
left center;
|
||||
&.selected {
|
||||
border: $s-2 solid var(--colorpicker-details-color-selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,9 +5,11 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.colorpicker.harmony
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.math :as mth]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]]
|
||||
[app.util.color :as uc]
|
||||
[app.util.dom :as dom]
|
||||
|
@ -57,13 +59,16 @@
|
|||
(gpt/point x y)))
|
||||
|
||||
(mf/defc harmony-selector [{:keys [color disable-opacity on-change on-start-drag on-finish-drag]}]
|
||||
(let [canvas-ref (mf/use-ref nil)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
canvas-ref (mf/use-ref nil)
|
||||
canvas-side (if new-css-system
|
||||
192
|
||||
152)
|
||||
{hue :h saturation :s value :v alpha :alpha} color
|
||||
|
||||
canvas-side 152
|
||||
pos-current (color->point canvas-side hue saturation)
|
||||
pos-current (color->point canvas-side hue saturation)
|
||||
pos-complement (color->point canvas-side (mod (+ hue 180) 360) saturation)
|
||||
dragging? (mf/use-state false)
|
||||
dragging? (mf/use-state false)
|
||||
|
||||
calculate-pos (fn [ev]
|
||||
(let [{:keys [left right top bottom]} (-> ev dom/get-target dom/get-bounding-rect)
|
||||
|
@ -75,7 +80,7 @@
|
|||
py (- (* 2 py) 1)
|
||||
|
||||
angle (mth/degrees (mth/atan2 px py))
|
||||
new-hue (mod (- angle 90 ) 360)
|
||||
new-hue (mod (- angle 90) 360)
|
||||
new-saturation (mth/clamp (mth/distance [px py] [0 0]) 0 1)
|
||||
hex (uc/hsv->hex [new-hue new-saturation value])
|
||||
[r g b] (uc/hex->rgb hex)]
|
||||
|
@ -123,41 +128,83 @@
|
|||
(mf/deps canvas-ref)
|
||||
(fn [] (when canvas-ref
|
||||
(create-color-wheel (mf/ref-val canvas-ref)))))
|
||||
|
||||
[:div.harmony-selector
|
||||
[:div.hue-wheel-wrapper
|
||||
[:canvas.hue-wheel
|
||||
{:ref canvas-ref
|
||||
:width canvas-side
|
||||
:height canvas-side
|
||||
:on-pointer-down handle-start-drag
|
||||
:on-pointer-up handle-stop-drag
|
||||
:on-lost-pointer-capture handle-stop-drag
|
||||
:on-click calculate-pos
|
||||
:on-pointer-move #(when @dragging? (calculate-pos %))}]
|
||||
[:div.handler {:style {:pointer-events "none"
|
||||
:left (:x pos-current)
|
||||
:top (:y pos-current)}}]
|
||||
[:div.handler.complement {:style {:left (:x pos-complement)
|
||||
:top (:y pos-complement)
|
||||
:cursor "pointer"}
|
||||
:on-click on-complement-click}]]
|
||||
[:div.handlers-wrapper
|
||||
[:& slider-selector {:class "value"
|
||||
:vertical? true
|
||||
:reverse? true
|
||||
:value value
|
||||
:max-value 255
|
||||
:vertical true
|
||||
:on-change on-change-value
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
(when (not disable-opacity)
|
||||
[:& slider-selector {:class "opacity"
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :harmony-selector)}
|
||||
[:div {:class (stl/css :handlers-wrapper)}
|
||||
[:& slider-selector {:type :value
|
||||
:vertical? true
|
||||
:value alpha
|
||||
:max-value 1
|
||||
:reverse? true
|
||||
:value value
|
||||
:max-value 255
|
||||
:vertical true
|
||||
:on-change on-change-opacity
|
||||
:on-change on-change-value
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}])]]))
|
||||
:on-finish-drag on-finish-drag}]
|
||||
(when (not disable-opacity)
|
||||
[[:& slider-selector {:type :opacity
|
||||
:vertical? true
|
||||
:value alpha
|
||||
:max-value 1
|
||||
:vertical true
|
||||
:on-change on-change-opacity
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]])]
|
||||
|
||||
[:div {:class (stl/css :hue-wheel-wrapper)}
|
||||
[:canvas {:class (stl/css :hue-wheel)
|
||||
:ref canvas-ref
|
||||
:width canvas-side
|
||||
:height canvas-side
|
||||
:on-pointer-down handle-start-drag
|
||||
:on-pointer-up handle-stop-drag
|
||||
:on-lost-pointer-capture handle-stop-drag
|
||||
:on-click calculate-pos
|
||||
:on-pointer-move #(when @dragging? (calculate-pos %))}]
|
||||
[:div {:class (stl/css :handler)
|
||||
:style {:pointer-events "none"
|
||||
:left (:x pos-current)
|
||||
:top (:y pos-current)}}]
|
||||
[:div {:class (stl/css-case :handler true
|
||||
:complement true)
|
||||
:style {:left (:x pos-complement)
|
||||
:top (:y pos-complement)
|
||||
:cursor "pointer"}
|
||||
:on-click on-complement-click}]]]
|
||||
|
||||
[:div.harmony-selector
|
||||
[:div.hue-wheel-wrapper
|
||||
[:canvas.hue-wheel
|
||||
{:ref canvas-ref
|
||||
:width canvas-side
|
||||
:height canvas-side
|
||||
:on-pointer-down handle-start-drag
|
||||
:on-pointer-up handle-stop-drag
|
||||
:on-lost-pointer-capture handle-stop-drag
|
||||
:on-click calculate-pos
|
||||
:on-pointer-move #(when @dragging? (calculate-pos %))}]
|
||||
[:div.handler {:style {:pointer-events "none"
|
||||
:left (:x pos-current)
|
||||
:top (:y pos-current)}}]
|
||||
[:div.handler.complement {:style {:left (:x pos-complement)
|
||||
:top (:y pos-complement)
|
||||
:cursor "pointer"}
|
||||
:on-click on-complement-click}]]
|
||||
[:div.handlers-wrapper
|
||||
[:& slider-selector {:class "value"
|
||||
:vertical? true
|
||||
:reverse? true
|
||||
:value value
|
||||
:max-value 255
|
||||
:vertical true
|
||||
:on-change on-change-value
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
(when (not disable-opacity)
|
||||
[:& slider-selector {:class "opacity"
|
||||
:vertical? true
|
||||
:value alpha
|
||||
:max-value 1
|
||||
:vertical true
|
||||
:on-change on-change-opacity
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}])]])))
|
||||
|
|
45
frontend/src/app/main/ui/workspace/colorpicker/harmony.scss
Normal file
45
frontend/src/app/main/ui/workspace/colorpicker/harmony.scss
Normal file
|
@ -0,0 +1,45 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.harmony-selector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-8;
|
||||
margin-top: $s-12;
|
||||
margin-bottom: $s-8;
|
||||
.hue-wheel-wrapper {
|
||||
@include flexCenter;
|
||||
position: relative;
|
||||
|
||||
.hue-wheel {
|
||||
width: $s-196;
|
||||
height: $s-196;
|
||||
}
|
||||
|
||||
.handler {
|
||||
@extend .colorpicker-handler;
|
||||
height: $s-16;
|
||||
width: $s-16;
|
||||
border: $s-2 solid var(--colorpicker-handlers-color);
|
||||
}
|
||||
|
||||
.handler.complement {
|
||||
background-color: var(--colorpicker-handlers-color);
|
||||
border: $s-2 solid var(--colorpicker-handlers-color);
|
||||
}
|
||||
}
|
||||
|
||||
.handlers-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
height: $s-200;
|
||||
width: $s-52;
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
|
@ -5,13 +5,16 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.colorpicker.hsva
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]]
|
||||
[app.util.color :as uc]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc hsva-selector [{:keys [color disable-opacity on-change on-start-drag on-finish-drag]}]
|
||||
(let [{hue :h saturation :s value :v alpha :alpha} color
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
{hue :h saturation :s value :v alpha :alpha} color
|
||||
handle-change-slider (fn [key]
|
||||
(fn [new-value]
|
||||
(let [change (hash-map key new-value)
|
||||
|
@ -22,42 +25,87 @@
|
|||
{:hex hex
|
||||
:r r :g g :b b})))))
|
||||
on-change-opacity (fn [new-alpha] (on-change {:alpha new-alpha}))]
|
||||
[:div.hsva-selector
|
||||
[:span.hsva-selector-label "H"]
|
||||
[:& slider-selector
|
||||
{:class "hue"
|
||||
:max-value 360
|
||||
:value hue
|
||||
:on-change (handle-change-slider :h)
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
|
||||
[:span.hsva-selector-label "S"]
|
||||
[:& slider-selector
|
||||
{:class "saturation"
|
||||
:max-value 1
|
||||
:value saturation
|
||||
:on-change (handle-change-slider :s)
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
|
||||
[:span.hsva-selector-label "V"]
|
||||
[:& slider-selector
|
||||
{:class "value"
|
||||
:reverse? false
|
||||
:max-value 255
|
||||
:value value
|
||||
:on-change (handle-change-slider :v)
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
|
||||
(when (not disable-opacity)
|
||||
[:*
|
||||
[:span.hsva-selector-label "A"]
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :hsva-selector)}
|
||||
[:div {:class (stl/css :hsva-row)}
|
||||
[:span {:class (stl/css :hsva-selector-label)} "H"]
|
||||
[:& slider-selector
|
||||
{:class "opacity"
|
||||
:max-value 1
|
||||
:value alpha
|
||||
:on-change on-change-opacity
|
||||
{:class (stl/css :hsva-bar)
|
||||
:type :hue
|
||||
:max-value 360
|
||||
:value hue
|
||||
:on-change (handle-change-slider :h)
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]])]))
|
||||
:on-finish-drag on-finish-drag}]]
|
||||
[:div {:class (stl/css :hsva-row)}
|
||||
[:span {:class (stl/css :hsva-selector-label)} "S"]
|
||||
[:& slider-selector
|
||||
{:class (stl/css :hsva-bar)
|
||||
:type :saturation
|
||||
:max-value 1
|
||||
:value saturation
|
||||
:on-change (handle-change-slider :s)
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]]
|
||||
[:div {:class (stl/css :hsva-row)}
|
||||
[:span {:class (stl/css :hsva-selector-label)} "V"]
|
||||
[:& slider-selector
|
||||
{:class (stl/css :hsva-bar)
|
||||
:type :value
|
||||
:reverse? false
|
||||
:max-value 255
|
||||
:value value
|
||||
:on-change (handle-change-slider :v)
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]]
|
||||
(when (not disable-opacity)
|
||||
[:div {:class (stl/css :hsva-row)}
|
||||
[:span {:class (stl/css :hsva-selector-label)} "A"]
|
||||
[:& slider-selector
|
||||
{:class (stl/css :hsva-bar)
|
||||
:type :opacity
|
||||
:max-value 1
|
||||
:value alpha
|
||||
:on-change on-change-opacity
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]])]
|
||||
|
||||
[:div.hsva-selector
|
||||
[:span.hsva-selector-label "H"]
|
||||
[:& slider-selector
|
||||
{:class "hue"
|
||||
:max-value 360
|
||||
:value hue
|
||||
:on-change (handle-change-slider :h)
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
|
||||
[:span.hsva-selector-label "S"]
|
||||
[:& slider-selector
|
||||
{:class "saturation"
|
||||
:max-value 1
|
||||
:value saturation
|
||||
:on-change (handle-change-slider :s)
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
[:span.hsva-selector-label "V"]
|
||||
[:& slider-selector
|
||||
{:class "value"
|
||||
:reverse? false
|
||||
:max-value 255
|
||||
:value value
|
||||
:on-change (handle-change-slider :v)
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
|
||||
(when (not disable-opacity)
|
||||
[:*
|
||||
[:span.hsva-selector-label "A"]
|
||||
[:& slider-selector
|
||||
{:class "opacity"
|
||||
:max-value 1
|
||||
:value alpha
|
||||
:on-change on-change-opacity
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]])])
|
||||
))
|
||||
|
|
30
frontend/src/app/main/ui/workspace/colorpicker/hsva.scss
Normal file
30
frontend/src/app/main/ui/workspace/colorpicker/hsva.scss
Normal file
|
@ -0,0 +1,30 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.hsva-selector {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
padding: $s-4;
|
||||
grid-row-gap: $s-8;
|
||||
margin-bottom: $s-8;
|
||||
.hsva-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.hsva-selector-label {
|
||||
@include tabTitleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
width: $s-32;
|
||||
}
|
||||
.hsva-bar {
|
||||
width: $s-228;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,9 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.colorpicker.libraries
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.events :as ev]
|
||||
[app.main.data.workspace :as dw]
|
||||
|
@ -13,6 +15,9 @@
|
|||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.color-bullet :refer [color-bullet]]
|
||||
[app.main.ui.components.color-bullet-new :as cb]
|
||||
[app.main.ui.components.select :refer [select]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.hooks :as h]
|
||||
[app.main.ui.hooks.resize :as r]
|
||||
[app.main.ui.icons :as i]
|
||||
|
@ -23,7 +28,8 @@
|
|||
|
||||
(mf/defc libraries
|
||||
[{:keys [state on-select-color on-add-library-color disable-gradient disable-opacity]}]
|
||||
(let [selected (h/use-shared-state mdc/colorpicker-selected-broadcast-key :recent)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
selected (h/use-shared-state mdc/colorpicker-selected-broadcast-key :recent)
|
||||
current-colors (mf/use-state [])
|
||||
|
||||
shared-libs (mf/deref refs/workspace-libraries)
|
||||
|
@ -34,7 +40,9 @@
|
|||
on-library-change
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(let [val (dom/get-target-val event)]
|
||||
(let [val (if new-css-system
|
||||
event
|
||||
(dom/get-target-val event))]
|
||||
(reset! selected
|
||||
(if (or (= val "recent")
|
||||
(= val "file"))
|
||||
|
@ -44,7 +52,30 @@
|
|||
check-valid-color?
|
||||
(fn [color]
|
||||
(and (or (not disable-gradient) (not (:gradient color)))
|
||||
(or (not disable-opacity) (= 1 (:opacity color)))))]
|
||||
(or (not disable-opacity) (= 1 (:opacity color)))))
|
||||
|
||||
toggle-palette
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(r/set-resize-type! :bottom)
|
||||
(dom/add-class! (dom/get-element-by-class "color-palette") "fade-out-down")
|
||||
(ts/schedule 300 #(st/emit! (dw/remove-layout-flag :textpalette)
|
||||
(-> (dw/toggle-layout-flag :colorpalette)
|
||||
(vary-meta assoc ::ev/origin "workspace-colorpicker"))))))
|
||||
|
||||
shared-libs-options (mapv (fn[lib] {:value (d/name (:id lib)) :label (:name lib)} ) (vals shared-libs))
|
||||
|
||||
|
||||
library-options [{:value "recent" :label (tr "workspace.libraries.colors.recent-colors")}
|
||||
{:value "file" :label (tr "workspace.libraries.colors.file-library")}]
|
||||
|
||||
options (concat library-options shared-libs-options)
|
||||
|
||||
on-color-click
|
||||
(mf/use-fn
|
||||
(mf/deps state)
|
||||
(fn[event]
|
||||
(on-select-color state event)))]
|
||||
|
||||
;; Load library colors when the select is changed
|
||||
(mf/with-effect [@selected recent-colors file-colors]
|
||||
|
@ -71,33 +102,59 @@
|
|||
(let [colors (vals file-colors)]
|
||||
(reset! current-colors (into [] (filter check-valid-color?) colors)))))
|
||||
|
||||
[:div.libraries
|
||||
[:select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:on-change on-library-change
|
||||
:value (name @selected)}
|
||||
[:option {:value "recent"} (tr "workspace.libraries.colors.recent-colors")]
|
||||
[:option {:value "file"} (tr "workspace.libraries.colors.file-library")]
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :libraries)}
|
||||
[:div {:class (stl/css :select-wrapper)}
|
||||
[:& select
|
||||
{:class (stl/css :shadow-type-select)
|
||||
:default-value (or (name @selected) "recent")
|
||||
:options options
|
||||
:on-change on-library-change}]]
|
||||
|
||||
(for [[_ {:keys [name id]}] shared-libs]
|
||||
[:option {:key id :value id} name])]
|
||||
[:div {:class (stl/css :selected-colors)}
|
||||
(when (= @selected :file)
|
||||
[:button {:class (stl/css :add-color-btn)
|
||||
:on-click on-add-library-color}
|
||||
i/add-refactor])
|
||||
|
||||
[:div.selected-colors
|
||||
(when (= @selected :file)
|
||||
[:div.color-bullet.button.plus-button {:style {:background-color "var(--color-white)"}
|
||||
:on-click on-add-library-color}
|
||||
i/plus])
|
||||
[:button {:class (stl/css :palette-btn)
|
||||
:on-click toggle-palette}
|
||||
i/swatches-refactor]
|
||||
|
||||
[:div.color-bullet.button {:style {:background-color "var(--color-white)"}
|
||||
:on-click(fn []
|
||||
(r/set-resize-type! :bottom)
|
||||
(dom/add-class! (dom/get-element-by-class "color-palette") "fade-out-down")
|
||||
(ts/schedule 300 #(st/emit! (dw/remove-layout-flag :textpalette)
|
||||
(-> (dw/toggle-layout-flag :colorpalette)
|
||||
(vary-meta assoc ::ev/origin "workspace-colorpicker")))))}
|
||||
i/palette]
|
||||
(for [[idx color] (map-indexed vector @current-colors)]
|
||||
[:& cb/color-bullet
|
||||
{:key (dm/str "color-" idx)
|
||||
:color color
|
||||
:on-click on-color-click}])]]
|
||||
|
||||
(for [[idx color] (map-indexed vector @current-colors)]
|
||||
[:& color-bullet
|
||||
{:key (dm/str "color-" idx)
|
||||
:color color
|
||||
:on-click (partial on-select-color state)}])]]))
|
||||
|
||||
[:div.libraries
|
||||
[:select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:on-change on-library-change
|
||||
:value (name @selected)}
|
||||
[:option {:value "recent"} (tr "workspace.libraries.colors.recent-colors")]
|
||||
[:option {:value "file"} (tr "workspace.libraries.colors.file-library")]
|
||||
|
||||
(for [[_ {:keys [name id]}] shared-libs]
|
||||
[:option {:key id :value id} name])]
|
||||
|
||||
[:div.selected-colors
|
||||
(when (= @selected :file)
|
||||
[:div.color-bullet.button.plus-button {:style {:background-color "var(--color-white)"}
|
||||
:on-click on-add-library-color}
|
||||
i/plus])
|
||||
|
||||
[:div.color-bullet.button {:style {:background-color "var(--color-white)"}
|
||||
:on-click (fn []
|
||||
(r/set-resize-type! :bottom)
|
||||
(dom/add-class! (dom/get-element-by-class "color-palette") "fade-out-down")
|
||||
(ts/schedule 300 #(st/emit! (dw/remove-layout-flag :textpalette)
|
||||
(-> (dw/toggle-layout-flag :colorpalette)
|
||||
(vary-meta assoc ::ev/origin "workspace-colorpicker")))))}
|
||||
i/palette]
|
||||
|
||||
(for [[idx color] (map-indexed vector @current-colors)]
|
||||
[:& color-bullet
|
||||
{:key (dm/str "color-" idx)
|
||||
:color color
|
||||
:on-click on-color-click}])]])))
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.libraries {
|
||||
margin-top: $s-8;
|
||||
width: 100%;
|
||||
|
||||
.selected-colors {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(8, 1fr);
|
||||
gap: $s-4;
|
||||
justify-content: space-between;
|
||||
overflow: auto;
|
||||
margin-top: $s-8;
|
||||
.add-color-btn,
|
||||
.palette-btn {
|
||||
@extend .button-secondary;
|
||||
height: $s-24;
|
||||
width: $s-24;
|
||||
border-radius: $br-circle;
|
||||
padding: 0;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
.selected-colors::after {
|
||||
content: "";
|
||||
flex: auto;
|
||||
}
|
||||
}
|
|
@ -5,16 +5,20 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.colorpicker.ramp
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.math :as mth]
|
||||
[app.main.ui.components.color-bullet :refer [color-bullet]]
|
||||
[app.main.ui.components.color-bullet-new :as cb]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.workspace.colorpicker.slider-selector :refer [slider-selector]]
|
||||
[app.util.color :as uc]
|
||||
[app.util.dom :as dom]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc value-saturation-selector [{:keys [saturation value on-change on-start-drag on-finish-drag]}]
|
||||
(let [dragging? (mf/use-state false)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
dragging? (mf/use-state false)
|
||||
calculate-pos
|
||||
(fn [ev]
|
||||
(let [{:keys [left right top bottom]} (-> ev dom/get-target dom/get-bounding-rect)
|
||||
|
@ -37,21 +41,33 @@
|
|||
(fn [event]
|
||||
(dom/release-pointer event)
|
||||
(reset! dragging? false)
|
||||
(on-finish-drag)))
|
||||
]
|
||||
[:div.value-saturation-selector
|
||||
{:on-pointer-down handle-start-drag
|
||||
:on-pointer-up handle-stop-drag
|
||||
:on-lost-pointer-capture handle-stop-drag
|
||||
:on-click calculate-pos
|
||||
:on-pointer-move #(when @dragging? (calculate-pos %))}
|
||||
[:div.handler {:style {:pointer-events "none"
|
||||
:left (str (* 100 saturation) "%")
|
||||
:top (str (* 100 (- 1 (/ value 255))) "%")}}]]))
|
||||
(on-finish-drag)))]
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :value-saturation-selector)
|
||||
:on-pointer-down handle-start-drag
|
||||
:on-pointer-up handle-stop-drag
|
||||
:on-lost-pointer-capture handle-stop-drag
|
||||
:on-click calculate-pos
|
||||
:on-pointer-move #(when @dragging? (calculate-pos %))}
|
||||
[:div {:class (stl/css :handler)
|
||||
:style {:pointer-events "none"
|
||||
:left (str (* 100 saturation) "%")
|
||||
:top (str (* 100 (- 1 (/ value 255))) "%")}}]]
|
||||
|
||||
[:div.value-saturation-selector
|
||||
{:on-pointer-down handle-start-drag
|
||||
:on-pointer-up handle-stop-drag
|
||||
:on-lost-pointer-capture handle-stop-drag
|
||||
:on-click calculate-pos
|
||||
:on-pointer-move #(when @dragging? (calculate-pos %))}
|
||||
[:div.handler {:style {:pointer-events "none"
|
||||
:left (str (* 100 saturation) "%")
|
||||
:top (str (* 100 (- 1 (/ value 255))) "%")}}]])))
|
||||
|
||||
|
||||
(mf/defc ramp-selector [{:keys [color disable-opacity on-change on-start-drag on-finish-drag]}]
|
||||
(let [{hex :hex
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
{hex :hex
|
||||
hue :h saturation :s value :v alpha :alpha} color
|
||||
|
||||
on-change-value-saturation
|
||||
|
@ -69,34 +85,65 @@
|
|||
[r g b] (uc/hex->rgb hex)]
|
||||
(on-change {:hex hex
|
||||
:r r :g g :b b
|
||||
:h new-hue} )))
|
||||
:h new-hue})))
|
||||
|
||||
on-change-opacity
|
||||
(fn [new-opacity]
|
||||
(on-change {:alpha new-opacity} ))]
|
||||
[:*
|
||||
[:& value-saturation-selector
|
||||
{:hue hue
|
||||
:saturation saturation
|
||||
:value value
|
||||
:on-change on-change-value-saturation
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
(on-change {:alpha new-opacity}))]
|
||||
(if new-css-system
|
||||
[:*
|
||||
[:& value-saturation-selector
|
||||
{:hue hue
|
||||
:saturation saturation
|
||||
:value value
|
||||
:on-change on-change-value-saturation
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
|
||||
[:div.shade-selector
|
||||
[:& color-bullet {:color {:color hex
|
||||
:opacity alpha}}]
|
||||
[:& slider-selector {:class "hue"
|
||||
:max-value 360
|
||||
:value hue
|
||||
:on-change on-change-hue
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
[:div {:class (stl/css new-css-system :shade-selector)
|
||||
:style #js {"--bullet-size" "52px"}}
|
||||
[:& cb/color-bullet {:color {:color hex
|
||||
:opacity alpha}
|
||||
:area true}]
|
||||
[:div {:class (stl/css :sliders-wrapper)}
|
||||
[:& slider-selector {:type :hue
|
||||
:max-value 360
|
||||
:value hue
|
||||
:on-change on-change-hue
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
|
||||
(when (not disable-opacity)
|
||||
[:& slider-selector {:class "opacity"
|
||||
:max-value 1
|
||||
:value alpha
|
||||
:on-change on-change-opacity
|
||||
(when (not disable-opacity)
|
||||
[:& slider-selector {:type :opacity
|
||||
:max-value 1
|
||||
:value alpha
|
||||
:on-change on-change-opacity
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}])]]]
|
||||
|
||||
[:*
|
||||
[:& value-saturation-selector
|
||||
{:hue hue
|
||||
:saturation saturation
|
||||
:value value
|
||||
:on-change on-change-value-saturation
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}]
|
||||
|
||||
[:div.shade-selector
|
||||
[:& color-bullet {:color {:color hex
|
||||
:opacity alpha}}]
|
||||
[:& slider-selector {:class "hue"
|
||||
:max-value 360
|
||||
:value hue
|
||||
:on-change on-change-hue
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}])]]))
|
||||
:on-finish-drag on-finish-drag}]
|
||||
|
||||
(when (not disable-opacity)
|
||||
[:& slider-selector {:class "opacity"
|
||||
:max-value 1
|
||||
:value alpha
|
||||
:on-change on-change-opacity
|
||||
:on-start-drag on-start-drag
|
||||
:on-finish-drag on-finish-drag}])]])))
|
||||
|
|
46
frontend/src/app/main/ui/workspace/colorpicker/ramp.scss
Normal file
46
frontend/src/app/main/ui/workspace/colorpicker/ramp.scss
Normal file
|
@ -0,0 +1,46 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.value-saturation-selector {
|
||||
background-color: rgba(var(--hue-rgb));
|
||||
position: relative;
|
||||
height: $s-140;
|
||||
width: $s-256;
|
||||
margin-top: $s-12;
|
||||
margin-bottom: $s-6;
|
||||
cursor: pointer;
|
||||
|
||||
.handler {
|
||||
@extend .colorpicker-handler;
|
||||
height: $s-16;
|
||||
width: $s-16;
|
||||
border: $s-2 solid var(--colorpicker-handlers-color);
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(to right, #fff, rgba(255, 255, 255, 0));
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(to top, #000, rgba(0, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
.shade-selector {
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
height: $s-52;
|
||||
cursor: pointer;
|
||||
}
|
|
@ -5,15 +5,19 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.colorpicker.slider-selector
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.math :as mth]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.object :as obj]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc slider-selector
|
||||
[{:keys [value class min-value max-value vertical? reverse? on-change on-start-drag on-finish-drag]}]
|
||||
(let [min-value (or min-value 0)
|
||||
[{:keys [value class min-value max-value vertical? reverse? on-change on-start-drag on-finish-drag type]}]
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
min-value (or min-value 0)
|
||||
max-value (or max-value 1)
|
||||
dragging? (mf/use-state false)
|
||||
|
||||
|
@ -49,23 +53,49 @@
|
|||
value (+ min-value (* unit-value (- max-value min-value)))]
|
||||
(on-change value))))]
|
||||
|
||||
[:div.slider-selector
|
||||
{:class (str (if vertical? "vertical " "") class)
|
||||
:on-pointer-down handle-start-drag
|
||||
:on-pointer-up handle-stop-drag
|
||||
:on-lost-pointer-capture handle-stop-drag
|
||||
:on-click calculate-pos
|
||||
:on-pointer-move #(when @dragging? (calculate-pos %))}
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css-case :opacity-wrapper (= type :opacity))}
|
||||
[:div {:class (dm/str class (stl/css-case :vertical vertical?
|
||||
:slider-selector true
|
||||
:hue (= type :hue)
|
||||
:opacity (= type :opacity)
|
||||
:value (= type :value)))
|
||||
:on-pointer-down handle-start-drag
|
||||
:on-pointer-up handle-stop-drag
|
||||
:on-lost-pointer-capture handle-stop-drag
|
||||
:on-click calculate-pos
|
||||
:on-pointer-move #(when @dragging? (calculate-pos %))}
|
||||
(let [value-percent (* (/ (- value min-value)
|
||||
(- max-value min-value)) 100)
|
||||
|
||||
(let [value-percent (* (/ (- value min-value)
|
||||
(- max-value min-value)) 100)
|
||||
value-percent (if reverse?
|
||||
(mth/abs (- value-percent 100))
|
||||
value-percent)
|
||||
value-percent-str (str value-percent "%")
|
||||
|
||||
value-percent (if reverse?
|
||||
(mth/abs (- value-percent 100))
|
||||
value-percent)
|
||||
value-percent-str (str value-percent "%")
|
||||
style-common #js {:pointerEvents "none"}
|
||||
style-horizontal (obj/merge! #js {:left value-percent-str} style-common)
|
||||
style-vertical (obj/merge! #js {:bottom value-percent-str} style-common)]
|
||||
[:div {:class (stl/css :handler)
|
||||
:style (if vertical? style-vertical style-horizontal)}])]]
|
||||
|
||||
style-common #js {:pointerEvents "none"}
|
||||
style-horizontal (obj/merge! #js {:left value-percent-str} style-common)
|
||||
style-vertical (obj/merge! #js {:bottom value-percent-str} style-common)]
|
||||
[:div.handler {:style (if vertical? style-vertical style-horizontal)}])]))
|
||||
[:div.slider-selector
|
||||
{:class (str (if vertical? "vertical " "") class)
|
||||
:on-pointer-down handle-start-drag
|
||||
:on-pointer-up handle-stop-drag
|
||||
:on-lost-pointer-capture handle-stop-drag
|
||||
:on-click calculate-pos
|
||||
:on-pointer-move #(when @dragging? (calculate-pos %))}
|
||||
|
||||
(let [value-percent (* (/ (- value min-value)
|
||||
(- max-value min-value)) 100)
|
||||
|
||||
value-percent (if reverse?
|
||||
(mth/abs (- value-percent 100))
|
||||
value-percent)
|
||||
value-percent-str (str value-percent "%")
|
||||
|
||||
style-common #js {:pointerEvents "none"}
|
||||
style-horizontal (obj/merge! #js {:left value-percent-str} style-common)
|
||||
style-vertical (obj/merge! #js {:bottom value-percent-str} style-common)]
|
||||
[:div.handler {:style (if vertical? style-vertical style-horizontal)}])])))
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.slider-selector {
|
||||
--gradient-direction: 90deg;
|
||||
--background-repeat: left;
|
||||
|
||||
&.vertical {
|
||||
--gradient-direction: 0deg;
|
||||
--background-repeat: top;
|
||||
}
|
||||
position: relative;
|
||||
align-self: center;
|
||||
height: $s-24;
|
||||
width: $s-200;
|
||||
border: $s-2 solid var(--colorpicker-details-color);
|
||||
border-radius: $br-6;
|
||||
background: linear-gradient(
|
||||
var(--gradient-direction),
|
||||
rgba(var(--color), 0) 0%,
|
||||
rgba(var(--color), 1) 100%
|
||||
);
|
||||
cursor: pointer;
|
||||
|
||||
&.vertical {
|
||||
width: $s-24;
|
||||
height: $s-200;
|
||||
}
|
||||
|
||||
&.hue {
|
||||
background: linear-gradient(
|
||||
var(--gradient-direction),
|
||||
#f00 0%,
|
||||
#ff0 17%,
|
||||
#0f0 33%,
|
||||
#0ff 50%,
|
||||
#00f 67%,
|
||||
#f0f 83%,
|
||||
#f00 100%
|
||||
);
|
||||
}
|
||||
|
||||
&.saturation {
|
||||
background: linear-gradient(
|
||||
var(--gradient-direction),
|
||||
var(--saturation-grad-from) 0%,
|
||||
var(--saturation-grad-to) 100%
|
||||
);
|
||||
}
|
||||
|
||||
&.opacity {
|
||||
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAADFJREFUOE9jZGBgEAFifOANPknGUQMYhkkYEEgG+NMJKAwIAbwJbdQABnBCIgRoG4gAIF8IsXB/Rs4AAAAASUVORK5CYII=")
|
||||
var(--background-repeat) center;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(
|
||||
var(--gradient-direction),
|
||||
rgba(var(--color), 0) 0%,
|
||||
rgba(var(--color), 1) 100%
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
&.value {
|
||||
background: linear-gradient(var(--gradient-direction), #000 0%, #fff 100%);
|
||||
}
|
||||
|
||||
.handler {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
width: calc($s-8 + $s-2);
|
||||
height: calc($s-24 + $s-1);
|
||||
border-radius: $br-4;
|
||||
z-index: $z-index-1;
|
||||
transform: translate(-4px, -3px);
|
||||
background-color: var(--colorpicker-handlers-color);
|
||||
}
|
||||
|
||||
&.vertical .handler {
|
||||
height: calc($s-8 + $s-2);
|
||||
width: calc($s-24 + $s-1);
|
||||
transform: translate(-12px, 5px);
|
||||
}
|
||||
}
|
||||
|
||||
.opacity-wrapper {
|
||||
background-color: var(--colorpicker-handlers-color);
|
||||
border-radius: $br-8;
|
||||
}
|
||||
|
||||
.slider-selector.hue {
|
||||
grid-area: hue;
|
||||
}
|
||||
|
||||
.slider-selector.opacity {
|
||||
grid-area: opacity;
|
||||
}
|
||||
|
||||
.slider-selector.value {
|
||||
background: linear-gradient(var(--gradient-direction), #000 0%, #fff 100%);
|
||||
}
|
||||
.slider-selector.saturation {
|
||||
background: linear-gradient(
|
||||
var(--gradient-direction),
|
||||
var(--saturation-grad-from) 0%,
|
||||
var(--saturation-grad-to) 100%
|
||||
);
|
||||
}
|
|
@ -83,9 +83,9 @@
|
|||
}
|
||||
.menu {
|
||||
@extend .menu-dropdown;
|
||||
position: absolute;
|
||||
top: $s-48;
|
||||
left: calc(var(--width, $s-256) - $s-16);
|
||||
width: $s-192;
|
||||
margin: 0;
|
||||
|
||||
.menu-item {
|
||||
|
@ -125,9 +125,9 @@
|
|||
}
|
||||
.sub-menu {
|
||||
@extend .menu-dropdown;
|
||||
position: absolute;
|
||||
left: calc(var(--width, $s-256) + $s-180);
|
||||
min-width: 270px;
|
||||
width: $s-192;
|
||||
min-width: calc($s-272 - $s-2);
|
||||
width: 110%;
|
||||
.shortcut {
|
||||
@extend .shortcut;
|
||||
|
|
|
@ -63,7 +63,6 @@
|
|||
}
|
||||
.dropdown {
|
||||
@extend .menu-dropdown;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: $s-48;
|
||||
width: $s-280;
|
||||
|
|
|
@ -94,7 +94,7 @@
|
|||
:shortcuts? shortcuts?
|
||||
:collapsable? true
|
||||
:handle-collapse handle-collapse
|
||||
:klass :tab-spacing}
|
||||
:class :tab-spacing}
|
||||
[:& tab-element {:id :layers :title (tr "workspace.sidebar.layers")}
|
||||
[:div {:class (stl/css :layers-tab)}
|
||||
[:& sitemap {:layout layout}]
|
||||
|
|
|
@ -20,10 +20,10 @@ $width-settings-bar-max: $s-500;
|
|||
|
||||
.resize-area {
|
||||
position: absolute;
|
||||
right: -8px;
|
||||
right: calc(-1 * $s-8);
|
||||
z-index: $z-index-3;
|
||||
width: $s-8;
|
||||
height: 100%;
|
||||
height: calc(100vh - $s-52);
|
||||
cursor: ew-resize;
|
||||
}
|
||||
.settings-bar-inside {
|
||||
|
|
|
@ -652,7 +652,6 @@
|
|||
:id "assets-group-component"
|
||||
:option-handler on-group})
|
||||
|
||||
|
||||
(when (and components-v2 (not multi-assets?))
|
||||
{:option-name (tr "workspace.shape.menu.show-main")
|
||||
:id "assets-show-main-component"
|
||||
|
|
|
@ -160,11 +160,12 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.filters-container {
|
||||
@extend .menu-dropdown;
|
||||
position: absolute;
|
||||
top: $s-44;
|
||||
left: $s-12;
|
||||
width: $s-192;
|
||||
.filter-menu-item {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
|
@ -201,16 +202,16 @@
|
|||
.filter-menu-item-name-wrapper {
|
||||
.filter-menu-item-icon {
|
||||
svg {
|
||||
stroke: var(--menu-foreground-color-selected);
|
||||
stroke: var(--menu-foreground-color);
|
||||
}
|
||||
}
|
||||
.filter-menu-item-name {
|
||||
color: var(--menu-foreground-color-selected);
|
||||
color: var(--menu-foreground-color);
|
||||
}
|
||||
}
|
||||
.filter-menu-item-tick {
|
||||
svg {
|
||||
stroke: var(--menu-foreground-color-selected);
|
||||
stroke: var(--menu-foreground-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@
|
|||
:selected section
|
||||
:collapsable? false
|
||||
:content-class (stl/css :content-class)
|
||||
:klass (stl/css :tab-spacing)}
|
||||
:class (stl/css :tab-spacing)}
|
||||
[:& tab-element {:id :design
|
||||
:title (tr "workspace.options.design")}
|
||||
[:div {:class (stl/css :element-options)}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
height: calc(100vh - $s-96);
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
.element-options {
|
||||
|
|
|
@ -5,21 +5,30 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.common
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.util.dom :as dom]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc advanced-options [{:keys [visible? children]}]
|
||||
(let [ref (mf/use-ref nil)]
|
||||
(mf/defc advanced-options [{:keys [visible? class children]}]
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
ref (mf/use-ref nil)]
|
||||
(mf/use-effect
|
||||
(mf/deps visible?)
|
||||
(fn []
|
||||
(when-let [node (mf/ref-val ref)]
|
||||
(when visible?
|
||||
(dom/scroll-into-view-if-needed! node)))))
|
||||
(if new-css-system
|
||||
(when visible?
|
||||
[:div {:class (dm/str class " " (stl/css :advanced-options-wrapper))
|
||||
:ref ref}
|
||||
children])
|
||||
|
||||
(when visible?
|
||||
[:div.advanced-options-wrapper {:ref ref}
|
||||
[:div.advanced-options {}
|
||||
children]])))
|
||||
(when visible?
|
||||
[:div.advanced-options-wrapper {:ref ref}
|
||||
[:div.advanced-options {}
|
||||
children]]))))
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.advanced-options-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
}
|
|
@ -5,10 +5,14 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.blur
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input*]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.options.rows.input-row :refer [input-row]]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
|
@ -24,9 +28,26 @@
|
|||
:hidden false}))
|
||||
|
||||
(mf/defc blur-menu [{:keys [ids type values]}]
|
||||
(let [blur (:blur values)
|
||||
has-value? (not (nil? blur))
|
||||
multiple? (= blur :multiple)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
blur (:blur values)
|
||||
has-value? (not (nil? blur))
|
||||
multiple? (= blur :multiple)
|
||||
|
||||
state* (mf/use-state {:show-content true
|
||||
:show-more-options false})
|
||||
|
||||
state (deref state*)
|
||||
|
||||
open? (:show-content state)
|
||||
more-options? (:show-more-options state)
|
||||
|
||||
|
||||
toggle-content
|
||||
(mf/use-fn #(swap! state* update :show-content not))
|
||||
|
||||
toggle-more-options
|
||||
(mf/use-fn #(swap! state* update :show-more-options not))
|
||||
|
||||
|
||||
change!
|
||||
(mf/use-callback
|
||||
|
@ -63,28 +84,74 @@
|
|||
(fn []
|
||||
(change! #(update-in % [:blur :hidden] not))))]
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span
|
||||
(case type
|
||||
:multiple (tr "workspace.options.blur-options.title.multiple")
|
||||
:group (tr "workspace.options.blur-options.title.group")
|
||||
(tr "workspace.options.blur-options.title"))]
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :element-set)}
|
||||
[:div {:class (stl/css :element-title)}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? (not open?)
|
||||
:on-collapsed toggle-content
|
||||
:title (case type
|
||||
:multiple (tr "workspace.options.blur-options.title.multiple")
|
||||
:group (tr "workspace.options.blur-options.title.group")
|
||||
(tr "workspace.options.blur-options.title"))
|
||||
:class (stl/css :title-spacing-blur)}
|
||||
|
||||
[:div.element-set-title-actions
|
||||
(when (and has-value? (not multiple?))
|
||||
[:div.add-page {:on-click handle-toggle-visibility} (if (:hidden blur) i/eye-closed i/eye)])
|
||||
(when-not has-value?
|
||||
[:button {:class (stl/css :add-blur)
|
||||
:on-click handle-add} i/add-refactor])]]
|
||||
|
||||
(if has-value?
|
||||
[:div.add-page {:on-click handle-delete} i/minus]
|
||||
[:div.add-page {:on-click handle-add} i/close])]]
|
||||
(when (and open? has-value?)
|
||||
[:div {:class (stl/css :element-set-content)}
|
||||
[:div {:class (stl/css :first-row)}
|
||||
[:div {:class (stl/css :blur-info)}
|
||||
[:button {:class (stl/css-case :show-more true
|
||||
:selected more-options?)
|
||||
:on-click toggle-more-options}
|
||||
i/menu-refactor]
|
||||
[:span {:class (stl/css :label)}
|
||||
(tr "workspace.options.blur-options.title")]]
|
||||
[:div {:class (stl/css :actions)}
|
||||
[:button {:class (stl/css :action-btn)
|
||||
:on-click handle-toggle-visibility}
|
||||
(if (:hidden blur)
|
||||
i/hide-refactor
|
||||
i/shown-refactor)]
|
||||
[:button {:class (stl/css :action-btn)
|
||||
:on-click handle-delete} i/remove-refactor]]]
|
||||
(when more-options?
|
||||
[:div {:class (stl/css :second-row)}
|
||||
[:span {:class (stl/css :label)}
|
||||
(tr "inspect.attributes.blur.value")]
|
||||
[:> numeric-input*
|
||||
{:className (stl/css :numeric-input)
|
||||
:placeholder "--"
|
||||
:min "0"
|
||||
:on-change handle-change
|
||||
:value (:value blur)}]])])]
|
||||
|
||||
(cond
|
||||
has-value?
|
||||
[:div.element-set-content
|
||||
[:& input-row {:label "Value"
|
||||
:class "pixels"
|
||||
:min "0"
|
||||
:value (:value blur)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:on-change handle-change}]])]))
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span
|
||||
(case type
|
||||
:multiple (tr "workspace.options.blur-options.title.multiple")
|
||||
:group (tr "workspace.options.blur-options.title.group")
|
||||
(tr "workspace.options.blur-options.title"))]
|
||||
|
||||
[:div.element-set-title-actions
|
||||
(when (and has-value? (not multiple?))
|
||||
[:div.add-page {:on-click handle-toggle-visibility} (if (:hidden blur) i/eye-closed i/eye)])
|
||||
|
||||
(if has-value?
|
||||
[:div.add-page {:on-click handle-delete} i/minus]
|
||||
[:div.add-page {:on-click handle-add} i/close])]]
|
||||
|
||||
(cond
|
||||
has-value?
|
||||
[:div.element-set-content
|
||||
[:& input-row {:label "Value"
|
||||
:class "pixels"
|
||||
:min "0"
|
||||
:value (:value blur)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:on-change handle-change}]])])))
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.element-set {
|
||||
.element-title {
|
||||
.add-blur {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-set-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
margin-bottom: $s-4;
|
||||
.first-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
width: 100%;
|
||||
.blur-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-1;
|
||||
flex-grow: 1;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--input-details-color);
|
||||
.show-more {
|
||||
@extend .button-secondary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
border-radius: $br-8 0 0 $br-8;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
&.selected {
|
||||
background-color: var(--button-secondary-background-color-active);
|
||||
color: var(--button-secondary-foreground-color-active);
|
||||
svg {
|
||||
stroke: var(--button-secondary-foreground-color-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
.label {
|
||||
@include tabTitleTipography;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
padding: 0 $s-8;
|
||||
border-radius: 0 $br-8 $br-8 0;
|
||||
background-color: var(--input-background-color);
|
||||
}
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.action-btn {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.second-row {
|
||||
@extend .input-element;
|
||||
gap: $s-4;
|
||||
width: $s-92;
|
||||
padding-left: $s-8;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.color-selection
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
|
@ -12,6 +13,8 @@
|
|||
[app.main.data.workspace.colors :as dc]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
|
@ -151,8 +154,15 @@
|
|||
(mf/defc color-selection-menu
|
||||
{::mf/wrap [#(mf/memo' % (mf/check-props ["shapes"]))]}
|
||||
[{:keys [shapes file-id shared-libs] :as props}]
|
||||
(let [{:keys [ grouped-colors library-colors colors]} (mf/with-memo [shapes file-id shared-libs]
|
||||
(prepare-colors shapes file-id shared-libs))
|
||||
(let [{:keys [grouped-colors library-colors colors]} (mf/with-memo [shapes file-id shared-libs]
|
||||
(prepare-colors shapes file-id shared-libs))
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
|
||||
state* (mf/use-state true)
|
||||
open? (deref state*)
|
||||
|
||||
toggle-content (mf/use-fn #(swap! state* not))
|
||||
|
||||
expand-lib-color (mf/use-state false)
|
||||
expand-color (mf/use-state false)
|
||||
|
||||
|
@ -202,26 +212,72 @@
|
|||
(mf/with-effect [grouped-colors]
|
||||
(reset! grouped-colors* grouped-colors))
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span (tr "workspace.options.selection-color")]]
|
||||
[:div.element-set-content
|
||||
[:div.selected-colors
|
||||
(for [[index color] (d/enumerate (take 3 library-colors))]
|
||||
[:& color-row {:key (dm/str "library-color-" (:color color))
|
||||
:color color
|
||||
:index index
|
||||
:on-detach on-detach
|
||||
:select-only select-only
|
||||
:on-change #(on-change %1 color %2)
|
||||
:on-open on-open
|
||||
:on-close on-close}])
|
||||
(when (and (false? @expand-lib-color) (< 3 (count library-colors)))
|
||||
[:div.expand-colors {:on-click #(reset! expand-lib-color true)}
|
||||
[:span i/actions]
|
||||
[:span.text (tr "workspace.options.more-lib-colors")]])
|
||||
(when @expand-lib-color
|
||||
(for [[index color] (d/enumerate (drop 3 library-colors))]
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :element-set)}
|
||||
[:div {:class (stl/css :element-title)}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? (not open?)
|
||||
:on-collapsed toggle-content
|
||||
:title (tr "workspace.options.selection-color")
|
||||
:class (stl/css :title-spacing-selected-colors)}]]
|
||||
|
||||
(when open?
|
||||
[:div {:class (stl/css :element-content)}
|
||||
[:div {:class (stl/css :selected-color-group)}
|
||||
(for [[index color] (d/enumerate (take 3 library-colors))]
|
||||
[:& color-row {:key (dm/str "library-color-" (:color color))
|
||||
:color color
|
||||
:index index
|
||||
:on-detach on-detach
|
||||
:select-only select-only
|
||||
:on-change #(on-change %1 color %2)
|
||||
:on-open on-open
|
||||
:on-close on-close}])
|
||||
(when (and (false? @expand-lib-color) (< 3 (count library-colors)))
|
||||
[:button {:class (stl/css :more-colors-btn)
|
||||
:on-click #(reset! expand-lib-color true)}
|
||||
(tr "workspace.options.more-lib-colors")])
|
||||
(when @expand-lib-color
|
||||
(for [[index color] (d/enumerate (drop 3 library-colors))]
|
||||
[:& color-row {:key (dm/str "library-color-" (:color color))
|
||||
:color color
|
||||
:index index
|
||||
:on-detach on-detach
|
||||
:select-only select-only
|
||||
:on-change #(on-change %1 color %2)
|
||||
:on-open on-open
|
||||
:on-close on-close}]))]
|
||||
[:div {:class (stl/css :selected-color-group)}
|
||||
(for [[index color] (d/enumerate (take 3 colors))]
|
||||
[:& color-row {:key (dm/str "color-" index)
|
||||
:color color
|
||||
:index index
|
||||
:select-only select-only
|
||||
:on-change #(on-change %1 color %2)
|
||||
:on-open on-open
|
||||
:on-close on-close}])
|
||||
(when (and (false? @expand-color) (< 3 (count colors)))
|
||||
[:button {:class (stl/css :more-colors-btn)
|
||||
:on-click #(reset! expand-color true)}
|
||||
(tr "workspace.options.more-colors")])
|
||||
|
||||
(when @expand-color
|
||||
(for [[index color] (d/enumerate (drop 3 colors))]
|
||||
[:& color-row {:key (dm/str "color-" (:color color))
|
||||
:color color
|
||||
:index index
|
||||
:select-only select-only
|
||||
:on-change #(on-change %1 color %2)
|
||||
:on-open on-open
|
||||
:on-close on-close}]))]])]
|
||||
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span (tr "workspace.options.selection-color")]]
|
||||
[:div.element-set-content
|
||||
[:div.selected-colors
|
||||
(for [[index color] (d/enumerate (take 3 library-colors))]
|
||||
[:& color-row {:key (dm/str "library-color-" (:color color))
|
||||
:color color
|
||||
:index index
|
||||
|
@ -229,27 +285,41 @@
|
|||
:select-only select-only
|
||||
:on-change #(on-change %1 color %2)
|
||||
:on-open on-open
|
||||
:on-close on-close}]))]
|
||||
:on-close on-close}])
|
||||
(when (and (false? @expand-lib-color) (< 3 (count library-colors)))
|
||||
[:div.expand-colors {:on-click #(reset! expand-lib-color true)}
|
||||
[:span i/actions]
|
||||
[:span.text (tr "workspace.options.more-lib-colors")]])
|
||||
(when @expand-lib-color
|
||||
(for [[index color] (d/enumerate (drop 3 library-colors))]
|
||||
[:& color-row {:key (dm/str "library-color-" (:color color))
|
||||
:color color
|
||||
:index index
|
||||
:on-detach on-detach
|
||||
:select-only select-only
|
||||
:on-change #(on-change %1 color %2)
|
||||
:on-open on-open
|
||||
:on-close on-close}]))]
|
||||
|
||||
[:div.selected-colors
|
||||
(for [[index color] (d/enumerate (take 3 colors))]
|
||||
[:& color-row {:key (dm/str "color-" index)
|
||||
:color color
|
||||
:index index
|
||||
:select-only select-only
|
||||
:on-change #(on-change %1 color %2)
|
||||
:on-open on-open
|
||||
:on-close on-close}])
|
||||
(when (and (false? @expand-color) (< 3 (count colors)))
|
||||
[:div.expand-colors {:on-click #(reset! expand-color true)}
|
||||
[:span i/actions]
|
||||
[:span.text (tr "workspace.options.more-colors")]])
|
||||
(when @expand-color
|
||||
(for [[index color] (d/enumerate (drop 3 colors))]
|
||||
[:& color-row {:key (dm/str "color-" (:color color))
|
||||
[:div.selected-colors
|
||||
(for [[index color] (d/enumerate (take 3 colors))]
|
||||
[:& color-row {:key (dm/str "color-" index)
|
||||
:color color
|
||||
:index index
|
||||
:select-only select-only
|
||||
:on-change #(on-change %1 color %2)
|
||||
:on-open on-open
|
||||
:on-close on-close}]))]]]))
|
||||
:on-close on-close}])
|
||||
(when (and (false? @expand-color) (< 3 (count colors)))
|
||||
[:div.expand-colors {:on-click #(reset! expand-color true)}
|
||||
[:span i/actions]
|
||||
[:span.text (tr "workspace.options.more-colors")]])
|
||||
(when @expand-color
|
||||
(for [[index color] (d/enumerate (drop 3 colors))]
|
||||
[:& color-row {:key (dm/str "color-" (:color color))
|
||||
:color color
|
||||
:index index
|
||||
:select-only select-only
|
||||
:on-change #(on-change %1 color %2)
|
||||
:on-open on-open
|
||||
:on-close on-close}]))]]])))
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.element-set {
|
||||
.element-title {
|
||||
.add-fill {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
.selected-color-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
.more-colors-btn {
|
||||
@extend .button-secondary;
|
||||
@include tabTitleTipography;
|
||||
height: $s-32;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.component
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.component :as ctk]
|
||||
|
@ -16,6 +17,8 @@
|
|||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.context-menu :refer [context-menu]]
|
||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
|
@ -143,7 +146,8 @@
|
|||
|
||||
(mf/defc component-menu
|
||||
[{:keys [ids values shape] :as props}]
|
||||
(let [current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
components-v2 (mf/use-ctx ctx/components-v2)
|
||||
|
||||
objects (deref refs/workspace-page-objects)
|
||||
|
@ -151,10 +155,16 @@
|
|||
can-update-main? (or (not components-v2) touched?)
|
||||
|
||||
id (first ids)
|
||||
local (mf/use-state {:menu-open false})
|
||||
state* (mf/use-state {:show-content true
|
||||
:menu-open false})
|
||||
state (deref state*)
|
||||
open? (:show-content state)
|
||||
menu-open? (:menu-open state)
|
||||
|
||||
toggle-content
|
||||
(mf/use-fn #(swap! state* update :show-content not))
|
||||
|
||||
shape-name (:name shape)
|
||||
|
||||
component-id (:component-id values)
|
||||
library-id (:component-file values)
|
||||
show? (some? component-id)
|
||||
|
@ -165,6 +175,7 @@
|
|||
lacks-annotation? (nil? (:annotation values))
|
||||
|
||||
local-component? (= library-id current-file-id)
|
||||
|
||||
workspace-data (deref refs/workspace-data)
|
||||
workspace-libraries (deref refs/workspace-libraries)
|
||||
component (if local-component?
|
||||
|
@ -174,17 +185,16 @@
|
|||
lib-exists? (and (not local-component?)
|
||||
(some? (get workspace-libraries library-id)))
|
||||
|
||||
|
||||
on-menu-click
|
||||
(mf/use-callback
|
||||
(mf/use-fn
|
||||
(fn [event]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(swap! local assoc :menu-open true)))
|
||||
(swap! state* update :menu-open not)))
|
||||
|
||||
on-menu-close
|
||||
(mf/use-callback
|
||||
#(swap! local assoc :menu-open false))
|
||||
#(swap! state* assoc :menu-open false))
|
||||
|
||||
do-detach-component
|
||||
#(st/emit! (dwl/detach-component id))
|
||||
|
@ -217,59 +227,171 @@
|
|||
do-create-annotation #(st/emit! (dw/set-annotations-id-for-create id))
|
||||
do-navigate-component-file #(st/emit! (dwl/nav-to-component-file library-id))]
|
||||
(when show?
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span (tr "workspace.options.component")]
|
||||
[:span (if main-instance?
|
||||
(tr "workspace.options.component.main")
|
||||
(tr "workspace.options.component.copy"))]
|
||||
]
|
||||
[:div.element-set-content
|
||||
[:div.row-flex.component-row
|
||||
(if main-instance?
|
||||
i/component
|
||||
i/component-copy)
|
||||
[:div.component-name shape-name]
|
||||
[:div.row-actions
|
||||
{:on-click on-menu-click}
|
||||
i/actions
|
||||
;; WARNING: this menu is the same as the shape context menu.
|
||||
;; If you change it, you must change equally the file
|
||||
;; app/main/ui/workspace/context_menu.cljs
|
||||
[:& context-menu {:on-close on-menu-close
|
||||
:show (:menu-open @local)
|
||||
:options
|
||||
(if main-component?
|
||||
[[(tr "workspace.shape.menu.show-in-assets") do-show-in-assets]
|
||||
(when (and components-v2 local-component? lacks-annotation?)
|
||||
[(tr "workspace.shape.menu.create-annotation") do-create-annotation])]
|
||||
(if local-component?
|
||||
(if is-dangling?
|
||||
[[(tr "workspace.shape.menu.detach-instance") do-detach-component]
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.reset-overrides") do-reset-component])
|
||||
(when components-v2
|
||||
[(tr "workspace.shape.menu.restore-main") do-restore-component])]
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :element-set)}
|
||||
[:div {:class (stl/css :element-title)}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? (not open?)
|
||||
:on-collapsed toggle-content
|
||||
:title (tr "workspace.options.component")
|
||||
:class (stl/css :title-spacing-component)}]]
|
||||
|
||||
[[(tr "workspace.shape.menu.detach-instance") do-detach-component]
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.reset-overrides") do-reset-component])
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.update-main") do-update-component])
|
||||
[(tr "workspace.shape.menu.show-main") do-show-component]])
|
||||
(when open?
|
||||
[:div {:class (stl/css :element-content)}
|
||||
[:div {:class (stl/css :component-wrapper)}
|
||||
[:div {:class (stl/css :component-name-wrapper)}
|
||||
[:span {:class (stl/css :component-icon)}
|
||||
(if main-instance?
|
||||
i/component-refactor
|
||||
i/copy-refactor)]
|
||||
|
||||
(if is-dangling?
|
||||
[[(tr "workspace.shape.menu.detach-instance") do-detach-component]
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.reset-overrides") do-reset-component])
|
||||
(when (and components-v2 lib-exists?)
|
||||
[(tr "workspace.shape.menu.restore-main") do-restore-component])]
|
||||
[[(tr "workspace.shape.menu.detach-instance") do-detach-component]
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.reset-overrides") do-reset-component])
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.update-main") do-update-remote-component])
|
||||
[(tr "workspace.shape.menu.go-main") do-navigate-component-file]])))}]]]
|
||||
[:div {:class (stl/css :component-name)} shape-name]]
|
||||
|
||||
(when components-v2
|
||||
[:& component-annotation {:id id :values values :shape shape :component component}])]])))
|
||||
[:div {:class (stl/css :component-actions)}
|
||||
[:button {:class (stl/css :menu-btn)
|
||||
:on-click on-menu-click}
|
||||
i/menu-refactor]
|
||||
|
||||
[:& dropdown {:show menu-open?
|
||||
:on-close on-menu-close}
|
||||
[:ul {:class (stl/css :custom-select-dropdown)}
|
||||
(if main-component?
|
||||
[:*
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-show-in-assets}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.show-in-assets")]]
|
||||
(when (and components-v2 local-component? lacks-annotation?)
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-create-annotation}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.create-annotation")]])]
|
||||
|
||||
(if local-component?
|
||||
(if is-dangling?
|
||||
[:*
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-detach-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.detach-instance")]]
|
||||
(when can-update-main?
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-reset-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.reset-overrides")]])
|
||||
(when components-v2
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-restore-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.restore-main")]])]
|
||||
|
||||
[:*
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-detach-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.detach-instance")]]
|
||||
(when can-update-main?
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-reset-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.reset-overrides")]]
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-update-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.update-main")]])
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-show-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.show-main")]]])
|
||||
(if is-dangling?
|
||||
[:*
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-detach-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.detach-instance")]]
|
||||
(when can-update-main?
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-reset-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.reset-overrides")]])
|
||||
|
||||
(when (and components-v2 lib-exists?)
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-restore-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.restore-main")]])]
|
||||
[:*
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-detach-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.detach-instance")]]
|
||||
(when can-update-main?
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-reset-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.reset-overrides")]]
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-update-remote-component}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.update-main")]])
|
||||
[:li {:class (stl/css :dropdown-element)
|
||||
:on-click do-navigate-component-file}
|
||||
[:span {:class (stl/css :dropdown-label)}
|
||||
(tr "workspace.shape.menu.go-main")]]])))]]]]
|
||||
(when components-v2
|
||||
[:& component-annotation {:id id :values values :shape shape :component component}])])]
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span (tr "workspace.options.component")]
|
||||
[:span (if main-instance?
|
||||
(tr "workspace.options.component.main")
|
||||
(tr "workspace.options.component.copy"))]]
|
||||
[:div.element-set-content
|
||||
[:div.row-flex.component-row
|
||||
(if main-instance?
|
||||
i/component
|
||||
i/component-copy)
|
||||
[:div.component-name shape-name]
|
||||
[:div.row-actions
|
||||
{:on-click on-menu-click}
|
||||
i/actions
|
||||
;; WARNING: this menu is the same as the shape context menu.
|
||||
;; If you change it, you must change equally the file
|
||||
;; app/main/ui/workspace/context_menu.cljs
|
||||
[:& context-menu {:on-close on-menu-close
|
||||
:show menu-open?
|
||||
:options (if main-component?
|
||||
[[(tr "workspace.shape.menu.show-in-assets") do-show-in-assets]
|
||||
(when (and components-v2 local-component? lacks-annotation?)
|
||||
[(tr "workspace.shape.menu.create-annotation") do-create-annotation])]
|
||||
(if local-component?
|
||||
(if is-dangling?
|
||||
[[(tr "workspace.shape.menu.detach-instance") do-detach-component]
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.reset-overrides") do-reset-component])
|
||||
(when components-v2
|
||||
[(tr "workspace.shape.menu.restore-main") do-restore-component])]
|
||||
|
||||
[[(tr "workspace.shape.menu.detach-instance") do-detach-component]
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.reset-overrides") do-reset-component])
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.update-main") do-update-component])
|
||||
[(tr "workspace.shape.menu.show-main") do-show-component]])
|
||||
|
||||
(if is-dangling?
|
||||
[[(tr "workspace.shape.menu.detach-instance") do-detach-component]
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.reset-overrides") do-reset-component])
|
||||
(when (and components-v2 lib-exists?)
|
||||
[(tr "workspace.shape.menu.restore-main") do-restore-component])]
|
||||
[[(tr "workspace.shape.menu.detach-instance") do-detach-component]
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.reset-overrides") do-reset-component])
|
||||
(when can-update-main?
|
||||
[(tr "workspace.shape.menu.update-main") do-update-remote-component])
|
||||
[(tr "workspace.shape.menu.go-main") do-navigate-component-file]])))}]]]
|
||||
|
||||
(when components-v2
|
||||
[:& component-annotation {:id id :values values :shape shape :component component}])]]))))
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
.element-set {
|
||||
.element-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
.component-wrapper {
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
.component-name-wrapper {
|
||||
@extend .asset-element;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
flex-grow: 1;
|
||||
.component-icon {
|
||||
@include flexCenter;
|
||||
height: $s-24;
|
||||
width: $s-24;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
}
|
||||
.component-name {
|
||||
@include titleTipography;
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
.component-actions {
|
||||
position: relative;
|
||||
|
||||
.menu-btn {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
.custom-select-dropdown {
|
||||
@extend .dropdown-wrapper;
|
||||
right: 0;
|
||||
left: unset;
|
||||
width: $s-252;
|
||||
.dropdown-element {
|
||||
@extend .dropdown-element-base;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.constraints
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.rect :as grc]
|
||||
|
@ -13,6 +14,9 @@
|
|||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.select :refer [select]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
|
@ -27,8 +31,15 @@
|
|||
|
||||
(mf/defc constraints-menu
|
||||
[{:keys [ids values] :as props}]
|
||||
(let [old-shapes (deref (refs/objects-by-id ids))
|
||||
frames (map #(deref (refs/object-by-id (:frame-id %))) old-shapes)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
|
||||
state* (mf/use-state true)
|
||||
open? (deref state*)
|
||||
|
||||
toggle-content (mf/use-fn #(swap! state* not))
|
||||
|
||||
old-shapes (deref (refs/objects-by-id ids))
|
||||
frames (map #(deref (refs/object-by-id (:frame-id %))) old-shapes)
|
||||
|
||||
shapes (as-> old-shapes $
|
||||
(map gsh/translate-to-frame $ frames))
|
||||
|
@ -53,127 +64,261 @@
|
|||
constraints-h (or (get values :constraints-h) (gsh/default-constraints-h values))
|
||||
constraints-v (or (get values :constraints-v) (gsh/default-constraints-v values))
|
||||
|
||||
on-constraint-button-clicked
|
||||
(mf/use-callback
|
||||
(mf/deps [ids values])
|
||||
(fn [button]
|
||||
(fn [_]
|
||||
(let [constraints-h (get values :constraints-h :scale)
|
||||
constraints-v (get values :constraints-v :scale)
|
||||
|
||||
[constraint new-value]
|
||||
(case button
|
||||
:top (case constraints-v
|
||||
:top [:constraints-v :scale]
|
||||
:topbottom [:constraints-v :bottom]
|
||||
:bottom [:constraints-v :topbottom]
|
||||
[:constraints-v :top])
|
||||
:bottom (case constraints-v
|
||||
:bottom [:constraints-v :scale]
|
||||
:topbottom [:constraints-v :top]
|
||||
:top [:constraints-v :topbottom]
|
||||
[:constraints-v :bottom])
|
||||
:left (case constraints-h
|
||||
:left [:constraints-h :scale]
|
||||
:leftright [:constraints-h :right]
|
||||
:right [:constraints-h :leftright]
|
||||
[:constraints-h :left])
|
||||
:right (case constraints-h
|
||||
:right [:constraints-h :scale]
|
||||
:leftright [:constraints-h :left]
|
||||
:left [:constraints-h :leftright]
|
||||
[:constraints-h :right])
|
||||
:centerv (case constraints-v
|
||||
:center [:constraints-v :scale]
|
||||
[:constraints-v :center])
|
||||
:centerh (case constraints-h
|
||||
:center [:constraints-h :scale]
|
||||
[:constraints-h :center]))]
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(assoc % constraint new-value)))))))
|
||||
on-constraint-button-clicked
|
||||
(mf/use-fn
|
||||
(mf/deps ids values)
|
||||
(fn [event]
|
||||
(let [button (-> (dom/get-current-target event)
|
||||
(dom/get-data "value")
|
||||
(keyword))
|
||||
constraints-h (get values :constraints-h :scale)
|
||||
constraints-v (get values :constraints-v :scale)
|
||||
|
||||
[constraint new-value]
|
||||
(case button
|
||||
:top (case constraints-v
|
||||
:top [:constraints-v :scale]
|
||||
:topbottom [:constraints-v :bottom]
|
||||
:bottom [:constraints-v :topbottom]
|
||||
[:constraints-v :top])
|
||||
:bottom (case constraints-v
|
||||
:bottom [:constraints-v :scale]
|
||||
:topbottom [:constraints-v :top]
|
||||
:top [:constraints-v :topbottom]
|
||||
[:constraints-v :bottom])
|
||||
:left (case constraints-h
|
||||
:left [:constraints-h :scale]
|
||||
:leftright [:constraints-h :right]
|
||||
:right [:constraints-h :leftright]
|
||||
[:constraints-h :left])
|
||||
:right (case constraints-h
|
||||
:right [:constraints-h :scale]
|
||||
:leftright [:constraints-h :left]
|
||||
:left [:constraints-h :leftright]
|
||||
[:constraints-h :right])
|
||||
:centerv (case constraints-v
|
||||
:center [:constraints-v :scale]
|
||||
[:constraints-v :center])
|
||||
:centerh (case constraints-h
|
||||
:center [:constraints-h :scale]
|
||||
[:constraints-h :center])
|
||||
nil ())]
|
||||
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(assoc % constraint new-value))))))
|
||||
|
||||
on-constraint-select-changed
|
||||
(mf/use-callback
|
||||
(mf/deps [ids values])
|
||||
(fn [constraint]
|
||||
(fn [event]
|
||||
(let [value (-> (dom/get-target-val event) (keyword))]
|
||||
(when-not (str/empty? value)
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(assoc % constraint value))))))))
|
||||
(mf/use-fn
|
||||
(mf/deps ids)
|
||||
(fn [event]
|
||||
(let [constraint (-> (dom/get-current-target event)
|
||||
(dom/get-data "value")
|
||||
(keyword))
|
||||
value (-> (dom/get-target-val event) (keyword))]
|
||||
(when-not (str/empty? value)
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(assoc % constraint value)))))))
|
||||
|
||||
on-constraint-h-select-changed
|
||||
(mf/use-fn
|
||||
(mf/deps ids)
|
||||
(fn [value]
|
||||
(when-not (str/empty? value)
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(assoc % :constraints-h (keyword value)))))))
|
||||
|
||||
on-constraint-v-select-changed
|
||||
(mf/use-fn
|
||||
(mf/deps ids)
|
||||
(fn [value]
|
||||
(when-not (str/empty? value)
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(assoc % :constraints-v (keyword value)))))))
|
||||
|
||||
on-fixed-scroll-clicked
|
||||
(mf/use-callback
|
||||
(mf/deps [ids values])
|
||||
(mf/use-fn
|
||||
(mf/deps ids)
|
||||
(fn [_]
|
||||
(st/emit! (dch/update-shapes ids #(update % :fixed-scroll not)))))]
|
||||
(st/emit! (dch/update-shapes ids #(update % :fixed-scroll not)))))
|
||||
|
||||
;; CONSTRAINTS
|
||||
(when in-frame?
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span (tr "workspace.options.constraints")]]
|
||||
options-h
|
||||
(mf/with-memo [constraints-h]
|
||||
(d/concat-vec
|
||||
(when (= constraints-h :multiple)
|
||||
[{:value "" :label (tr "settings.multiple")}])
|
||||
[{:value "left" :label (tr "workspace.options.constraints.left")}
|
||||
{:value "right" :label (tr "workspace.options.constraints.right")}
|
||||
{:value "leftright" :label (tr "workspace.options.constraints.leftright")}
|
||||
{:value "center" :label (tr "workspace.options.constraints.center")}
|
||||
{:value "scale" :label (tr "workspace.options.constraints.scale")}]))
|
||||
|
||||
[:div.element-set-content
|
||||
[:div.row-flex.align-top
|
||||
options-v
|
||||
(mf/with-memo [constraints-v]
|
||||
(d/concat-vec
|
||||
(when (= constraints-v :multiple)
|
||||
[{:value "" :label (tr "settings.multiple")}])
|
||||
[{:value "top" :label (tr "workspace.options.constraints.top")}
|
||||
{:value "bottom" :label (tr "workspace.options.constraints.bottom")}
|
||||
{:value "topbottom" :label (tr "workspace.options.constraints.topbottom")}
|
||||
{:value "center" :label (tr "workspace.options.constraints.center")}
|
||||
{:value "scale" :label (tr "workspace.options.constraints.scale")}]))]
|
||||
|
||||
[:div.constraints-widget
|
||||
[:div.constraints-box]
|
||||
[:div.constraint-button.top
|
||||
{:class (dom/classnames :active (or (= constraints-v :top)
|
||||
(= constraints-v :topbottom)))
|
||||
:on-click (on-constraint-button-clicked :top)}]
|
||||
[:div.constraint-button.bottom
|
||||
{:class (dom/classnames :active (or (= constraints-v :bottom)
|
||||
(= constraints-v :topbottom)))
|
||||
:on-click (on-constraint-button-clicked :bottom)}]
|
||||
[:div.constraint-button.left
|
||||
{:class (dom/classnames :active (or (= constraints-h :left)
|
||||
(= constraints-h :leftright)))
|
||||
:on-click (on-constraint-button-clicked :left)}]
|
||||
[:div.constraint-button.right
|
||||
{:class (dom/classnames :active (or (= constraints-h :right)
|
||||
(= constraints-h :leftright)))
|
||||
:on-click (on-constraint-button-clicked :right)}]
|
||||
[:div.constraint-button.centerv
|
||||
{:class (dom/classnames :active (= constraints-v :center))
|
||||
:on-click (on-constraint-button-clicked :centerv)}]
|
||||
[:div.constraint-button.centerh
|
||||
{:class (dom/classnames :active (= constraints-h :center))
|
||||
:on-click (on-constraint-button-clicked :centerh)}]]
|
||||
|
||||
[:div.constraints-form
|
||||
[:div.row-flex
|
||||
[:span.left-right i/full-screen]
|
||||
[:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:on-change (on-constraint-select-changed :constraints-h)
|
||||
:value (d/name constraints-h "scale")}
|
||||
(when (= constraints-h :multiple)
|
||||
[:option {:value ""} (tr "settings.multiple")])
|
||||
[:option {:value "left"} (tr "workspace.options.constraints.left")]
|
||||
[:option {:value "right"} (tr "workspace.options.constraints.right")]
|
||||
[:option {:value "leftright"} (tr "workspace.options.constraints.leftright")]
|
||||
[:option {:value "center"} (tr "workspace.options.constraints.center")]
|
||||
[:option {:value "scale"} (tr "workspace.options.constraints.scale")]]]
|
||||
[:div.row-flex
|
||||
[:span.top-bottom i/full-screen]
|
||||
[:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:on-change (on-constraint-select-changed :constraints-v)
|
||||
:value (d/name constraints-v "scale")}
|
||||
(when (= constraints-v :multiple)
|
||||
[:option {:value ""} (tr "settings.multiple")])
|
||||
[:option {:value "top"} (tr "workspace.options.constraints.top")]
|
||||
[:option {:value "bottom"} (tr "workspace.options.constraints.bottom")]
|
||||
[:option {:value "topbottom"} (tr "workspace.options.constraints.topbottom")]
|
||||
[:option {:value "center"} (tr "workspace.options.constraints.center")]
|
||||
[:option {:value "scale"} (tr "workspace.options.constraints.scale")]]]
|
||||
(when first-level?
|
||||
[:div.row-flex
|
||||
[:div.fix-when {:class (dom/classnames :active (:fixed-scroll values))
|
||||
:on-click on-fixed-scroll-clicked}
|
||||
(if (:fixed-scroll values)
|
||||
i/pin-fill
|
||||
i/pin)
|
||||
[:span (tr "workspace.options.constraints.fix-when-scrolling")]]])]]]])))
|
||||
;; CONSTRAINTS
|
||||
(when in-frame?
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :element-set)}
|
||||
[:div {:class (stl/css :element-title)}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? (not open?)
|
||||
:on-collapsed toggle-content
|
||||
:title (tr "workspace.options.constraints")}]]
|
||||
(when open?
|
||||
[:div {:class (stl/css :element-set-content)}
|
||||
[:div {:class (stl/css :constraints-widget)}
|
||||
[:div {:class (stl/css :constraints-top)}
|
||||
[:button {:class (stl/css-case :constraint-btn true
|
||||
:active (or (= constraints-v :top)
|
||||
(= constraints-v :topbottom)))
|
||||
:data-value :top
|
||||
:on-click on-constraint-button-clicked}
|
||||
[:span {:class (stl/css :resalted-area)}]]]
|
||||
[:div {:class (stl/css :constraints-left)}
|
||||
[:button {:class (stl/css-case :constraint-btn true
|
||||
:constraint-btn-rotated true
|
||||
:active (or (= constraints-h :left)
|
||||
(= constraints-h :leftright)))
|
||||
:data-value :left
|
||||
:on-click on-constraint-button-clicked}
|
||||
[:span {:class (stl/css :resalted-area)}]]]
|
||||
[:div {:class (stl/css :constraints-center)}
|
||||
[:button {:class (stl/css-case :constraint-btn true
|
||||
:active (= constraints-h :center))
|
||||
:data-value :centerh
|
||||
:on-click on-constraint-button-clicked}
|
||||
[:span {:class (stl/css :resalted-area)}]]
|
||||
[:button {:class (stl/css-case :constraint-btn-special true
|
||||
:constraint-btn-rotated true
|
||||
:active (= constraints-v :center))
|
||||
:data-value :centerv
|
||||
:on-click on-constraint-button-clicked}
|
||||
[:span {:class (stl/css :resalted-area)}]]]
|
||||
[:div {:class (stl/css :constraints-right)}
|
||||
[:button {:class (stl/css-case :constraint-btn true
|
||||
:constraint-btn-rotated true
|
||||
:active (or (= constraints-h :right)
|
||||
(= constraints-h :leftright)))
|
||||
:data-value :right
|
||||
:on-click on-constraint-button-clicked}
|
||||
[:span {:class (stl/css :resalted-area)}]]]
|
||||
[:div {:class (stl/css :constraints-bottom)}
|
||||
[:button {:class (stl/css-case :constraint-btn true
|
||||
:active (or (= constraints-v :bottom)
|
||||
(= constraints-v :topbottom)))
|
||||
:data-value :bottom
|
||||
:on-click on-constraint-button-clicked}
|
||||
[:span {:class (stl/css :resalted-area)}]]]]
|
||||
[:div {:class (stl/css :contraints-selects)}
|
||||
[:div {:class (stl/css :horizontal-select)}
|
||||
[:& select
|
||||
{:default-value (d/name constraints-h "scale")
|
||||
:options options-h
|
||||
:on-change on-constraint-h-select-changed}]]
|
||||
[:div {:class (stl/css :vertical-select)}
|
||||
[:& select
|
||||
{:default-value (d/name constraints-v "scale")
|
||||
:options options-v
|
||||
:on-change on-constraint-v-select-changed}]]
|
||||
(when first-level?
|
||||
[:div {:class (stl/css :checkbox)}
|
||||
|
||||
[:label {:for "fixed-on-scroll"
|
||||
:class (stl/css-case :checked (:fixed-scroll values))}
|
||||
[:span {:class (stl/css-case :check-mark true
|
||||
:checked (:fixed-scroll values))}
|
||||
(when (:fixed-scroll values)
|
||||
i/status-tick-refactor)]
|
||||
(tr "workspace.options.constraints.fix-when-scrolling")
|
||||
[:input {:type "checkbox"
|
||||
:id "fixed-on-scroll"
|
||||
:checked (:fixed-scroll values)
|
||||
:on-change on-fixed-scroll-clicked}]]])]])]
|
||||
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span (tr "workspace.options.constraints")]]
|
||||
|
||||
[:div.element-set-content
|
||||
[:div.row-flex.align-top
|
||||
[:div.constraints-widget
|
||||
[:div.constraints-box]
|
||||
[:div.constraint-button.top
|
||||
{:class (dom/classnames :active (or (= constraints-v :top)
|
||||
(= constraints-v :topbottom)))
|
||||
:data-value :top
|
||||
:on-click on-constraint-button-clicked}]
|
||||
[:div.constraint-button.bottom
|
||||
{:class (dom/classnames :active (or (= constraints-v :bottom)
|
||||
(= constraints-v :topbottom)))
|
||||
:data-value :bottom
|
||||
:on-click on-constraint-button-clicked}]
|
||||
[:div.constraint-button.left
|
||||
{:class (dom/classnames :active (or (= constraints-h :left)
|
||||
(= constraints-h :leftright)))
|
||||
:data-value :left
|
||||
:on-click on-constraint-button-clicked}]
|
||||
[:div.constraint-button.right
|
||||
{:class (dom/classnames :active (or (= constraints-h :right)
|
||||
(= constraints-h :leftright)))
|
||||
:data-value :right
|
||||
:on-click on-constraint-button-clicked}]
|
||||
[:div.constraint-button.centerv
|
||||
{:class (dom/classnames :active (= constraints-v :center))
|
||||
:data-value :centerv
|
||||
:on-click on-constraint-button-clicked}]
|
||||
[:div.constraint-button.centerh
|
||||
{:class (dom/classnames :active (= constraints-h :center))
|
||||
:data-value :centerh
|
||||
:on-click on-constraint-button-clicked}]]
|
||||
|
||||
[:div.constraints-form
|
||||
[:div.row-flex
|
||||
[:span.left-right i/full-screen]
|
||||
[:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:data-value :constraints-h
|
||||
:on-change on-constraint-select-changed
|
||||
:value (d/name constraints-h "scale")}
|
||||
(when (= constraints-h :multiple)
|
||||
[:option {:value ""} (tr "settings.multiple")])
|
||||
[:option {:value "left"} (tr "workspace.options.constraints.left")]
|
||||
[:option {:value "right"} (tr "workspace.options.constraints.right")]
|
||||
[:option {:value "leftright"} (tr "workspace.options.constraints.leftright")]
|
||||
[:option {:value "center"} (tr "workspace.options.constraints.center")]
|
||||
[:option {:value "scale"} (tr "workspace.options.constraints.scale")]]]
|
||||
[:div.row-flex
|
||||
[:span.top-bottom i/full-screen]
|
||||
[:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:data-value :constraints-v
|
||||
:on-change on-constraint-select-changed
|
||||
:value (d/name constraints-v "scale")}
|
||||
(when (= constraints-v :multiple)
|
||||
[:option {:value ""} (tr "settings.multiple")])
|
||||
[:option {:value "top"} (tr "workspace.options.constraints.top")]
|
||||
[:option {:value "bottom"} (tr "workspace.options.constraints.bottom")]
|
||||
[:option {:value "topbottom"} (tr "workspace.options.constraints.topbottom")]
|
||||
[:option {:value "center"} (tr "workspace.options.constraints.center")]
|
||||
[:option {:value "scale"} (tr "workspace.options.constraints.scale")]]]
|
||||
(when first-level?
|
||||
[:div.row-flex
|
||||
[:div.fix-when {:class (dom/classnames :active (:fixed-scroll values))
|
||||
:on-click on-fixed-scroll-clicked}
|
||||
(if (:fixed-scroll values)
|
||||
i/pin-fill
|
||||
i/pin)
|
||||
[:span (tr "workspace.options.constraints.fix-when-scrolling")]]])]]]]))))
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.element-set {
|
||||
.element-set-content {
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
.constraints-widget {
|
||||
background-color: var(--constraint-widget-background-color);
|
||||
display: grid;
|
||||
grid-template-columns: $s-24 $s-72 $s-24;
|
||||
grid-template-rows: $s-24 $s-72 $s-24;
|
||||
grid-template-areas:
|
||||
"top top top"
|
||||
"left center right"
|
||||
"bottom bottom bottom";
|
||||
height: $s-120;
|
||||
width: $s-120;
|
||||
border-radius: $br-8;
|
||||
.constraints-top,
|
||||
.constraints-left,
|
||||
.constraints-center,
|
||||
.constraints-right,
|
||||
.constraints-bottom {
|
||||
@include flexCenter;
|
||||
grid-area: top;
|
||||
.constraint-btn,
|
||||
.constraint-btn-special,
|
||||
.constraint-btn-rotated {
|
||||
@include buttonStyle;
|
||||
@include flexCenter;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.resalted-area {
|
||||
width: $s-40;
|
||||
height: $s-4;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--button-constraint-background-color-rest);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
&.active .resalted-area {
|
||||
outline: $s-4 solid var(--button-constraint-border-color-hover);
|
||||
background-color: var(--button-constraint-background-color-hover);
|
||||
}
|
||||
&:hover .resalted-area,
|
||||
&:focus .resalted-area {
|
||||
outline: $s-4 solid var(--button-constraint-border-color-hover);
|
||||
background-color: var(--button-constraint-background-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
.constraints-left {
|
||||
grid-area: left;
|
||||
.constraint-btn-rotated {
|
||||
height: $s-72;
|
||||
width: $s-24;
|
||||
.resalted-area {
|
||||
height: $s-40;
|
||||
width: $s-4;
|
||||
}
|
||||
}
|
||||
}
|
||||
.constraints-center {
|
||||
grid-area: center;
|
||||
position: relative;
|
||||
background-color: var(--constraint-center-area-background-color);
|
||||
border-radius: $br-8;
|
||||
.constraint-btn {
|
||||
width: $s-72;
|
||||
height: $s-24;
|
||||
.resalted-area {
|
||||
width: $s-40;
|
||||
height: $s-4;
|
||||
}
|
||||
}
|
||||
.constraint-btn-special {
|
||||
position: absolute;
|
||||
height: $s-72;
|
||||
width: $s-24;
|
||||
.resalted-area {
|
||||
height: $s-40;
|
||||
width: $s-4;
|
||||
}
|
||||
}
|
||||
}
|
||||
.constraints-right {
|
||||
grid-area: right;
|
||||
.constraint-btn-rotated {
|
||||
height: $s-72;
|
||||
width: $s-24;
|
||||
.resalted-area {
|
||||
height: $s-40;
|
||||
width: $s-4;
|
||||
}
|
||||
}
|
||||
}
|
||||
.constraints-bottom {
|
||||
grid-area: bottom;
|
||||
}
|
||||
}
|
||||
.contraints-selects {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
|
||||
.horizontal-select,
|
||||
.vertical-select {
|
||||
width: $s-124;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: $s-8;
|
||||
margin-top: $s-8;
|
||||
padding-left: 0;
|
||||
input {
|
||||
margin: 0;
|
||||
}
|
||||
label {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-2;
|
||||
cursor: pointer;
|
||||
.check-mark {
|
||||
@include flexCenter;
|
||||
width: $s-16;
|
||||
height: $s-16;
|
||||
border-radius: $br-6;
|
||||
background-color: var(--input-background-color);
|
||||
&.checked {
|
||||
background-color: var(--input-border-color-active);
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--input-details-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.exports
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.main.data.exports :as de]
|
||||
|
@ -12,6 +13,9 @@
|
|||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.select :refer [select]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.export]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.util.dom :as dom]
|
||||
|
@ -26,7 +30,13 @@
|
|||
(mf/defc exports-menu
|
||||
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type" "page-id" "file-id"]))]}
|
||||
[{:keys [ids type values page-id file-id] :as props}]
|
||||
(let [exports (:exports values [])
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
exports (:exports values [])
|
||||
|
||||
comp-state* (mf/use-state true)
|
||||
open? (deref comp-state*)
|
||||
|
||||
toggle-content (mf/use-fn #(swap! comp-state* not))
|
||||
|
||||
state (mf/deref refs/export)
|
||||
in-progress? (:in-progress state)
|
||||
|
@ -107,19 +117,23 @@
|
|||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [index event]
|
||||
(let [target (dom/get-target event)
|
||||
value (dom/get-value target)
|
||||
value (d/parse-double value)]
|
||||
(let [scale (if new-css-system
|
||||
(d/parse-double event)
|
||||
(-> event
|
||||
(dom/get-target-val)
|
||||
(d/parse-double)))]
|
||||
(st/emit! (dch/update-shapes ids
|
||||
(fn [shape]
|
||||
(assoc-in shape [:exports index :scale] value)))))))
|
||||
(assoc-in shape [:exports index :scale] scale)))))))
|
||||
|
||||
on-suffix-change
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [index event]
|
||||
(let [target (dom/get-target event)
|
||||
value (dom/get-value target)]
|
||||
(fn [event]
|
||||
(let [value (dom/get-target-val event)
|
||||
index (-> (dom/get-current-target event)
|
||||
(dom/get-data "value")
|
||||
(int))]
|
||||
(st/emit! (dch/update-shapes ids
|
||||
(fn [shape]
|
||||
(assoc-in shape [:exports index :suffix] value)))))))
|
||||
|
@ -128,12 +142,14 @@
|
|||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [index event]
|
||||
(let [target (dom/get-target event)
|
||||
value (dom/get-value target)
|
||||
value (keyword value)]
|
||||
(let [type (if new-css-system
|
||||
(keyword event)
|
||||
(-> event
|
||||
(dom/get-target-val)
|
||||
(keyword)))]
|
||||
(st/emit! (dch/update-shapes ids
|
||||
(fn [shape]
|
||||
(assoc-in shape [:exports index :type] value)))))))
|
||||
(assoc-in shape [:exports index :type] type)))))))
|
||||
|
||||
on-remove-all
|
||||
(mf/use-callback
|
||||
|
@ -147,58 +163,135 @@
|
|||
(fn [event]
|
||||
(let [esc? (kbd/esc? event)]
|
||||
(when esc?
|
||||
(dom/blur! (dom/get-target event))))))]
|
||||
(dom/blur! (dom/get-target event))))))
|
||||
|
||||
[:div.element-set.exports-options
|
||||
[:div.element-set-title
|
||||
[:span (tr (if (> (count ids) 1) "workspace.options.export-multiple" "workspace.options.export"))]
|
||||
(when (not (= :multiple exports))
|
||||
[:div.add-page {:on-click add-export} i/close])]
|
||||
size-options [{:value "0.5" :label "0.5x"}
|
||||
{:value "0.75" :label "0.75x"}
|
||||
{:value "1" :label "1x"}
|
||||
{:value "1.5" :label "1.5x"}
|
||||
{:value "2" :label "2x"}
|
||||
{:value "4" :label "4x"}
|
||||
{:value "6" :label "6"}]
|
||||
|
||||
(cond
|
||||
(= :multiple exports)
|
||||
[:div.element-set-options-group
|
||||
[:div.element-set-label (tr "settings.multiple")]
|
||||
[:div.element-set-actions
|
||||
[:div.element-set-actions-button {:on-click on-remove-all}
|
||||
i/minus]]]
|
||||
format-options [{:value "png" :label "PNG"}
|
||||
{:value "jpeg" :label "JPE"}
|
||||
{:value "svg" :label "SVG"}
|
||||
{:value "pdf" :label "PDF"}]]
|
||||
|
||||
(seq exports)
|
||||
[:div.element-set-content
|
||||
(for [[index export] (d/enumerate exports)]
|
||||
[:div.element-set-options-group
|
||||
{:key index}
|
||||
(when (scale-enabled? export)
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :element-set)}
|
||||
[:div {:class (stl/css :element-title)}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? (not open?)
|
||||
:on-collapsed toggle-content
|
||||
:title (tr (if (> (count ids) 1) "workspace.options.export-multiple" "workspace.options.export"))
|
||||
:class (stl/css :title-spacing-export)}
|
||||
[:button {:class (stl/css :add-export)
|
||||
:on-click add-export} i/add-refactor]]]
|
||||
(when open?
|
||||
[:div {:class (stl/css :element-set-content)}
|
||||
|
||||
(cond
|
||||
(= :multiple exports)
|
||||
[:div {:class (stl/css :multiple-exports)}
|
||||
[:div {:class (stl/css :label)} (tr "settings.multiple")]
|
||||
[:div {:class (stl/css :actions)}
|
||||
[:button {:class (stl/css :action-btn)
|
||||
:on-click on-remove-all}
|
||||
i/remove-refactor]]]
|
||||
|
||||
(seq exports)
|
||||
[:*
|
||||
(for [[index export] (d/enumerate exports)]
|
||||
[:div {:class (stl/css :element-group)
|
||||
:key index}
|
||||
[:div {:class (stl/css :input-wrapper)}
|
||||
[:div {:class (stl/css :format-select)}
|
||||
[:& select
|
||||
{:default-value (d/name (:type export))
|
||||
:options format-options
|
||||
:on-change (partial on-type-change index)}]]
|
||||
(when (scale-enabled? export)
|
||||
[:div {:class (stl/css :size-select)}
|
||||
[:& select
|
||||
{:default-value (str (:scale export))
|
||||
:options size-options
|
||||
:on-change (partial on-scale-change index)}]])
|
||||
[:div {:class (stl/css :suffix-input)}
|
||||
[:input {:class (stl/css :type-input)
|
||||
:value (:suffix export)
|
||||
:placeholder (tr "workspace.options.export.suffix")
|
||||
:data-value index
|
||||
:on-change on-suffix-change
|
||||
:on-key-down manage-key-down}]]]
|
||||
|
||||
[:button {:class (stl/css :action-btn)
|
||||
:on-click (partial delete-export index)}
|
||||
i/remove-refactor]])])
|
||||
|
||||
(when (or (= :multiple exports) (seq exports))
|
||||
[:button
|
||||
{:on-click (when-not in-progress? on-download)
|
||||
:class (stl/css-case
|
||||
:export-btn true
|
||||
:btn-disabled in-progress?)
|
||||
:disabled in-progress?}
|
||||
(if in-progress?
|
||||
(tr "workspace.options.exporting-object")
|
||||
(tr "workspace.options.export-object" (c (count shapes-with-exports))))])])]
|
||||
|
||||
|
||||
[:div.element-set.exports-options
|
||||
[:div.element-set-title
|
||||
[:span (tr (if (> (count ids) 1) "workspace.options.export-multiple" "workspace.options.export"))]
|
||||
(when (not (= :multiple exports))
|
||||
[:div.add-page {:on-click add-export} i/close])]
|
||||
|
||||
(cond
|
||||
(= :multiple exports)
|
||||
[:div.element-set-options-group
|
||||
[:div.element-set-label (tr "settings.multiple")]
|
||||
[:div.element-set-actions
|
||||
[:div.element-set-actions-button {:on-click on-remove-all}
|
||||
i/minus]]]
|
||||
|
||||
(seq exports)
|
||||
[:div.element-set-content
|
||||
(for [[index export] (d/enumerate exports)]
|
||||
[:div.element-set-options-group
|
||||
{:key index}
|
||||
(when (scale-enabled? export)
|
||||
[:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:on-change (partial on-scale-change index)
|
||||
:value (:scale export)}
|
||||
[:option {:value "0.5"} "0.5x"]
|
||||
[:option {:value "0.75"} "0.75x"]
|
||||
[:option {:value "1"} "1x"]
|
||||
[:option {:value "1.5"} "1.5x"]
|
||||
[:option {:value "2"} "2x"]
|
||||
[:option {:value "4"} "4x"]
|
||||
[:option {:value "6"} "6x"]])
|
||||
[:input.input-text {:value (:suffix export)
|
||||
:placeholder (tr "workspace.options.export.suffix")
|
||||
:data-value index
|
||||
:on-change on-suffix-change
|
||||
:on-key-down manage-key-down}]
|
||||
[:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:on-change (partial on-scale-change index)
|
||||
:value (:scale export)}
|
||||
[:option {:value "0.5"} "0.5x"]
|
||||
[:option {:value "0.75"} "0.75x"]
|
||||
[:option {:value "1"} "1x"]
|
||||
[:option {:value "1.5"} "1.5x"]
|
||||
[:option {:value "2"} "2x"]
|
||||
[:option {:value "4"} "4x"]
|
||||
[:option {:value "6"} "6x"]])
|
||||
[:input.input-text {:value (:suffix export)
|
||||
:placeholder (tr "workspace.options.export.suffix")
|
||||
:on-change (partial on-suffix-change index)
|
||||
:on-key-down manage-key-down}]
|
||||
[:select.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:value (d/name (:type export))
|
||||
:on-change (partial on-type-change index)}
|
||||
[:option {:value "png"} "PNG"]
|
||||
[:option {:value "jpeg"} "JPEG"]
|
||||
[:option {:value "svg"} "SVG"]
|
||||
[:option {:value "pdf"} "PDF"]]
|
||||
[:div.delete-icon {:on-click (partial delete-export index)}
|
||||
i/minus]])])
|
||||
:value (d/name (:type export))
|
||||
:on-change (partial on-type-change index)}
|
||||
[:option {:value "png"} "PNG"]
|
||||
[:option {:value "jpeg"} "JPEG"]
|
||||
[:option {:value "svg"} "SVG"]
|
||||
[:option {:value "pdf"} "PDF"]]
|
||||
[:div.delete-icon {:on-click (partial delete-export index)}
|
||||
i/minus]])])
|
||||
|
||||
(when (or (= :multiple exports) (seq exports))
|
||||
[:div.btn-icon-dark.download-button
|
||||
{:on-click (when-not in-progress? on-download)
|
||||
:class (dom/classnames
|
||||
:btn-disabled in-progress?)
|
||||
:disabled in-progress?}
|
||||
(if in-progress?
|
||||
(tr "workspace.options.exporting-object")
|
||||
(tr "workspace.options.export-object" (c (count shapes-with-exports))))])]))
|
||||
(when (or (= :multiple exports) (seq exports))
|
||||
[:div.btn-icon-dark.download-button
|
||||
{:on-click (when-not in-progress? on-download)
|
||||
:class (dom/classnames
|
||||
:btn-disabled in-progress?)
|
||||
:disabled in-progress?}
|
||||
(if in-progress?
|
||||
(tr "workspace.options.exporting-object")
|
||||
(tr "workspace.options.export-object" (c (count shapes-with-exports))))])])))
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.element-set {
|
||||
.element-title {
|
||||
.add-export {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-set-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
margin-bottom: $s-4;
|
||||
.multiple-exports {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.label {
|
||||
@extend .mixed-bar;
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.action-btn {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.input-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.format-select {
|
||||
width: $s-60;
|
||||
padding: 0;
|
||||
}
|
||||
.size-select {
|
||||
width: $s-60;
|
||||
padding: 0;
|
||||
}
|
||||
.suffix-input {
|
||||
@extend .input-element;
|
||||
min-width: $s-92;
|
||||
padding: 0 $s-8;
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
.action-btn {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
.export-btn {
|
||||
@extend .button-secondary;
|
||||
@include tabTitleTipography;
|
||||
height: $s-32;
|
||||
width: $s-252;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,12 +5,15 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.fill
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.colors :as clr]
|
||||
[app.common.data :as d]
|
||||
[app.common.types.shape.attrs :refer [default-color]]
|
||||
[app.main.data.workspace.colors :as dc]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.hooks :as h]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
|
||||
|
@ -41,11 +44,17 @@
|
|||
(mf/defc fill-menu
|
||||
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values"]))]}
|
||||
[{:keys [ids type values disable-remove?] :as props}]
|
||||
(let [label (case type
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
label (case type
|
||||
:multiple (tr "workspace.options.selection-fill")
|
||||
:group (tr "workspace.options.group-fill")
|
||||
(tr "workspace.options.fill"))
|
||||
|
||||
state* (mf/use-state true)
|
||||
open? (deref state*)
|
||||
|
||||
toggle-content (mf/use-fn #(swap! state* not))
|
||||
|
||||
;; Excluding nil values
|
||||
values (d/without-nils values)
|
||||
|
||||
|
@ -103,20 +112,81 @@
|
|||
disable-drag (mf/use-state false)
|
||||
|
||||
on-focus (fn [_]
|
||||
(reset! disable-drag true))
|
||||
(reset! disable-drag true))
|
||||
|
||||
on-blur (fn [_]
|
||||
(reset! disable-drag false))]
|
||||
|
||||
(mf/use-layout-effect
|
||||
(mf/deps hide-fill-on-export?)
|
||||
#(let [checkbox (mf/ref-val checkbox-ref)]
|
||||
(when checkbox
|
||||
(mf/deps hide-fill-on-export?)
|
||||
#(let [checkbox (mf/ref-val checkbox-ref)]
|
||||
(when checkbox
|
||||
;; Note that the "indeterminate" attribute only may be set by code, not as a static attribute.
|
||||
;; See https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#attr-indeterminate
|
||||
(if (= hide-fill-on-export? :multiple)
|
||||
(dom/set-attribute! checkbox "indeterminate" true)
|
||||
(dom/remove-attribute! checkbox "indeterminate")))))
|
||||
(if (= hide-fill-on-export? :multiple)
|
||||
(dom/set-attribute! checkbox "indeterminate" true)
|
||||
(dom/remove-attribute! checkbox "indeterminate")))))
|
||||
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :element-set)}
|
||||
[:div {:class (stl/css :element-title)}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? (not open?)
|
||||
:on-collapsed toggle-content
|
||||
:title label
|
||||
:class (stl/css :title-spacing-fill)}
|
||||
|
||||
(when (and (not disable-remove?) (not (= :multiple (:fills values))))
|
||||
[:button {:class (stl/css :add-fill)
|
||||
:on-click on-add} i/add-refactor])]]
|
||||
|
||||
(when open?
|
||||
[:div {:class (stl/css :element-content)}
|
||||
(cond
|
||||
(= :multiple (:fills values))
|
||||
[:div {:class (stl/css :element-set-options-group)}
|
||||
[:div {:class (stl/css :group-label)}
|
||||
(tr "settings.multiple")]
|
||||
[:button {:on-click on-remove-all
|
||||
:class (stl/css :remove-btn)}
|
||||
i/remove-refactor]]
|
||||
|
||||
(seq (:fills values))
|
||||
[:& h/sortable-container {}
|
||||
(for [[index value] (d/enumerate (:fills values []))]
|
||||
[:& color-row {:color {:color (:fill-color value)
|
||||
:opacity (:fill-opacity value)
|
||||
:id (:fill-color-ref-id value)
|
||||
:file-id (:fill-color-ref-file value)
|
||||
:gradient (:fill-color-gradient value)}
|
||||
:key index
|
||||
:index index
|
||||
:title (tr "workspace.options.fill")
|
||||
:on-change (on-change index)
|
||||
:on-reorder (on-reorder index)
|
||||
:on-detach (on-detach index)
|
||||
:on-remove (on-remove index)
|
||||
:disable-drag disable-drag
|
||||
:on-focus on-focus
|
||||
:select-on-focus (not @disable-drag)
|
||||
:on-blur on-blur}])])
|
||||
|
||||
(when (or (= type :frame)
|
||||
(and (= type :multiple) (some? (:hide-fill-on-export values))))
|
||||
[:div {:class (stl/css :checkbox)}
|
||||
|
||||
[:label {:for "show-fill-on-export"
|
||||
:class (stl/css-case :checked (not hide-fill-on-export?))}
|
||||
[:span {:class (stl/css-case :check-mark true
|
||||
:checked (not hide-fill-on-export?))}
|
||||
(when(not hide-fill-on-export?)
|
||||
i/status-tick-refactor)]
|
||||
(tr "workspace.options.show-fill-on-export")
|
||||
[:input {:type "checkbox"
|
||||
:id "show-fill-on-export"
|
||||
:ref checkbox-ref
|
||||
:checked (not hide-fill-on-export?)
|
||||
:on-change on-change-show-fill-on-export}]]])])]
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
|
@ -164,4 +234,4 @@
|
|||
:on-change on-change-show-fill-on-export}]
|
||||
|
||||
[:label {:for "show-fill-on-export"}
|
||||
(tr "workspace.options.show-fill-on-export")]])]]))
|
||||
(tr "workspace.options.show-fill-on-export")]])]])))
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.element-set {
|
||||
.element-title {
|
||||
.add-fill {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-12;
|
||||
.element-set-options-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.group-label {
|
||||
@extend .mixed-bar;
|
||||
}
|
||||
.remove-btn {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
.checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: $s-8;
|
||||
margin-top: calc(-1 * $s-4);
|
||||
padding-left: $s-8;
|
||||
input {
|
||||
margin: 0;
|
||||
}
|
||||
label {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-6;
|
||||
cursor: pointer;
|
||||
.check-mark {
|
||||
@include flexCenter;
|
||||
width: $s-16;
|
||||
height: $s-16;
|
||||
border-radius: $br-6;
|
||||
background-color: var(--input-background-color);
|
||||
&.checked {
|
||||
background-color: var(--input-border-color-active);
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--input-details-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.frame-grid
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.geom.grid :as gg]
|
||||
[app.main.data.workspace.grid :as dw]
|
||||
|
@ -13,6 +14,8 @@
|
|||
[app.main.ui.components.editable-select :refer [editable-select]]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input*]]
|
||||
[app.main.ui.components.select :refer [select]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.options.common :refer [advanced-options]]
|
||||
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
|
||||
|
@ -32,17 +35,28 @@
|
|||
(mf/defc grid-options
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [shape-id index grid frame-width frame-height default-grid-params]}]
|
||||
(let [on-change (mf/use-fn (mf/deps shape-id index) #(st/emit! (dw/set-frame-grid shape-id index %)))
|
||||
on-remove (mf/use-fn (mf/deps shape-id index) #(st/emit! (dw/remove-frame-grid shape-id index)))
|
||||
on-save-default (mf/use-fn #(st/emit! (dw/set-default-grid (:type %) (:params %))))
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
on-change (mf/use-fn (mf/deps shape-id index) #(st/emit! (dw/set-frame-grid shape-id index %)))
|
||||
on-remove (mf/use-fn (mf/deps shape-id index) #(st/emit! (dw/remove-frame-grid shape-id index)))
|
||||
on-save-default (mf/use-fn #(st/emit! (dw/set-default-grid (:type %) (:params %))))
|
||||
|
||||
size-options (mf/use-memo get-size-options)
|
||||
state (mf/use-state {:show-advanced-options false})
|
||||
size-options (mf/use-memo get-size-options)
|
||||
state* (mf/use-state {:show-advanced-options false
|
||||
:show-more-options false})
|
||||
state (deref state*)
|
||||
|
||||
open? (:show-advanced-options state)
|
||||
show-more-options? (:show-more-options state)
|
||||
|
||||
is-hidden? (not (:display grid))
|
||||
|
||||
{:keys [type display params]} grid
|
||||
|
||||
toggle-advanced-options
|
||||
(mf/use-fn #(swap! state update :show-advanced-options not))
|
||||
(mf/use-fn #(swap! state* update :show-advanced-options not))
|
||||
|
||||
toggle-more-options
|
||||
(mf/use-fn #(swap! state* update :show-more-options not))
|
||||
|
||||
handle-toggle-visibility
|
||||
(mf/use-fn
|
||||
|
@ -119,146 +133,314 @@
|
|||
(mf/use-fn (mf/deps grid) #(on-save-default grid))
|
||||
|
||||
is-default (= (->> grid :params)
|
||||
(->> grid :type default-grid-params))
|
||||
(->> grid :type default-grid-params))]
|
||||
|
||||
open? (:show-advanced-options @state)]
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :grid-option)}
|
||||
[:div {:class (stl/css :grid-title)}
|
||||
[:div {:class (stl/css-case :option-row true
|
||||
:hidden is-hidden?)}
|
||||
[:button {:class (stl/css-case :show-options true
|
||||
:selected open?)
|
||||
:on-click toggle-advanced-options}
|
||||
i/menu-refactor]
|
||||
[:div {:class (stl/css :type-select-wrapper)}
|
||||
[:& select
|
||||
{:class (stl/css :grid-type-select)
|
||||
:default-value type
|
||||
:options [{:value :square :label (tr "workspace.options.grid.square")}
|
||||
{:value :column :label (tr "workspace.options.grid.column")}
|
||||
{:value :row :label (tr "workspace.options.grid.row")}]
|
||||
:on-change handle-change-type}]]
|
||||
(if (= type :square)
|
||||
[:div {:class (stl/css :grid-size)
|
||||
:title (tr "workspace.options.size")}
|
||||
[:> numeric-input* {:min 0.01
|
||||
:value (or (:size params) "")
|
||||
:no-validate true
|
||||
:className (stl/css :numeric-input)
|
||||
:on-change (handle-change :params :size)}]]
|
||||
|
||||
[:div.grid-option
|
||||
[:div.grid-option-main {:style {:display (when open? "none")}}
|
||||
[:button.custom-button {:class (when open? "is-active")
|
||||
:on-click toggle-advanced-options} i/actions]
|
||||
[:div {:class (stl/css :editable-select-wrapper)}
|
||||
[:& editable-select {:value (:size params)
|
||||
:type "number"
|
||||
:class (stl/css :column-select)
|
||||
:input-class (stl/css :numeric-input)
|
||||
:min 1
|
||||
:options size-options
|
||||
:placeholder "Auto"
|
||||
:on-change handle-change-size}]])]
|
||||
|
||||
[:& select
|
||||
{:class "flex-grow"
|
||||
:default-value type
|
||||
:options [{:value :square :label (tr "workspace.options.grid.square")}
|
||||
{:value :column :label (tr "workspace.options.grid.column")}
|
||||
{:value :row :label (tr "workspace.options.grid.row")}]
|
||||
:on-change handle-change-type}]
|
||||
[:div {:class (stl/css :actions)}
|
||||
[:button {:class (stl/css :action-btn)
|
||||
:on-click handle-toggle-visibility}
|
||||
(if display i/shown-refactor i/hide-refactor)]
|
||||
[:button {:class (stl/css :action-btn)
|
||||
:on-click on-remove}
|
||||
i/remove-refactor]]]
|
||||
|
||||
(if (= type :square)
|
||||
[:div.input-element.pixels {:title (tr "workspace.options.size")}
|
||||
[:> numeric-input* {:min 0.01
|
||||
:value (or (:size params) "")
|
||||
:no-validate true
|
||||
:on-change (handle-change :params :size)}]]
|
||||
[:& advanced-options {:class (stl/css :grid-advanced-options)
|
||||
:visible? open?
|
||||
:on-close toggle-advanced-options}
|
||||
;; square
|
||||
(when (= :square type)
|
||||
[:div {:class (stl/css :square-row)}
|
||||
[:div {:class (stl/css :advanced-row)}
|
||||
[:& color-row {:color (:color params)
|
||||
:title (tr "workspace.options.grid.params.color")
|
||||
:disable-gradient true
|
||||
:on-change handle-change-color
|
||||
:on-detach handle-detach-color}]
|
||||
[:button {:class (stl/css :show-more-options)
|
||||
:on-click toggle-more-options}
|
||||
i/menu-refactor]]
|
||||
(when show-more-options?
|
||||
[:div {:class (stl/css :second-row)}
|
||||
[:button {:class (stl/css-case :btn-options true
|
||||
:disabled is-default)
|
||||
:disabled is-default
|
||||
:on-click handle-use-default}
|
||||
[:span (tr "workspace.options.grid.params.use-default")]]
|
||||
[:button {:class (stl/css-case :btn-options true
|
||||
:disabled is-default)
|
||||
:disabled is-default
|
||||
:on-click handle-set-as-default}
|
||||
[:span (tr "workspace.options.grid.params.set-default")]]])])
|
||||
|
||||
[:& editable-select {:value (:size params)
|
||||
:type "number"
|
||||
:class "input-option"
|
||||
:min 1
|
||||
:options size-options
|
||||
:placeholder "Auto"
|
||||
:on-change handle-change-size}])
|
||||
(when (or (= :column type) (= :row type))
|
||||
[:div {:class (stl/css :column-row)}
|
||||
[:div {:class (stl/css :advanced-row)}
|
||||
[:div {:class (stl/css :select-wrapper)}
|
||||
[:& select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:default-value (:type params)
|
||||
:class (stl/css :orientation)
|
||||
:options [{:value :stretch :label (tr "workspace.options.grid.params.type.stretch")}
|
||||
{:value :left :label (if (= type :row)
|
||||
(tr "workspace.options.grid.params.type.top")
|
||||
(tr "workspace.options.grid.params.type.left"))}
|
||||
{:value :center :label (tr "workspace.options.grid.params.type.center")}
|
||||
{:value :right :label (if (= type :row)
|
||||
(tr "workspace.options.grid.params.type.bottom")
|
||||
(tr "workspace.options.grid.params.type.right"))}]
|
||||
:on-change (handle-change :params :type)}]]
|
||||
|
||||
[:div.grid-option-main-actions
|
||||
[:button.custom-button {:on-click handle-toggle-visibility} (if display i/eye i/eye-closed)]
|
||||
[:button.custom-button {:on-click on-remove} i/minus]]]
|
||||
[:div {:class (stl/css :color-wrapper)}
|
||||
[:& color-row {:color (:color params)
|
||||
:title (tr "workspace.options.grid.params.color")
|
||||
:disable-gradient true
|
||||
:on-change handle-change-color
|
||||
:on-detach handle-detach-color}]]]
|
||||
|
||||
[:& advanced-options {:visible? open? :on-close toggle-advanced-options}
|
||||
[:button.custom-button {:on-click toggle-advanced-options} i/actions]
|
||||
(when (= :square type)
|
||||
[:& input-row {:label (tr "workspace.options.grid.params.size")
|
||||
:class "pixels"
|
||||
:min 0.01
|
||||
:value (:size params)
|
||||
:on-change (handle-change :params :size)}])
|
||||
[:div {:class (stl/css :advanced-row)}
|
||||
[:div {:class (stl/css :height)
|
||||
:title (if (= :row type)
|
||||
(tr "workspace.options.grid.params.height")
|
||||
(tr "workspace.options.grid.params.width"))}
|
||||
[:span {:class (stl/css :icon-text)}
|
||||
(if (= :row type)
|
||||
"H"
|
||||
"W")]
|
||||
[:> numeric-input* {:placeholder "Auto"
|
||||
:on-change handle-change-item-length
|
||||
:nillable true
|
||||
:className (stl/css :numeric-input)
|
||||
:value (or (:item-length params) "")}]]
|
||||
|
||||
(when (= :row type)
|
||||
[:& input-row {:label (tr "workspace.options.grid.params.rows")
|
||||
:type :editable-select
|
||||
:options size-options
|
||||
:value (:size params)
|
||||
:min 1
|
||||
:placeholder "Auto"
|
||||
:on-change handle-change-size}])
|
||||
[:div {:class (stl/css :gutter)
|
||||
:title (tr "workspace.options.grid.params.gutter")}
|
||||
[:span {:class (stl/css-case :icon true
|
||||
:rotated (= type :row))} i/gap-horizontal-refactor]
|
||||
[:> numeric-input* {:placeholder "0"
|
||||
:on-change (handle-change :params :gutter)
|
||||
:nillable true
|
||||
:className (stl/css :numeric-input)
|
||||
:value (or (:gutter params) 0)}]]
|
||||
|
||||
(when (= :column type)
|
||||
[:& input-row {:label (tr "workspace.options.grid.params.columns")
|
||||
:type :editable-select
|
||||
:options size-options
|
||||
:value (:size params)
|
||||
:min 1
|
||||
:placeholder "Auto"
|
||||
:on-change handle-change-size}])
|
||||
[:div {:class (stl/css :margin)
|
||||
:title (tr "workspace.options.grid.params.margin")}
|
||||
[:span {:class (stl/css-case :icon true
|
||||
:rotated (= type :column))} i/grid-margin-refactor]
|
||||
[:> numeric-input* {:placeholder "0"
|
||||
:on-change (handle-change :params :margin)
|
||||
:nillable true
|
||||
:className (stl/css :numeric-input)
|
||||
:value (or (:margin params) 0)}]]
|
||||
|
||||
(when (#{:row :column} type)
|
||||
[:& input-row {:label (tr "workspace.options.grid.params.type")
|
||||
:type :select
|
||||
:options [{:value :stretch :label (tr "workspace.options.grid.params.type.stretch")}
|
||||
{:value :left :label (if (= type :row)
|
||||
(tr "workspace.options.grid.params.type.top")
|
||||
(tr "workspace.options.grid.params.type.left"))}
|
||||
{:value :center :label (tr "workspace.options.grid.params.type.center")}
|
||||
{:value :right :label (if (= type :row)
|
||||
(tr "workspace.options.grid.params.type.bottom")
|
||||
(tr "workspace.options.grid.params.type.right"))}]
|
||||
:value (:type params)
|
||||
:on-change (handle-change :params :type)}])
|
||||
[:button {:class (stl/css :show-more-options)
|
||||
:on-click toggle-more-options}
|
||||
i/menu-refactor]
|
||||
(when show-more-options?
|
||||
[:div {:class (stl/css :more-options)}
|
||||
[:button {:disabled is-default
|
||||
:class (stl/css :option-btn)
|
||||
:on-click handle-use-default} (tr "workspace.options.grid.params.use-default")]
|
||||
[:button {:disabled is-default
|
||||
:class (stl/css :option-btn)
|
||||
:on-click handle-set-as-default} (tr "workspace.options.grid.params.set-default")]])]])]]
|
||||
|
||||
(when (#{:row :column} type)
|
||||
[:& input-row-v2
|
||||
{:class "pixels"
|
||||
:label (if (= :row type)
|
||||
(tr "workspace.options.grid.params.height")
|
||||
(tr "workspace.options.grid.params.width"))}
|
||||
[:> numeric-input*
|
||||
{:placeholder "Auto"
|
||||
:value (or (:item-length params) "")
|
||||
:nillable true
|
||||
:on-change handle-change-item-length}]])
|
||||
[:div.grid-option
|
||||
[:div.grid-option-main {:style {:display (when open? "none")}}
|
||||
[:button.custom-button {:class (when open? "is-active")
|
||||
:on-click toggle-advanced-options} i/actions]
|
||||
[:& select
|
||||
{:class "flex-grow"
|
||||
:default-value type
|
||||
:options [{:value :square :label (tr "workspace.options.grid.square")}
|
||||
{:value :column :label (tr "workspace.options.grid.column")}
|
||||
{:value :row :label (tr "workspace.options.grid.row")}]
|
||||
:on-change handle-change-type}]
|
||||
|
||||
(when (#{:row :column} type)
|
||||
[:*
|
||||
[:& input-row {:label (tr "workspace.options.grid.params.gutter")
|
||||
:class "pixels"
|
||||
:value (:gutter params)
|
||||
:min 0
|
||||
:nillable true
|
||||
:default 0
|
||||
:placeholder "0"
|
||||
:on-change (handle-change :params :gutter)}]
|
||||
[:& input-row {:label (tr "workspace.options.grid.params.margin")
|
||||
:class "pixels"
|
||||
:min 0
|
||||
:nillable true
|
||||
:default 0
|
||||
:placeholder "0"
|
||||
:value (:margin params)
|
||||
:on-change (handle-change :params :margin)}]])
|
||||
(if (= type :square)
|
||||
[:div.input-element.pixels {:title (tr "workspace.options.size")}
|
||||
[:> numeric-input* {:min 0.01
|
||||
:value (or (:size params) "")
|
||||
:no-validate true
|
||||
:on-change (handle-change :params :size)}]]
|
||||
|
||||
[:& color-row {:color (:color params)
|
||||
:title (tr "workspace.options.grid.params.color")
|
||||
:disable-gradient true
|
||||
:on-change handle-change-color
|
||||
:on-detach handle-detach-color}]
|
||||
[:div.row-flex
|
||||
[:button.btn-options {:disabled is-default
|
||||
:on-click handle-use-default} (tr "workspace.options.grid.params.use-default")]
|
||||
[:button.btn-options {:disabled is-default
|
||||
:on-click handle-set-as-default} (tr "workspace.options.grid.params.set-default")]]]]))
|
||||
[:& editable-select {:value (:size params)
|
||||
:type "number"
|
||||
:class "input-option"
|
||||
:min 1
|
||||
:options size-options
|
||||
:placeholder "Auto"
|
||||
:on-change handle-change-size}])
|
||||
|
||||
[:div.grid-option-main-actions
|
||||
[:button.custom-button {:on-click handle-toggle-visibility} (if display i/eye i/eye-closed)]
|
||||
[:button.custom-button {:on-click on-remove} i/minus]]]
|
||||
|
||||
[:& advanced-options {:visible? open? :on-close toggle-advanced-options}
|
||||
[:button.custom-button {:on-click toggle-advanced-options} i/actions]
|
||||
(when (= :square type)
|
||||
[:& input-row {:label (tr "workspace.options.grid.params.size")
|
||||
:class "pixels"
|
||||
:min 0.01
|
||||
:value (:size params)
|
||||
:on-change (handle-change :params :size)}])
|
||||
|
||||
(when (= :row type)
|
||||
[:& input-row {:label (tr "workspace.options.grid.params.rows")
|
||||
:type :editable-select
|
||||
:options size-options
|
||||
:value (:size params)
|
||||
:min 1
|
||||
:placeholder "Auto"
|
||||
:on-change handle-change-size}])
|
||||
|
||||
(when (= :column type)
|
||||
[:& input-row {:label (tr "workspace.options.grid.params.columns")
|
||||
:type :editable-select
|
||||
:options size-options
|
||||
:value (:size params)
|
||||
:min 1
|
||||
:placeholder "Auto"
|
||||
:on-change handle-change-size}])
|
||||
|
||||
(when (#{:row :column} type)
|
||||
[:& input-row {:label (tr "workspace.options.grid.params.type")
|
||||
:type :select
|
||||
:options [{:value :stretch :label (tr "workspace.options.grid.params.type.stretch")}
|
||||
{:value :left :label (if (= type :row)
|
||||
(tr "workspace.options.grid.params.type.top")
|
||||
(tr "workspace.options.grid.params.type.left"))}
|
||||
{:value :center :label (tr "workspace.options.grid.params.type.center")}
|
||||
{:value :right :label (if (= type :row)
|
||||
(tr "workspace.options.grid.params.type.bottom")
|
||||
(tr "workspace.options.grid.params.type.right"))}]
|
||||
:value (:type params)
|
||||
:on-change (handle-change :params :type)}])
|
||||
|
||||
(when (#{:row :column} type)
|
||||
[:& input-row-v2
|
||||
{:class "pixels"
|
||||
:label (if (= :row type)
|
||||
(tr "workspace.options.grid.params.height")
|
||||
(tr "workspace.options.grid.params.width"))}
|
||||
[:> numeric-input*
|
||||
{:placeholder "Auto"
|
||||
:value (or (:item-length params) "")
|
||||
:nillable true
|
||||
:on-change handle-change-item-length}]])
|
||||
|
||||
(when (#{:row :column} type)
|
||||
[:*
|
||||
[:& input-row {:label (tr "workspace.options.grid.params.gutter")
|
||||
:class "pixels"
|
||||
:value (:gutter params)
|
||||
:min 0
|
||||
:nillable true
|
||||
:default 0
|
||||
:placeholder "0"
|
||||
:on-change (handle-change :params :gutter)}]
|
||||
[:& input-row {:label (tr "workspace.options.grid.params.margin")
|
||||
:class "pixels"
|
||||
:min 0
|
||||
:nillable true
|
||||
:default 0
|
||||
:placeholder "0"
|
||||
:value (:margin params)
|
||||
:on-change (handle-change :params :margin)}]])
|
||||
|
||||
[:& color-row {:color (:color params)
|
||||
:title (tr "workspace.options.grid.params.color")
|
||||
:disable-gradient true
|
||||
:on-change handle-change-color
|
||||
:on-detach handle-detach-color}]
|
||||
[:div.row-flex
|
||||
[:button.btn-options {:disabled is-default
|
||||
:on-click handle-use-default} (tr "workspace.options.grid.params.use-default")]
|
||||
[:button.btn-options {:disabled is-default
|
||||
:on-click handle-set-as-default} (tr "workspace.options.grid.params.set-default")]]]])))
|
||||
|
||||
(mf/defc frame-grid
|
||||
[{:keys [shape]}]
|
||||
(let [id (:id shape)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
state* (mf/use-state true)
|
||||
open? (deref state*)
|
||||
|
||||
toggle-content (mf/use-fn #(swap! state* not))
|
||||
id (:id shape)
|
||||
saved-grids (mf/deref workspace-saved-grids)
|
||||
default-grid-params (mf/use-memo (mf/deps saved-grids) #(merge dw/default-grid-params saved-grids))
|
||||
handle-create-grid (mf/use-fn (mf/deps id) #(st/emit! (dw/add-frame-grid id)))]
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span (tr "workspace.options.grid.grid-title")]
|
||||
[:div.add-page {:on-click handle-create-grid} i/close]]
|
||||
|
||||
(when (seq (:grids shape))
|
||||
[:div.element-set-content
|
||||
(for [[index grid] (map-indexed vector (:grids shape))]
|
||||
[:& grid-options {:key (str id "-" index)
|
||||
:shape-id id
|
||||
:grid grid
|
||||
:index index
|
||||
:frame-width (:width shape)
|
||||
:frame-height (:height shape)
|
||||
:default-grid-params default-grid-params
|
||||
}])])]))
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :element-set)}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? (not open?)
|
||||
:on-collapsed toggle-content
|
||||
:title (tr "workspace.options.grid.grid-title")}
|
||||
|
||||
[:button {:on-click handle-create-grid
|
||||
:class (stl/css :add-grid)}
|
||||
i/add-refactor]]
|
||||
|
||||
(when (and open? (seq (:grids shape)))
|
||||
[:div {:class (stl/css :element-set-content)}
|
||||
(for [[index grid] (map-indexed vector (:grids shape))]
|
||||
[:& grid-options {:key (str id "-" index)
|
||||
:shape-id id
|
||||
:grid grid
|
||||
:index index
|
||||
:frame-width (:width shape)
|
||||
:frame-height (:height shape)
|
||||
:default-grid-params default-grid-params}])])]
|
||||
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span (tr "workspace.options.grid.grid-title")]
|
||||
[:div.add-page {:on-click handle-create-grid} i/close]]
|
||||
|
||||
(when (seq (:grids shape))
|
||||
[:div.element-set-content
|
||||
(for [[index grid] (map-indexed vector (:grids shape))]
|
||||
[:& grid-options {:key (str id "-" index)
|
||||
:shape-id id
|
||||
:grid grid
|
||||
:index index
|
||||
:frame-width (:width shape)
|
||||
:frame-height (:height shape)
|
||||
:default-grid-params default-grid-params}])])])))
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,240 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.element-set {
|
||||
.add-grid {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
.element-set-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
.grid-option {
|
||||
.grid-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.option-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-1;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--input-details-color);
|
||||
.show-options {
|
||||
@extend .button-secondary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
border-radius: $br-8 0 0 $br-8;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
&.selected {
|
||||
background-color: var(--button-secondary-background-color-active);
|
||||
color: var(--button-secondary-foreground-color-active);
|
||||
svg {
|
||||
stroke: var(--button-secondary-foreground-color-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
.type-select-wrapper {
|
||||
width: $s-96;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
height: $s-32;
|
||||
.grid-type-select {
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
.grid-size {
|
||||
@extend .asset-element;
|
||||
width: $s-60;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-left: $s-8;
|
||||
border-radius: 0 $br-8 $br-8 0;
|
||||
.numeric-input {
|
||||
@extend .input-base;
|
||||
}
|
||||
}
|
||||
.editable-select-wrapper {
|
||||
@extend .asset-element;
|
||||
width: $s-60;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: $s-1 solid var(--input-background-color);
|
||||
position: relative;
|
||||
border-radius: 0 $br-8 $br-8 0;
|
||||
.column-select {
|
||||
height: $s-32;
|
||||
.numeric-input {
|
||||
@extend .input-base;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
span {
|
||||
@include flexCenter;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
.show-options,
|
||||
.type-select-wrapper,
|
||||
.editable-select-wrapper {
|
||||
background-color: transparent;
|
||||
border: $s-1 solid var(--input-border-color-disabled);
|
||||
color: var(--input-foreground-color-disabled);
|
||||
.column-select,
|
||||
.grid-type-select {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
.grid-size {
|
||||
background-color: transparent;
|
||||
border: $s-1 solid var(--input-border-color-disabled);
|
||||
color: var(--input-foreground-color-disabled);
|
||||
|
||||
.icon {
|
||||
stroke: var(--input-foreground-color-disabled);
|
||||
}
|
||||
.numeric-input {
|
||||
color: var(--input-foreground-color-disabled);
|
||||
}
|
||||
}
|
||||
.actions {
|
||||
.hidden-btn,
|
||||
.lock-btn {
|
||||
background-color: transparent;
|
||||
svg {
|
||||
stroke: var(--input-foreground-color-disabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.action-btn {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.grid-advanced-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
margin-top: $s-4;
|
||||
.column-row,
|
||||
.square-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
position: relative;
|
||||
.advanced-row {
|
||||
position: relative;
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
.select-wrapper {
|
||||
width: $s-92;
|
||||
padding: 0;
|
||||
}
|
||||
.color-wrapper {
|
||||
width: $s-156;
|
||||
}
|
||||
.show-more-options {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-32;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
.height {
|
||||
@extend .input-element;
|
||||
width: $s-108;
|
||||
padding-left: $s-8;
|
||||
.icon-text {
|
||||
padding-top: $s-1;
|
||||
}
|
||||
}
|
||||
.gutter,
|
||||
.margin {
|
||||
@extend .input-element;
|
||||
width: $s-108;
|
||||
padding-left: $s-8;
|
||||
.icon {
|
||||
&.rotated svg {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
.more-options {
|
||||
@include menuShadow;
|
||||
position: absolute;
|
||||
top: $s-36;
|
||||
right: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
width: $s-156;
|
||||
max-height: $s-300;
|
||||
padding: $s-2;
|
||||
margin: 0 0 $s-40 0;
|
||||
margin-top: $s-4;
|
||||
border-radius: $br-8;
|
||||
z-index: $z-index-3;
|
||||
overflow-y: auto;
|
||||
background-color: var(--menu-background-color);
|
||||
.option-btn {
|
||||
@include buttonStyle;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
padding: 0 $s-8;
|
||||
border-radius: $br-6;
|
||||
color: var(--menu-foreground-color);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--menu-background-color-hover);
|
||||
color: var(--menu-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.second-row {
|
||||
@extend .dropdown-wrapper;
|
||||
left: unset;
|
||||
right: 0;
|
||||
width: $s-108;
|
||||
.btn-options {
|
||||
@include buttonStyle;
|
||||
@extend .dropdown-element-base;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,28 +12,13 @@
|
|||
height: $s-32;
|
||||
gap: $s-4;
|
||||
.select {
|
||||
@extend .asset-element;
|
||||
width: $s-124;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 1px solid var(--input-background-color);
|
||||
}
|
||||
.input {
|
||||
@extend .input-element;
|
||||
width: $s-60;
|
||||
padding-left: $s-8;
|
||||
border: 1px solid var(--input-background-color);
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
margin-right: $s-4;
|
||||
}
|
||||
.numeric-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
|
@ -54,13 +39,13 @@
|
|||
&.hidden {
|
||||
.select {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--input-border-color-disabled);
|
||||
border: $s-1 solid var(--input-border-color-disabled);
|
||||
color: var(--input-foreground-color-disabled);
|
||||
}
|
||||
.input {
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--input-border-color-disabled);
|
||||
color: var(--input-foreground-color-disable);
|
||||
border: $s-1 solid var(--input-border-color-disabled);
|
||||
color: var(--input-foreground-color-disabled);
|
||||
|
||||
.icon {
|
||||
stroke: var(--input-foreground-color-disabled);
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
.element-set {
|
||||
.element-title {
|
||||
margin-right: $s-12;
|
||||
.title-spacing-layout {
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -74,74 +73,16 @@
|
|||
@extend .input-element;
|
||||
width: $s-108;
|
||||
padding-left: $s-8;
|
||||
.numeric-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
}
|
||||
&.disabled {
|
||||
background-color: var(--input-background-color-disabled);
|
||||
border: 1px solid var(--input-border-color-disabled);
|
||||
color: var(--input-foreground-color-disabled);
|
||||
.numeric-input {
|
||||
pointer-events: none;
|
||||
cursor: default;
|
||||
color: var(--input-foreground-color-disabled);
|
||||
}
|
||||
.icon {
|
||||
svg {
|
||||
stroke: var(--input-foreground-color-disabled);
|
||||
}
|
||||
}
|
||||
@extend .disabled-input;
|
||||
}
|
||||
}
|
||||
.row-gap {
|
||||
@extend .input-element;
|
||||
width: $s-108;
|
||||
padding-left: $s-8;
|
||||
.numeric-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
}
|
||||
&.disabled {
|
||||
background-color: var(--input-background-color-disabled);
|
||||
border: 1px solid var(--input-border-color-disabled);
|
||||
color: var(--input-foreground-color-disabled);
|
||||
.numeric-input {
|
||||
pointer-events: none;
|
||||
cursor: default;
|
||||
color: var(--input-foreground-color-disabled);
|
||||
}
|
||||
.icon {
|
||||
svg {
|
||||
stroke: var(--input-foreground-color-disabled);
|
||||
}
|
||||
}
|
||||
@extend .disabled-input;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -158,23 +99,6 @@
|
|||
@extend .input-element;
|
||||
width: $s-108;
|
||||
padding-left: $s-8;
|
||||
.numeric-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.paddings-multiple {
|
||||
|
@ -185,23 +109,6 @@
|
|||
@extend .input-element;
|
||||
width: $s-108;
|
||||
padding-left: $s-8;
|
||||
.numeric-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -224,15 +131,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.grid-layout-menu {
|
||||
background-color: antiquewhite;
|
||||
.first-row {
|
||||
.direction-edit {
|
||||
.direction {
|
||||
}
|
||||
.edit {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -518,108 +518,109 @@
|
|||
:id :static-position}]
|
||||
[:& radio-button {:value "absolute"
|
||||
:id :absolute-position}]]])]]
|
||||
[:div {:class (stl/css :flex-element-menu)}
|
||||
[:div {:class (stl/css :first-row)}
|
||||
[:& element-behaviour {:fill? is-layout-child?
|
||||
:auto? is-layout-container?
|
||||
:layout-item-v-sizing (or (:layout-item-v-sizing values) :fix)
|
||||
:layout-item-h-sizing (or (:layout-item-h-sizing values) :fix)
|
||||
:on-change-behaviour-h-refactor on-change-behaviour-h
|
||||
:on-change-behaviour-v-refactor on-change-behaviour-v
|
||||
:on-change on-change-behaviour}]
|
||||
(when is-absolute?
|
||||
[:div {:class (stl/css-case :z-index-wrapper true)
|
||||
:title "z-index"}
|
||||
|
||||
[:span {:class (stl/css :icon-text)}
|
||||
"Z"]
|
||||
[:> numeric-input*
|
||||
{:className (stl/css :numeric-input)
|
||||
:placeholder "--"
|
||||
:on-focus #(dom/select-target %)
|
||||
:on-change #(on-change-z-index %)
|
||||
:nillable true
|
||||
:value (:layout-item-z-index values)}]])]
|
||||
|
||||
(when (and is-layout-child? is-flex-parent?)
|
||||
[:div {:class (stl/css :second-row)}
|
||||
[:& align-self-row {:is-col? is-col?
|
||||
:align-self align-self
|
||||
:on-changer set-align-self-refactor}]])
|
||||
|
||||
(when is-layout-child?
|
||||
[:div {:class (stl/css :third-row)}
|
||||
[:& margin-section {:values values
|
||||
:change-margin-style change-margin-style
|
||||
:on-margin-change on-margin-change}]])
|
||||
|
||||
[:div {:class (stl/css :forth-row)}
|
||||
[:div {:class (stl/css :advanced-options)}
|
||||
(when (= (:layout-item-h-sizing values) :fill)
|
||||
[:div {:class (stl/css :horizontal-fill)}
|
||||
[:div {:class (stl/css :layout-item-min-w)
|
||||
:title (tr "workspace.options.layout-item.layout-item-min-w")}
|
||||
(when open?
|
||||
[:div {:class (stl/css :flex-element-menu)}
|
||||
[:div {:class (stl/css :first-row)}
|
||||
[:& element-behaviour {:fill? is-layout-child?
|
||||
:auto? is-layout-container?
|
||||
:layout-item-v-sizing (or (:layout-item-v-sizing values) :fix)
|
||||
:layout-item-h-sizing (or (:layout-item-h-sizing values) :fix)
|
||||
:on-change-behaviour-h-refactor on-change-behaviour-h
|
||||
:on-change-behaviour-v-refactor on-change-behaviour-v
|
||||
:on-change on-change-behaviour}]
|
||||
(when is-absolute?
|
||||
[:div {:class (stl/css :z-index-wrapper)
|
||||
:title "z-index"}
|
||||
|
||||
[:span {:class (stl/css :icon-text)}
|
||||
"MIN W"]
|
||||
"Z"]
|
||||
[:> numeric-input*
|
||||
{:className (stl/css :numeric-input)
|
||||
:no-validate true
|
||||
:min 0
|
||||
:data-wrap true
|
||||
:placeholder "--"
|
||||
:on-focus #(dom/select-target %)
|
||||
:on-change (partial on-size-change :layout-item-min-w)
|
||||
:value (get values :layout-item-min-w)
|
||||
:nillable true}]]
|
||||
:on-change #(on-change-z-index %)
|
||||
:nillable true
|
||||
:value (:layout-item-z-index values)}]])]
|
||||
|
||||
[:div {:class (stl/css :layout-item-max-w)
|
||||
:title (tr "workspace.options.layout-item.layout-item-max-w")}
|
||||
[:span {:class (stl/css :icon-text)}
|
||||
"MAX W"]
|
||||
[:> numeric-input*
|
||||
{:className (stl/css :numeric-input)
|
||||
:no-validate true
|
||||
:min 0
|
||||
:data-wrap true
|
||||
:placeholder "--"
|
||||
:on-focus #(dom/select-target %)
|
||||
:on-change (partial on-size-change :layout-item-max-w)
|
||||
:value (get values :layout-item-max-w)
|
||||
:nillable true}]]])
|
||||
(when (= (:layout-item-v-sizing values) :fill)
|
||||
[:div {:class (stl/css :vertical-fill)}
|
||||
[:div {:class (stl/css :layout-item-min-h)
|
||||
:title (tr "workspace.options.layout-item.layout-item-min-h")}
|
||||
(when (and is-layout-child? is-flex-parent?)
|
||||
[:div {:class (stl/css :second-row)}
|
||||
[:& align-self-row {:is-col? is-col?
|
||||
:align-self align-self
|
||||
:on-changer set-align-self-refactor}]])
|
||||
|
||||
[:span {:class (stl/css :icon-text)}
|
||||
"MIN H"]
|
||||
[:> numeric-input*
|
||||
{:className (stl/css :numeric-input)
|
||||
:no-validate true
|
||||
:min 0
|
||||
:data-wrap true
|
||||
:placeholder "--"
|
||||
:on-focus #(dom/select-target %)
|
||||
:on-change (partial on-size-change :layout-item-min-h)
|
||||
:value (get values :layout-item-min-h)
|
||||
:nillable true}]]
|
||||
(when is-layout-child?
|
||||
[:div {:class (stl/css :third-row)}
|
||||
[:& margin-section {:values values
|
||||
:change-margin-style change-margin-style
|
||||
:on-margin-change on-margin-change}]])
|
||||
|
||||
[:div {:class (stl/css :layout-item-max-h)
|
||||
:title (tr "workspace.options.layout-item.layout-item-max-h")}
|
||||
[:div {:class (stl/css :forth-row)}
|
||||
[:div {:class (stl/css :advanced-options)}
|
||||
(when (= (:layout-item-h-sizing values) :fill)
|
||||
[:div {:class (stl/css :horizontal-fill)}
|
||||
[:div {:class (stl/css :layout-item-min-w)
|
||||
:title (tr "workspace.options.layout-item.layout-item-min-w")}
|
||||
|
||||
[:span {:class (stl/css :icon-text)}
|
||||
"MAX H"]
|
||||
[:> numeric-input*
|
||||
{:className (stl/css :numeric-input)
|
||||
:no-validate true
|
||||
:min 0
|
||||
:data-wrap true
|
||||
:placeholder "--"
|
||||
:on-focus #(dom/select-target %)
|
||||
:on-change (partial on-size-change :layout-item-max-h)
|
||||
:value (get values :layout-item-max-h)
|
||||
:nillable true}]]])]]]]
|
||||
[:span {:class (stl/css :icon-text)}
|
||||
"MIN W"]
|
||||
[:> numeric-input*
|
||||
{:className (stl/css :numeric-input)
|
||||
:no-validate true
|
||||
:min 0
|
||||
:data-wrap true
|
||||
:placeholder "--"
|
||||
:on-focus #(dom/select-target %)
|
||||
:on-change (partial on-size-change :layout-item-min-w)
|
||||
:value (get values :layout-item-min-w)
|
||||
:nillable true}]]
|
||||
|
||||
[:div {:class (stl/css :layout-item-max-w)
|
||||
:title (tr "workspace.options.layout-item.layout-item-max-w")}
|
||||
[:span {:class (stl/css :icon-text)}
|
||||
"MAX W"]
|
||||
[:> numeric-input*
|
||||
{:className (stl/css :numeric-input)
|
||||
:no-validate true
|
||||
:min 0
|
||||
:data-wrap true
|
||||
:placeholder "--"
|
||||
:on-focus #(dom/select-target %)
|
||||
:on-change (partial on-size-change :layout-item-max-w)
|
||||
:value (get values :layout-item-max-w)
|
||||
:nillable true}]]])
|
||||
(when (= (:layout-item-v-sizing values) :fill)
|
||||
[:div {:class (stl/css :vertical-fill)}
|
||||
[:div {:class (stl/css :layout-item-min-h)
|
||||
:title (tr "workspace.options.layout-item.layout-item-min-h")}
|
||||
|
||||
[:span {:class (stl/css :icon-text)}
|
||||
"MIN H"]
|
||||
[:> numeric-input*
|
||||
{:className (stl/css :numeric-input)
|
||||
:no-validate true
|
||||
:min 0
|
||||
:data-wrap true
|
||||
:placeholder "--"
|
||||
:on-focus #(dom/select-target %)
|
||||
:on-change (partial on-size-change :layout-item-min-h)
|
||||
:value (get values :layout-item-min-h)
|
||||
:nillable true}]]
|
||||
|
||||
[:div {:class (stl/css :layout-item-max-h)
|
||||
:title (tr "workspace.options.layout-item.layout-item-max-h")}
|
||||
|
||||
[:span {:class (stl/css :icon-text)}
|
||||
"MAX H"]
|
||||
[:> numeric-input*
|
||||
{:className (stl/css :numeric-input)
|
||||
:no-validate true
|
||||
:min 0
|
||||
:data-wrap true
|
||||
:placeholder "--"
|
||||
:on-focus #(dom/select-target %)
|
||||
:on-change (partial on-size-change :layout-item-max-h)
|
||||
:value (get values :layout-item-max-h)
|
||||
:nillable true}]]])]]])]
|
||||
|
||||
|
||||
[:div.element-set
|
||||
|
@ -667,12 +668,12 @@
|
|||
[:div.layout-row
|
||||
[:div.row-title.sizing "Sizing"]
|
||||
[:& element-behaviour {:fill? is-layout-child?
|
||||
:auto? is-layout-container?
|
||||
:layout-item-v-sizing (or (:layout-item-v-sizing values) :fix)
|
||||
:layout-item-h-sizing (or (:layout-item-h-sizing values) :fix)
|
||||
:on-change-behaviour-h-refactor on-change-behaviour-h
|
||||
:on-change-behaviour-v-refactor on-change-behaviour-v
|
||||
:on-change on-change-behaviour}]]
|
||||
:auto? is-layout-container?
|
||||
:layout-item-v-sizing (or (:layout-item-v-sizing values) :fix)
|
||||
:layout-item-h-sizing (or (:layout-item-h-sizing values) :fix)
|
||||
:on-change-behaviour-h-refactor on-change-behaviour-h
|
||||
:on-change-behaviour-v-refactor on-change-behaviour-v
|
||||
:on-change on-change-behaviour}]]
|
||||
|
||||
(when (and is-layout-child? is-flex-parent?)
|
||||
[:div.layout-row
|
||||
|
@ -713,7 +714,4 @@
|
|||
:on-focus #(dom/select-target %)
|
||||
:on-change (partial on-size-change item)
|
||||
:value (get values item)
|
||||
:nillable true}]]])]]]]]
|
||||
)
|
||||
|
||||
))
|
||||
:nillable true}]]])]]]]])))
|
||||
|
|
|
@ -50,27 +50,11 @@
|
|||
width: $s-92;
|
||||
}
|
||||
}
|
||||
&.wrap {
|
||||
}
|
||||
}
|
||||
.z-index-wrapper {
|
||||
@extend .input-element;
|
||||
width: $s-124;
|
||||
padding-left: $s-8;
|
||||
.icon-text {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
padding-top: $s-2;
|
||||
}
|
||||
.numeric-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
.second-row {
|
||||
|
@ -107,23 +91,6 @@
|
|||
@extend .input-element;
|
||||
width: $s-108;
|
||||
padding-left: $s-8;
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
}
|
||||
.numeric-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
.margin-multiple {
|
||||
|
@ -137,23 +104,6 @@
|
|||
@extend .input-element;
|
||||
width: $s-108;
|
||||
padding-left: $s-8;
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
}
|
||||
.numeric-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -176,21 +126,10 @@
|
|||
width: $s-108;
|
||||
padding-left: $s-8;
|
||||
.icon-text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
justify-content: flex-start;
|
||||
width: $s-80;
|
||||
margin-right: $s-4;
|
||||
padding-top: $s-2;
|
||||
}
|
||||
.numeric-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -392,7 +392,8 @@
|
|||
:id :horiz}]]])
|
||||
(when (options :size)
|
||||
[:div {:class (stl/css :size)}
|
||||
[:div {:class (stl/css :height)
|
||||
[:div {:class (stl/css-case :width true
|
||||
:disabled disabled-width-sizing?)
|
||||
:title (tr "workspace.options.width")}
|
||||
[:span {:class (stl/css :icon-text)} "W"]
|
||||
[:> numeric-input* {:min 0.01
|
||||
|
@ -402,7 +403,8 @@
|
|||
:disabled disabled-width-sizing?
|
||||
:className (stl/css :numeric-input)
|
||||
:value (:width values)}]]
|
||||
[:div {:class (stl/css :height)
|
||||
[:div {:class (stl/css-case :height true
|
||||
:disabled disabled-height-sizing?)
|
||||
:title (tr "workspace.options.height")}
|
||||
[:span {:class (stl/css :icon-text)} "H"]
|
||||
[:> numeric-input* {:min 0.01
|
||||
|
@ -422,7 +424,8 @@
|
|||
i/unlock-refactor)]])
|
||||
(when (options :position)
|
||||
[:div {:class (stl/css :position)}
|
||||
[:div {:class (stl/css :x-position)
|
||||
[:div {:class (stl/css-case :x-position true
|
||||
:disabled disabled-position-x?)
|
||||
:title (tr "workspace.options.x")}
|
||||
[:span {:class (stl/css :icon-text)} "X"]
|
||||
[:> numeric-input* {:no-validate true
|
||||
|
@ -432,7 +435,8 @@
|
|||
:className (stl/css :numeric-input)
|
||||
:value (:x values)}]]
|
||||
|
||||
[:div {:class (stl/css :y-position)
|
||||
[:div {:class (stl/css-case :y-position true
|
||||
:disabled disabled-position-y?)
|
||||
:title (tr "workspace.options.y")}
|
||||
[:span {:class (stl/css :icon-text)} "Y"]
|
||||
[:> numeric-input* {:no-validate true
|
||||
|
|
|
@ -40,28 +40,11 @@
|
|||
}
|
||||
}
|
||||
.custom-select-dropdown {
|
||||
@include menuShadow;
|
||||
position: absolute;
|
||||
top: $s-32;
|
||||
left: 0;
|
||||
max-height: 300px;
|
||||
@extend .dropdown-wrapper;
|
||||
width: $s-252;
|
||||
padding: $s-2;
|
||||
margin: 0;
|
||||
margin-top: $s-4;
|
||||
border-radius: $br-8;
|
||||
z-index: $z-index-3;
|
||||
overflow-y: auto;
|
||||
background-color: var(--menu-background-color);
|
||||
.dropdown-element {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-8;
|
||||
height: $s-32;
|
||||
padding: 0 $s-8;
|
||||
border-radius: $br-6;
|
||||
cursor: pointer;
|
||||
@extend .dropdown-element-base;
|
||||
|
||||
&.disabled {
|
||||
pointer-events: none;
|
||||
cursor: default;
|
||||
|
@ -119,25 +102,11 @@
|
|||
@extend .input-element;
|
||||
width: $s-108;
|
||||
padding-left: $s-8;
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
width: $s-12;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
}
|
||||
.icon-text {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
y .icon-text {
|
||||
padding-top: $s-1;
|
||||
}
|
||||
.numeric-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--input-foreground-color-active);
|
||||
&.disabled {
|
||||
@extend .disabled-input;
|
||||
}
|
||||
}
|
||||
.lock-size-btn {
|
||||
|
@ -160,25 +129,11 @@
|
|||
@extend .input-element;
|
||||
width: $s-108;
|
||||
padding-left: $s-8;
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
width: $s-12;
|
||||
margin-right: $s-4;
|
||||
}
|
||||
.icon-text {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
padding-top: $s-1;
|
||||
}
|
||||
.numeric-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--input-foreground-color-active);
|
||||
&.disabled {
|
||||
@extend .disabled-input;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -192,28 +147,8 @@
|
|||
width: $s-108;
|
||||
padding-left: $s-8;
|
||||
.icon-text {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
padding-top: $s-1;
|
||||
}
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
}
|
||||
.numeric-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
}
|
||||
.radius {
|
||||
display: flex;
|
||||
|
@ -226,25 +161,6 @@
|
|||
@extend .input-element;
|
||||
width: $s-108;
|
||||
padding-left: $s-8;
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
}
|
||||
|
||||
.numeric-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: $s-1 $s-2;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
}
|
||||
.radius-4 {
|
||||
display: grid;
|
||||
|
@ -254,14 +170,6 @@
|
|||
@extend .input-element;
|
||||
width: $s-52;
|
||||
padding-left: $s-8;
|
||||
.numeric-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.shadow
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.colors :as clr]
|
||||
[app.common.data :as d]
|
||||
|
@ -16,6 +17,9 @@
|
|||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input*]]
|
||||
[app.main.ui.components.select :refer [select]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.hooks :as h]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.options.common :refer [advanced-options]]
|
||||
|
@ -47,7 +51,8 @@
|
|||
|
||||
(mf/defc shadow-entry
|
||||
[{:keys [ids index value on-reorder disable-drag? on-blur open-state-ref]}]
|
||||
(let [basic-offset-x-ref (mf/use-ref nil)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
basic-offset-x-ref (mf/use-ref nil)
|
||||
basic-offset-y-ref (mf/use-ref nil)
|
||||
basic-blur-ref (mf/use-ref nil)
|
||||
|
||||
|
@ -56,7 +61,9 @@
|
|||
adv-blur-ref (mf/use-ref nil)
|
||||
adv-spread-ref (mf/use-ref nil)
|
||||
|
||||
shadow-style (dm/str (:style value))
|
||||
shadow-style (if new-css-system
|
||||
(:style value)
|
||||
(dm/str (:style value)))
|
||||
shadow-id (:id value)
|
||||
|
||||
open-status-ref (mf/with-memo [open-state-ref shadow-id]
|
||||
|
@ -66,12 +73,9 @@
|
|||
|
||||
on-remove-shadow
|
||||
(mf/use-fn
|
||||
(mf/deps ids)
|
||||
(fn [event]
|
||||
(let [index (-> (dom/get-current-target event)
|
||||
(dom/get-data "index")
|
||||
(parse-long))]
|
||||
(st/emit! (dch/update-shapes ids #(update % :shadow remove-shadow-by-index index))))))
|
||||
(mf/deps ids index)
|
||||
(fn []
|
||||
(st/emit! (dch/update-shapes ids #(update % :shadow remove-shadow-by-index index)))))
|
||||
|
||||
on-drop
|
||||
(mf/use-fn
|
||||
|
@ -105,66 +109,147 @@
|
|||
(dom/set-value! update-node value))))))
|
||||
|
||||
update-color
|
||||
(fn [index]
|
||||
(fn [color]
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(assoc-in % [:shadow index :color] color)))))
|
||||
(mf/use-fn
|
||||
(mf/deps ids index)
|
||||
(fn [color]
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(assoc-in % [:shadow index :color] color)))))
|
||||
|
||||
detach-color
|
||||
(fn [index]
|
||||
(fn [_color _opacity]
|
||||
(when-not (string? (:color value))
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(assoc-in % [:shadow index :color]
|
||||
(dissoc (:color value) :id :file-id)))))))
|
||||
(mf/use-fn
|
||||
(mf/deps ids index)
|
||||
(fn [_color _opacity]
|
||||
(when-not (string? (:color value))
|
||||
(st/emit! (dch/update-shapes
|
||||
ids
|
||||
#(assoc-in % [:shadow index :color]
|
||||
(dissoc (:color value) :id :file-id)))))))
|
||||
|
||||
toggle-visibility
|
||||
(fn [index]
|
||||
(fn []
|
||||
(st/emit! (dch/update-shapes ids #(update-in % [:shadow index :hidden] not)))))
|
||||
(mf/use-fn
|
||||
(mf/deps ids index)
|
||||
(fn []
|
||||
(st/emit! (dch/update-shapes ids #(update-in % [:shadow index :hidden] not)))))
|
||||
|
||||
on-toggle-open-shadow
|
||||
(fn []
|
||||
(swap! open-state-ref update shadow-id not))]
|
||||
[:*
|
||||
[:div.shadow-option {:class (dom/classnames
|
||||
(swap! open-state-ref update shadow-id not))
|
||||
|
||||
on-type-change
|
||||
(mf/use-fn
|
||||
(mf/deps ids index)
|
||||
(fn [event]
|
||||
(let [value (if new-css-system
|
||||
(keyword event)
|
||||
(-> event dom/get-target-val d/read-string))]
|
||||
(st/emit! (dch/update-shapes ids #(assoc-in % [:shadow index :style] value))))))
|
||||
|
||||
type-options [{:value "drop-shadow" :label (tr "workspace.options.shadow-options.drop-shadow")}
|
||||
{:value "inner-shadow" :label (tr "workspace.options.shadow-options.inner-shadow")}]]
|
||||
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css-case :shadow-element true
|
||||
:dnd-over-top (= (:over dprops) :top)
|
||||
:dnd-over-bot (= (:over dprops) :bot))
|
||||
:ref dref}
|
||||
[:div.shadow-option-main {:style {:display (when open-shadow "none")}}
|
||||
[:div.element-set-actions-button
|
||||
{:on-click on-toggle-open-shadow}
|
||||
i/actions]
|
||||
:ref dref}
|
||||
[:div {:class (stl/css :basic-options)}
|
||||
[:div {:class (stl/css :shadow-info)}
|
||||
[:button {:class (stl/css :more-options)
|
||||
:on-click on-toggle-open-shadow}
|
||||
i/menu-refactor]
|
||||
[:div {:class (stl/css :type-select)}
|
||||
[:& select
|
||||
{:class (stl/css :shadow-type-select)
|
||||
:default-value (d/name shadow-style)
|
||||
:options type-options
|
||||
:on-change on-type-change}]]]
|
||||
[:div {:class (stl/css :actions)}
|
||||
[:button {:class (stl/css :action-btn)
|
||||
:on-click toggle-visibility}
|
||||
(if (:hidden value)
|
||||
i/hide-refactor
|
||||
i/shown-refactor)]
|
||||
[:button {:class (stl/css :action-btn)
|
||||
:on-click on-remove-shadow}
|
||||
i/remove-refactor]]]
|
||||
|
||||
[:select.input-select
|
||||
{:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:default-value shadow-style
|
||||
:on-change (fn [event]
|
||||
(let [value (-> event dom/get-target dom/get-value d/read-string)]
|
||||
(st/emit! (dch/update-shapes ids #(assoc-in % [:shadow index :style] value)))))}
|
||||
[:option {:value ":drop-shadow"
|
||||
:selected (when (= shadow-style ":drop-shadow") "selected")}
|
||||
(tr "workspace.options.shadow-options.drop-shadow")]
|
||||
[:option {:value ":inner-shadow"
|
||||
:selected (when (= shadow-style ":inner-shadow") "selected")}
|
||||
(tr "workspace.options.shadow-options.inner-shadow")]]
|
||||
(when open-shadow
|
||||
[:& advanced-options {:class (stl/css :shadow-advanced-options)
|
||||
:visible? open-shadow
|
||||
:on-close on-toggle-open-shadow}
|
||||
|
||||
[:div.shadow-option-main-actions
|
||||
[:div.element-set-actions-button {:on-click (toggle-visibility index)}
|
||||
(if (:hidden value) i/eye-closed i/eye)]
|
||||
[:div.element-set-actions-button
|
||||
{:data-index index
|
||||
:on-click on-remove-shadow}
|
||||
i/minus]]]
|
||||
[:div {:class (stl/css :first-row)}
|
||||
[:div {:class (stl/css :offset-x-input)
|
||||
:title (tr "workspace.options.shadow-options.offsetx")}
|
||||
[:span {:class (stl/css :input-label)}
|
||||
"X"]
|
||||
[:> numeric-input* {:className (stl/css :numeric-input)
|
||||
:ref adv-offset-x-ref
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-change (update-attr index :offset-x basic-offset-x-ref)
|
||||
:on-blur on-blur
|
||||
:value (:offset-x value)}]]
|
||||
|
||||
[:& advanced-options {:visible? open-shadow
|
||||
:on-close on-toggle-open-shadow}
|
||||
[:div.color-data
|
||||
[:div {:class (stl/css :blur-input)
|
||||
:title (tr "workspace.options.shadow-options.blur")}
|
||||
[:span {:class (stl/css :input-label)}
|
||||
(tr "workspace.options.shadow-options.blur")]
|
||||
[:> numeric-input* {:ref adv-blur-ref
|
||||
:className (stl/css :numeric-input)
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-change (update-attr index :blur basic-blur-ref)
|
||||
:on-blur on-blur
|
||||
:min 0
|
||||
:value (:blur value)}]]
|
||||
|
||||
[:div {:class (stl/css :spread-input)
|
||||
:title (tr "workspace.options.shadow-options.spread")}
|
||||
[:span {:class (stl/css :input-label)}
|
||||
(tr "workspace.options.shadow-options.spread")]
|
||||
[:> numeric-input* {:ref adv-spread-ref
|
||||
:className (stl/css :numeric-input)
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-change (update-attr index :spread)
|
||||
:on-blur on-blur
|
||||
:value (:spread value)}]]]
|
||||
|
||||
|
||||
[:div {:class (stl/css :second-row)}
|
||||
[:div {:class (stl/css :offset-y-input)
|
||||
:title (tr "workspace.options.shadow-options.offsety")}
|
||||
[:span {:class (stl/css :input-label)}
|
||||
"Y"]
|
||||
[:> numeric-input* {:ref adv-offset-y-ref
|
||||
:className (stl/css :numeric-input)
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-change (update-attr index :offset-y basic-offset-y-ref)
|
||||
:on-blur on-blur
|
||||
:value (:offset-y value)}]]
|
||||
[:& color-row {:color (if (string? (:color value))
|
||||
;; Support for old format colors
|
||||
{:color (:color value) :opacity (:opacity value)}
|
||||
(:color value))
|
||||
:title (tr "workspace.options.shadow-options.color")
|
||||
:disable-gradient true
|
||||
:on-change update-color
|
||||
:on-detach detach-color
|
||||
:on-open #(st/emit! (dwu/start-undo-transaction :color-row))
|
||||
:on-close #(st/emit! (dwu/commit-undo-transaction :color-row))}]]])]
|
||||
|
||||
[:div.shadow-option {:class (dom/classnames
|
||||
:dnd-over-top (= (:over dprops) :top)
|
||||
:dnd-over-bot (= (:over dprops) :bot))
|
||||
:ref dref}
|
||||
[:div.shadow-option-main {:style {:display (when open-shadow "none")}}
|
||||
[:div.element-set-actions-button
|
||||
{:on-click on-toggle-open-shadow}
|
||||
i/actions]
|
||||
|
||||
[:select.input-select
|
||||
{:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:default-value shadow-style
|
||||
|
@ -176,70 +261,106 @@
|
|||
(tr "workspace.options.shadow-options.drop-shadow")]
|
||||
[:option {:value ":inner-shadow"
|
||||
:selected (when (= shadow-style ":inner-shadow") "selected")}
|
||||
(tr "workspace.options.shadow-options.inner-shadow")]]]
|
||||
(tr "workspace.options.shadow-options.inner-shadow")]]
|
||||
|
||||
[:div.row-grid-2
|
||||
[:div.input-element {:title (tr "workspace.options.shadow-options.offsetx")}
|
||||
[:> numeric-input* {:ref adv-offset-x-ref
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-change (update-attr index :offset-x basic-offset-x-ref)
|
||||
:on-blur on-blur
|
||||
:value (:offset-x value)}]
|
||||
[:span.after (tr "workspace.options.shadow-options.offsetx")]]
|
||||
[:div.shadow-option-main-actions
|
||||
[:div.element-set-actions-button {:on-click (toggle-visibility index)}
|
||||
(if (:hidden value) i/eye-closed i/eye)]
|
||||
[:div.element-set-actions-button
|
||||
{:data-index index
|
||||
:on-click on-remove-shadow}
|
||||
i/minus]]]
|
||||
|
||||
[:div.input-element {:title (tr "workspace.options.shadow-options.offsety")}
|
||||
[:> numeric-input* {:ref adv-offset-y-ref
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-change (update-attr index :offset-y basic-offset-y-ref)
|
||||
:on-blur on-blur
|
||||
:value (:offset-y value)}]
|
||||
[:span.after (tr "workspace.options.shadow-options.offsety")]]]
|
||||
[:& advanced-options {:visible? open-shadow
|
||||
:on-close on-toggle-open-shadow}
|
||||
[:div.color-data
|
||||
[:div.element-set-actions-button
|
||||
{:on-click on-toggle-open-shadow}
|
||||
i/actions]
|
||||
[:select.input-select
|
||||
{:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:default-value shadow-style
|
||||
:on-change (fn [event]
|
||||
(let [value (-> event dom/get-target dom/get-value d/read-string)]
|
||||
(st/emit! (dch/update-shapes ids #(assoc-in % [:shadow index :style] value)))))}
|
||||
[:option {:value ":drop-shadow"
|
||||
:selected (when (= shadow-style ":drop-shadow") "selected")}
|
||||
(tr "workspace.options.shadow-options.drop-shadow")]
|
||||
[:option {:value ":inner-shadow"
|
||||
:selected (when (= shadow-style ":inner-shadow") "selected")}
|
||||
(tr "workspace.options.shadow-options.inner-shadow")]]]
|
||||
|
||||
[:div.row-grid-2
|
||||
[:div.input-element {:title (tr "workspace.options.shadow-options.blur")}
|
||||
[:> numeric-input* {:ref adv-blur-ref
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-change (update-attr index :blur basic-blur-ref)
|
||||
:on-blur on-blur
|
||||
:min 0
|
||||
:value (:blur value)}]
|
||||
[:span.after (tr "workspace.options.shadow-options.blur")]]
|
||||
[:div.row-grid-2
|
||||
[:div.input-element {:title (tr "workspace.options.shadow-options.offsetx")}
|
||||
[:> numeric-input* {:ref adv-offset-x-ref
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-change (update-attr index :offset-x basic-offset-x-ref)
|
||||
:on-blur on-blur
|
||||
:value (:offset-x value)}]
|
||||
[:span.after (tr "workspace.options.shadow-options.offsetx")]]
|
||||
|
||||
[:div.input-element {:title (tr "workspace.options.shadow-options.spread")}
|
||||
[:> numeric-input* {:ref adv-spread-ref
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-change (update-attr index :spread)
|
||||
:on-blur on-blur
|
||||
:value (:spread value)}]
|
||||
[:span.after (tr "workspace.options.shadow-options.spread")]]]
|
||||
[:div.input-element {:title (tr "workspace.options.shadow-options.offsety")}
|
||||
[:> numeric-input* {:ref adv-offset-y-ref
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-change (update-attr index :offset-y basic-offset-y-ref)
|
||||
:on-blur on-blur
|
||||
:value (:offset-y value)}]
|
||||
[:span.after (tr "workspace.options.shadow-options.offsety")]]]
|
||||
|
||||
[:div.color-row-wrap
|
||||
[:& color-row {:color (if (string? (:color value))
|
||||
;; Support for old format colors
|
||||
{:color (:color value) :opacity (:opacity value)}
|
||||
(:color value))
|
||||
:title (tr "workspace.options.shadow-options.color")
|
||||
:disable-gradient true
|
||||
:on-change (update-color index)
|
||||
:on-detach (detach-color index)
|
||||
:on-open #(st/emit! (dwu/start-undo-transaction :color-row))
|
||||
:on-close #(st/emit! (dwu/commit-undo-transaction :color-row))}]]]]]))
|
||||
[:div.row-grid-2
|
||||
[:div.input-element {:title (tr "workspace.options.shadow-options.blur")}
|
||||
[:> numeric-input* {:ref adv-blur-ref
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-change (update-attr index :blur basic-blur-ref)
|
||||
:on-blur on-blur
|
||||
:min 0
|
||||
:value (:blur value)}]
|
||||
[:span.after (tr "workspace.options.shadow-options.blur")]]
|
||||
|
||||
[:div.input-element {:title (tr "workspace.options.shadow-options.spread")}
|
||||
[:> numeric-input* {:ref adv-spread-ref
|
||||
:no-validate true
|
||||
:placeholder "--"
|
||||
:on-change (update-attr index :spread)
|
||||
:on-blur on-blur
|
||||
:value (:spread value)}]
|
||||
[:span.after (tr "workspace.options.shadow-options.spread")]]]
|
||||
|
||||
[:div.color-row-wrap
|
||||
[:& color-row {:color (if (string? (:color value))
|
||||
;; Support for old format colors
|
||||
{:color (:color value) :opacity (:opacity value)}
|
||||
(:color value))
|
||||
:title (tr "workspace.options.shadow-options.color")
|
||||
:disable-gradient true
|
||||
:on-change update-color
|
||||
:on-detach detach-color
|
||||
:on-open #(st/emit! (dwu/start-undo-transaction :color-row))
|
||||
:on-close #(st/emit! (dwu/commit-undo-transaction :color-row))}]]]])))
|
||||
(mf/defc shadow-menu
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [ids (unchecked-get props "ids")
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
ids (unchecked-get props "ids")
|
||||
type (unchecked-get props "type")
|
||||
values (unchecked-get props "values")
|
||||
|
||||
shadows (:shadow values [])
|
||||
open-state-ref (mf/with-memo [] (l/atom {}))
|
||||
|
||||
disable-drag* (mf/use-state false)
|
||||
disable-drag? (deref disable-drag*)
|
||||
|
||||
state* (mf/use-state {:show-content true
|
||||
:disable-drag false})
|
||||
|
||||
state (deref state*)
|
||||
open? (:show-content state)
|
||||
disable-drag? (:disable-drag state)
|
||||
|
||||
toggle-content
|
||||
(mf/use-fn #(swap! state* update :show-content not))
|
||||
|
||||
on-remove-all
|
||||
(mf/use-fn
|
||||
|
@ -255,43 +376,84 @@
|
|||
|
||||
on-blur
|
||||
(mf/use-fn
|
||||
#(reset! disable-drag* false))
|
||||
#(swap! state* assoc :disable-drag false))
|
||||
|
||||
on-add-shadow
|
||||
(mf/use-fn
|
||||
(mf/deps ids)
|
||||
#(st/emit! (dc/add-shadow ids (create-shadow))))]
|
||||
|
||||
[:div.element-set.shadow-options
|
||||
[:div.element-set-title
|
||||
[:span
|
||||
(case type
|
||||
:multiple (tr "workspace.options.shadow-options.title.multiple")
|
||||
:group (tr "workspace.options.shadow-options.title.group")
|
||||
(tr "workspace.options.shadow-options.title"))]
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :element-set)}
|
||||
[:div {:class (stl/css :element-title)}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? (not open?)
|
||||
:on-collapsed toggle-content
|
||||
:title (case type
|
||||
:multiple (tr "workspace.options.shadow-options.title.multiple")
|
||||
:group (tr "workspace.options.shadow-options.title.group")
|
||||
(tr "workspace.options.shadow-options.title"))
|
||||
:class (stl/css :title-spacing-shadow)}
|
||||
|
||||
(when-not (= :multiple shadows)
|
||||
[:div.add-page {:on-click on-add-shadow} i/close])]
|
||||
(when-not (= :multiple shadows)
|
||||
[:button {:class (stl/css :add-shadow)
|
||||
:on-click on-add-shadow} i/add-refactor])]]
|
||||
|
||||
(cond
|
||||
(= :multiple shadows)
|
||||
[:div.element-set-content
|
||||
[:div.element-set-options-group
|
||||
[:div.element-set-label (tr "settings.multiple")]
|
||||
[:div.element-set-actions
|
||||
[:div.element-set-actions-button {:on-click on-remove-all}
|
||||
i/minus]]]]
|
||||
(when open?
|
||||
(cond
|
||||
(= :multiple shadows)
|
||||
[:div {:class (stl/css :element-set-content)}
|
||||
[:div {:class (stl/css :multiple-shadows)}
|
||||
[:div {:class (stl/css :label)} (tr "settings.multiple")]
|
||||
[:div {:class (stl/css :actions)}
|
||||
[:button {:class (stl/css :action-btn)
|
||||
:on-click on-remove-all}
|
||||
i/remove-refactor]]]]
|
||||
|
||||
(seq shadows)
|
||||
[:& h/sortable-container {}
|
||||
[:div.element-set-content
|
||||
(for [[index value] (d/enumerate shadows)]
|
||||
[:& shadow-entry
|
||||
{:key (dm/str "shadow-" index)
|
||||
:ids ids
|
||||
:value value
|
||||
:on-reorder handle-reorder
|
||||
:disable-drag? disable-drag?
|
||||
:on-blur on-blur
|
||||
:index index
|
||||
:open-state-ref open-state-ref}])]])]))
|
||||
(seq shadows)
|
||||
[:& h/sortable-container {}
|
||||
[:div {:class (stl/css :element-set-content)}
|
||||
(for [[index value] (d/enumerate shadows)]
|
||||
[:& shadow-entry
|
||||
{:key (dm/str "shadow-" index)
|
||||
:ids ids
|
||||
:value value
|
||||
:on-reorder handle-reorder
|
||||
:disable-drag? disable-drag?
|
||||
:on-blur on-blur
|
||||
:index index
|
||||
:open-state-ref open-state-ref}])]]))]
|
||||
|
||||
[:div.element-set.shadow-options
|
||||
[:div.element-set-title
|
||||
[:span
|
||||
(case type
|
||||
:multiple (tr "workspace.options.shadow-options.title.multiple")
|
||||
:group (tr "workspace.options.shadow-options.title.group")
|
||||
(tr "workspace.options.shadow-options.title"))]
|
||||
|
||||
(when-not (= :multiple shadows)
|
||||
[:div.add-page {:on-click on-add-shadow} i/close])]
|
||||
|
||||
(cond
|
||||
(= :multiple shadows)
|
||||
[:div.element-set-content
|
||||
[:div.element-set-options-group
|
||||
[:div.element-set-label (tr "settings.multiple")]
|
||||
[:div.element-set-actions
|
||||
[:div.element-set-actions-button {:on-click on-remove-all}
|
||||
i/minus]]]]
|
||||
|
||||
(seq shadows)
|
||||
[:& h/sortable-container {}
|
||||
[:div.element-set-content
|
||||
(for [[index value] (d/enumerate shadows)]
|
||||
[:& shadow-entry
|
||||
{:key (dm/str "shadow-" index)
|
||||
:ids ids
|
||||
:value value
|
||||
:on-reorder handle-reorder
|
||||
:disable-drag? disable-drag?
|
||||
:on-blur on-blur
|
||||
:index index
|
||||
:open-state-ref open-state-ref}])]])])))
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.element-set {
|
||||
.element-title {
|
||||
.add-shadow {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-set-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
.multiple-shadows {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.label {
|
||||
@extend .mixed-bar;
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.action-btn {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.shadow-element {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
.basic-options {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.shadow-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-1;
|
||||
width: $s-188;
|
||||
.more-options {
|
||||
@extend .button-secondary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
border-radius: $br-8 0 0 $br-8;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
&.selected {
|
||||
background-color: var(--button-secondary-background-color-active);
|
||||
color: var(--button-secondary-foreground-color-active);
|
||||
svg {
|
||||
stroke: var(--button-secondary-foreground-color-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
.type-select {
|
||||
padding: 0;
|
||||
border-radius: 0 $br-8 $br-8 0;
|
||||
flex-grow: 1;
|
||||
.shadow-type-select {
|
||||
flex-grow: 1;
|
||||
border-radius: 0 $br-8 $br-8 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.action-btn {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.shadow-advanced-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
.first-row,
|
||||
.second-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.offset-x-input,
|
||||
.blur-input,
|
||||
.spread-input,
|
||||
.offset-y-input {
|
||||
@extend .input-element;
|
||||
width: $s-60;
|
||||
min-width: $s-60;
|
||||
padding: 0 0 0 $s-8;
|
||||
input {
|
||||
width: $s-32;
|
||||
}
|
||||
}
|
||||
.blur-input,
|
||||
.spread-input {
|
||||
width: $s-92;
|
||||
.input-label {
|
||||
width: $s-44;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,12 +5,15 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.stroke
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.colors :as clr]
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.workspace.colors :as dc]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.hooks :as h]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.options.rows.stroke-row :refer [stroke-row]]
|
||||
|
@ -35,11 +38,17 @@
|
|||
(mf/defc stroke-menu
|
||||
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "type" "show-caps"]))]}
|
||||
[{:keys [ids type values show-caps disable-stroke-style] :as props}]
|
||||
(let [label (case type
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
label (case type
|
||||
:multiple (tr "workspace.options.selection-stroke")
|
||||
:group (tr "workspace.options.group-stroke")
|
||||
(tr "workspace.options.stroke"))
|
||||
|
||||
state* (mf/use-state true)
|
||||
open? (deref state*)
|
||||
|
||||
toggle-content (mf/use-fn #(swap! state* not))
|
||||
|
||||
handle-change-stroke-color
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
|
@ -47,14 +56,25 @@
|
|||
(fn [color]
|
||||
(st/emit! (dc/change-stroke ids color index)))))
|
||||
|
||||
on-color-change-refactor
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [index color]
|
||||
(st/emit! (dc/change-stroke ids color index))))
|
||||
|
||||
handle-remove
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [index]
|
||||
(fn []
|
||||
(st/emit! (dc/remove-stroke ids index)))))
|
||||
on-remove-refactor
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [index]
|
||||
(st/emit! (dc/remove-stroke ids index))))
|
||||
|
||||
handle-remove-remove-all
|
||||
handle-remove-all
|
||||
(fn [_]
|
||||
(st/emit! (dc/remove-all-strokes ids)))
|
||||
|
||||
|
@ -67,6 +87,14 @@
|
|||
(assoc :id nil :file-id nil))]
|
||||
(st/emit! (dc/change-stroke ids color index))))))
|
||||
|
||||
on-color-detach-refactor
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [index color]
|
||||
(let [color (-> color
|
||||
(assoc :id nil :file-id nil))]
|
||||
(st/emit! (dc/change-stroke ids color index)))))
|
||||
|
||||
handle-reorder
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
|
@ -82,6 +110,13 @@
|
|||
(d/read-string))]
|
||||
(st/emit! (dc/change-stroke ids {:stroke-style value} index)))))
|
||||
|
||||
on-stroke-style-change-refactor
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [index value]
|
||||
(st/emit! (dc/change-stroke ids {:stroke-style value} index))))
|
||||
|
||||
|
||||
on-stroke-alignment-change
|
||||
(fn [index]
|
||||
(fn [event]
|
||||
|
@ -91,12 +126,24 @@
|
|||
(when-not (str/empty? value)
|
||||
(st/emit! (dc/change-stroke ids {:stroke-alignment value} index))))))
|
||||
|
||||
on-stroke-alignment-change-refactor
|
||||
(fn [index value]
|
||||
(when-not (str/empty? value)
|
||||
(st/emit! (dc/change-stroke ids {:stroke-alignment value} index))))
|
||||
|
||||
|
||||
on-stroke-width-change
|
||||
(fn [index]
|
||||
(fn [value]
|
||||
(when-not (str/empty? value)
|
||||
(st/emit! (dc/change-stroke ids {:stroke-width value} index)))))
|
||||
|
||||
on-stroke-width-change-refactor
|
||||
(fn [index value]
|
||||
(when-not (str/empty? value)
|
||||
(st/emit! (dc/change-stroke ids {:stroke-width value} index))))
|
||||
|
||||
|
||||
open-caps-select
|
||||
(fn [caps-state]
|
||||
(fn [event]
|
||||
|
@ -147,48 +194,96 @@
|
|||
disable-drag (mf/use-state false)
|
||||
|
||||
on-focus (fn [_]
|
||||
(reset! disable-drag true))
|
||||
(reset! disable-drag true))
|
||||
|
||||
on-blur (fn [_]
|
||||
(reset! disable-drag false))]
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span label]
|
||||
[:div.add-page {:on-click on-add-stroke} i/close]]
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :element-set)}
|
||||
[:div {:class (stl/css :element-title)}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? (not open?)
|
||||
:on-collapsed toggle-content
|
||||
:title label
|
||||
:class (stl/css :title-spacing-fill)}
|
||||
|
||||
[:div.element-set-content
|
||||
(cond
|
||||
(= :multiple (:strokes values))
|
||||
[:div.element-set-options-group
|
||||
[:div.element-set-label (tr "settings.multiple")]
|
||||
[:div.element-set-actions
|
||||
[:div.element-set-actions-button {:on-click handle-remove-remove-all}
|
||||
i/minus]]]
|
||||
[:button {:class (stl/css :add-stroke)
|
||||
:on-click on-add-stroke} i/add-refactor]]]
|
||||
(when open?
|
||||
[:div {:class (stl/css :element-content)}
|
||||
(cond
|
||||
(= :multiple (:strokes values))
|
||||
[:div {:class (stl/css :element-set-options-group)}
|
||||
[:div {:class (stl/css :group-label)}
|
||||
(tr "settings.multiple")]
|
||||
[:button {:on-click handle-remove-all
|
||||
:class (stl/css :remove-btn)}
|
||||
i/remove-refactor]]
|
||||
(seq (:strokes values))
|
||||
[:& h/sortable-container {}
|
||||
(for [[index value] (d/enumerate (:strokes values []))]
|
||||
[:& stroke-row {:key (dm/str "stroke-" index)
|
||||
:stroke value
|
||||
:title (tr "workspace.options.stroke-color")
|
||||
:index index
|
||||
:show-caps show-caps
|
||||
:on-color-change on-color-change-refactor
|
||||
:on-color-detach on-color-detach-refactor
|
||||
:on-stroke-width-change on-stroke-width-change-refactor
|
||||
:on-stroke-style-change on-stroke-style-change-refactor
|
||||
:on-stroke-alignment-change on-stroke-alignment-change-refactor
|
||||
:open-caps-select open-caps-select
|
||||
:close-caps-select close-caps-select
|
||||
:on-stroke-cap-start-change on-stroke-cap-start-change
|
||||
:on-stroke-cap-end-change on-stroke-cap-end-change
|
||||
:on-stroke-cap-switch on-stroke-cap-switch
|
||||
:on-remove on-remove-refactor
|
||||
:on-reorder (handle-reorder index)
|
||||
:disable-drag disable-drag
|
||||
:on-focus on-focus
|
||||
:select-on-focus (not @disable-drag)
|
||||
:on-blur on-blur
|
||||
:disable-stroke-style disable-stroke-style}])])])]
|
||||
|
||||
|
||||
(seq (:strokes values))
|
||||
[:& h/sortable-container {}
|
||||
(for [[index value] (d/enumerate (:strokes values []))]
|
||||
[:& stroke-row {:key (dm/str "stroke-" index)
|
||||
:stroke value
|
||||
:title (tr "workspace.options.stroke-color")
|
||||
:index index
|
||||
:show-caps show-caps
|
||||
:on-color-change handle-change-stroke-color
|
||||
:on-color-detach handle-detach
|
||||
:on-stroke-width-change on-stroke-width-change
|
||||
:on-stroke-style-change on-stroke-style-change
|
||||
:on-stroke-alignment-change on-stroke-alignment-change
|
||||
:open-caps-select open-caps-select
|
||||
:close-caps-select close-caps-select
|
||||
:on-stroke-cap-start-change on-stroke-cap-start-change
|
||||
:on-stroke-cap-end-change on-stroke-cap-end-change
|
||||
:on-stroke-cap-switch on-stroke-cap-switch
|
||||
:on-remove handle-remove
|
||||
:on-reorder (handle-reorder index)
|
||||
:disable-drag disable-drag
|
||||
:on-focus on-focus
|
||||
:select-on-focus (not @disable-drag)
|
||||
:on-blur on-blur
|
||||
:disable-stroke-style disable-stroke-style}])])]]))
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span label]
|
||||
[:div.add-page {:on-click on-add-stroke} i/close]]
|
||||
|
||||
[:div.element-set-content
|
||||
(cond
|
||||
(= :multiple (:strokes values))
|
||||
[:div.element-set-options-group
|
||||
[:div.element-set-label (tr "settings.multiple")]
|
||||
[:div.element-set-actions
|
||||
[:div.element-set-actions-button {:on-click handle-remove-all}
|
||||
i/minus]]]
|
||||
|
||||
|
||||
(seq (:strokes values))
|
||||
[:& h/sortable-container {}
|
||||
(for [[index value] (d/enumerate (:strokes values []))]
|
||||
[:& stroke-row {:key (dm/str "stroke-" index)
|
||||
:stroke value
|
||||
:title (tr "workspace.options.stroke-color")
|
||||
:index index
|
||||
:show-caps show-caps
|
||||
:on-color-change handle-change-stroke-color
|
||||
:on-color-detach handle-detach
|
||||
:on-stroke-width-change on-stroke-width-change
|
||||
:on-stroke-style-change on-stroke-style-change
|
||||
:on-stroke-alignment-change on-stroke-alignment-change
|
||||
:open-caps-select open-caps-select
|
||||
:close-caps-select close-caps-select
|
||||
:on-stroke-cap-start-change on-stroke-cap-start-change
|
||||
:on-stroke-cap-end-change on-stroke-cap-end-change
|
||||
:on-stroke-cap-switch on-stroke-cap-switch
|
||||
:on-remove handle-remove
|
||||
:on-reorder (handle-reorder index)
|
||||
:disable-drag disable-drag
|
||||
:on-focus on-focus
|
||||
:select-on-focus (not @disable-drag)
|
||||
:on-blur on-blur
|
||||
:disable-stroke-style disable-stroke-style}])])]])))
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.element-set {
|
||||
.element-title {
|
||||
.add-stroke {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.element-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-12;
|
||||
.element-set-options-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.group-label {
|
||||
@extend .mixed-bar;
|
||||
}
|
||||
.remove-btn {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,10 +5,13 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.svg-attrs
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.options.rows.input-row :refer [input-row]]
|
||||
[app.util.dom :as dom]
|
||||
|
@ -16,7 +19,8 @@
|
|||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc attribute-value [{:keys [attr value on-change on-delete] :as props}]
|
||||
(let [handle-change
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
handle-change
|
||||
(mf/use-callback
|
||||
(mf/deps attr on-change)
|
||||
(fn [event]
|
||||
|
@ -29,32 +33,62 @@
|
|||
(on-delete attr)))
|
||||
|
||||
label (->> attr last d/name)]
|
||||
[:div.element-set-content
|
||||
(if (string? value)
|
||||
[:div.row-flex.row-flex-removable
|
||||
[:& input-row {:label label
|
||||
:type :text
|
||||
:class "large"
|
||||
:value (str value)
|
||||
:on-change handle-change}]
|
||||
[:div.element-set-actions
|
||||
[:div.element-set-actions-button {:on-click handle-delete}
|
||||
i/minus]]]
|
||||
(if new-css-system
|
||||
[:*
|
||||
(if (string? value)
|
||||
[:div {:class (stl/css :attr-content)}
|
||||
[:span {:class (stl/css :attr-name)} label]
|
||||
[:div {:class (stl/css :attr-input)}
|
||||
[:input {:value value
|
||||
:class "input-text"
|
||||
:on-change handle-change}]]
|
||||
[:div {:class (stl/css :attr-actions)}
|
||||
[:button {:class (stl/css :attr-action-btn)
|
||||
:on-click handle-delete}
|
||||
i/remove-refactor]]]
|
||||
[:div {:class (stl/css :attr-row)}
|
||||
[:span {:class (stl/css :attr-title)}
|
||||
(str (d/name (last attr)))]
|
||||
|
||||
[:*
|
||||
[:div.element-set-title
|
||||
{:style {:border-bottom "1px solid #444" :margin-bottom "0.5rem"}}
|
||||
[:span (str (d/name (last attr)))]]
|
||||
(for [[key value] value]
|
||||
[:& attribute-value {:key key
|
||||
:attr (conj attr key)
|
||||
:value value
|
||||
:on-change on-change
|
||||
:on-delete on-delete}])])]
|
||||
|
||||
(for [[key value] value]
|
||||
[:& attribute-value {:key key
|
||||
:attr (conj attr key)
|
||||
:value value
|
||||
:on-change on-change
|
||||
:on-delete on-delete}])])]))
|
||||
|
||||
[:div.element-set-content
|
||||
(if (string? value)
|
||||
[:div.row-flex.row-flex-removable
|
||||
[:& input-row {:label label
|
||||
:type :text
|
||||
:class "large"
|
||||
:value (str value)
|
||||
:on-change handle-change}]
|
||||
[:div.element-set-actions
|
||||
[:div.element-set-actions-button {:on-click handle-delete}
|
||||
i/minus]]]
|
||||
|
||||
[:*
|
||||
[:div.element-set-title
|
||||
{:style {:border-bottom "1px solid #444" :margin-bottom "0.5rem"}}
|
||||
[:span (str (d/name (last attr)))]]
|
||||
|
||||
(for [[key value] value]
|
||||
[:& attribute-value {:key key
|
||||
:attr (conj attr key)
|
||||
:value value
|
||||
:on-change on-change
|
||||
:on-delete on-delete}])])])))
|
||||
|
||||
(mf/defc svg-attrs-menu [{:keys [ids values]}]
|
||||
(let [handle-change
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
state* (mf/use-state true)
|
||||
open? (deref state*)
|
||||
|
||||
toggle-content (mf/use-fn #(swap! state* not))
|
||||
handle-change
|
||||
(mf/use-callback
|
||||
(mf/deps ids)
|
||||
(fn [attr value]
|
||||
|
@ -75,18 +109,32 @@
|
|||
(empty? (get-in shape [:svg-attrs :style]))
|
||||
(update :svg-attrs dissoc :style))]
|
||||
shape))]
|
||||
(st/emit! (dch/update-shapes ids update-fn)))))
|
||||
|
||||
]
|
||||
(st/emit! (dch/update-shapes ids update-fn)))))]
|
||||
|
||||
(when-not (empty? (:svg-attrs values))
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span (tr "workspace.sidebar.options.svg-attrs.title")]]
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :element-set)}
|
||||
[:div {:class (stl/css :element-set-title)}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? (not open?)
|
||||
:on-collapsed toggle-content
|
||||
:title (tr "workspace.sidebar.options.svg-attrs.title")
|
||||
:class (stl/css :title-spacing-svg-attrs)}]]
|
||||
[:div {:class (stl/css :element-set-content)}
|
||||
(for [[attr-key attr-value] (:svg-attrs values)]
|
||||
[:& attribute-value {:key attr-key
|
||||
:attr [attr-key]
|
||||
:value attr-value
|
||||
:on-change handle-change
|
||||
:on-delete handle-delete}])]]
|
||||
|
||||
(for [[attr-key attr-value] (:svg-attrs values)]
|
||||
[:& attribute-value {:key attr-key
|
||||
:attr [attr-key]
|
||||
:value attr-value
|
||||
:on-change handle-change
|
||||
:on-delete handle-delete}])])))
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span (tr "workspace.sidebar.options.svg-attrs.title")]]
|
||||
|
||||
(for [[attr-key attr-value] (:svg-attrs values)]
|
||||
[:& attribute-value {:key attr-key
|
||||
:attr [attr-key]
|
||||
:value attr-value
|
||||
:on-change handle-change
|
||||
:on-delete handle-delete}])]))))
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.element-set {
|
||||
.element-set-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
.attr-row {
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
.attr-title {
|
||||
@include tabTitleTipography;
|
||||
border-bottom: $s-1 solid var(--color-foreground-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
.attr-content {
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
.attr-name {
|
||||
@include titleTipography;
|
||||
@include twoLineTextEllipsis;
|
||||
width: $s-92;
|
||||
margin: auto $s-4;
|
||||
margin-right: 0;
|
||||
}
|
||||
.attr-input {
|
||||
@extend .input-element;
|
||||
width: $s-124;
|
||||
padding-left: $s-8;
|
||||
}
|
||||
.attr-actions {
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
.attr-action-btn {
|
||||
@extend .button-tertiary;
|
||||
width: $s-28;
|
||||
height: $s-32;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.text
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.text :as txt]
|
||||
|
@ -16,6 +17,8 @@
|
|||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons nilable-option]]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.options.menus.typography :refer [typography-entry typography-options]]
|
||||
|
@ -27,147 +30,309 @@
|
|||
(mf/defc text-align-options
|
||||
[{:keys [values on-change on-blur] :as props}]
|
||||
(let [{:keys [text-align]} values
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
|
||||
handle-change
|
||||
(fn [_ new-align]
|
||||
(on-change {:text-align new-align})
|
||||
(when (some? on-blur) (on-blur)))]
|
||||
(mf/use-fn
|
||||
(fn [value]
|
||||
(let [new-align (if new-css-system
|
||||
value
|
||||
(-> (dom/get-current-target value)
|
||||
(dom/get-data "value")))]
|
||||
(on-change {:text-align new-align})
|
||||
(when (some? on-blur) (on-blur)))))]
|
||||
|
||||
;; --- Align
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.text-align-left" (sc/get-tooltip :text-align-left))
|
||||
:class (dom/classnames :current (= "left" text-align))
|
||||
:on-click #(handle-change % "left")}
|
||||
i/text-align-left]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.text-align-center" (sc/get-tooltip :text-align-center))
|
||||
:class (dom/classnames :current (= "center" text-align))
|
||||
:on-click #(handle-change % "center")}
|
||||
i/text-align-center]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.text-align-right" (sc/get-tooltip :text-align-right))
|
||||
:class (dom/classnames :current (= "right" text-align))
|
||||
:on-click #(handle-change % "right")}
|
||||
i/text-align-right]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.text-align-justify" (sc/get-tooltip :text-align-justify))
|
||||
:class (dom/classnames :current (= "justify" text-align))
|
||||
:on-click #(handle-change % "justify")}
|
||||
i/text-align-justify]]))
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :align-options)}
|
||||
[:& radio-buttons {:selected text-align
|
||||
:on-change handle-change
|
||||
:name "align-text-options"}
|
||||
[:& radio-button {:value "left"
|
||||
:id "text-align-left"
|
||||
:title (tr "workspace.options.text-options.text-align-left" (sc/get-tooltip :text-align-left))
|
||||
:icon i/text-align-left-refactor}]
|
||||
[:& radio-button {:value "center"
|
||||
:id "text-align-center"
|
||||
:title (tr "workspace.options.text-options.text-align-center" (sc/get-tooltip :text-align-center))
|
||||
:icon i/text-align-center-refactor}]
|
||||
[:& radio-button {:value "right"
|
||||
:id "text-align-right"
|
||||
:title (tr "workspace.options.text-options.text-align-right" (sc/get-tooltip :text-align-right))
|
||||
:icon i/text-align-right-refactor}]
|
||||
[:& radio-button {:value "justify"
|
||||
:id "text-align-justify"
|
||||
:title (tr "workspace.options.text-options.text-align-justify" (sc/get-tooltip :text-align-justify))
|
||||
:icon i/text-justify-refactor}]]]
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.text-align-left" (sc/get-tooltip :text-align-left))
|
||||
:class (dom/classnames :current (= "left" text-align))
|
||||
:data-value "left"
|
||||
:on-click handle-change}
|
||||
i/text-align-left]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.text-align-center" (sc/get-tooltip :text-align-center))
|
||||
:class (dom/classnames :current (= "center" text-align))
|
||||
:data-value "center"
|
||||
:on-click handle-change}
|
||||
i/text-align-center]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.text-align-right" (sc/get-tooltip :text-align-right))
|
||||
:class (dom/classnames :current (= "right" text-align))
|
||||
:data-value "right"
|
||||
:on-click handle-change}
|
||||
i/text-align-right]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.text-align-justify" (sc/get-tooltip :text-align-justify))
|
||||
:class (dom/classnames :current (= "justify" text-align))
|
||||
:data-value "justify"
|
||||
:on-click handle-change}
|
||||
i/text-align-justify]])))
|
||||
|
||||
(mf/defc text-direction-options
|
||||
[{:keys [values on-change on-blur] :as props}]
|
||||
(let [direction (:text-direction values)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
direction (:text-direction values)
|
||||
handle-change
|
||||
(fn [_ val]
|
||||
(on-change {:text-direction val})
|
||||
(when (some? on-blur) (on-blur)))]
|
||||
(mf/use-fn
|
||||
(mf/deps direction)
|
||||
(fn [value]
|
||||
(let [val (if new-css-system
|
||||
value
|
||||
(-> (dom/get-current-target value)
|
||||
(dom/get-data "value")))
|
||||
dir (if (= val direction)
|
||||
"none"
|
||||
val)]
|
||||
(on-change {:text-direction dir})
|
||||
(when (some? on-blur) (on-blur)))))]
|
||||
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :text-direction-options)}
|
||||
[:& radio-buttons {:selected direction
|
||||
:on-change handle-change
|
||||
:name "text-direction-options"}
|
||||
[:& nilable-option {:value "ltr"
|
||||
:id "ltr-text-direction"
|
||||
:title (tr "workspace.options.text-options.direction-ltr")
|
||||
:icon i/text-ltr-refactor}]
|
||||
[:& nilable-option {:value "rtl"
|
||||
:id "rtl-text-direction"
|
||||
:title (tr "workspace.options.text-options.direction-rtl")
|
||||
:icon i/text-rtl-refactor}]]]
|
||||
;; --- Align
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom-left
|
||||
{:alt (tr "workspace.options.text-options.direction-ltr")
|
||||
:class (dom/classnames :current (= "ltr" direction))
|
||||
:on-click #(handle-change % "ltr")}
|
||||
:data-value "ltr"
|
||||
:on-click handle-change}
|
||||
i/text-direction-ltr]
|
||||
[:span.tooltip.tooltip-bottom-left
|
||||
{:alt (tr "workspace.options.text-options.direction-rtl")
|
||||
:class (dom/classnames :current (= "rtl" direction))
|
||||
:on-click #(handle-change % "rtl")}
|
||||
i/text-direction-rtl]]))
|
||||
:data-value "rtl"
|
||||
:on-click handle-change}
|
||||
i/text-direction-rtl]])))
|
||||
|
||||
(mf/defc vertical-align
|
||||
[{:keys [values on-change on-blur] :as props}]
|
||||
(let [{:keys [vertical-align]} values
|
||||
new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
vertical-align (or vertical-align "top")
|
||||
handle-change
|
||||
(fn [_ new-align]
|
||||
(on-change {:vertical-align new-align})
|
||||
(when (some? on-blur) (on-blur)))]
|
||||
(mf/use-fn
|
||||
(fn [value]
|
||||
(let [new-align (if new-css-system
|
||||
value
|
||||
(-> (dom/get-current-target value)
|
||||
(dom/get-data "value")))]
|
||||
(on-change {:vertical-align new-align})
|
||||
(when (some? on-blur) (on-blur)))))]
|
||||
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom-left
|
||||
{:alt (tr "workspace.options.text-options.align-top")
|
||||
:class (dom/classnames :current (= "top" vertical-align))
|
||||
:on-click #(handle-change % "top")}
|
||||
i/align-top]
|
||||
[:span.tooltip.tooltip-bottom-left
|
||||
{:alt (tr "workspace.options.text-options.align-middle")
|
||||
:class (dom/classnames :current (= "center" vertical-align))
|
||||
:on-click #(handle-change % "center")}
|
||||
i/align-middle]
|
||||
[:span.tooltip.tooltip-bottom-left
|
||||
{:alt (tr "workspace.options.text-options.align-bottom")
|
||||
:class (dom/classnames :current (= "bottom" vertical-align))
|
||||
:on-click #(handle-change % "bottom")}
|
||||
i/align-bottom]]))
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :vertical-align-options)}
|
||||
[:& radio-buttons {:selected vertical-align
|
||||
:on-change handle-change
|
||||
:name "vertical-align-text-options"}
|
||||
[:& radio-button {:value "top"
|
||||
:id "vertical-text-align-top"
|
||||
:title (tr "workspace.options.text-options.align-top")
|
||||
:icon i/text-top-refactor}]
|
||||
[:& radio-button {:value "center"
|
||||
:id "vertical-text-align-center"
|
||||
:title (tr "workspace.options.text-options.align-middle")
|
||||
:icon i/text-middle-refactor}]
|
||||
[:& radio-button {:value "bottom"
|
||||
:id "vertical-text-align-bottom"
|
||||
:title (tr "workspace.options.text-options.align-bottom")
|
||||
:icon i/text-bottom-refactor}]]]
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom-left
|
||||
{:alt (tr "workspace.options.text-options.align-top")
|
||||
:class (dom/classnames :current (= "top" vertical-align))
|
||||
:data-value "top"
|
||||
:on-click handle-change}
|
||||
i/align-top]
|
||||
[:span.tooltip.tooltip-bottom-left
|
||||
{:alt (tr "workspace.options.text-options.align-middle")
|
||||
:class (dom/classnames :current (= "center" vertical-align))
|
||||
:data-value "center"
|
||||
:on-click handle-change}
|
||||
i/align-middle]
|
||||
[:span.tooltip.tooltip-bottom-left
|
||||
{:alt (tr "workspace.options.text-options.align-bottom")
|
||||
:class (dom/classnames :current (= "bottom" vertical-align))
|
||||
:data-value "bottom"
|
||||
:on-click handle-change}
|
||||
i/align-bottom]])))
|
||||
|
||||
(mf/defc grow-options
|
||||
[{:keys [ids values on-blur] :as props}]
|
||||
(let [grow-type (:grow-type values)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
grow-type (:grow-type values)
|
||||
|
||||
handle-change-grow
|
||||
(fn [_ grow-type]
|
||||
(let [uid (js/Symbol)]
|
||||
(mf/use-fn
|
||||
(mf/deps ids)
|
||||
(fn [value]
|
||||
(let [uid (js/Symbol)
|
||||
|
||||
grow-type (if new-css-system
|
||||
(keyword value)
|
||||
(-> (dom/get-current-target value)
|
||||
(dom/get-data "value")
|
||||
(keyword)))]
|
||||
(st/emit!
|
||||
(dwu/start-undo-transaction uid)
|
||||
(dch/update-shapes ids #(assoc % :grow-type grow-type)))
|
||||
;; We asynchronously commit so every sychronous event is resolved first and inside the transaction
|
||||
(ts/schedule #(st/emit! (dwu/commit-undo-transaction uid))))
|
||||
(when (some? on-blur) (on-blur)))]
|
||||
(when (some? on-blur) (on-blur))))]
|
||||
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.grow-fixed")
|
||||
:class (dom/classnames :current (= :fixed grow-type))
|
||||
:on-click #(handle-change-grow % :fixed)}
|
||||
i/auto-fix]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.grow-auto-width")
|
||||
:class (dom/classnames :current (= :auto-width grow-type))
|
||||
:on-click #(handle-change-grow % :auto-width)}
|
||||
i/auto-width]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.grow-auto-height")
|
||||
:class (dom/classnames :current (= :auto-height grow-type))
|
||||
:on-click #(handle-change-grow % :auto-height)}
|
||||
i/auto-height]]))
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :grow-options)}
|
||||
[:& radio-buttons {:selected (d/name grow-type)
|
||||
:on-change handle-change-grow
|
||||
:name "grow-text-options"}
|
||||
[:& radio-button {:value "fixed"
|
||||
:id "text-fixed-grow"
|
||||
:title (tr "workspace.options.text-options.grow-fixed")
|
||||
:icon i/text-fixed-refactor}]
|
||||
[:& radio-button {:value "auto-width"
|
||||
:id "text-auto-width-grow"
|
||||
:title (tr "workspace.options.text-options.grow-auto-width")
|
||||
:icon i/text-auto-width-refactor}]
|
||||
[:& radio-button {:value "auto-height"
|
||||
:id "text-auto-height-grow"
|
||||
:title (tr "workspace.options.text-options.grow-auto-height")
|
||||
:icon i/text-auto-height-refactor}]]]
|
||||
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.grow-fixed")
|
||||
:class (dom/classnames :current (= :fixed grow-type))
|
||||
:data-value "fixed"
|
||||
:on-click handle-change-grow}
|
||||
i/auto-fix]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.grow-auto-width")
|
||||
:data-value "auto-width"
|
||||
:class (dom/classnames :current (= :auto-width grow-type))
|
||||
:on-click handle-change-grow}
|
||||
i/auto-width]
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.grow-auto-height")
|
||||
:class (dom/classnames :current (= :auto-height grow-type))
|
||||
:data-value "auto-height"
|
||||
:on-click handle-change-grow}
|
||||
i/auto-height]])))
|
||||
|
||||
(mf/defc text-decoration-options
|
||||
[{:keys [values on-change on-blur] :as props}]
|
||||
(let [text-decoration (or (:text-decoration values) "none")
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
text-decoration (or (:text-decoration values) "none")
|
||||
handle-change
|
||||
(fn [_ type]
|
||||
(on-change {:text-decoration type})
|
||||
(when (some? on-blur) (on-blur)))]
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.none")
|
||||
:class (dom/classnames :current (= "none" text-decoration))
|
||||
:on-click #(handle-change % "none")}
|
||||
i/minus]
|
||||
(mf/use-fn
|
||||
(mf/deps text-decoration)
|
||||
(fn [value]
|
||||
(let [val (if new-css-system
|
||||
value
|
||||
(-> (dom/get-current-target value)
|
||||
(dom/get-data "value")))
|
||||
decoration (if (= val text-decoration)
|
||||
"none"
|
||||
val)]
|
||||
(on-change {:text-decoration decoration})
|
||||
(when (some? on-blur) (on-blur)))))]
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :text-decoration-options)}
|
||||
[:& radio-buttons {:selected text-decoration
|
||||
:on-change handle-change
|
||||
:name "text-decoration-options"}
|
||||
[:& nilable-option {:value "underline"
|
||||
:id "underline-text-decoration"
|
||||
:title (tr "workspace.options.text-options.underline" (sc/get-tooltip :underline))
|
||||
:icon i/text-underlined-refactor}]
|
||||
[:& nilable-option {:value "line-through"
|
||||
:id "line-through-text-decoration"
|
||||
:title (tr "workspace.options.text-options.strikethrough" (sc/get-tooltip :line-through))
|
||||
:icon i/text-stroked-refactor}]]]
|
||||
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.underline" (sc/get-tooltip :underline))
|
||||
:class (dom/classnames :current (= "underline" text-decoration))
|
||||
:on-click #(handle-change % "underline")}
|
||||
i/underline]
|
||||
[:div.align-icons
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.none")
|
||||
:class (dom/classnames :current (= "none" text-decoration))
|
||||
:data-value "none"
|
||||
:on-click handle-change}
|
||||
i/minus]
|
||||
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.strikethrough" (sc/get-tooltip :line-through))
|
||||
:class (dom/classnames :current (= "line-through" text-decoration))
|
||||
:on-click #(handle-change % "line-through")}
|
||||
i/strikethrough]]))
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.underline" (sc/get-tooltip :underline))
|
||||
:class (dom/classnames :current (= "underline" text-decoration))
|
||||
:data-value "underline"
|
||||
:on-click handle-change}
|
||||
i/underline]
|
||||
|
||||
[:span.tooltip.tooltip-bottom
|
||||
{:alt (tr "workspace.options.text-options.strikethrough" (sc/get-tooltip :line-through))
|
||||
:class (dom/classnames :current (= "line-through" text-decoration))
|
||||
:data-value "line-through"
|
||||
:on-click handle-change}
|
||||
i/strikethrough]])))
|
||||
|
||||
(mf/defc text-menu
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [ids type values] :as props}]
|
||||
|
||||
(let [file-id (mf/use-ctx ctx/current-file-id)
|
||||
typographies (mf/deref refs/workspace-file-typography)
|
||||
shared-libs (mf/deref refs/workspace-libraries)
|
||||
label (case type
|
||||
:multiple (tr "workspace.options.text-options.title-selection")
|
||||
:group (tr "workspace.options.text-options.title-group")
|
||||
(tr "workspace.options.text-options.title"))
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
file-id (mf/use-ctx ctx/current-file-id)
|
||||
typographies (mf/deref refs/workspace-file-typography)
|
||||
shared-libs (mf/deref refs/workspace-libraries)
|
||||
label (case type
|
||||
:multiple (tr "workspace.options.text-options.title-selection")
|
||||
:group (tr "workspace.options.text-options.title-group")
|
||||
(tr "workspace.options.text-options.title"))
|
||||
|
||||
state* (mf/use-state {:main-menu true
|
||||
:more-options false})
|
||||
state (deref state*)
|
||||
main-menu-open? (:main-menu state)
|
||||
more-options-open? (:more-options state)
|
||||
|
||||
toggle-main-menu
|
||||
(mf/use-fn
|
||||
(mf/deps main-menu-open?)
|
||||
#(swap! state* assoc-in [:main-menu] (not main-menu-open?)))
|
||||
|
||||
toggle-more-options
|
||||
(mf/use-fn
|
||||
(mf/deps more-options-open?)
|
||||
#(swap! state* assoc-in [:more-options] (not more-options-open?)))
|
||||
|
||||
typography-id (:typography-ref-id values)
|
||||
typography-file (:typography-ref-file values)
|
||||
|
||||
emit-update!
|
||||
(mf/use-callback
|
||||
|
@ -188,17 +353,17 @@
|
|||
(mf/deps values file-id shared-libs)
|
||||
(fn []
|
||||
(cond
|
||||
(and (:typography-ref-id values)
|
||||
(not= (:typography-ref-id values) :multiple)
|
||||
(not= (:typography-ref-file values) file-id))
|
||||
(and typography-id
|
||||
(not= typography-id :multiple)
|
||||
(not= typography-file file-id))
|
||||
(-> shared-libs
|
||||
(get-in [(:typography-ref-file values) :data :typographies (:typography-ref-id values)])
|
||||
(assoc :file-id (:typography-ref-file values)))
|
||||
(get-in [typography-file :data :typographies typography-id])
|
||||
(assoc :file-id typography-file))
|
||||
|
||||
(and (:typography-ref-id values)
|
||||
(not= (:typography-ref-id values) :multiple)
|
||||
(= (:typography-ref-file values) file-id))
|
||||
(get typographies (:typography-ref-id values)))))
|
||||
(and typography-id
|
||||
(not= typography-id :multiple)
|
||||
(= typography-file file-id))
|
||||
(get typographies typography-id))))
|
||||
|
||||
on-convert-to-typography
|
||||
(fn [_]
|
||||
|
@ -243,39 +408,87 @@
|
|||
(let [node (dom/get-element-by-class "public-DraftEditor-content")]
|
||||
(dom/focus! node))))))}]
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span label]
|
||||
(when (and (not typography) (not multiple?))
|
||||
[:div.add-page {:on-click on-convert-to-typography} i/close])]
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :element-set)}
|
||||
[:div {:class (stl/css :element-title)}
|
||||
[:& title-bar {:collapsable? true
|
||||
:collapsed? (not main-menu-open?)
|
||||
:on-collapsed toggle-main-menu
|
||||
:title label
|
||||
:class (stl/css :title-spacing-text)}
|
||||
(when (and (not typography) (not multiple?))
|
||||
[:button {:class (stl/css :add-typography)
|
||||
:on-click on-convert-to-typography}
|
||||
i/add-refactor])]]
|
||||
|
||||
(cond
|
||||
typography
|
||||
[:& typography-entry {:typography typography
|
||||
:local? (= (:typography-ref-file values) file-id)
|
||||
:file (get shared-libs (:typography-ref-file values))
|
||||
:on-detach handle-detach-typography
|
||||
:on-change handle-change-typography}]
|
||||
(when main-menu-open?
|
||||
[:div {:class (stl/css :element-content)}
|
||||
(cond
|
||||
typography
|
||||
[:& typography-entry {:typography typography
|
||||
:local? (= typography-file file-id)
|
||||
:file (get shared-libs typography-file)
|
||||
:on-detach handle-detach-typography
|
||||
:on-change handle-change-typography}]
|
||||
|
||||
(= (:typography-ref-id values) :multiple)
|
||||
[:div.multiple-typography
|
||||
[:div.multiple-typography-text (tr "workspace.libraries.text.multiple-typography")]
|
||||
[:div.multiple-typography-button {:on-click handle-detach-typography
|
||||
:title (tr "workspace.libraries.text.multiple-typography-tooltip")} i/unchain]]
|
||||
(= typography-id :multiple)
|
||||
[:div {:class (stl/css :multiple-typography)}
|
||||
[:span {:class (stl/css :multiple-text)} (tr "workspace.libraries.text.multiple-typography")]
|
||||
[:div {:class (stl/css :multiple-typography-button)
|
||||
:on-click handle-detach-typography
|
||||
:title (tr "workspace.libraries.text.multiple-typography-tooltip")}
|
||||
i/detach-refactor]]
|
||||
|
||||
:else
|
||||
[:> typography-options opts])
|
||||
:else
|
||||
[:> typography-options opts])
|
||||
|
||||
[:div.element-set-content
|
||||
[:div {:class (stl/css :text-align-options)}
|
||||
[:> text-align-options opts]
|
||||
[:> grow-options opts]
|
||||
[:button {:class (stl/css :more-options)
|
||||
:on-click toggle-more-options}
|
||||
i/menu-refactor]]
|
||||
|
||||
[:div.row-flex
|
||||
[:> text-align-options opts]
|
||||
[:> vertical-align opts]]
|
||||
(when more-options-open?
|
||||
[:div {:class (stl/css :text-decoration-options)}
|
||||
[:> vertical-align opts]
|
||||
[:> text-decoration-options opts]
|
||||
[:> text-direction-options opts]])])]
|
||||
|
||||
[:div.row-flex
|
||||
[:> text-decoration-options opts]
|
||||
[:> text-direction-options opts]]
|
||||
|
||||
[:div.row-flex
|
||||
[:> grow-options opts]
|
||||
[:div.align-icons]]]]))
|
||||
[:div.element-set
|
||||
[:div.element-set-title
|
||||
[:span label]
|
||||
(when (and (not typography) (not multiple?))
|
||||
[:div.add-page {:on-click on-convert-to-typography} i/close])]
|
||||
|
||||
(cond
|
||||
typography
|
||||
[:& typography-entry {:typography typography
|
||||
:local? (= typography-file file-id)
|
||||
:file (get shared-libs typography-file)
|
||||
:on-detach handle-detach-typography
|
||||
:on-change handle-change-typography}]
|
||||
|
||||
(= typography-id :multiple)
|
||||
[:div.multiple-typography
|
||||
[:div.multiple-typography-text (tr "workspace.libraries.text.multiple-typography")]
|
||||
[:div.multiple-typography-button {:on-click handle-detach-typography
|
||||
:title (tr "workspace.libraries.text.multiple-typography-tooltip")} i/unchain]]
|
||||
|
||||
:else
|
||||
[:> typography-options opts])
|
||||
|
||||
[:div.element-set-content
|
||||
|
||||
[:div.row-flex
|
||||
[:> text-align-options opts]
|
||||
[:> vertical-align opts]]
|
||||
|
||||
[:div.row-flex
|
||||
[:> text-decoration-options opts]
|
||||
[:> text-direction-options opts]]
|
||||
|
||||
[:div.row-flex
|
||||
[:> grow-options opts]
|
||||
[:div.align-icons]]]])))
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.element-set {
|
||||
.element-title {
|
||||
.add-typography {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
.element-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
.multiple-typography {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 $s-8;
|
||||
gap: $s-4;
|
||||
border-radius: $s-8;
|
||||
background-color: var(--input-background-color);
|
||||
height: $s-32;
|
||||
flex-grow: 1;
|
||||
.multiple-text {
|
||||
@include titleTipography;
|
||||
flex-grow: 1;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
.multiple-typography-button {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
.text-align-options {
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
.align-options,
|
||||
.text-direction-options,
|
||||
.vertical-align-options,
|
||||
.grow-options,
|
||||
.text-decoration-options {
|
||||
height: $s-32;
|
||||
}
|
||||
.more-options {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
.text-decoration-options {
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.menus.typography
|
||||
(:require-macros [app.main.style :refer [css]])
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
["react-virtualized" :as rvt]
|
||||
[app.common.data :as d]
|
||||
|
@ -73,15 +73,14 @@
|
|||
(dom/scroll-into-view! element))))))
|
||||
|
||||
(if new-css-system
|
||||
[:div {:class (css :font-wrapper)
|
||||
[:div {:class (stl/css :font-wrapper)
|
||||
:style style
|
||||
:ref item-ref
|
||||
:on-click on-click}
|
||||
[:div {:class (dom/classnames
|
||||
(css :font-item) true
|
||||
(css :selected) current?)}
|
||||
[:span {:class (css :label)} (:name font)]
|
||||
[:span {:class (css :icon)} (when current? i/tick-refactor)]]]
|
||||
[:div {:class (stl/css-case :font-item true
|
||||
:selected current?)}
|
||||
[:span {:class (stl/css :label)} (:name font)]
|
||||
[:span {:class (stl/css :icon)} (when current? i/tick-refactor)]]]
|
||||
|
||||
[:div.font-item {:ref item-ref
|
||||
:style style
|
||||
|
@ -186,9 +185,9 @@
|
|||
(.scrollToPosition ^js inst offset)))))
|
||||
|
||||
(if new-css-system
|
||||
[:div {:class (css :font-selector)}
|
||||
[:div {:class (css :font-selector-dropdown)}
|
||||
[:div {:class (css :header)}
|
||||
[:div {:class (stl/css :font-selector)}
|
||||
[:div {:class (stl/css :font-selector-dropdown)}
|
||||
[:div {:class (stl/css :header)}
|
||||
[:& search-bar {:on-change on-filter-change
|
||||
:value (:term @state)
|
||||
:placeholder (tr "workspace.options.search-font")}]
|
||||
|
@ -202,7 +201,7 @@
|
|||
:on-click on-select-and-close
|
||||
:current? (= (:id font) (:id @selected))}])])]
|
||||
|
||||
[:div {:class (css :fonts-list)}
|
||||
[:div {:class (stl/css :fonts-list)}
|
||||
[:> rvt/AutoSizer {}
|
||||
(fn [props]
|
||||
(let [width (unchecked-get props "width")
|
||||
|
@ -341,7 +340,7 @@
|
|||
:show-recent show-recent}])
|
||||
|
||||
[:div
|
||||
{:class (css :font-option)
|
||||
{:class (stl/css :font-option)
|
||||
:on-click #(reset! open-selector? true)}
|
||||
(cond
|
||||
(= :multiple font-id)
|
||||
|
@ -349,31 +348,30 @@
|
|||
|
||||
(some? font)
|
||||
[:*
|
||||
[:span {:class (css :name)}
|
||||
[:span {:class (stl/css :name)}
|
||||
(:name font)]
|
||||
[:span {:class (css :icon)}
|
||||
[:span {:class (stl/css :icon)}
|
||||
i/arrow-refactor]]
|
||||
|
||||
:else
|
||||
(tr "dashboard.fonts.deleted-placeholder"))]
|
||||
|
||||
[:div {:class (css :font-modifiers)}
|
||||
[:div {:class (css :font-size-options)}
|
||||
(let [sizes [8 9 10 11 12 14 16 18 24 36 48 72]
|
||||
basic-size-options (map (fn [number]
|
||||
{:value (dm/str number) :key (dm/str "size-" number) :label (dm/str number)}) sizes)
|
||||
size-options (if (= font-size :multiple)
|
||||
(conj {:value :key :mulitple-sizes :multiple :label "--"} basic-size-options)
|
||||
basic-size-options)]
|
||||
|
||||
[:& select
|
||||
{:class (css :font-size-select)
|
||||
:default-value (attr->string font-size)
|
||||
[:div {:class (stl/css :font-modifiers)}
|
||||
[:div {:class (stl/css :font-size-options)}
|
||||
(let [size-options [8 9 10 11 12 14 16 18 24 36 48 72]
|
||||
size-options (if (= font-size :multiple) (into [""] size-options) size-options)]
|
||||
[:& editable-select
|
||||
{:value (attr->string font-size)
|
||||
:class (stl/css :font-size-select)
|
||||
:input-class (stl/css :numeric-input)
|
||||
:options size-options
|
||||
:type "number"
|
||||
:placeholder "--"
|
||||
:min 3
|
||||
:max 1000
|
||||
:on-change on-font-size-change
|
||||
:on-blur on-blur}])]
|
||||
|
||||
[:div {:class (css :font-variant-options)}
|
||||
[:div {:class (stl/css :font-variant-options)}
|
||||
(let [basic-variant-options (map (fn [variant]
|
||||
{:value (:id variant) :key (pr-str variant) :label (:name variant)}) (:variants font))
|
||||
variant-options (if (= font-size :multiple)
|
||||
|
@ -381,7 +379,7 @@
|
|||
basic-variant-options)]
|
||||
;; TODO Add disabled mode
|
||||
[:& select
|
||||
{:class (css :font-variant-select)
|
||||
{:class (stl/css :font-variant-select)
|
||||
:default-value (attr->string font-variant-id)
|
||||
:options variant-options
|
||||
:on-change on-font-variant-change
|
||||
|
@ -451,34 +449,33 @@
|
|||
(fn [value attr]
|
||||
(on-change {attr (str value)}))]
|
||||
(if new-css-system
|
||||
[:div {:class (css :spacing-options)}
|
||||
[:div {:class (css :line-height)}
|
||||
[:span {:class (css :icon)
|
||||
[:div {:class (stl/css :spacing-options)}
|
||||
[:div {:class (stl/css :line-height)}
|
||||
[:span {:class (stl/css :icon)
|
||||
:alt (tr "workspace.options.text-options.line-height")}
|
||||
i/text-lineheight-refactor]
|
||||
|
||||
[:> numeric-input*
|
||||
{:min -200
|
||||
:max 200
|
||||
:step 0.1
|
||||
:default "1.2"
|
||||
:class (css :line-height-input)
|
||||
:class (stl/css :line-height-input)
|
||||
:value (attr->string line-height)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:nillable line-height-nillable
|
||||
:on-change #(handle-change % :line-height)
|
||||
:on-blur on-blur}]]
|
||||
|
||||
[:div {:class (css :letter-spacing)}
|
||||
[:div {:class (stl/css :letter-spacing)}
|
||||
[:span
|
||||
{:class (css :icon)
|
||||
{:class (stl/css :icon)
|
||||
:alt (tr "workspace.options.text-options.letter-spacing")}
|
||||
i/text-letterspacing-refactor]
|
||||
[:> numeric-input*
|
||||
{:min -200
|
||||
:max 200
|
||||
:step 0.1
|
||||
:class (css :letter-spacing-input)
|
||||
:class (stl/css :letter-spacing-input)
|
||||
:value (attr->string letter-spacing)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:on-change #(handle-change % :letter-spacing)
|
||||
|
@ -525,7 +522,7 @@
|
|||
(on-change {:text-transform type}))
|
||||
(when (some? on-blur) (on-blur)))]
|
||||
(if new-css-system
|
||||
[:div {:class (css :text-transform)}
|
||||
[:div {:class (stl/css :text-transform)}
|
||||
[:& radio-buttons {:selected text-transform
|
||||
:on-change handle-change
|
||||
:name "text-transform"}
|
||||
|
@ -574,9 +571,9 @@
|
|||
:show-recent show-recent}]
|
||||
|
||||
(if new-css-system
|
||||
[:div {:class (css :typography-options)}
|
||||
[:div {:class (stl/css :typography-options)}
|
||||
[:> font-options opts]
|
||||
[:div {:class (css :typography-variations)}
|
||||
[:div {:class (stl/css :typography-variations)}
|
||||
[:> spacing-options opts]
|
||||
[:> text-transform-options opts]]]
|
||||
|
||||
|
@ -601,26 +598,26 @@
|
|||
|
||||
(when visible?
|
||||
[:div {:ref ref
|
||||
:class (css :advanced-options-wrapper)}
|
||||
:class (stl/css :advanced-options-wrapper)}
|
||||
(if ^boolean editable?
|
||||
[:*
|
||||
[:div {:class (css :font-name-wrapper)}
|
||||
[:div {:class (stl/css :font-name-wrapper)}
|
||||
[:div
|
||||
{:class (dom/classnames (css :typography-sample-input) true)
|
||||
{:class (stl/css :typography-sample-input)
|
||||
:style {:font-family (:font-family typography)
|
||||
:font-weight (:font-weight typography)
|
||||
:font-style (:font-style typography)}}
|
||||
(tr "workspace.assets.typography.sample")]
|
||||
|
||||
[:input
|
||||
{:class (css :adv-typography-name)
|
||||
{:class (stl/css :adv-typography-name)
|
||||
:type "text"
|
||||
:ref name-input-ref
|
||||
:default-value (:name typography)
|
||||
:on-key-down on-key-down
|
||||
:on-blur on-name-blur}]
|
||||
|
||||
[:div {:class (css :action-btn)
|
||||
[:div {:class (stl/css :action-btn)
|
||||
:on-click on-close}
|
||||
i/tick-refactor]]
|
||||
|
||||
|
@ -738,49 +735,49 @@
|
|||
(dom/select-text! node)))))
|
||||
(if new-css-system
|
||||
[:*
|
||||
[:div {:class (dom/classnames (css :typography-entry) true
|
||||
(css :selected) ^boolean selected?)
|
||||
[:div {:class (stl/css-case :typography-entry true
|
||||
:selected ^boolean selected?)
|
||||
:style {:display (when ^boolean open? "none")}}
|
||||
(if renaming?
|
||||
[:div {:class (css :font-name-wrapper)}
|
||||
[:div {:class (stl/css :font-name-wrapper)}
|
||||
[:div
|
||||
{:class (dom/classnames (css :typography-sample-input) true)
|
||||
{:class (stl/css :typography-sample-input)
|
||||
:style {:font-family (:font-family typography)
|
||||
:font-weight (:font-weight typography)
|
||||
:font-style (:font-style typography)}}
|
||||
(tr "workspace.assets.typography.sample")]
|
||||
|
||||
[:input
|
||||
{:class (css :adv-typography-name)
|
||||
{:class (stl/css :adv-typography-name)
|
||||
:type "text"
|
||||
:ref name-input-ref
|
||||
:default-value (:name typography)
|
||||
:on-key-down on-key-down
|
||||
:on-blur on-name-blur}]]
|
||||
[:div
|
||||
{:class (dom/classnames (css :typography-selection-wrapper) true
|
||||
(css :is-selectable) ^boolean on-click)
|
||||
{:class (stl/css-case :typography-selection-wrapper true
|
||||
:is-selectable ^boolean on-click)
|
||||
:on-click on-click
|
||||
:on-context-menu on-context-menu}
|
||||
[:div
|
||||
{:class (dom/classnames (css :typography-sample) true)
|
||||
{:class (stl/css :typography-sample)
|
||||
:style {:font-family (:font-family typography)
|
||||
:font-weight (:font-weight typography)
|
||||
:font-style (:font-style typography)}}
|
||||
(tr "workspace.assets.typography.sample")]
|
||||
|
||||
[:div {:class (dom/classnames (css :typography-name) true)
|
||||
[:div {:class (stl/css :typography-name)
|
||||
:title (:name typography)} (:name typography)]
|
||||
|
||||
(when-not name-only?
|
||||
[:div {:class (dom/classnames (css :typography-font) true)
|
||||
[:div {:class (stl/css :typography-font)
|
||||
:title (:name font-data)}
|
||||
(:name font-data)])])
|
||||
|
||||
(when ^boolean on-detach
|
||||
[:div {:class (dom/classnames (css :element-set-actions) true)}
|
||||
[:div {:class (stl/css :element-set-actions)}
|
||||
[:div
|
||||
{:class (dom/classnames (css :element-set-actions-button) true)
|
||||
{:class (stl/css :element-set-actions-button)
|
||||
:on-pointer-enter on-pointer-enter
|
||||
:on-pointer-leave on-pointer-leave
|
||||
:on-click on-detach}
|
||||
|
|
|
@ -109,137 +109,109 @@
|
|||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: var(--assets-title-background-color);
|
||||
}
|
||||
|
||||
.typography-options {
|
||||
position: relative;
|
||||
.font-option {
|
||||
@include titleTipography;
|
||||
.typography-options {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
.font-option {
|
||||
@include titleTipography;
|
||||
@extend .asset-element;
|
||||
padding-right: 0;
|
||||
cursor: pointer;
|
||||
.name {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-28;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
stroke: var(--icon-foreground);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
.font-modifiers {
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
.font-size-options {
|
||||
@extend .asset-element;
|
||||
padding-right: 0;
|
||||
margin-bottom: $s-4;
|
||||
cursor: pointer;
|
||||
.name {
|
||||
flex-grow: 1;
|
||||
@include titleTipography;
|
||||
flex-grow: 1;
|
||||
width: $s-60;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: $s-1 solid var(--input-background-color);
|
||||
position: relative;
|
||||
.font-size-select {
|
||||
height: $s-32;
|
||||
.numeric-input {
|
||||
@extend .input-base;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
span {
|
||||
@include flexCenter;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-28;
|
||||
width: $s-28;
|
||||
min-width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
stroke: var(--icon-foreground);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
.font-modifiers {
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
.font-size-options {
|
||||
@extend .asset-element;
|
||||
.font-size-select {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-bottom: $s-4;
|
||||
flex-grow: 1;
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-28;
|
||||
min-width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
stroke: var(--icon-foreground);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
.font-size-select {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
.font-variant-options {
|
||||
@extend .asset-element;
|
||||
@include titleTipography;
|
||||
padding: 0;
|
||||
margin-bottom: $s-4;
|
||||
flex-grow: 2;
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-28;
|
||||
min-width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
stroke: var(--icon-foreground);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
.font-variant-select {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--assets-item-name-foreground-color);
|
||||
option {
|
||||
color: var(--assets-item-name-foreground-color);
|
||||
}
|
||||
&:hover {
|
||||
color: var(--assets-item-name-foreground-color-hover);
|
||||
option {
|
||||
color: var(--assets-item-name-foreground-color-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.typography-variations {
|
||||
.font-variant-options {
|
||||
padding: 0;
|
||||
flex-grow: 2;
|
||||
}
|
||||
}
|
||||
.typography-variations {
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
align-items: center;
|
||||
.spacing-options {
|
||||
display: flex;
|
||||
gap: $s-4;
|
||||
align-items: center;
|
||||
.spacing-options {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.line-height,
|
||||
.letter-spacing {
|
||||
@extend .asset-element;
|
||||
margin-bottom: $s-4;
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
stroke: var(--icon-foreground);
|
||||
}
|
||||
}
|
||||
.line-height-input,
|
||||
.letter-spacing-input {
|
||||
@include removeInputStyle;
|
||||
@include titleTipography;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
color: var(--assets-item-name-foreground-color);
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
color: var(--assets-item-name-foreground-color-hover);
|
||||
}
|
||||
gap: $s-4;
|
||||
.line-height,
|
||||
.letter-spacing {
|
||||
@extend .input-element;
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon-small;
|
||||
}
|
||||
}
|
||||
}
|
||||
.text-transform {
|
||||
@extend .asset-element;
|
||||
width: fit-content;
|
||||
padding: 0;
|
||||
margin-bottom: $s-4;
|
||||
}
|
||||
.text-transform {
|
||||
@extend .asset-element;
|
||||
width: fit-content;
|
||||
padding: 0;
|
||||
background-color: var(--radio-btns-background-color);
|
||||
&:hover {
|
||||
background-color: var(--radio-btns-background-color);
|
||||
&:hover {
|
||||
background-color: var(--radio-btns-background-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,12 +6,15 @@
|
|||
|
||||
(ns app.main.ui.workspace.sidebar.options.page
|
||||
"Page options menu entries."
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.colors :as clr]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
@ -20,20 +23,38 @@
|
|||
{::mf/wrap [mf/memo]
|
||||
::mf/wrap-props false}
|
||||
[]
|
||||
(let [options (mf/deref refs/workspace-page-options)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
options (mf/deref refs/workspace-page-options)
|
||||
on-change (mf/use-fn #(st/emit! (dw/change-canvas-color %)))
|
||||
on-open (mf/use-fn #(st/emit! (dwu/start-undo-transaction :options)))
|
||||
on-close (mf/use-fn #(st/emit! (dwu/commit-undo-transaction :options)))]
|
||||
[:div.element-set
|
||||
[:div.element-set-title (tr "workspace.options.canvas-background")]
|
||||
[:div.element-set-content
|
||||
[:& color-row
|
||||
{:disable-gradient true
|
||||
:disable-opacity true
|
||||
:title (tr "workspace.options.canvas-background")
|
||||
:color {:color (get options :background clr/canvas)
|
||||
:opacity 1}
|
||||
:on-change on-change
|
||||
:on-open on-open
|
||||
:on-close on-close}]]]))
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css :element-set)}
|
||||
[:div {:class (stl/css :element-title)}
|
||||
[:& title-bar {:collapsable? false
|
||||
:title (tr "workspace.options.canvas-background")
|
||||
:class (stl/css :title-spacing-page)}]]
|
||||
[:div {:class (stl/css :element-content)}
|
||||
[:& color-row
|
||||
{:disable-gradient true
|
||||
:disable-opacity true
|
||||
:title (tr "workspace.options.canvas-background")
|
||||
:color {:color (get options :background clr/canvas)
|
||||
:opacity 1}
|
||||
:on-change on-change
|
||||
:on-open on-open
|
||||
:on-close on-close}]]]
|
||||
|
||||
[:div.element-set
|
||||
[:div.element-set-title (tr "workspace.options.canvas-background")]
|
||||
[:div.element-set-content
|
||||
[:& color-row
|
||||
{:disable-gradient true
|
||||
:disable-opacity true
|
||||
:title (tr "workspace.options.canvas-background")
|
||||
:color {:color (get options :background clr/canvas)
|
||||
:opacity 1}
|
||||
:on-change on-change
|
||||
:on-open on-open
|
||||
:on-close on-close}]]])))
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
|
@ -5,6 +5,7 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.rows.color-row
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
|
@ -13,7 +14,7 @@
|
|||
[app.main.data.workspace.libraries :as dwl]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.components.color-bullet :as cb]
|
||||
[app.main.ui.components.color-bullet-new :as cb]
|
||||
[app.main.ui.components.color-input :refer [color-input*]]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input*]]
|
||||
[app.main.ui.context :as ctx]
|
||||
|
@ -42,7 +43,8 @@
|
|||
[{:keys [index color disable-gradient disable-opacity on-change
|
||||
on-reorder on-detach on-open on-close title on-remove
|
||||
disable-drag on-focus on-blur select-only select-on-focus]}]
|
||||
(let [current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
current-file-id (mf/use-ctx ctx/current-file-id)
|
||||
file-colors (mf/deref refs/workspace-file-colors)
|
||||
shared-libs (mf/deref refs/workspace-libraries)
|
||||
hover-detach (mf/use-state false)
|
||||
|
@ -53,6 +55,11 @@
|
|||
|
||||
color-name (dm/get-in src-colors [(:id color) :name])
|
||||
|
||||
multiple-colors? (uc/multiple? color)
|
||||
library-color? (and (:id color) color-name (not multiple-colors?))
|
||||
gradient-color? (and (not multiple-colors?)
|
||||
(:gradient color)
|
||||
(get-in color [:gradient :type]))
|
||||
parse-color
|
||||
(mf/use-fn
|
||||
(fn [color]
|
||||
|
@ -79,7 +86,7 @@
|
|||
(assoc :color new-value)
|
||||
(dissoc :gradient))]
|
||||
(st/emit! (dwl/add-recent-color color)
|
||||
(on-change color)))))
|
||||
(on-change color)))))
|
||||
|
||||
handle-opacity-change
|
||||
(mf/use-fn
|
||||
|
@ -90,14 +97,14 @@
|
|||
:id nil
|
||||
:file-id nil)]
|
||||
(st/emit! (dwl/add-recent-color color)
|
||||
(on-change color)))))
|
||||
(on-change color)))))
|
||||
|
||||
handle-click-color
|
||||
(mf/use-fn
|
||||
(mf/deps disable-gradient disable-opacity on-change on-close on-open)
|
||||
(fn [color event]
|
||||
(let [color (cond
|
||||
(uc/multiple? color)
|
||||
multiple-colors?
|
||||
{:color default-color
|
||||
:opacity 1}
|
||||
|
||||
|
@ -149,73 +156,153 @@
|
|||
(when (not= prev-color color)
|
||||
(modal/update-props! :colorpicker {:data (parse-color color)})))
|
||||
|
||||
[:div.row-flex.color-data {:title title
|
||||
:class (dom/classnames
|
||||
:dnd-over-top (= (:over dprops) :top)
|
||||
:dnd-over-bot (= (:over dprops) :bot))
|
||||
:ref dref}
|
||||
[:& cb/color-bullet {:color (cond-> color
|
||||
(nil? color-name) (assoc
|
||||
:id nil
|
||||
:file-id nil))
|
||||
:on-click handle-click-color}]
|
||||
|
||||
(cond
|
||||
;; Rendering a color with ID
|
||||
(and (:id color) color-name (not (uc/multiple? color)))
|
||||
[:*
|
||||
[:div.color-info
|
||||
[:div.color-name (str color-name)]]
|
||||
(when on-detach
|
||||
[:div.element-set-actions-button
|
||||
{:on-pointer-enter #(reset! hover-detach true)
|
||||
:on-pointer-leave #(reset! hover-detach false)
|
||||
:on-click detach-value}
|
||||
(if @hover-detach i/unchain i/chain)])
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css-case
|
||||
:color-data true
|
||||
:dnd-over-top (= (:over dprops) :top)
|
||||
:dnd-over-bot (= (:over dprops) :bot))
|
||||
:ref dref}
|
||||
[:span {:class (stl/css :color-info)}
|
||||
[:span {:class (stl/css-case :color-name-wrapper true
|
||||
:gradient-name-wrapper gradient-color?)}
|
||||
[:span {:class (stl/css :color-bullet-wrapper)}
|
||||
[:& cb/color-bullet {:color (cond-> color
|
||||
(nil? color-name) (assoc
|
||||
:id nil
|
||||
:file-id nil))
|
||||
:on-click handle-click-color}]]
|
||||
(cond
|
||||
;; Rendering a color with ID
|
||||
library-color?
|
||||
[:*
|
||||
[:div {:class (stl/css :color-name)
|
||||
:title (str color-name)}
|
||||
|
||||
(when select-only
|
||||
[:div.element-set-actions-button {:on-click handle-select}
|
||||
i/pointer-inner])]
|
||||
(str color-name)]
|
||||
(when on-detach
|
||||
[:button
|
||||
{:class (stl/css :detach-btn)
|
||||
:title (tr "settings.detach")
|
||||
:on-pointer-enter #(reset! hover-detach true)
|
||||
:on-pointer-leave #(reset! hover-detach false)
|
||||
:on-click detach-value}
|
||||
i/detach-refactor])]
|
||||
|
||||
;; Rendering a gradient
|
||||
(and (not (uc/multiple? color))
|
||||
(:gradient color)
|
||||
(get-in color [:gradient :type]))
|
||||
[:*
|
||||
[:div.color-info
|
||||
[:div.color-name (uc/gradient-type->string (get-in color [:gradient :type]))]]
|
||||
(when select-only
|
||||
[:div.element-set-actions-button {:on-click handle-select}
|
||||
i/pointer-inner])]
|
||||
;; Rendering a gradient
|
||||
gradient-color?
|
||||
[:*
|
||||
[:div {:class (stl/css :color-name)}
|
||||
(uc/gradient-type->string (get-in color [:gradient :type]))]]
|
||||
|
||||
;; Rendering a plain color
|
||||
:else
|
||||
[:span {:class (stl/css :color-input-wrapper)}
|
||||
[:> color-input* {:value (if multiple-colors?
|
||||
""
|
||||
(-> color :color uc/remove-hash))
|
||||
:placeholder (tr "settings.multiple")
|
||||
:className (stl/css :color-input)
|
||||
:on-focus on-focus
|
||||
:on-blur on-blur
|
||||
:on-change handle-value-change}]])]
|
||||
|
||||
(when (and (not gradient-color?)
|
||||
(not multiple-colors?)
|
||||
(not library-color?))
|
||||
|
||||
|
||||
;; Rendering a plain color/opacity
|
||||
:else
|
||||
[:*
|
||||
[:div.color-info
|
||||
[:> color-input* {:value (if (uc/multiple? color)
|
||||
""
|
||||
(-> color :color uc/remove-hash))
|
||||
:placeholder (tr "settings.multiple")
|
||||
:on-focus on-focus
|
||||
:on-blur on-blur
|
||||
:on-change handle-value-change}]]
|
||||
|
||||
(when (and (not disable-opacity)
|
||||
(not (:gradient color)))
|
||||
[:div.input-element
|
||||
{:class (dom/classnames :percentail (not= (:opacity color) :multiple))}
|
||||
[:div {:class (stl/css :opacity-element-wrapper)}
|
||||
[:span {:class (stl/css :icon-text)}
|
||||
"%"]
|
||||
[:> numeric-input* {:value (-> color :opacity opacity->string)
|
||||
:className (stl/css :opacity-input)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:select-on-focus select-on-focus
|
||||
:on-focus on-focus
|
||||
:on-blur on-blur
|
||||
:on-change handle-opacity-change
|
||||
:min 0
|
||||
:max 100}]])
|
||||
(when select-only
|
||||
[:div.element-set-actions-button {:on-click handle-select}
|
||||
i/pointer-inner])])
|
||||
(when (some? on-remove)
|
||||
[:div.element-set-actions-button.remove {:on-click on-remove} i/minus])]))
|
||||
:max 100}]])]
|
||||
|
||||
(when (some? on-remove)
|
||||
[:button {:class (stl/css :remove-btn)
|
||||
:on-click on-remove} i/remove-refactor])
|
||||
(when select-only
|
||||
[:button {:class (stl/css :select-btn)
|
||||
:on-click handle-select}
|
||||
i/move-refactor])]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[:div.row-flex.color-data {:title title
|
||||
:class (dom/classnames
|
||||
:dnd-over-top (= (:over dprops) :top)
|
||||
:dnd-over-bot (= (:over dprops) :bot))
|
||||
:ref dref}
|
||||
[:& cb/color-bullet {:color (cond-> color
|
||||
(nil? color-name) (assoc
|
||||
:id nil
|
||||
:file-id nil))
|
||||
:on-click handle-click-color}]
|
||||
|
||||
(cond
|
||||
;; Rendering a color with ID
|
||||
library-color?
|
||||
[:*
|
||||
[:div.color-info
|
||||
[:div.color-name (str color-name)]]
|
||||
(when on-detach
|
||||
[:div.element-set-actions-button
|
||||
{:on-pointer-enter #(reset! hover-detach true)
|
||||
:on-pointer-leave #(reset! hover-detach false)
|
||||
:on-click detach-value}
|
||||
(if @hover-detach i/unchain i/chain)])]
|
||||
|
||||
;; Rendering a gradient
|
||||
gradient-color?
|
||||
[:*
|
||||
[:div.color-info
|
||||
[:div.color-name (uc/gradient-type->string (get-in color [:gradient :type]))]]
|
||||
(when select-only
|
||||
[:div.element-set-actions-button {:on-click handle-select}
|
||||
i/pointer-inner])]
|
||||
|
||||
;; Rendering a plain color/opacity
|
||||
:else
|
||||
[:*
|
||||
[:div.color-info
|
||||
[:> color-input* {:value (if multiple-colors?
|
||||
""
|
||||
(-> color :color uc/remove-hash))
|
||||
:placeholder (tr "settings.multiple")
|
||||
:on-focus on-focus
|
||||
:on-blur on-blur
|
||||
:on-change handle-value-change}]]
|
||||
|
||||
(when (and (not disable-opacity)
|
||||
(not (:gradient color)))
|
||||
[:div.input-element
|
||||
{:class (dom/classnames :percentail (not= (:opacity color) :multiple))}
|
||||
[:> numeric-input* {:value (-> color :opacity opacity->string)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:select-on-focus select-on-focus
|
||||
:on-focus on-focus
|
||||
:on-blur on-blur
|
||||
:on-change handle-opacity-change
|
||||
:min 0
|
||||
:max 100}]])
|
||||
(when select-only
|
||||
[:div.element-set-actions-button {:on-click handle-select}
|
||||
i/pointer-inner])])
|
||||
(when (some? on-remove)
|
||||
[:div.element-set-actions-button.remove {:on-click on-remove} i/minus])])
|
||||
|
||||
))
|
||||
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.color-data {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.color-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-1;
|
||||
border-radius: $s-8;
|
||||
background-color: var(--input-details-color);
|
||||
height: $s-32;
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
.color-name-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: $br-8;
|
||||
background-color: var(--input-background-color);
|
||||
flex-grow: 1;
|
||||
|
||||
.color-bullet-wrapper {
|
||||
@extend .input-element;
|
||||
background-color: transparent;
|
||||
border-radius: $br-8 0 0 $br-8;
|
||||
padding: 0 $s-4 0 $s-8;
|
||||
&:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
.color-name {
|
||||
@include titleTipography;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: $s-32;
|
||||
flex-grow: 1;
|
||||
color: var(--input-foreground-color-active);
|
||||
}
|
||||
.detach-btn {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
border-radius: 0 $br-8 $br-8 0;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
.color-input-wrapper {
|
||||
@extend .input-element;
|
||||
border-radius: $br-0;
|
||||
}
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:focus-within {
|
||||
.color-bullet-wrapper,
|
||||
.color-name,
|
||||
.detach-btn,
|
||||
.color-input-wrapper {
|
||||
background-color: var(--input-background-color-hover);
|
||||
}
|
||||
.detach-btn svg {
|
||||
stroke: var(--input-foreground-color-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
.gradient-name-wrapper {
|
||||
.color-name {
|
||||
border-radius: 0 $br-8 $br-8 0;
|
||||
}
|
||||
}
|
||||
.opacity-element-wrapper {
|
||||
@extend .input-element;
|
||||
width: $s-60;
|
||||
border-radius: 0 $br-8 $br-8 0;
|
||||
padding-left: $s-8;
|
||||
.opacity-input {
|
||||
border-radius: 0 $br-8 $br-8 0;
|
||||
min-width: $s-28;
|
||||
}
|
||||
.icon-text {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
margin-right: $s-4;
|
||||
padding-top: $s-2;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.detach-btn,
|
||||
.select-btn {
|
||||
background-color: transparent;
|
||||
svg {
|
||||
stroke: var(--input-foreground-color-active);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.remove-btn,
|
||||
.select-btn {
|
||||
@extend .button-tertiary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
|
||||
&.dnd-over-top {
|
||||
border-top: $s-1 solid var(--layer-row-foreground-color-drag);
|
||||
}
|
||||
&.dnd-over-bot {
|
||||
border-bottom: $s-1 solid var(--layer-row-foreground-color-drag);
|
||||
}
|
||||
}
|
|
@ -5,11 +5,14 @@
|
|||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.main.ui.workspace.sidebar.options.rows.stroke-row
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||
[app.main.ui.components.numeric-input :refer [numeric-input*]]
|
||||
[app.main.ui.components.select :refer [select]]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.hooks :as h]
|
||||
[app.main.ui.icons :as i]
|
||||
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
|
||||
|
@ -49,10 +52,34 @@
|
|||
|
||||
(mf/defc stroke-row
|
||||
{::mf/wrap-props false}
|
||||
[{:keys [index stroke title show-caps on-color-change on-reorder on-color-detach on-remove on-stroke-width-change on-stroke-style-change on-stroke-alignment-change open-caps-select close-caps-select on-stroke-cap-start-change on-stroke-cap-end-change on-stroke-cap-switch disable-drag on-focus on-blur disable-stroke-style select-on-focus]}]
|
||||
(let [start-caps-state (mf/use-state {:open? false
|
||||
:top 0
|
||||
:left 0})
|
||||
[{:keys [index
|
||||
stroke
|
||||
title
|
||||
show-caps
|
||||
on-color-change
|
||||
on-reorder
|
||||
on-color-detach
|
||||
on-remove
|
||||
on-stroke-width-change
|
||||
on-stroke-style-change
|
||||
on-stroke-alignment-change
|
||||
open-caps-select
|
||||
close-caps-select
|
||||
on-stroke-cap-start-change
|
||||
on-stroke-cap-end-change
|
||||
on-stroke-cap-switch
|
||||
disable-drag
|
||||
on-focus
|
||||
on-blur
|
||||
disable-stroke-style
|
||||
select-on-focus]}]
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
start-caps-state* (mf/use-state {:open? false
|
||||
:top 0
|
||||
:left 0})
|
||||
|
||||
start-caps-state (deref start-caps-state*)
|
||||
|
||||
end-caps-state (mf/use-state {:open? false
|
||||
:top 0
|
||||
:left 0})
|
||||
|
@ -69,99 +96,255 @@
|
|||
:data {:id (str "stroke-row-" index)
|
||||
:index index
|
||||
:name (str "Border row" index)})
|
||||
[nil nil])]
|
||||
[nil nil])
|
||||
|
||||
[:div.border-data {:class (dom/classnames
|
||||
:dnd-over-top (= (:over dprops) :top)
|
||||
:dnd-over-bot (= (:over dprops) :bot))
|
||||
:ref dref}
|
||||
;; Stroke Color
|
||||
[:& color-row {:color {:color (:stroke-color stroke)
|
||||
:opacity (:stroke-opacity stroke)
|
||||
:id (:stroke-color-ref-id stroke)
|
||||
:file-id (:stroke-color-ref-file stroke)
|
||||
:gradient (:stroke-color-gradient stroke)}
|
||||
:index index
|
||||
:title title
|
||||
:on-change (on-color-change index)
|
||||
:on-detach (on-color-detach index)
|
||||
:on-remove (on-remove index)
|
||||
:disable-drag disable-drag
|
||||
:on-focus on-focus
|
||||
:select-on-focus select-on-focus
|
||||
:on-blur on-blur}]
|
||||
on-color-change-refactor
|
||||
(mf/use-callback
|
||||
(mf/deps index on-color-change)
|
||||
(fn [color]
|
||||
(on-color-change index color)))
|
||||
|
||||
;; Stroke Width, Alignment & Style
|
||||
[:div.row-flex
|
||||
[:div.input-element
|
||||
{:class (dom/classnames :pixels (not= (:stroke-width stroke) :multiple))
|
||||
:title (tr "workspace.options.stroke-width")}
|
||||
on-color-detach-refactor
|
||||
(mf/use-callback
|
||||
(mf/deps index on-color-detach)
|
||||
(fn [color]
|
||||
(on-color-detach index color)))
|
||||
|
||||
[:> numeric-input*
|
||||
{:min 0
|
||||
:value (-> (:stroke-width stroke) width->string)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:on-change (on-stroke-width-change index)
|
||||
:on-focus on-focus
|
||||
:select-on-focus select-on-focus
|
||||
:on-blur on-blur}]]
|
||||
on-remove-refactor
|
||||
(mf/use-callback
|
||||
(mf/deps index on-remove)
|
||||
#(on-remove index))
|
||||
|
||||
[:select#style.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:value (enum->string (:stroke-alignment stroke))
|
||||
:on-change (on-stroke-alignment-change index)}
|
||||
(when (= (:stroke-alignment stroke) :multiple)
|
||||
[:option {:value ""} "--"])
|
||||
[:option {:value ":center"} (tr "workspace.options.stroke.center")]
|
||||
[:option {:value ":inner"} (tr "workspace.options.stroke.inner")]
|
||||
[:option {:value ":outer"} (tr "workspace.options.stroke.outer")]]
|
||||
stroke-width (:stroke-width stroke)
|
||||
|
||||
(when-not disable-stroke-style
|
||||
[:select#style.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:value (enum->string (:stroke-style stroke))
|
||||
:on-change (on-stroke-style-change index)}
|
||||
(when (= (:stroke-style stroke) :multiple)
|
||||
[:option {:value ""} "--"])
|
||||
[:option {:value ":solid"} (tr "workspace.options.stroke.solid")]
|
||||
[:option {:value ":dotted"} (tr "workspace.options.stroke.dotted")]
|
||||
[:option {:value ":dashed"} (tr "workspace.options.stroke.dashed")]
|
||||
[:option {:value ":mixed"} (tr "workspace.options.stroke.mixed")]])]
|
||||
on-width-change
|
||||
(mf/use-callback
|
||||
(mf/deps index on-stroke-width-change)
|
||||
#(on-stroke-width-change index %))
|
||||
|
||||
;; Stroke Caps
|
||||
(when show-caps
|
||||
stroke-alignment (or (:stroke-alignment stroke) :center)
|
||||
|
||||
stroke-alignment-options
|
||||
(mf/with-memo [stroke-alignment]
|
||||
(d/concat-vec
|
||||
(when (= :multiple stroke-alignment)
|
||||
[{:value :multiple :label "--"}])
|
||||
[{:value :center :label (tr "workspace.options.stroke.center")}
|
||||
{:value :inner :label (tr "workspace.options.stroke.inner")}
|
||||
{:value :outer :label (tr "workspace.options.stroke.outer")}]))
|
||||
|
||||
on-alignment-change
|
||||
(mf/use-callback
|
||||
(mf/deps index on-stroke-alignment-change)
|
||||
#(on-stroke-alignment-change index (keyword %)))
|
||||
|
||||
stroke-style (or (:stroke-style stroke) :solid)
|
||||
|
||||
stroke-style-options
|
||||
(mf/with-memo [stroke-style]
|
||||
(d/concat-vec
|
||||
(when (= :multiple stroke-style)
|
||||
[{:value :multiple :label "--"}])
|
||||
[{:value :solid :label (tr "workspace.options.stroke.solid")}
|
||||
{:value :dotted :label (tr "workspace.options.stroke.dotted")}
|
||||
{:value :dashed :label (tr "workspace.options.stroke.dashed")}
|
||||
{:value :mixed :label (tr "workspace.options.stroke.mixed")}]))
|
||||
|
||||
on-style-change
|
||||
(mf/use-callback
|
||||
(mf/deps index on-stroke-style-change)
|
||||
#(on-stroke-style-change index (keyword %)))
|
||||
|
||||
on-caps-start-change
|
||||
(mf/use-callback
|
||||
(mf/deps index on-stroke-cap-start-change)
|
||||
#(on-stroke-cap-start-change index (keyword %)))
|
||||
|
||||
on-caps-end-change
|
||||
(mf/use-callback
|
||||
(mf/deps index on-stroke-cap-end-change)
|
||||
#(on-stroke-cap-end-change index (keyword %)))
|
||||
|
||||
stroke-caps-options
|
||||
[{:value nil :label (tr "workspace.options.stroke-cap.none")}
|
||||
:separator
|
||||
{:value :line-arrow :label (tr "workspace.options.stroke-cap.line-arrow-short")}
|
||||
{:value :triangle-arrow :label (tr "workspace.options.stroke-cap.triangle-arrow-short")}
|
||||
{:value :square-marker :label (tr "workspace.options.stroke-cap.square-marker-short")}
|
||||
{:value :circle-marker :label (tr "workspace.options.stroke-cap.circle-marker-short")}
|
||||
{:value :diamond-marker :label (tr "workspace.options.stroke-cap.diamond-marker-short")}
|
||||
:separator
|
||||
{:value :round :label (tr "workspace.options.stroke-cap.round")}
|
||||
{:value :square :label (tr "workspace.options.stroke-cap.square")}]
|
||||
|
||||
on-cap-switch
|
||||
(mf/use-callback
|
||||
(mf/deps index on-stroke-cap-switch)
|
||||
#(on-stroke-cap-switch index))]
|
||||
|
||||
(if new-css-system
|
||||
[:div {:class (stl/css-case
|
||||
:stroke-data true
|
||||
:dnd-over-top (= (:over dprops) :top)
|
||||
:dnd-over-bot (= (:over dprops) :bot))
|
||||
:ref dref}
|
||||
;; Stroke Color
|
||||
[:& color-row {:color {:color (:stroke-color stroke)
|
||||
:opacity (:stroke-opacity stroke)
|
||||
:id (:stroke-color-ref-id stroke)
|
||||
:file-id (:stroke-color-ref-file stroke)
|
||||
:gradient (:stroke-color-gradient stroke)}
|
||||
:index index
|
||||
:title title
|
||||
:on-change on-color-change-refactor
|
||||
:on-detach on-color-detach-refactor
|
||||
:on-remove on-remove-refactor
|
||||
:disable-drag disable-drag
|
||||
:on-focus on-focus
|
||||
:select-on-focus select-on-focus
|
||||
:on-blur on-blur}]
|
||||
|
||||
;; Stroke Width, Alignment & Style
|
||||
[:div {:class (stl/css :stroke-options)}
|
||||
[:div {:class (stl/css :stroke-width-input-element)
|
||||
:title (tr "workspace.options.stroke-width")}
|
||||
[:span {:class (stl/css :icon)}
|
||||
i/stroke-size-refactor]
|
||||
[:> numeric-input*
|
||||
{:min 0
|
||||
:className (stl/css :stroke-width-input)
|
||||
:value stroke-width
|
||||
:placeholder (tr "settings.multiple")
|
||||
:on-change on-width-change
|
||||
:on-focus on-focus
|
||||
:select-on-focus select-on-focus
|
||||
:on-blur on-blur}]]
|
||||
|
||||
[:div {:class (stl/css :select-wrapper)}
|
||||
[:& select
|
||||
{:default-value stroke-alignment
|
||||
:options stroke-alignment-options
|
||||
:on-change on-alignment-change}]]
|
||||
|
||||
(when-not disable-stroke-style
|
||||
[:div {:class (stl/css :select-wrapper)}
|
||||
[:& select
|
||||
{:default-value stroke-style
|
||||
:options stroke-style-options
|
||||
:on-change on-style-change}]])]
|
||||
|
||||
;; Stroke Caps
|
||||
(when show-caps
|
||||
[:div {:class (stl/css :stroke-caps-options)}
|
||||
[:div {:class (stl/css :cap-select)}
|
||||
[:& select
|
||||
{:default-value (:stroke-cap-start stroke)
|
||||
:options stroke-caps-options
|
||||
:on-change on-caps-start-change}]]
|
||||
|
||||
[:button {:class (stl/css :swap-caps-btn)
|
||||
:on-click on-cap-switch}
|
||||
i/switch-refactor]
|
||||
|
||||
[:div {:class (stl/css :cap-select)}
|
||||
[:& select
|
||||
{:default-value (:stroke-cap-end stroke)
|
||||
:options stroke-caps-options
|
||||
:on-change on-caps-end-change}]]])]
|
||||
|
||||
|
||||
|
||||
[:div.border-data {:class (dom/classnames
|
||||
:dnd-over-top (= (:over dprops) :top)
|
||||
:dnd-over-bot (= (:over dprops) :bot))
|
||||
:ref dref}
|
||||
;; Stroke Color
|
||||
[:& color-row {:color {:color (:stroke-color stroke)
|
||||
:opacity (:stroke-opacity stroke)
|
||||
:id (:stroke-color-ref-id stroke)
|
||||
:file-id (:stroke-color-ref-file stroke)
|
||||
:gradient (:stroke-color-gradient stroke)}
|
||||
:index index
|
||||
:title title
|
||||
:on-change (on-color-change index)
|
||||
:on-detach (on-color-detach index)
|
||||
:on-remove (on-remove index)
|
||||
:disable-drag disable-drag
|
||||
:on-focus on-focus
|
||||
:select-on-focus select-on-focus
|
||||
:on-blur on-blur}]
|
||||
|
||||
;; Stroke Width, Alignment & Style
|
||||
[:div.row-flex
|
||||
[:div.cap-select {:tab-index 0 ;; tab-index to make the element focusable
|
||||
:on-click (open-caps-select start-caps-state)}
|
||||
(value->name (:stroke-cap-start stroke))
|
||||
[:span.cap-select-button
|
||||
i/arrow-down]]
|
||||
[:& dropdown {:show (:open? @start-caps-state)
|
||||
:on-close (close-caps-select start-caps-state)}
|
||||
[:ul.dropdown.cap-select-dropdown {:style {:top (:top @start-caps-state)
|
||||
:left (:left @start-caps-state)}}
|
||||
(for [[idx [value label separator]] (d/enumerate (stroke-cap-names))]
|
||||
(let [img (value->img value)]
|
||||
[:li {:key (dm/str "start-cap-" idx)
|
||||
:class (dom/classnames :separator separator)
|
||||
:on-click #(on-stroke-cap-start-change index value)}
|
||||
(when img [:img {:src (value->img value)}])
|
||||
label]))]]
|
||||
[:div.input-element
|
||||
{:class (dom/classnames :pixels (not= (:stroke-width stroke) :multiple))
|
||||
:title (tr "workspace.options.stroke-width")}
|
||||
|
||||
[:div.element-set-actions-button {:on-click #(on-stroke-cap-switch index)}
|
||||
i/switch]
|
||||
[:> numeric-input*
|
||||
{:min 0
|
||||
:value (-> (:stroke-width stroke) width->string)
|
||||
:placeholder (tr "settings.multiple")
|
||||
:on-change (on-stroke-width-change index)
|
||||
:on-focus on-focus
|
||||
:select-on-focus select-on-focus
|
||||
:on-blur on-blur}]]
|
||||
|
||||
[:div.cap-select {:tab-index 0
|
||||
:on-click (open-caps-select end-caps-state)}
|
||||
(value->name (:stroke-cap-end stroke))
|
||||
[:span.cap-select-button
|
||||
i/arrow-down]]
|
||||
[:& dropdown {:show (:open? @end-caps-state)
|
||||
:on-close (close-caps-select end-caps-state)}
|
||||
[:ul.dropdown.cap-select-dropdown {:style {:top (:top @end-caps-state)
|
||||
:left (:left @end-caps-state)}}
|
||||
(for [[idx [value label separator]] (d/enumerate (stroke-cap-names))]
|
||||
(let [img (value->img value)]
|
||||
[:li {:key (dm/str "end-cap-" idx)
|
||||
:class (dom/classnames :separator separator)
|
||||
:on-click #(on-stroke-cap-end-change index value)}
|
||||
(when img [:img {:src (value->img value)}])
|
||||
label]))]]])]))
|
||||
[:select#style.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:value (enum->string (:stroke-alignment stroke))
|
||||
:on-change (on-stroke-alignment-change index)}
|
||||
(when (= (:stroke-alignment stroke) :multiple)
|
||||
[:option {:value ""} "--"])
|
||||
[:option {:value ":center"} (tr "workspace.options.stroke.center")]
|
||||
[:option {:value ":inner"} (tr "workspace.options.stroke.inner")]
|
||||
[:option {:value ":outer"} (tr "workspace.options.stroke.outer")]]
|
||||
|
||||
(when-not disable-stroke-style
|
||||
[:select#style.input-select {:data-mousetrap-dont-stop true ;; makes mousetrap to not stop at this element
|
||||
:value (enum->string (:stroke-style stroke))
|
||||
:on-change (on-stroke-style-change index)}
|
||||
(when (= (:stroke-style stroke) :multiple)
|
||||
[:option {:value ""} "--"])
|
||||
[:option {:value ":solid"} (tr "workspace.options.stroke.solid")]
|
||||
[:option {:value ":dotted"} (tr "workspace.options.stroke.dotted")]
|
||||
[:option {:value ":dashed"} (tr "workspace.options.stroke.dashed")]
|
||||
[:option {:value ":mixed"} (tr "workspace.options.stroke.mixed")]])]
|
||||
|
||||
;; Stroke Caps
|
||||
(when show-caps
|
||||
[:div.row-flex
|
||||
[:div.cap-select {:tab-index 0 ;; tab-index to make the element focusable
|
||||
:on-click (open-caps-select start-caps-state*)}
|
||||
(value->name (:stroke-cap-start stroke))
|
||||
[:span.cap-select-button
|
||||
i/arrow-down]]
|
||||
[:& dropdown {:show (:open? start-caps-state)
|
||||
:on-close (close-caps-select start-caps-state*)}
|
||||
[:ul.dropdown.cap-select-dropdown {:style {:top (:top start-caps-state)
|
||||
:left (:left start-caps-state)}}
|
||||
(for [[idx [value label separator]] (d/enumerate (stroke-cap-names))]
|
||||
(let [img (value->img value)]
|
||||
[:li {:key (dm/str "start-cap-" idx)
|
||||
:class (dom/classnames :separator separator)
|
||||
:on-click #(on-stroke-cap-start-change index value)}
|
||||
(when img [:img {:src (value->img value)}])
|
||||
label]))]]
|
||||
|
||||
[:div.element-set-actions-button {:on-click #(on-stroke-cap-switch index)}
|
||||
i/switch]
|
||||
|
||||
[:div.cap-select {:tab-index 0
|
||||
:on-click (open-caps-select end-caps-state)}
|
||||
(value->name (:stroke-cap-end stroke))
|
||||
[:span.cap-select-button
|
||||
i/arrow-down]]
|
||||
[:& dropdown {:show (:open? @end-caps-state)
|
||||
:on-close (close-caps-select end-caps-state)}
|
||||
[:ul.dropdown.cap-select-dropdown {:style {:top (:top @end-caps-state)
|
||||
:left (:left @end-caps-state)}}
|
||||
(for [[idx [value label separator]] (d/enumerate (stroke-cap-names))]
|
||||
(let [img (value->img value)]
|
||||
[:li {:key (dm/str "end-cap-" idx)
|
||||
:class (dom/classnames :separator separator)
|
||||
:on-click #(on-stroke-cap-end-change index value)}
|
||||
(when img [:img {:src (value->img value)}])
|
||||
label]))]]])])))
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// Copyright (c) KALEIDOS INC
|
||||
|
||||
@import "refactor/common-refactor.scss";
|
||||
|
||||
.stroke-data {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $s-4;
|
||||
.stroke-options {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.stroke-width-input-element {
|
||||
@extend .input-element;
|
||||
width: $s-60;
|
||||
border-radius: $br-8;
|
||||
padding: $s-8;
|
||||
.icon {
|
||||
@include flexCenter;
|
||||
height: $s-32;
|
||||
width: $s-12;
|
||||
margin-right: $s-4;
|
||||
}
|
||||
}
|
||||
.select-wrapper {
|
||||
width: $s-124;
|
||||
}
|
||||
}
|
||||
.stroke-caps-options {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: $s-4;
|
||||
.cap-select {
|
||||
width: $s-124;
|
||||
}
|
||||
.swap-caps-btn {
|
||||
@extend .button-secondary;
|
||||
height: $s-32;
|
||||
width: $s-28;
|
||||
svg {
|
||||
@extend .button-icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.dnd-over-top {
|
||||
border-top: $s-1 solid var(--layer-row-foreground-color-drag);
|
||||
}
|
||||
&.dnd-over-bot {
|
||||
border-bottom: $s-1 solid var(--layer-row-foreground-color-drag);
|
||||
}
|
||||
}
|
|
@ -44,7 +44,7 @@
|
|||
}
|
||||
.resize-area {
|
||||
position: absolute;
|
||||
bottom: -8px;
|
||||
bottom: calc(-1 * $s-8);
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: $s-12;
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
position: absolute;
|
||||
left: auto;
|
||||
bottom: $s-0;
|
||||
max-width: $s-248;
|
||||
max-width: $s-480;
|
||||
padding: $s-4;
|
||||
margin: 0 0 $s-4 0;
|
||||
z-index: $z-index-3;
|
||||
|
@ -22,6 +22,7 @@
|
|||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
gap: $s-8;
|
||||
padding: $s-8;
|
||||
margin-bottom: $s-4;
|
||||
|
@ -41,7 +42,6 @@
|
|||
max-width: $s-380;
|
||||
}
|
||||
.lib-num {
|
||||
background-color: green;
|
||||
margin-left: $s-4;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.rasterizer :as thr]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.css-cursors :as cur]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.keyboard :as kbd]
|
||||
|
@ -23,7 +24,8 @@
|
|||
(mf/defc pixel-overlay
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [vport (unchecked-get props "vport")
|
||||
(let [new-css-system (mf/use-ctx ctx/new-css-system)
|
||||
vport (unchecked-get props "vport")
|
||||
|
||||
viewport-ref (unchecked-get props "viewport-ref")
|
||||
viewport-node (mf/ref-val viewport-ref)
|
||||
|
@ -52,7 +54,9 @@
|
|||
(when-let [zoom-view-node (dom/get-element "picker-detail")]
|
||||
(when-not (mf/ref-val zoom-view-context)
|
||||
(mf/set-ref-val! zoom-view-context (.getContext zoom-view-node "2d")))
|
||||
(let [{brx :left bry :top} (dom/get-bounding-rect viewport-node)
|
||||
(let [canvas-width (if new-css-system 260 200)
|
||||
canvas-height (if new-css-system 140 160)
|
||||
{brx :left bry :top} (dom/get-bounding-rect viewport-node)
|
||||
|
||||
x (- (.-clientX event) brx)
|
||||
y (- (.-clientY event) bry)
|
||||
|
@ -75,8 +79,8 @@
|
|||
sh 40
|
||||
dx 0
|
||||
dy 0
|
||||
dw 200
|
||||
dh 160]
|
||||
dw canvas-width
|
||||
dh canvas-height]
|
||||
(when (obj/get zoom-context "imageSmoothingEnabled")
|
||||
(obj/set! zoom-context "imageSmoothingEnabled" false))
|
||||
(.drawImage zoom-context canvas sx sy sw sh dx dy dw dh)
|
||||
|
|
|
@ -2284,6 +2284,10 @@ msgstr "Go to login"
|
|||
msgid "settings.multiple"
|
||||
msgstr "Mixed"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs,
|
||||
msgid "settings.detach"
|
||||
msgstr "Detach"
|
||||
|
||||
# SECTIONS
|
||||
msgid "shortcut-section.basics"
|
||||
msgstr "Basics"
|
||||
|
@ -4140,14 +4144,26 @@ msgstr "Stroke"
|
|||
msgid "workspace.options.stroke-cap.circle-marker"
|
||||
msgstr "Circle marker"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.circle-marker-short"
|
||||
msgstr "Circle"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.diamond-marker"
|
||||
msgstr "Diamond marker"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.diamond-marker-short"
|
||||
msgstr "Diamond"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.line-arrow"
|
||||
msgstr "Line arrow"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.line-arrow-short"
|
||||
msgstr "Arrow"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.none"
|
||||
msgstr "None"
|
||||
|
@ -4164,10 +4180,18 @@ msgstr "Square"
|
|||
msgid "workspace.options.stroke-cap.square-marker"
|
||||
msgstr "Square marker"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.square-marker-short"
|
||||
msgstr "Rectangle"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.triangle-arrow"
|
||||
msgstr "Triangle arrow"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.triangle-arrow-short"
|
||||
msgstr "Triangle"
|
||||
|
||||
msgid "workspace.options.stroke-color"
|
||||
msgstr "Stroke color"
|
||||
|
||||
|
|
|
@ -2357,6 +2357,10 @@ msgstr "Ir al login"
|
|||
msgid "settings.multiple"
|
||||
msgstr "Varios"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/rows/color_row.cljs,
|
||||
msgid "settings.detach"
|
||||
msgstr "Desacoplar"
|
||||
|
||||
# SECTIONS
|
||||
msgid "shortcut-section.basics"
|
||||
msgstr "Básicos"
|
||||
|
@ -4235,14 +4239,26 @@ msgstr "Borde"
|
|||
msgid "workspace.options.stroke-cap.circle-marker"
|
||||
msgstr "Marcador círculo"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.circle-marker-short"
|
||||
msgstr "Círculo"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.diamond-marker"
|
||||
msgstr "Marcador diamante"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.diamond-marker-short"
|
||||
msgstr "Diamante"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.line-arrow"
|
||||
msgstr "Flecha de línea"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.line-arrow-short"
|
||||
msgstr "Flecha"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.none"
|
||||
msgstr "Ninguno"
|
||||
|
@ -4259,10 +4275,18 @@ msgstr "Cuadrado"
|
|||
msgid "workspace.options.stroke-cap.square-marker"
|
||||
msgstr "Marcador cuadrado"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.square-marker-short"
|
||||
msgstr "Rectángulo"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.triangle-arrow"
|
||||
msgstr "Flecha triángulo"
|
||||
|
||||
#: src/app/main/ui/workspace/sidebar/options/menus/stroke.cljs
|
||||
msgid "workspace.options.stroke-cap.triangle-arrow-short"
|
||||
msgstr "Triángulo"
|
||||
|
||||
msgid "workspace.options.stroke-color"
|
||||
msgstr "Color del trazo"
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue