mirror of
https://github.com/penpot/penpot.git
synced 2026-01-19 11:50:40 -05:00
Compare commits
4 Commits
staging-re
...
niwinz-pat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e52de90f6 | ||
|
|
3ecf509f3b | ||
|
|
7f395b2642 | ||
|
|
2a62bd2586 |
@@ -223,7 +223,7 @@ http {
|
||||
add_header X-Cache-Status $upstream_cache_status;
|
||||
}
|
||||
|
||||
location ~* \.(jpg|png|svg|ttf|woff|woff2)$ {
|
||||
location ~* \.(jpg|png|svg|ttf|woff|woff2|gif)$ {
|
||||
add_header Cache-Control "public, max-age=604800" always; # 7 days
|
||||
}
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ http {
|
||||
location / {
|
||||
include /etc/nginx/overrides/location.d/*.conf;
|
||||
|
||||
location ~* \.(js|css|jpg|png|svg|ttf|woff|woff2|wasm)$ {
|
||||
location ~* \.(js|css|jpg|png|svg|gif|ttf|woff|woff2|wasm)$ {
|
||||
add_header Cache-Control "public, max-age=604800" always; # 7 days
|
||||
}
|
||||
|
||||
|
||||
BIN
frontend/resources/images/features/2.13-shadow-tokens.gif
Normal file
BIN
frontend/resources/images/features/2.13-shadow-tokens.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 389 KiB |
BIN
frontend/resources/images/features/2.13-slide-0.jpg
Normal file
BIN
frontend/resources/images/features/2.13-slide-0.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
BIN
frontend/resources/images/features/2.13-trash.gif
Normal file
BIN
frontend/resources/images/features/2.13-trash.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 284 KiB |
@@ -17,14 +17,12 @@
|
||||
|
||||
(defn generate-path-changes
|
||||
"Generates changes to update the new content of the shape"
|
||||
[it objects page-id shape old-content new-content]
|
||||
[it objects page-id shape-id old-content new-content]
|
||||
|
||||
(assert (path/content? old-content))
|
||||
(assert (path/content? new-content))
|
||||
|
||||
(let [shape-id (:id shape)
|
||||
|
||||
;; We set the old values so the update-shapes works
|
||||
(let [;; We set the old values so the update-shapes works
|
||||
objects
|
||||
(update objects shape-id
|
||||
(fn [shape]
|
||||
@@ -82,7 +80,7 @@
|
||||
shape (st/get-path state)]
|
||||
|
||||
(if (and (some? old-content) (some? (:id shape)))
|
||||
(let [changes (generate-path-changes it objects page-id shape old-content (:content shape))]
|
||||
(let [changes (generate-path-changes it objects page-id id old-content (:content shape))]
|
||||
(rx/of (dch/commit-changes changes)))
|
||||
(rx/empty)))))))
|
||||
|
||||
|
||||
@@ -65,14 +65,45 @@
|
||||
point-change (->> (map hash-map old-points new-points) (reduce merge))]
|
||||
|
||||
(when (and (some? new-content) (some? shape))
|
||||
(let [changes (changes/generate-path-changes it objects page-id shape (:content shape) new-content)]
|
||||
(let [changes (changes/generate-path-changes it objects page-id id (:content shape) new-content)]
|
||||
(if (empty? new-content)
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(dwe/clear-edition-mode))
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(selection/update-selection point-change)
|
||||
(selection/update-selection id point-change)
|
||||
(fn [state] (update-in state [:workspace-local :edit-path id] dissoc :content-modifiers :moving-nodes :moving-handler))))))))))))
|
||||
|
||||
|
||||
|
||||
(defn apply-content-modifiers2
|
||||
[shape-id old-content]
|
||||
(ptk/reify ::apply-content-modifiers2
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(let [ ;; FIXME: hide under getter function under state
|
||||
content-modifiers
|
||||
(dm/get-in state [:workspace-local :edit-path shape-id :content-modifiers])]
|
||||
|
||||
(if (nil? content-modifiers)
|
||||
(rx/of (dwe/clear-edition-mode))
|
||||
(let [page-id (get state :current-page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
new-content (path/apply-content-modifiers old-content content-modifiers)
|
||||
point-change (->> (map hash-map
|
||||
(path.segment/get-points old-content)
|
||||
(path.segment/get-points new-content))
|
||||
(reduce merge))
|
||||
changes (changes/generate-path-changes it objects page-id shape-id old-content new-content)]
|
||||
|
||||
(if (empty? new-content)
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(dwe/clear-edition-mode))
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(selection/update-selection shape-id point-change)
|
||||
(fn [state]
|
||||
(update-in state [:workspace-local :edit-path shape-id]
|
||||
dissoc :content-modifiers :moving-nodes :moving-handler))))))))))
|
||||
|
||||
(defn modify-content-point
|
||||
[content {dx :x dy :y} modifiers point]
|
||||
(let [point-indices (path.segment/point-indices content point) ;; [indices]
|
||||
@@ -335,22 +366,21 @@
|
||||
(watch [_ _ _]
|
||||
(rx/of (ptk/data-event :layout/update {:ids [id]})))))
|
||||
|
||||
(defn split-segments
|
||||
[{:keys [from-p to-p t]}]
|
||||
(defn- split-segments
|
||||
[shape-id {:keys [from-p to-p t]}]
|
||||
(ptk/reify ::split-segments
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [id (st/get-path-id state)
|
||||
content (st/get-path state :content)]
|
||||
(-> state
|
||||
(assoc-in [:workspace-local :edit-path id :old-content] content)
|
||||
(st/set-content (-> content
|
||||
(path.segment/split-segments #{from-p to-p} t)
|
||||
(path/content))))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/of (changes/save-path-content {:preserve-move-to true})))))
|
||||
(watch [it state _]
|
||||
(let [page-id (get state :current-page-id)
|
||||
objects (dsh/lookup-page-objects state page-id)
|
||||
shape (get objects shape-id)
|
||||
old-content (get shape :content)
|
||||
new-content (-> old-content
|
||||
(path.segment/split-segments #{from-p to-p} t)
|
||||
(path/content))
|
||||
changes (changes/generate-path-changes it objects page-id shape-id old-content new-content)]
|
||||
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
(defn create-node-at-position
|
||||
[event]
|
||||
@@ -359,4 +389,4 @@
|
||||
(watch [_ state _]
|
||||
(let [id (st/get-path-id state)]
|
||||
(rx/of (dwsh/update-shapes [id] path/convert-to-path)
|
||||
(split-segments event))))))
|
||||
(split-segments id event))))))
|
||||
|
||||
@@ -149,12 +149,11 @@
|
||||
(rx/of (clear-area-selection))))))))
|
||||
|
||||
(defn update-selection
|
||||
[point-change]
|
||||
[id point-change]
|
||||
(ptk/reify ::update-selection
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [id (st/get-path-id state)
|
||||
selected-points (dm/get-in state [:workspace-local :edit-path id :selected-points] #{})
|
||||
(let [selected-points (dm/get-in state [:workspace-local :edit-path id :selected-points] #{})
|
||||
selected-points (into #{} (map point-change) selected-points)]
|
||||
(-> state
|
||||
(assoc-in [:workspace-local :edit-path id :selected-points] selected-points))))))
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
[app.common.types.path.shape-to-path :as stp]))
|
||||
|
||||
(defn get-path-id
|
||||
"Retrieves the currently editing path id"
|
||||
"Retrieves the currently editing shape path id"
|
||||
[state]
|
||||
(or (dm/get-in state [:workspace-local :edition])
|
||||
(dm/get-in state [:workspace-drawing :object :id])))
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
(path/close-subpaths))
|
||||
|
||||
changes
|
||||
(changes/generate-path-changes it objects page-id shape (:content shape) new-content)]
|
||||
(changes/generate-path-changes it objects page-id (:id shape) (:content shape) new-content)]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (dwsh/update-shapes [id] path/convert-to-path)
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
[app.main.ui.releases.v2-10]
|
||||
[app.main.ui.releases.v2-11]
|
||||
[app.main.ui.releases.v2-12]
|
||||
[app.main.ui.releases.v2-13]
|
||||
[app.main.ui.releases.v2-2]
|
||||
[app.main.ui.releases.v2-3]
|
||||
[app.main.ui.releases.v2-4]
|
||||
@@ -103,4 +104,4 @@
|
||||
|
||||
(defmethod rc/render-release-notes "0.0"
|
||||
[params]
|
||||
(rc/render-release-notes (assoc params :version "2.12")))
|
||||
(rc/render-release-notes (assoc params :version "2.13")))
|
||||
|
||||
118
frontend/src/app/main/ui/releases/v2_13.cljs
Normal file
118
frontend/src/app/main/ui/releases/v2_13.cljs
Normal file
@@ -0,0 +1,118 @@
|
||||
;; 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
|
||||
|
||||
(ns app.main.ui.releases.v2-13
|
||||
(:require-macros [app.main.style :as stl])
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.ui.releases.common :as c]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(defmethod c/render-release-notes "2.13"
|
||||
[{:keys [slide klass next finish navigate version]}]
|
||||
(mf/html
|
||||
(case slide
|
||||
:start
|
||||
[:div {:class (stl/css-case :modal-overlay true)}
|
||||
[:div.animated {:class klass}
|
||||
[:div {:class (stl/css :modal-container)}
|
||||
[:img {:src "images/features/2.13-slide-0.jpg"
|
||||
:class (stl/css :start-image)
|
||||
:border "0"
|
||||
:alt "Penpot 2.13 is here!"}]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:div {:class (stl/css :modal-header)}
|
||||
[:h1 {:class (stl/css :modal-title)}
|
||||
"What’s new in Penpot?"]
|
||||
|
||||
[:div {:class (stl/css :version-tag)}
|
||||
(dm/str "Version " version)]]
|
||||
|
||||
[:div {:class (stl/css :features-block)}
|
||||
[:span {:class (stl/css :feature-title)}
|
||||
"The first release of the year, and we’re just getting started 🚀"]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"This is our first release of the year, and it sets the tone for what’s coming next. We’re kicking off an exciting year where we’ll take Penpot to a whole new level, with improved performance, stronger design system foundations, long-requested features, and new capabilities that unlock better workflows for teams."]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"This release brings two highlights the community has been asking for, along with solid improvements under the hood to keep everything fast and smooth."]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Let’s dive in!"]]
|
||||
|
||||
[:div {:class (stl/css :navigation)}
|
||||
[:button {:class (stl/css :next-btn)
|
||||
:on-click next} "Continue"]]]]]]
|
||||
|
||||
0
|
||||
[:div {:class (stl/css-case :modal-overlay true)}
|
||||
[:div.animated {:class klass}
|
||||
[:div {:class (stl/css :modal-container)}
|
||||
[:img {:src "images/features/2.13-trash.gif"
|
||||
:class (stl/css :start-image)
|
||||
:border "0"
|
||||
:alt "The Trash"}]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:div {:class (stl/css :modal-header)}
|
||||
[:h1 {:class (stl/css :modal-title)}
|
||||
"The Trash"]]
|
||||
|
||||
[:div {:class (stl/css :feature)}
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Deleting a file no longer means it’s gone forever. Introducing The Trash, a dedicated space in the dashboard where deleted files and projects live before being permanently removed."]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"From here, you can recover content deleted by mistake or clean things up for good when you’re sure you don’t need them anymore. The Trash works for both files and projects, and items are automatically removed after a period of time depending on your Penpot plan."]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Highly requested, long overdue, and now officially here."]]
|
||||
|
||||
[:div {:class (stl/css :navigation)}
|
||||
[:& c/navigation-bullets
|
||||
{:slide slide
|
||||
:navigate navigate
|
||||
:total 3}]
|
||||
|
||||
[:button {:on-click next
|
||||
:class (stl/css :next-btn)} "Continue"]]]]]]
|
||||
|
||||
1
|
||||
[:div {:class (stl/css-case :modal-overlay true)}
|
||||
[:div.animated {:class klass}
|
||||
[:div {:class (stl/css :modal-container)}
|
||||
[:img {:src "images/features/2.13-shadow-tokens.gif"
|
||||
:class (stl/css :start-image)
|
||||
:border "0"
|
||||
:alt "Shadow tokens: Reusable shadows, at last!"}]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:div {:class (stl/css :modal-header)}
|
||||
[:h1 {:class (stl/css :modal-title)}
|
||||
"Shadow tokens: Reusable shadows, at last!"]]
|
||||
[:div {:class (stl/css :feature)}
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"With Shadow tokens, we’re introducing our second composite token, right after Typography tokens. This is a big step forward for design systems in Penpot."]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Until now, shadows couldn’t be defined as reusable styles the way colors could before color tokens existed. Shadow tokens change that. You can now create reusable, consistent shadows, made of one or multiple layers, fully tokenized and ready to scale across your designs."]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"Each shadow can reference existing tokens or use custom values, supports both Drop Shadow and Inner Shadow, and even allows shadow tokens to reference other shadow tokens. A brand-new capability, unlocked."]]
|
||||
|
||||
[:div {:class (stl/css :navigation)}
|
||||
|
||||
[:& c/navigation-bullets
|
||||
{:slide slide
|
||||
:navigate navigate
|
||||
:total 2}]
|
||||
|
||||
[:button {:on-click finish
|
||||
:class (stl/css :next-btn)} "Let's go"]]]]]])))
|
||||
|
||||
102
frontend/src/app/main/ui/releases/v2_13.scss
Normal file
102
frontend/src/app/main/ui/releases/v2_13.scss
Normal file
@@ -0,0 +1,102 @@
|
||||
// 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
|
||||
|
||||
@use "refactor/common-refactor.scss" as deprecated;
|
||||
|
||||
.modal-overlay {
|
||||
@extend .modal-overlay-base;
|
||||
}
|
||||
|
||||
.modal-container {
|
||||
display: grid;
|
||||
grid-template-columns: deprecated.$s-324 1fr;
|
||||
height: deprecated.$s-500;
|
||||
width: deprecated.$s-888;
|
||||
border-radius: deprecated.$br-8;
|
||||
background-color: var(--modal-background-color);
|
||||
border: deprecated.$s-2 solid var(--modal-border-color);
|
||||
}
|
||||
|
||||
.start-image {
|
||||
width: deprecated.$s-324;
|
||||
border-radius: deprecated.$br-8 0 0 deprecated.$br-8;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
padding: deprecated.$s-40;
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr deprecated.$s-32;
|
||||
gap: deprecated.$s-24;
|
||||
|
||||
a {
|
||||
color: var(--button-primary-background-color-rest);
|
||||
}
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: grid;
|
||||
gap: deprecated.$s-8;
|
||||
}
|
||||
|
||||
.version-tag {
|
||||
@include deprecated.flexCenter;
|
||||
@include deprecated.headlineSmallTypography;
|
||||
height: deprecated.$s-32;
|
||||
width: deprecated.$s-96;
|
||||
background-color: var(--communication-tag-background-color);
|
||||
color: var(--communication-tag-foreground-color);
|
||||
border-radius: deprecated.$br-8;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
@include deprecated.headlineLargeTypography;
|
||||
color: var(--modal-title-foreground-color);
|
||||
}
|
||||
|
||||
.features-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: deprecated.$s-16;
|
||||
width: deprecated.$s-440;
|
||||
}
|
||||
|
||||
.feature {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: deprecated.$s-8;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
@include deprecated.bodyLargeTypography;
|
||||
color: var(--modal-title-foreground-color);
|
||||
}
|
||||
|
||||
.feature-content {
|
||||
@include deprecated.bodyMediumTypography;
|
||||
margin: 0;
|
||||
color: var(--modal-text-foreground-color);
|
||||
}
|
||||
|
||||
.feature-list {
|
||||
@include deprecated.bodyMediumTypography;
|
||||
color: var(--modal-text-foreground-color);
|
||||
list-style: disc;
|
||||
display: grid;
|
||||
gap: deprecated.$s-8;
|
||||
}
|
||||
|
||||
.navigation {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-areas: "bullets button";
|
||||
}
|
||||
|
||||
.next-btn {
|
||||
@extend .button-primary;
|
||||
width: deprecated.$s-100;
|
||||
justify-self: flex-end;
|
||||
grid-area: button;
|
||||
}
|
||||
@@ -273,4 +273,4 @@
|
||||
{:label (tr "workspace.tokens.import-menu-folder-option") :value :folder}]
|
||||
:on-click handle-import-action
|
||||
:text-render render-button-text
|
||||
:default :zip}]]]))
|
||||
:default :file}]]]))
|
||||
|
||||
Reference in New Issue
Block a user