diff --git a/CHANGES.md b/CHANGES.md index f5194aa21..ef0a0fe8e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,7 @@ - Outline highlights on layer hovering [Taiga #2645](https://tree.taiga.io/project/penpot/us/2645) by @andrewzhurov - Add zoom to shape on double click up on its icon [Taiga #3929](https://tree.taiga.io/project/penpot/us/3929) by @andrewzhurov - Add Libraries & Templates carousel [Taiga #3860](https://tree.taiga.io/project/penpot/us/3860) +- Ungroup frames [Taiga #4012](https://tree.taiga.io/project/penpot/us/4012) ### :bug: Bugs fixed diff --git a/frontend/src/app/main/data/workspace/groups.cljs b/frontend/src/app/main/data/workspace/groups.cljs index 5906db729..34d7b7df6 100644 --- a/frontend/src/app/main/data/workspace/groups.cljs +++ b/frontend/src/app/main/data/workspace/groups.cljs @@ -94,7 +94,7 @@ [group changes])) -(defn prepare-remove-group +(defn remove-group-changes [it page-id group objects] (let [children (mapv #(get objects %) (:shapes group)) parent-id (cph/get-parent-id objects (:id group)) @@ -126,6 +126,18 @@ (some? ids-to-detach) (pcb/update-shapes ids-to-detach detach-fn)))) +(defn remove-frame-changes + [it page-id frame objects] + + (let [children (mapv #(get objects %) (:shapes frame)) + parent-id (cph/get-parent-id objects (:id frame)) + idx-in-parent (cph/get-position-on-parent objects (:id frame))] + + (-> (pcb/empty-changes it page-id) + (pcb/with-objects objects) + (pcb/change-parent parent-id children idx-in-parent) + (pcb/remove-objects [(:id frame)])))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; GROUPS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -149,17 +161,22 @@ (ptk/reify ::ungroup-selected ptk/WatchEvent (watch [it state _] - (let [page-id (:current-page-id state) - objects (wsh/lookup-page-objects state page-id) - is-group? #(or (= :bool (:type %)) (= :group (:type %))) - lookup #(get objects %) - prepare #(prepare-remove-group it page-id % objects) + (let [page-id (:current-page-id state) + objects (wsh/lookup-page-objects state page-id) + + prepare + (fn [shape-id] + (let [shape (get objects shape-id)] + (cond + (or (cph/group-shape? shape) (cph/bool-shape? shape)) + (remove-group-changes it page-id shape objects) + + (cph/frame-shape? shape) + (remove-frame-changes it page-id shape objects)))) changes-list (sequence - (comp (map lookup) - (filter is-group?) - (map prepare)) - (wsh/lookup-selected state)) + (keep prepare) + (wsh/lookup-selected state)) changes {:redo-changes (vec (mapcat :redo-changes changes-list)) :undo-changes (vec (mapcat :undo-changes changes-list)) diff --git a/frontend/src/app/main/ui/workspace/context_menu.cljs b/frontend/src/app/main/ui/workspace/context_menu.cljs index 404836014..650afdb79 100644 --- a/frontend/src/app/main/ui/workspace/context_menu.cljs +++ b/frontend/src/app/main/ui/workspace/context_menu.cljs @@ -213,8 +213,9 @@ single? (= (count shapes) 1) do-create-artboard-from-selection #(st/emit! (dw/create-artboard-from-selection)) - has-group? (->> shapes (d/seek #(= :group (:type %)))) - has-bool? (->> shapes (d/seek #(= :bool (:type %)))) + has-frame? (->> shapes (d/seek cph/frame-shape?)) + has-group? (->> shapes (d/seek cph/group-shape?)) + has-bool? (->> shapes (d/seek cph/bool-shape?)) has-mask? (->> shapes (d/seek :masked-group?)) is-group? (and single? has-group?) @@ -226,7 +227,7 @@ do-unmask-group #(st/emit! dw/unmask-group)] [:* - (when (or has-bool? has-group? has-mask?) + (when (or has-bool? has-group? has-mask? has-frame?) [:& menu-entry {:title (tr "workspace.shape.menu.ungroup") :shortcut (sc/get-tooltip :ungroup) :on-click do-remove-group}]) @@ -266,9 +267,9 @@ (let [multiple? (> (count shapes) 1) single? (= (count shapes) 1) - has-group? (->> shapes (d/seek #(= :group (:type %)))) - has-bool? (->> shapes (d/seek #(= :bool (:type %)))) - has-frame? (->> shapes (d/seek #(= :frame (:type %)))) + has-group? (->> shapes (d/seek cph/group-shape?)) + has-bool? (->> shapes (d/seek cph/bool-shape?)) + has-frame? (->> shapes (d/seek cph/frame-shape?)) is-group? (and single? has-group?) is-bool? (and single? has-bool?) @@ -350,7 +351,7 @@ prototype? (= options-mode :prototype) single? (= (count shapes) 1) - has-frame? (->> shapes (d/seek #(= :frame (:type %)))) + has-frame? (->> shapes (d/seek cph/frame-shape?)) is-frame? (and single? has-frame?)] (when (and prototype? is-frame?) @@ -366,7 +367,7 @@ [{:keys [shapes]}] (let [single? (= (count shapes) 1) - has-frame? (->> shapes (d/seek #(= :frame (:type %)))) + has-frame? (->> shapes (d/seek cph/frame-shape?)) has-component? (some true? (map #(contains? % :component-id) shapes)) is-component? (and single? (-> shapes first :component-id some?))