mirror of
https://github.com/penpot/penpot.git
synced 2026-07-30 18:06:15 +00:00
Merge remote-tracking branch 'origin/main-staging' into staging
This commit is contained in:
commit
89a1ee7813
27
.opencode/agents/commiter.md
Normal file
27
.opencode/agents/commiter.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
name: commiter
|
||||||
|
description: Git commit assistant following CONTRIBUTING.md commit rules
|
||||||
|
mode: primary
|
||||||
|
---
|
||||||
|
|
||||||
|
Role: You are responsible for creating git commits for Penpot and must follow
|
||||||
|
the repository commit-format rules exactly.
|
||||||
|
|
||||||
|
Requirements:
|
||||||
|
|
||||||
|
* Read `CONTRIBUTING.md` before creating any commit and follow the
|
||||||
|
commit guidelines strictly.
|
||||||
|
* Use commit messages in the form `:emoji: <imperative subject>`.
|
||||||
|
* Keep the subject capitalized, concise, 70 characters or fewer, and
|
||||||
|
without a trailing period.
|
||||||
|
* Keep the description (commit body) with maximum line length of 80
|
||||||
|
characters. Use manual line breaks to wrap text before it exceeds
|
||||||
|
this limit.
|
||||||
|
* Separate the subject from the body with a blank line.
|
||||||
|
* Write a clear and concise body when needed.
|
||||||
|
* Use `git commit -s` so the commit includes the required
|
||||||
|
`Signed-off-by` line.
|
||||||
|
* Do not guess or hallucinate git author information (Name or
|
||||||
|
Email). Never include the `--author` flag in git commands unless
|
||||||
|
specifically instructed by the user for a unique case; assume the
|
||||||
|
local environment is already configured.
|
||||||
30
AGENTS.md
30
AGENTS.md
@ -32,6 +32,36 @@ precision while maintaining a strong focus on maintainability and performance.
|
|||||||
5. When searching code, prefer `ripgrep` (`rg`) over `grep` — it respects
|
5. When searching code, prefer `ripgrep` (`rg`) over `grep` — it respects
|
||||||
`.gitignore` by default.
|
`.gitignore` by default.
|
||||||
|
|
||||||
|
## GitHub Operations
|
||||||
|
|
||||||
|
To obtain the list of repository members/collaborators:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gh api repos/:owner/:repo/collaborators --paginate --jq '.[].login'
|
||||||
|
```
|
||||||
|
|
||||||
|
To obtain the list of open PRs authored by members:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
MEMBERS=$(gh api repos/:owner/:repo/collaborators --paginate --jq '.[].login' | tr '\n' '|' | sed 's/|$//')
|
||||||
|
gh pr list --state open --limit 200 --json author,title,number | jq -r --arg members "$MEMBERS" '
|
||||||
|
($members | split("|")) as $m |
|
||||||
|
.[] | select(.author.login as $a | $m | index($a)) |
|
||||||
|
"\(.number)\t\(.author.login)\t\(.title)"
|
||||||
|
'
|
||||||
|
```
|
||||||
|
|
||||||
|
To obtain the list of open PRs from external contributors (non-members):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
MEMBERS=$(gh api repos/:owner/:repo/collaborators --paginate --jq '.[].login' | tr '\n' '|' | sed 's/|$//')
|
||||||
|
gh pr list --state open --limit 200 --json author,title,number | jq -r --arg members "$MEMBERS" '
|
||||||
|
($members | split("|")) as $m |
|
||||||
|
.[] | select(.author.login as $a | $m | index($a) | not) |
|
||||||
|
"\(.number)\t\(.author.login)\t\(.title)"
|
||||||
|
'
|
||||||
|
```
|
||||||
|
|
||||||
## Architecture Overview
|
## Architecture Overview
|
||||||
|
|
||||||
Penpot is an open-source design tool composed of several modules:
|
Penpot is an open-source design tool composed of several modules:
|
||||||
|
|||||||
@ -75,6 +75,7 @@
|
|||||||
- Fix wrong `mapcat` call in `collect-main-shapes`
|
- Fix wrong `mapcat` call in `collect-main-shapes`
|
||||||
- Fix stale accumulator in `get-children-in-instance` recursion
|
- Fix stale accumulator in `get-children-in-instance` recursion
|
||||||
- Fix typo `:podition` in swap-shapes grid cell
|
- Fix typo `:podition` in swap-shapes grid cell
|
||||||
|
- Fix multiple selection on shapes with token applied to stroke color
|
||||||
|
|
||||||
|
|
||||||
## 2.14.2
|
## 2.14.2
|
||||||
|
|||||||
@ -29,9 +29,10 @@
|
|||||||
.project-tree {
|
.project-tree {
|
||||||
position: relative;
|
position: relative;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
flex-shrink: 1;
|
||||||
|
min-width: 0;
|
||||||
height: deprecated.$s-32;
|
height: deprecated.$s-32;
|
||||||
min-height: deprecated.$s-32;
|
min-height: deprecated.$s-32;
|
||||||
max-width: calc(100% - deprecated.$s-64);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.project-name,
|
.project-name,
|
||||||
|
|||||||
@ -49,16 +49,16 @@
|
|||||||
• :prop → the property type (:fill, :stroke, :shadow, etc.)
|
• :prop → the property type (:fill, :stroke, :shadow, etc.)
|
||||||
• :shape-id → the UUID of the shape using this color
|
• :shape-id → the UUID of the shape using this color
|
||||||
• :index → index of the color in the shape's fill/stroke list
|
• :index → index of the color in the shape's fill/stroke list
|
||||||
|
|
||||||
Example of groups:
|
Example of groups:
|
||||||
{
|
{
|
||||||
{:color \"#9f2929\", :opacity 0.3, :token-name \"asd2\" :has-token-applied true}
|
{:color \"#9f2929\", :opacity 0.3, :token-name \"asd2\" :has-token-applied true}
|
||||||
[{:prop :fill, :shape-id #uuid \"d0231035-25c9-80d5-8006-eae4c3dff32e\", :index 0}]
|
[{:prop :fill, :shape-id #uuid \"d0231035-25c9-80d5-8006-eae4c3dff32e\", :index 0}]
|
||||||
|
|
||||||
{:color \"#1b54b6\", :opacity 1}
|
{:color \"#1b54b6\", :opacity 1}
|
||||||
[{:prop :fill, :shape-id #uuid \"aab34f9a-98c1-801a-8006-eae5e8236f1b\", :index 0}]
|
[{:prop :fill, :shape-id #uuid \"aab34f9a-98c1-801a-8006-eae5e8236f1b\", :index 0}]
|
||||||
}
|
}
|
||||||
|
|
||||||
This structure allows fast lookups of all shapes using the same visual color,
|
This structure allows fast lookups of all shapes using the same visual color,
|
||||||
regardless of whether it comes from local fills, strokes or shadow-colors."
|
regardless of whether it comes from local fills, strokes or shadow-colors."
|
||||||
|
|
||||||
@ -106,12 +106,11 @@
|
|||||||
open? (deref open*)
|
open? (deref open*)
|
||||||
|
|
||||||
has-colors? (or (some? (seq colors)) (some? (seq library-colors)))
|
has-colors? (or (some? (seq colors)) (some? (seq library-colors)))
|
||||||
|
|
||||||
toggle-content (mf/use-fn #(swap! open* not))
|
toggle-content (mf/use-fn #(swap! open* not))
|
||||||
|
|
||||||
expand-lib-color (mf/use-state false)
|
expand-lib-color (mf/use-state false)
|
||||||
expand-color (mf/use-state false)
|
expand-color (mf/use-state false)
|
||||||
expand-token-color (mf/use-state false)
|
expand-token-color (mf/use-state false)
|
||||||
|
|
||||||
;; TODO: Review if this is still necessary.
|
;; TODO: Review if this is still necessary.
|
||||||
prev-colors-ref (mf/use-ref nil)
|
prev-colors-ref (mf/use-ref nil)
|
||||||
|
|||||||
@ -194,7 +194,9 @@
|
|||||||
[:div {:class (stl/css-case :stroke-content true
|
[:div {:class (stl/css-case :stroke-content true
|
||||||
:stroke-content-empty (not has-strokes?))}
|
:stroke-content-empty (not has-strokes?))}
|
||||||
(cond
|
(cond
|
||||||
(= :multiple strokes)
|
(or (= :multiple (:stroke-color applied-tokens))
|
||||||
|
(= :multiple (:stroke-width applied-tokens))
|
||||||
|
(= :multiple strokes))
|
||||||
[:div {:class (stl/css :stroke-multiple)}
|
[:div {:class (stl/css :stroke-multiple)}
|
||||||
[:div {:class (stl/css :stroke-multiple-label)}
|
[:div {:class (stl/css :stroke-multiple-label)}
|
||||||
(tr "settings.multiple")]
|
(tr "settings.multiple")]
|
||||||
|
|||||||
@ -71,12 +71,13 @@
|
|||||||
[{:keys [active-tokens applied-token-name color on-swatch-click-token detach-token open-modal-from-token]}]
|
[{:keys [active-tokens applied-token-name color on-swatch-click-token detach-token open-modal-from-token]}]
|
||||||
(let [;; `active-tokens` may be provided as a `delay` (lazy computation).
|
(let [;; `active-tokens` may be provided as a `delay` (lazy computation).
|
||||||
;; In that case we must deref it (`@active-tokens`) to force evaluation
|
;; In that case we must deref it (`@active-tokens`) to force evaluation
|
||||||
;; and obtain the actual value. If it’s already realized (not a delay),
|
;; and obtain the actual value. If it's already realized (not a delay),
|
||||||
;; we just use it directly.
|
;; we just use it directly.
|
||||||
active-tokens (if (delay? active-tokens)
|
active-tokens (if (delay? active-tokens)
|
||||||
@active-tokens
|
@active-tokens
|
||||||
active-tokens)
|
active-tokens)
|
||||||
|
|
||||||
|
|
||||||
active-color-tokens (:color active-tokens)
|
active-color-tokens (:color active-tokens)
|
||||||
|
|
||||||
token (some #(when (= (:name %) applied-token-name) %) active-color-tokens)
|
token (some #(when (= (:name %) applied-token-name) %) active-color-tokens)
|
||||||
@ -354,6 +355,10 @@
|
|||||||
:dnd-over-top (= (:over dprops) :top)
|
:dnd-over-top (= (:over dprops) :top)
|
||||||
:dnd-over-bot (= (:over dprops) :bot))]
|
:dnd-over-bot (= (:over dprops) :bot))]
|
||||||
|
|
||||||
|
(when (= applied-token :multiple)
|
||||||
|
;; (js/console.trace "color-row*")
|
||||||
|
(prn "color-row*" index color applied-token))
|
||||||
|
|
||||||
(mf/with-effect [color prev-color disable-picker]
|
(mf/with-effect [color prev-color disable-picker]
|
||||||
(when (and (not disable-picker) (not= prev-color color))
|
(when (and (not disable-picker) (not= prev-color color))
|
||||||
(modal/update-props! :colorpicker {:data (parse-color color)})))
|
(modal/update-props! :colorpicker {:data (parse-color color)})))
|
||||||
|
|||||||
@ -192,6 +192,8 @@
|
|||||||
(when (some? on-reorder)
|
(when (some? on-reorder)
|
||||||
[:> reorder-handler* {:ref dref}])
|
[:> reorder-handler* {:ref dref}])
|
||||||
|
|
||||||
|
(prn "stroke-row*" applied-tokens)
|
||||||
|
|
||||||
;; Stroke Color
|
;; Stroke Color
|
||||||
;; FIXME: memorize stroke color
|
;; FIXME: memorize stroke color
|
||||||
[:> color-row* {:color (ctc/stroke->color stroke)
|
[:> color-row* {:color (ctc/stroke->color stroke)
|
||||||
|
|||||||
@ -93,11 +93,13 @@
|
|||||||
on-delete
|
on-delete
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps id)
|
(mf/deps id)
|
||||||
#(st/emit! (modal/show
|
(fn [event]
|
||||||
{:type :confirm
|
(dom/stop-propagation event)
|
||||||
:title (tr "modals.delete-page.title")
|
(st/emit! (modal/show
|
||||||
:message (tr "modals.delete-page.body")
|
{:type :confirm
|
||||||
:on-accept delete-fn})))
|
:title (tr "modals.delete-page.title")
|
||||||
|
:message (tr "modals.delete-page.body")
|
||||||
|
:on-accept delete-fn}))))
|
||||||
|
|
||||||
on-double-click
|
on-double-click
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user