Add naturalChildOrdering flag to Plugin's API

This commit is contained in:
alonso.torres
2026-01-28 15:21:37 +01:00
committed by Andrey Antukh
parent 717a048b73
commit 512a31d375
8 changed files with 140 additions and 31 deletions

View File

@@ -44,6 +44,20 @@
(update [_ state]
(update-in state [:workspace-local :open-plugins] (fnil conj #{}) id))))
(defn reset-plugin-flags
[id]
(ptk/reify ::reset-plugin-flags
ptk/UpdateEvent
(update [_ state]
(update-in state [:workspace-local :plugin-flags] assoc id {}))))
(defn set-plugin-flag
[id key value]
(ptk/reify ::reset-plugin-flags
ptk/UpdateEvent
(update [_ state]
(update-in state [:workspace-local :plugin-flags id] assoc key value))))
(defn remove-current-plugin
[id]
(ptk/reify ::remove-current-plugin
@@ -54,7 +68,9 @@
(defn- load-plugin!
[{:keys [plugin-id name description host code icon permissions]}]
(try
(st/emit! (save-current-plugin plugin-id))
(st/emit! (save-current-plugin plugin-id)
(reset-plugin-flags plugin-id))
(.ɵloadPlugin
^js ug/global
#js {:pluginId plugin-id

View File

@@ -32,6 +32,7 @@
[app.main.ui.shapes.text.fontfaces :refer [shapes->fonts]]
[app.plugins.events :as events]
[app.plugins.file :as file]
[app.plugins.flags :as flags]
[app.plugins.fonts :as fonts]
[app.plugins.format :as format]
[app.plugins.history :as history]
@@ -124,6 +125,9 @@
:fonts
{:get (fn [] (fonts/fonts-subcontext plugin-id))}
:flags
{:get (fn [] (flags/flags-proxy plugin-id))}
:library
{:get (fn [] (library/library-subcontext plugin-id))}

View File

@@ -0,0 +1,33 @@
;; 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.plugins.flags
(:require
[app.main.data.plugins :as dp]
[app.main.store :as st]
[app.plugins.utils :as u]
[app.util.object :as obj]))
(defn flags-proxy
[plugin-id]
(obj/reify {:name "FlagProxy"}
:naturalChildOrdering
{:this false
:get
(fn []
(boolean
(get-in
@st/state
[:workspace-local :plugin-flags plugin-id :natural-child-ordering])))
:set
(fn [value]
(cond
(not (boolean? value))
(u/display-not-valid :naturalChildOrdering value)
:else
(st/emit! (dp/set-plugin-flag plugin-id :natural-child-ordering value))))}))

View File

@@ -52,6 +52,7 @@
[app.plugins.parser :as parser]
[app.plugins.register :as r]
[app.plugins.ruler-guides :as rg]
[app.plugins.state :refer [natural-child-ordering?]]
[app.plugins.text :as text]
[app.plugins.utils :as u]
[app.util.http :as http]
@@ -921,7 +922,6 @@
(fn []
(let [shape (u/locate-shape file-id page-id id)]
(cond
(and (not (cfh/frame-shape? shape))
(not (cfh/group-shape? shape))
(not (cfh/svg-raw-shape? shape))
@@ -929,9 +929,14 @@
(u/display-not-valid :getChildren (:type shape))
:else
(->> (u/locate-shape file-id page-id id)
(:shapes)
(format/format-array #(shape-proxy plugin-id file-id page-id %))))))
(let [is-reversed? (ctl/flex-layout? shape)
reverse-fn
(if (and (natural-child-ordering? plugin-id) is-reversed?)
reverse identity)]
(->> (u/locate-shape file-id page-id id)
(:shapes)
(reverse-fn)
(format/format-array #(shape-proxy plugin-id file-id page-id %)))))))
:appendChild
(fn [child]
@@ -950,8 +955,10 @@
(u/display-not-valid :appendChild "Plugin doesn't have 'content:write' permission")
:else
(let [child-id (obj/get child "$id")]
(st/emit! (dwsh/relocate-shapes #{child-id} id 0))))))
(let [child-id (obj/get child "$id")
is-reversed? (ctl/flex-layout? shape)
index (if (and (natural-child-ordering? plugin-id) is-reversed?) 0 (count (:shapes shape)))]
(st/emit! (dwsh/relocate-shapes #{child-id} id index))))))
:insertChild
(fn [index child]
@@ -970,7 +977,12 @@
(u/display-not-valid :insertChild "Plugin doesn't have 'content:write' permission")
:else
(let [child-id (obj/get child "$id")]
(let [child-id (obj/get child "$id")
is-reversed? (ctl/flex-layout? shape)
index
(if (and (natural-child-ordering? plugin-id) is-reversed?)
(- (count (:shapes shape)) index)
index)]
(st/emit! (dwsh/relocate-shapes #{child-id} id index))))))
;; Only for frames
@@ -1360,7 +1372,8 @@
(let [shape (u/proxy->shape self)
file-id (obj/get self "$file")
page-id (obj/get self "$page")
ids (->> children (map #(obj/get % "$id")))]
reverse-fn (if (natural-child-ordering? plugin-id) reverse identity)
ids (->> children reverse-fn (map #(obj/get % "$id")))]
(cond
(not= (set ids) (set (:shapes shape)))

View File

@@ -0,0 +1,16 @@
;; 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.plugins.state
(:require
[app.main.store :as st]))
(defn natural-child-ordering?
[plugin-id]
(boolean
(get-in
@st/state
[:workspace-local :plugin-flags plugin-id :natural-child-ordering])))

View File

@@ -1,6 +1,10 @@
## 1.5.0 (Unreleased)
- **plugin-types**: Added a flags subcontexts with the flag `naturalChildrenOrdering`
## 1.4.2 (2026-01-21)
- **plugin-types:** fix atob/btoa functions
- **plugin-runtime:** fix atob/btoa functions
## 1.4.0 (2026-01-21)

View File

@@ -804,6 +804,11 @@ export interface Context {
*/
readonly viewport: Viewport;
/**
* Provides flags to customize the API behavior.
*/
readonly flags: Flags;
/**
* Context encapsulating the history operations
*
@@ -1679,6 +1684,19 @@ export interface Fill {
fillImage?: ImageData;
}
/**
* This subcontext allows the API o change certain defaults
*/
export interface Flags {
/**
* If `true` the .children property will be always sorted in the z-index ordering.
* Also, appendChild method will be append the children in the top-most position.
* The insertchild method is changed acordingly to respect this ordering.
* Defaults to false
*/
naturalChildOrdering: boolean;
}
/**
* Represents a flexible layout configuration in Penpot.
* This interface extends `CommonLayout` and includes properties for defining the direction,

View File

@@ -1,31 +1,32 @@
import type {
Penpot,
EventsMap,
Page,
Shape,
Rectangle,
Board,
Group,
Viewport,
Text,
File,
Theme,
LibraryContext,
Ellipse,
Path,
BooleanType,
Boolean,
User,
ActiveUser,
FontsContext,
SvgRaw,
Board,
Boolean,
BooleanType,
Color,
ColorShapeInfo,
Ellipse,
EventsMap,
File,
Flags,
FontsContext,
Group,
HistoryContext,
LocalStorage,
VariantContainer,
LibraryComponent,
LibraryContext,
LibraryVariantComponent,
LocalStorage,
Page,
Path,
Penpot,
Rectangle,
Shape,
SvgRaw,
Text,
Theme,
User,
VariantContainer,
Viewport,
} from '@penpot/plugin-types';
import { Permissions } from '../models/manifest.model.js';
@@ -193,6 +194,10 @@ export function createApi(
return plugin.context.fonts;
},
get flags(): Flags {
return plugin.context.flags;
},
get currentUser(): User {
checkPermission('user:read');
return plugin.context.currentUser;