mirror of
https://github.com/penpot/penpot.git
synced 2026-02-07 05:03:42 -05:00
Compare commits
24 Commits
2.9.0-RC5
...
niwinz-doc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04f573cb23 | ||
|
|
d46ad9d6f1 | ||
|
|
2e8d08d047 | ||
|
|
9c57596954 | ||
|
|
cc41fb569d | ||
|
|
79ad322809 | ||
|
|
362ea401a0 | ||
|
|
7afb5abf35 | ||
|
|
1b16129c45 | ||
|
|
ff2e845f2c | ||
|
|
8e0a6e4123 | ||
|
|
0131cd6f8b | ||
|
|
288a7b21d6 | ||
|
|
32bd08533d | ||
|
|
c1aae12327 | ||
|
|
23a6f4b7c1 | ||
|
|
133e6e1e68 | ||
|
|
6abd045273 | ||
|
|
778a608854 | ||
|
|
a76a9fae41 | ||
|
|
f7cfbdd229 | ||
|
|
e28d2842f6 | ||
|
|
ccc3ca0948 | ||
|
|
4501d13961 |
105
.github/workflows/build-bundles.yml
vendored
105
.github/workflows/build-bundles.yml
vendored
@@ -1,28 +1,14 @@
|
||||
name: Build and Upload Penpot Bundles non-prod
|
||||
name: Build and Upload Penpot Bundles
|
||||
|
||||
on:
|
||||
# Create bundler for every tag
|
||||
push:
|
||||
tags:
|
||||
- '**' # Pattern matched against refs/tags
|
||||
# Create bundler every hour between 5:00 and 20:00 on working days
|
||||
schedule:
|
||||
- cron: '0 5-20 * * 1-5'
|
||||
# Create bundler from manual action
|
||||
# Create bundle from manual action
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
inputs:
|
||||
zip_mode:
|
||||
# zip_mode defines how the build artifacts are packaged:
|
||||
# - 'individual': creates one ZIP file per component (frontend, backend, exporter)
|
||||
# - 'all': creates a single ZIP containing all components
|
||||
# - null: for the rest of cases (non-manual events)
|
||||
description: 'Bundle packaging mode'
|
||||
required: false
|
||||
default: 'individual'
|
||||
type: choice
|
||||
options:
|
||||
- individual
|
||||
- all
|
||||
gh_ref:
|
||||
description: 'Name of the branch'
|
||||
type: string
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build-bundles:
|
||||
@@ -38,15 +24,15 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ inputs.gh_ref }}
|
||||
|
||||
- name: Extract somer useful variables
|
||||
- name: Extract some useful variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "commit_hash=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
echo "gh_branch=${{ github.base_ref || github.ref_name }}" >> $GITHUB_OUTPUT
|
||||
|
||||
# Set up Docker Buildx for multi-arch build
|
||||
- name: Set up Docker Buildx
|
||||
- name: Set up Docker Buildx for multi-arch build
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Run manage.sh build-bundle from host
|
||||
@@ -57,73 +43,22 @@ jobs:
|
||||
mkdir zips
|
||||
mv bundles penpot
|
||||
|
||||
- name: Create zip bundles for zip_mode == 'all'
|
||||
if: ${{ github.event.inputs.zip_mode == 'all' }}
|
||||
- name: Create zip bundles
|
||||
run: |
|
||||
echo "📦 Packaging Penpot 'all' bundles..."
|
||||
zip -r zips/penpot-all-bundles.zip penpot
|
||||
echo "📦 Packaging Penpot bundles..."
|
||||
zip -r zips/penpot.zip penpot
|
||||
|
||||
- name: Create zip bundles for zip_mode != 'all'
|
||||
if: ${{ github.event.inputs.zip_mode != 'all' }}
|
||||
- name: Upload Penpot bundle to S3
|
||||
run: |
|
||||
echo "📦 Packaging Penpot 'individual' bundles..."
|
||||
zip -r zips/penpot-frontend.zip penpot/frontend
|
||||
zip -r zips/penpot-backend.zip penpot/backend
|
||||
zip -r zips/penpot-exporter.zip penpot/exporter
|
||||
aws s3 cp zips/penpot.zip s3://${{ secrets.S3_BUCKET }}/penpot-${{ steps.vars.outputs.gh_branch}}-latest.zip
|
||||
aws s3 cp zips/penpot.zip s3://${{ secrets.S3_BUCKET }}/penpot-${{ steps.vars.outputs.commit_hash }}.zip
|
||||
|
||||
- name: Upload unified 'all' bundle
|
||||
if: ${{ github.event.inputs.zip_mode == 'all' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: penpot-all-bundles
|
||||
path: zips/penpot-all-bundles.zip
|
||||
|
||||
- name: Upload individual bundles
|
||||
if: ${{ github.event.inputs.zip_mode != 'all' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: penpot-individual-bundles
|
||||
path: |
|
||||
zips/penpot-frontend.zip
|
||||
zips/penpot-backend.zip
|
||||
zips/penpot-exporter.zip
|
||||
|
||||
- name: Upload unified 'all' bundle to S3
|
||||
if: ${{ github.event.inputs.zip_mode == 'all' }}
|
||||
run: |
|
||||
aws s3 cp zips/penpot-all-bundles.zip s3://${{ secrets.S3_BUCKET }}/penpot-all-bundles-${{ steps.vars.outputs.gh_branch}}.zip
|
||||
aws s3 cp zips/penpot-all-bundles.zip s3://${{ secrets.S3_BUCKET }}/penpot-all-bundles-${{ steps.vars.outputs.commit_hash }}.zip
|
||||
|
||||
- name: Upload 'individual' bundles to S3
|
||||
if: ${{ github.event.inputs.zip_mode != 'all' }}
|
||||
run: |
|
||||
for name in penpot-frontend penpot-backend penpot-exporter; do
|
||||
aws s3 cp zips/${name}.zip s3://${{ secrets.S3_BUCKET }}/${name}-${{ steps.vars.outputs.gh_branch }}-latest.zip
|
||||
aws s3 cp zips/${name}.zip s3://${{ secrets.S3_BUCKET }}/${name}-${{ steps.vars.outputs.commit_hash }}.zip
|
||||
done
|
||||
|
||||
- name: Notify Mattermost about automatic bundles
|
||||
if: github.event_name == 'pull_request'
|
||||
- name: Notify Mattermost
|
||||
if: failure()
|
||||
uses: mattermost/action-mattermost-notify@master
|
||||
with:
|
||||
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK }}
|
||||
TEXT: |
|
||||
📦 *Penpot bundle automatically generated*
|
||||
📄 PR: ${{ github.event.pull_request.title }}
|
||||
🔁 From: \`${{ github.head_ref }}\` to \`{{ github.base_ref }}\`
|
||||
❌ *[PENPOT] Error during the execution of the job*
|
||||
📄 Triggered from ref: `${{ steps.vars.outputs.gh_branch}}`
|
||||
🔗 Run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
|
||||
- name: Notify Mattermost about manual bundles
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: mattermost/action-mattermost-notify@master
|
||||
with:
|
||||
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK }}
|
||||
TEXT: |
|
||||
📦 *Penpot bundle manually generated*
|
||||
📄 Triggered from branch: `${{ github.ref_name}}`
|
||||
🔗 Run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
|
||||
- name: Print artifact summary URL
|
||||
run: |
|
||||
echo "📦 Artifacts available at:"
|
||||
echo "🔗 https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
||||
|
||||
12
.github/workflows/build-develop.yml
vendored
Normal file
12
.github/workflows/build-develop.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
name: Build and Upload Penpot DEVELOP Bundles
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '16 5-20 * * 1-5'
|
||||
|
||||
jobs:
|
||||
build-develop-bundle:
|
||||
uses: ./.github/workflows/build-bundles.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
gh_ref: "develop"
|
||||
12
.github/workflows/build-staging.yml
vendored
Normal file
12
.github/workflows/build-staging.yml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
name: Build and Upload Penpot STAGING Bundles
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 5 * * 1-5'
|
||||
|
||||
jobs:
|
||||
build-staging-bundle:
|
||||
uses: ./.github/workflows/build-bundles.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
gh_ref: "staging"
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -31,6 +31,7 @@
|
||||
/.clj-kondo/.cache
|
||||
/_dump
|
||||
/notes
|
||||
/playground/
|
||||
/backend/*.md
|
||||
/backend/*.sql
|
||||
/backend/*.txt
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
- Add the ability to show login dialog on profile settings [Github #6871](https://github.com/penpot/penpot/pull/6871)
|
||||
- Improve the application of tokens with object specific tokens [Taiga #10209](https://tree.taiga.io/project/penpot/us/10209)
|
||||
- Add info to apply-token event [Taiga #11710](https://tree.taiga.io/project/penpot/task/11710)
|
||||
- Fix double click on set name input [Taiga #11747](https://tree.taiga.io/project/penpot/issue/11747)
|
||||
|
||||
|
||||
### :bug: Bugs fixed
|
||||
|
||||
@@ -58,6 +60,7 @@
|
||||
- Fix export button width on inspect tab [Taiga #11394](https://tree.taiga.io/project/penpot/issue/11394)
|
||||
- Fix stroke width token application [Taiga #11724](https://tree.taiga.io/project/penpot/issue/11724)
|
||||
- Fix number token application on shape [Taiga #11331](https://tree.taiga.io/project/penpot/task/11331)
|
||||
- Fix auto height is fixed in the HTML inspect tab for text elements [Taiga #11680](https://tree.taiga.io/project/penpot/task/11680)
|
||||
|
||||
## 2.8.1
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
[app.rpc :as-alias rpc]
|
||||
[app.rpc.doc :as-alias rpc.doc]
|
||||
[app.setup :as-alias setup]
|
||||
[app.worker :as wrk]
|
||||
[integrant.core :as ig]
|
||||
[promesa.exec :as px]
|
||||
[reitit.core :as r]
|
||||
@@ -63,7 +64,7 @@
|
||||
(assert (sm/check schema:server-params params)))
|
||||
|
||||
(defmethod ig/init-key ::server
|
||||
[_ {:keys [::handler ::router ::host ::port] :as cfg}]
|
||||
[_ {:keys [::handler ::router ::host ::port ::wrk/executor] :as cfg}]
|
||||
(l/info :hint "starting http server" :port port :host host)
|
||||
(let [options {:http/port port
|
||||
:http/host host
|
||||
@@ -72,7 +73,7 @@
|
||||
:xnio/direct-buffers false
|
||||
:xnio/io-threads (or (::io-threads cfg)
|
||||
(max 3 (px/get-available-processors)))
|
||||
:xnio/dispatch :virtual
|
||||
:xnio/dispatch executor
|
||||
:ring/compat :ring2
|
||||
:socket/backlog 4069}
|
||||
|
||||
|
||||
@@ -231,7 +231,8 @@
|
||||
::http/router (ig/ref ::http/router)
|
||||
::http/io-threads (cf/get :http-server-io-threads)
|
||||
::http/max-body-size (cf/get :http-server-max-body-size)
|
||||
::http/max-multipart-body-size (cf/get :http-server-max-multipart-body-size)}
|
||||
::http/max-multipart-body-size (cf/get :http-server-max-multipart-body-size)
|
||||
::wrk/executor (ig/ref ::wrk/executor)}
|
||||
|
||||
::ldap/provider
|
||||
{:host (cf/get :ldap-host)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.logging :as l]
|
||||
[app.common.media :as cm]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.schema.openapi :as-alias oapi]
|
||||
@@ -21,6 +22,7 @@
|
||||
[buddy.core.bytes :as bb]
|
||||
[buddy.core.codecs :as bc]
|
||||
[clojure.java.shell :as sh]
|
||||
[clojure.string]
|
||||
[clojure.xml :as xml]
|
||||
[cuerdas.core :as str]
|
||||
[datoteka.fs :as fs]
|
||||
@@ -215,6 +217,23 @@
|
||||
{:width (int width)
|
||||
:height (int height)})))]))
|
||||
|
||||
(defn- get-dimensions-with-orientation [^String path]
|
||||
;; Image magick doesn't give info about exif rotation so we use the identify command
|
||||
;; If we are processing an animated gif we use the first frame with -scene 0
|
||||
(let [dim-result (sh/sh "identify" "-format" "%w %h\n" path)
|
||||
orient-result (sh/sh "identify" "-format" "%[EXIF:Orientation]\n" path)]
|
||||
(if (and (= 0 (:exit dim-result))
|
||||
(= 0 (:exit orient-result)))
|
||||
(let [[w h] (-> (:out dim-result)
|
||||
str/trim
|
||||
(clojure.string/split #"\s+")
|
||||
(->> (mapv #(Integer/parseInt %))))
|
||||
orientation (-> orient-result :out str/trim)]
|
||||
(case orientation
|
||||
("6" "8") {:width h :height w} ; Rotated 90 or 270 degrees
|
||||
{:width w :height h})) ; Normal or unknown orientation
|
||||
nil)))
|
||||
|
||||
(defmethod process :info
|
||||
[{:keys [input] :as params}]
|
||||
(let [{:keys [path mtype] :as input} (check-input input)]
|
||||
@@ -234,13 +253,17 @@
|
||||
:code :media-type-mismatch
|
||||
:hint (str "Seems like you are uploading a file whose content does not match the extension."
|
||||
"Expected: " mtype ". Got: " mtype')))
|
||||
;; For an animated GIF, getImageWidth/Height returns the delta size of one frame (if no frame given
|
||||
;; it returns size of the last one), whereas getPageWidth/Height always return the full size of
|
||||
;; any frame.
|
||||
(assoc input
|
||||
:width (.getPageWidth instance)
|
||||
:height (.getPageHeight instance)
|
||||
:ts (dt/now))))))
|
||||
(let [{:keys [width height]}
|
||||
(or (get-dimensions-with-orientation (str path))
|
||||
(do
|
||||
(l/warn "Failed to read image dimensions with orientation; falling back to im4java"
|
||||
{:path path})
|
||||
{:width (.getPageWidth instance)
|
||||
:height (.getPageHeight instance)}))]
|
||||
(assoc input
|
||||
:width width
|
||||
:height height
|
||||
:ts (dt/now)))))))
|
||||
|
||||
(defmethod process-error org.im4java.core.InfoException
|
||||
[error]
|
||||
|
||||
@@ -357,7 +357,7 @@
|
||||
[:id ::sm/uuid]
|
||||
[:file-id ::sm/uuid]
|
||||
[:created-at ::dt/instant]
|
||||
[:content any?]])
|
||||
[:content ::sm/any]])
|
||||
|
||||
(def schema:get-file-fragment
|
||||
[:map {:title "get-file-fragment"}
|
||||
|
||||
@@ -185,7 +185,7 @@
|
||||
[:map {:title "PartialFile"}
|
||||
[:id ::sm/uuid]
|
||||
[:revn {:min 0} ::sm/int]
|
||||
[:page :any]])
|
||||
[:page [:map-of :keyword ::sm/any]]])
|
||||
|
||||
(sv/defmethod ::get-file-data-for-thumbnail
|
||||
"Retrieves the data for generate the thumbnail of the file. Used
|
||||
|
||||
36
backend/test/backend_tests/rpc_doc_test.clj
Normal file
36
backend/test/backend_tests/rpc_doc_test.clj
Normal file
@@ -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
|
||||
|
||||
(ns backend-tests.rpc-doc-test
|
||||
"Internal binfile test, no RPC involved"
|
||||
(:require
|
||||
[app.common.json :as json]
|
||||
[app.common.pprint :as pp]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.schema.generators :as sg]
|
||||
[app.common.schema.test :as smt]
|
||||
[app.rpc :as-alias rpc]
|
||||
[app.rpc.doc :as rpc.doc]
|
||||
[backend-tests.helpers :as th]
|
||||
[clojure.test :as t]))
|
||||
|
||||
(t/use-fixtures :once th/state-init)
|
||||
|
||||
(t/deftest openapi-context-json-encode
|
||||
(smt/check!
|
||||
(smt/for [context (->> sg/int
|
||||
(sg/fmap (fn [_]
|
||||
(rpc.doc/prepare-openapi-context (::rpc/methods th/*system*)))))]
|
||||
(try
|
||||
(json/encode context)
|
||||
true
|
||||
(catch Throwable _cause
|
||||
false)))
|
||||
{:num 30}))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -177,12 +177,6 @@
|
||||
:title "Change"
|
||||
:decode/json #(update % :type keyword)
|
||||
::smd/simplified true}
|
||||
[:set-option
|
||||
|
||||
;; DEPRECATED: remove before 2.3 release
|
||||
;;
|
||||
;; Is still there for not cause error when event is received
|
||||
[:map {:title "SetOptionChange"}]]
|
||||
|
||||
[:set-comment-thread-position
|
||||
[:map
|
||||
@@ -195,7 +189,7 @@
|
||||
[:map {:title "AddObjChange"}
|
||||
[:type [:= :add-obj]]
|
||||
[:id ::sm/uuid]
|
||||
[:obj :map]
|
||||
[:obj cts/schema:shape]
|
||||
[:page-id {:optional true} ::sm/uuid]
|
||||
[:component-id {:optional true} ::sm/uuid]
|
||||
[:frame-id ::sm/uuid]
|
||||
@@ -328,7 +322,9 @@
|
||||
[:id ::sm/uuid]
|
||||
[:name :string]
|
||||
[:shapes {:optional true} [:vector {:gen/max 3} ::sm/any]]
|
||||
[:path {:optional true} :string]]]
|
||||
[:path {:optional true} :string]
|
||||
[:main-instance-id ::sm/uuid]
|
||||
[:main-instance-page ::sm/uuid]]]
|
||||
|
||||
[:mod-component
|
||||
[:map {:title "ModCompoenentChange"}
|
||||
@@ -418,7 +414,14 @@
|
||||
[:type [:= :set-token-set]]
|
||||
[:set-name :string]
|
||||
[:group? :boolean]
|
||||
[:token-set [:maybe [:fn ctob/token-set?]]]]]
|
||||
|
||||
;; FIXME: we should not pass private types as part of changes
|
||||
;; protocol, the changes protocol should reflect a
|
||||
;; method/protocol for perform surgical operations on file data,
|
||||
;; this has nothing todo with internal types of a file data
|
||||
;; structure.
|
||||
[:token-set {:gen/gen (sg/generator ctob/schema:token-set)}
|
||||
[:maybe [:fn ctob/token-set?]]]]]
|
||||
|
||||
[:set-token
|
||||
[:map {:title "SetTokenChange"}
|
||||
@@ -539,11 +542,6 @@
|
||||
#?(:clj (validate-shapes! data result items))
|
||||
result))))
|
||||
|
||||
;; DEPRECATED: remove after 2.3 release
|
||||
(defmethod process-change :set-option
|
||||
[data _]
|
||||
data)
|
||||
|
||||
;; --- Comment Threads
|
||||
|
||||
(defmethod process-change :set-comment-thread-position
|
||||
@@ -1083,21 +1081,23 @@
|
||||
|
||||
;; === Operations
|
||||
|
||||
(def ^:private decode-shape
|
||||
(sm/decoder cts/schema:shape sm/json-transformer))
|
||||
(def decode-shape-attrs
|
||||
(sm/decoder cts/schema:shape-attrs sm/json-transformer))
|
||||
|
||||
(defmethod process-operation :assign
|
||||
[{:keys [type] :as shape} {:keys [value] :as op}]
|
||||
(let [modifications (assoc value :type type)
|
||||
modifications (decode-shape modifications)]
|
||||
modifications (decode-shape-attrs modifications)]
|
||||
(reduce-kv (fn [shape k v]
|
||||
(process-operation shape {:type :set
|
||||
:attr k
|
||||
:val v
|
||||
:ignore-touched (:ignore-touched op)
|
||||
:ignore-geometry (:ignore-geometry op)}))
|
||||
(if (not= v (get shape k))
|
||||
(process-operation shape {:type :set
|
||||
:attr k
|
||||
:val v
|
||||
:ignore-touched (:ignore-touched op)
|
||||
:ignore-geometry (:ignore-geometry op)})
|
||||
shape))
|
||||
shape
|
||||
modifications)))
|
||||
(dissoc modifications :type))))
|
||||
|
||||
(defmethod process-operation :set
|
||||
[shape op]
|
||||
|
||||
@@ -1618,4 +1618,4 @@
|
||||
"0007-clear-invalid-strokes-and-fills-v2"
|
||||
"0008-fix-library-colors-v4"
|
||||
"0009-clean-library-colors"
|
||||
"0009-add-partial-text-touched-flags"]))
|
||||
#_"0009-add-partial-text-touched-flags"]))
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
(defmethod visit :fn [_ _ _ _] "FN")
|
||||
|
||||
(defmethod visit :vector [_ _ children _]
|
||||
(str "[" (last children) "]"))
|
||||
(str "[" (str/trim (last children)) "]"))
|
||||
|
||||
(defn -tagged [children] (map (fn [[tag _ c]] (str c " (tag: " tag ")")) children))
|
||||
|
||||
@@ -137,8 +137,14 @@
|
||||
(some? suffix)
|
||||
(str suffix))))
|
||||
|
||||
(defmethod visit :map-of [_ _ children _]
|
||||
(str "map[" (first children) "," (second children) "]"))
|
||||
(defmethod visit :map-of
|
||||
[_ schema children _]
|
||||
(let [props (m/properties schema)
|
||||
title (some->> (:title props) str/camel str/capital)]
|
||||
(str (if title
|
||||
(str "type " title ": ")
|
||||
"")
|
||||
"map[" (first children) "," (second children) "]")))
|
||||
|
||||
(defmethod visit :union [_ _ children _]
|
||||
(str/join " | " children))
|
||||
@@ -156,61 +162,123 @@
|
||||
(or (:title props)
|
||||
"*")))
|
||||
|
||||
|
||||
(defn- format-map
|
||||
[schema children]
|
||||
(let [props (m/properties schema)
|
||||
closed? (get props :closed)
|
||||
title (some->> (:title props) str/camel str/capital)
|
||||
level 0
|
||||
optional (into #{} (comp (filter (m/-comp :optional second))
|
||||
(map first))
|
||||
children)
|
||||
entries (->> children
|
||||
(map (fn [[k _ s]]
|
||||
;; NOTE: maybe we can detect multiple lines
|
||||
;; and then just insert a break line
|
||||
(str (pad " " level) (str/camel k)
|
||||
(when (contains? optional k) "?")
|
||||
": " (str/trim s))))
|
||||
(str/join ",\n"))
|
||||
|
||||
header (cond-> (str "type " title)
|
||||
closed? (str "!")
|
||||
(some? title) (str " "))]
|
||||
|
||||
(str (pad header level) "{\n" entries "\n" (pad "}\n" level))))
|
||||
|
||||
(defmethod visit :map
|
||||
[_ schema children {:keys [::level ::max-level] :as options}]
|
||||
(let [props (m/properties schema)
|
||||
closed? (:closed props)
|
||||
title (some->> (:title props) str/camel str/capital)]
|
||||
(let [props (m/properties schema)
|
||||
closed? (get props :closed)
|
||||
title (some->> (:title props) str/camel str/capital)
|
||||
extracted? (get props ::extracted false)]
|
||||
|
||||
(if (>= level max-level)
|
||||
(or (some-> title str)
|
||||
"<untitled>")
|
||||
(let [optional (into #{} (comp (filter (m/-comp :optional second))
|
||||
(map first))
|
||||
children)
|
||||
entries (->> children
|
||||
(map (fn [[k _ s]]
|
||||
(str (pad " " level) (str/camel k)
|
||||
(when (contains? optional k) "?")
|
||||
": " s)))
|
||||
(str/join ",\n"))
|
||||
(if (= level 0)
|
||||
(format-map schema children)
|
||||
|
||||
header (cond-> (str "type " title)
|
||||
closed? (str "!")
|
||||
(some? title) (str " "))]
|
||||
(if title
|
||||
(if extracted?
|
||||
(format-map schema children)
|
||||
(let [schema (mu/update-properties schema assoc ::extracted true)]
|
||||
(swap! *definitions* conj (describe* schema options))
|
||||
(pad title level)))
|
||||
(format-map schema children)))))
|
||||
|
||||
(str (pad header level) "{\n" entries "\n" (pad "}\n" level))))))
|
||||
(defn format-multi
|
||||
[s children]
|
||||
(let [props (m/properties s)
|
||||
title (some-> (:title props) str/camel str/capital)
|
||||
dispatcher (or (-> s m/properties :dispatch-description)
|
||||
(-> s m/properties :dispatch))
|
||||
|
||||
(defmethod visit :multi
|
||||
[_ s children {:keys [::level ::max-level] :as options}]
|
||||
(let [props (m/properties s)
|
||||
title (some-> (:title props) str/camel str/capital)]
|
||||
(if (>= level max-level)
|
||||
title
|
||||
(let [dispatcher (or (-> s m/properties :dispatch-description)
|
||||
(-> s m/properties :dispatch))
|
||||
entries (->> children
|
||||
(map (fn [[_ _ shape]]
|
||||
(str shape)))
|
||||
(str/join ",\n"))
|
||||
|
||||
prefix (apply str (take (inc level) (repeat " ")))
|
||||
|
||||
entries (->> children
|
||||
(map (fn [[_ _ shape]]
|
||||
(str prefix shape)))
|
||||
(str/join ",\n"))
|
||||
|
||||
header (cond-> "multi"
|
||||
header (cond-> "multi"
|
||||
(some? title) (str " " title)
|
||||
:always (str " [dispatch=" (d/name dispatcher) "]"))]
|
||||
|
||||
(str header " {\n" entries "\n" (pad "}" level))))))
|
||||
(str header " {\n" entries "\n}")))
|
||||
|
||||
(defmethod visit :multi
|
||||
[_ schema children {:keys [::level ::max-level] :as options}]
|
||||
(let [props (m/properties schema)
|
||||
title (some-> (:title props) str/camel str/capital)
|
||||
extracted? (get props ::extracted false)]
|
||||
|
||||
(cond
|
||||
(zero? level)
|
||||
(format-multi schema children)
|
||||
|
||||
(and title extracted?)
|
||||
(format-multi schema children)
|
||||
|
||||
(and title (not extracted?))
|
||||
(let [schema (mu/update-properties schema assoc ::extracted true)]
|
||||
(swap! *definitions* conj (describe* schema options))
|
||||
(pad title level))
|
||||
|
||||
:else
|
||||
(format-multi schema children))))
|
||||
|
||||
(defn- format-merge
|
||||
[schema children]
|
||||
|
||||
(let [props (m/properties schema)
|
||||
entries (->> children
|
||||
(map (fn [shape]
|
||||
(str shape)))
|
||||
(str/join ",\n"))
|
||||
title (some-> (:title props) str/camel str/capital)
|
||||
|
||||
|
||||
header (str "merge type " title)]
|
||||
|
||||
(str header " {\n" entries "\n}")))
|
||||
|
||||
(defmethod visit :merge
|
||||
[_ schema children _]
|
||||
(let [entries (str/join ",\n" children)
|
||||
props (m/properties schema)
|
||||
title (or (some-> (:title props) str/camel str/capital)
|
||||
"<untitled>")]
|
||||
(str "merge type " title " { \n" entries "\n}\n")))
|
||||
[_ schema children {:keys [::level ::max-level] :as options}]
|
||||
(let [props (m/properties schema)
|
||||
title (some-> (:title props) str/camel str/capital)
|
||||
extracted? (get props ::extracted false)]
|
||||
|
||||
(cond
|
||||
(zero? level)
|
||||
(format-merge schema children)
|
||||
|
||||
(and title extracted?)
|
||||
(format-merge schema children)
|
||||
|
||||
(and title (not extracted?))
|
||||
(let [schema (mu/update-properties schema assoc ::extracted true)]
|
||||
(swap! *definitions* conj (describe* schema options))
|
||||
(pad title level))
|
||||
|
||||
:else
|
||||
(format-merge schema children))))
|
||||
|
||||
(defmethod visit ::sm/one-of
|
||||
[_ _ children _]
|
||||
@@ -219,8 +287,21 @@
|
||||
(map d/name)
|
||||
(str/join "|")) ")")))
|
||||
|
||||
(defmethod visit :schema [_ schema children options]
|
||||
(visit ::m/schema schema children options))
|
||||
(defmethod visit :schema
|
||||
[_ schema children options]
|
||||
(let [props (m/properties schema)
|
||||
title (some-> (:title props) str/camel str/capital)
|
||||
extracted? (get props ::extracted false)]
|
||||
|
||||
(if title
|
||||
(if extracted?
|
||||
(str "type " title ": "
|
||||
(visit ::m/schema schema children options))
|
||||
(let [schema (mu/update-properties schema assoc ::extracted true)]
|
||||
(swap! *definitions* conj (describe* schema options))
|
||||
title))
|
||||
|
||||
(visit ::m/schema schema children options))))
|
||||
|
||||
(defmethod visit ::m/schema
|
||||
[_ schema _ {:keys [::level ::limit ::max-level] :as options}]
|
||||
@@ -239,9 +320,12 @@
|
||||
(describe* schema' options)))
|
||||
|
||||
(and ref title)
|
||||
(do
|
||||
(when (<= limit max-level)
|
||||
(swap! *definitions* conj (describe* schema' (assoc options ::base-limit limit))))
|
||||
(let [options (-> options
|
||||
(assoc ::base-level level)
|
||||
)]
|
||||
|
||||
;; (when (<= limit max-level)
|
||||
(swap! *definitions* conj (describe* schema' options))
|
||||
|
||||
title)
|
||||
|
||||
@@ -254,10 +338,11 @@
|
||||
(describe* schema' (assoc options ::base-level level ::base-limit limit)))))
|
||||
|
||||
(defn describe* [s options]
|
||||
(letfn [(walk-fn [schema path children {:keys [::base-level ::base-limit] :or {base-level 0 base-limit 0} :as options}]
|
||||
(let [options (assoc options
|
||||
::limit (+ base-limit (count path))
|
||||
::level (+ base-level (count path)))]
|
||||
(letfn [(walk-fn [schema path children {:keys [::base-level ::base-limit]
|
||||
:or {base-level 0 base-limit 0} :as options}]
|
||||
(let [options (-> options
|
||||
(assoc ::limit (+ base-limit (count path)))
|
||||
(assoc ::level (+ base-level (count path))))]
|
||||
(visit (m/type schema) schema children options)))]
|
||||
(m/walk s walk-fn options)))
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
(def schema:plugin-data
|
||||
(sm/register!
|
||||
^{::sm/type ::plugin-data}
|
||||
[:map-of {:gen/max 5}
|
||||
[:map-of {:gen/max 5 :title "PluginsData"}
|
||||
schema:keyword
|
||||
[:map-of {:gen/max 5}
|
||||
schema:string
|
||||
|
||||
@@ -185,50 +185,50 @@
|
||||
[:height ::sm/safe-number]])
|
||||
|
||||
(def schema:shape-generic-attrs
|
||||
[:map {:title "ShapeAttrs"}
|
||||
[:page-id {:optional true} ::sm/uuid]
|
||||
[:component-id {:optional true} ::sm/uuid]
|
||||
[:component-file {:optional true} ::sm/uuid]
|
||||
[:component-root {:optional true} :boolean]
|
||||
[:main-instance {:optional true} :boolean]
|
||||
[:remote-synced {:optional true} :boolean]
|
||||
[:shape-ref {:optional true} ::sm/uuid]
|
||||
[:touched {:optional true} [:maybe [:set :keyword]]]
|
||||
[:blocked {:optional true} :boolean]
|
||||
[:collapsed {:optional true} :boolean]
|
||||
[:locked {:optional true} :boolean]
|
||||
[:hidden {:optional true} :boolean]
|
||||
[:masked-group {:optional true} :boolean]
|
||||
[:fills {:optional true}
|
||||
[:vector {:gen/max 2} schema:fill]]
|
||||
[:proportion {:optional true} ::sm/safe-number]
|
||||
[:proportion-lock {:optional true} :boolean]
|
||||
[:constraints-h {:optional true}
|
||||
[::sm/one-of horizontal-constraint-types]]
|
||||
[:constraints-v {:optional true}
|
||||
[::sm/one-of vertical-constraint-types]]
|
||||
[:fixed-scroll {:optional true} :boolean]
|
||||
[:r1 {:optional true} ::sm/safe-number]
|
||||
[:r2 {:optional true} ::sm/safe-number]
|
||||
[:r3 {:optional true} ::sm/safe-number]
|
||||
[:r4 {:optional true} ::sm/safe-number]
|
||||
[:opacity {:optional true} ::sm/safe-number]
|
||||
[:grids {:optional true}
|
||||
[:vector {:gen/max 2} ::ctg/grid]]
|
||||
[:exports {:optional true}
|
||||
[:vector {:gen/max 2} ::ctse/export]]
|
||||
[:strokes {:optional true}
|
||||
[:vector {:gen/max 2} schema:stroke]]
|
||||
[:blend-mode {:optional true}
|
||||
[::sm/one-of blend-modes]]
|
||||
[:map {:title "ShapeGenericAttrs"}
|
||||
;; [:page-id {:optional true} ::sm/uuid]
|
||||
;; [:component-id {:optional true} ::sm/uuid]
|
||||
;; [:component-file {:optional true} ::sm/uuid]
|
||||
;; [:component-root {:optional true} :boolean]
|
||||
;; [:main-instance {:optional true} :boolean]
|
||||
;; [:remote-synced {:optional true} :boolean]
|
||||
;; [:shape-ref {:optional true} ::sm/uuid]
|
||||
;; [:touched {:optional true} [:maybe [:set :keyword]]]
|
||||
;; [:blocked {:optional true} :boolean]
|
||||
;; [:collapsed {:optional true} :boolean]
|
||||
;; [:locked {:optional true} :boolean]
|
||||
;; [:hidden {:optional true} :boolean]
|
||||
;; [:masked-group {:optional true} :boolean]
|
||||
;; [:fills {:optional true}
|
||||
;; [:vector {:gen/max 2} schema:fill]]
|
||||
;; [:proportion {:optional true} ::sm/safe-number]
|
||||
;; [:proportion-lock {:optional true} :boolean]
|
||||
;; [:constraints-h {:optional true}
|
||||
;; [::sm/one-of horizontal-constraint-types]]
|
||||
;; [:constraints-v {:optional true}
|
||||
;; [::sm/one-of vertical-constraint-types]]
|
||||
;; [:fixed-scroll {:optional true} :boolean]
|
||||
;; [:r1 {:optional true} ::sm/safe-number]
|
||||
;; [:r2 {:optional true} ::sm/safe-number]
|
||||
;; [:r3 {:optional true} ::sm/safe-number]
|
||||
;; [:r4 {:optional true} ::sm/safe-number]
|
||||
;; [:opacity {:optional true} ::sm/safe-number]
|
||||
;; [:grids {:optional true}
|
||||
;; [:vector {:gen/max 2} ::ctg/grid]]
|
||||
;; [:exports {:optional true}
|
||||
;; [:vector {:gen/max 2} ::ctse/export]]
|
||||
;; [:strokes {:optional true}
|
||||
;; [:vector {:gen/max 2} schema:stroke]]
|
||||
;; [:blend-mode {:optional true}
|
||||
;; [::sm/one-of blend-modes]]
|
||||
[:interactions {:optional true}
|
||||
[:vector {:gen/max 2} ::ctsi/interaction]]
|
||||
[:shadow {:optional true}
|
||||
[:vector {:gen/max 1} ctss/schema:shadow]]
|
||||
[:blur {:optional true} ::ctsb/blur]
|
||||
;; [:shadow {:optional true}
|
||||
;; [:vector {:gen/max 1} ctss/schema:shadow]]
|
||||
;; [:blur {:optional true} ::ctsb/blur]
|
||||
[:grow-type {:optional true}
|
||||
[::sm/one-of grow-types]]
|
||||
[:applied-tokens {:optional true} cto/schema:applied-tokens]
|
||||
;; [:applied-tokens {:optional true} cto/schema:applied-tokens]
|
||||
[:plugin-data {:optional true} ::ctpg/plugin-data]])
|
||||
|
||||
(def schema:group-attrs
|
||||
@@ -306,6 +306,15 @@
|
||||
(merge attrs1 shape attrs2 attrs3)))))
|
||||
(sg/fmap create-shape)))
|
||||
|
||||
|
||||
(def kaka
|
||||
[:merge {:title "BoolShape"}
|
||||
ctsl/schema:layout-child-attrs
|
||||
schema:bool-attrs
|
||||
schema:shape-generic-attrs
|
||||
schema:shape-base-attrs])
|
||||
|
||||
|
||||
(def schema:shape-attrs
|
||||
[:multi {:dispatch :type
|
||||
:decode/json (fn [shape]
|
||||
|
||||
@@ -175,21 +175,23 @@
|
||||
[:url :string]])
|
||||
|
||||
(def schema:interaction
|
||||
[:and {:title "Interaction"
|
||||
:gen/gen (sg/one-of (sg/generator schema:navigate-interaction)
|
||||
(sg/generator schema:open-overlay-interaction)
|
||||
(sg/generator schema:close-overlay-interaction)
|
||||
(sg/generator schema:toggle-overlay-interaction)
|
||||
(sg/generator schema:prev-scren-interaction)
|
||||
(sg/generator schema:open-url-interaction))}
|
||||
schema:interaction-attrs
|
||||
[:multi {:dispatch :action-type}
|
||||
[:navigate schema:navigate-interaction]
|
||||
[:open-overlay schema:open-overlay-interaction]
|
||||
[:toggle-overlay schema:toggle-overlay-interaction]
|
||||
[:close-overlay schema:close-overlay-interaction]
|
||||
[:prev-screen schema:prev-scren-interaction]
|
||||
[:open-url schema:open-url-interaction]]])
|
||||
[:schema {:title "Interaction"
|
||||
:gen/gen (sg/one-of (sg/generator schema:navigate-interaction)
|
||||
(sg/generator schema:open-overlay-interaction)
|
||||
(sg/generator schema:close-overlay-interaction)
|
||||
(sg/generator schema:toggle-overlay-interaction)
|
||||
(sg/generator schema:prev-scren-interaction)
|
||||
(sg/generator schema:open-url-interaction))}
|
||||
[:and
|
||||
schema:interaction-attrs
|
||||
[:multi {:dispatch :action-type}
|
||||
;; [:navigate schema:navigate-interaction]
|
||||
;; [:open-overlay schema:open-overlay-interaction]
|
||||
;; [:toggle-overlay schema:toggle-overlay-interaction]
|
||||
;; [:close-overlay schema:close-overlay-interaction]
|
||||
;; [:prev-screen schema:prev-scren-interaction]
|
||||
[:open-url schema:open-url-interaction]
|
||||
]]])
|
||||
|
||||
(sm/register! ::interaction schema:interaction)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.schema.desc-js-like :as smdj]
|
||||
[clojure.data :as data]
|
||||
[clojure.set :as set]
|
||||
[malli.util :as mu]))
|
||||
@@ -51,7 +52,8 @@
|
||||
(into #{} (keys token-type->dtcg-token-type)))
|
||||
|
||||
(def token-name-ref
|
||||
[:and :string [:re #"^(?!\$)([a-zA-Z0-9-$_]+\.?)*(?<!\.)$"]])
|
||||
[:schema {:title "TokenNameRef"}
|
||||
[:and :string [:re #"^(?!\$)([a-zA-Z0-9-$_]+\.?)*(?<!\.)$"]]])
|
||||
|
||||
(def ^:private schema:color
|
||||
[:map
|
||||
@@ -61,7 +63,7 @@
|
||||
(def color-keys (schema-keys schema:color))
|
||||
|
||||
(def ^:private schema:border-radius
|
||||
[:map
|
||||
[:map {:title "BorderRadiusTokenAttrs"}
|
||||
[:r1 {:optional true} token-name-ref]
|
||||
[:r2 {:optional true} token-name-ref]
|
||||
[:r3 {:optional true} token-name-ref]
|
||||
@@ -76,7 +78,7 @@
|
||||
(def stroke-width-keys (schema-keys schema:stroke-width))
|
||||
|
||||
(def ^:private schema:sizing
|
||||
[:map
|
||||
[:map {:title "SizingTokenAttrs"}
|
||||
[:width {:optional true} token-name-ref]
|
||||
[:height {:optional true} token-name-ref]
|
||||
[:layout-item-min-w {:optional true} token-name-ref]
|
||||
@@ -87,44 +89,46 @@
|
||||
(def sizing-keys (schema-keys schema:sizing))
|
||||
|
||||
(def ^:private schema:opacity
|
||||
[:map
|
||||
[:map {:title "OpacityTokenAttrs"}
|
||||
[:opacity {:optional true} token-name-ref]])
|
||||
|
||||
(def opacity-keys (schema-keys schema:opacity))
|
||||
|
||||
(def ^:private schema:spacing-gap
|
||||
[:map
|
||||
[:map {:title "SpacingGapTokenAttrs"}
|
||||
[:row-gap {:optional true} token-name-ref]
|
||||
[:column-gap {:optional true} token-name-ref]])
|
||||
|
||||
(def ^:private schema:spacing-padding
|
||||
[:map
|
||||
[:map {:title "SpacingPaddingTokenAttrs"}
|
||||
[:p1 {:optional true} token-name-ref]
|
||||
[:p2 {:optional true} token-name-ref]
|
||||
[:p3 {:optional true} token-name-ref]
|
||||
[:p4 {:optional true} token-name-ref]])
|
||||
|
||||
(def ^:private schema:spacing-margin
|
||||
[:map
|
||||
[:map {:title "SpacingMarginTokenAttrs"}
|
||||
[:m1 {:optional true} token-name-ref]
|
||||
[:m2 {:optional true} token-name-ref]
|
||||
[:m3 {:optional true} token-name-ref]
|
||||
[:m4 {:optional true} token-name-ref]])
|
||||
|
||||
(def ^:private schema:spacing
|
||||
(reduce mu/union [schema:spacing-gap
|
||||
schema:spacing-padding
|
||||
schema:spacing-margin]))
|
||||
(-> (reduce mu/union [schema:spacing-gap
|
||||
schema:spacing-padding
|
||||
schema:spacing-margin])
|
||||
(mu/update-properties assoc :title "SpacingTokenAttrs")))
|
||||
|
||||
(def spacing-margin-keys (schema-keys schema:spacing-margin))
|
||||
|
||||
(def spacing-keys (schema-keys schema:spacing))
|
||||
|
||||
(def ^:private schema:dimensions
|
||||
(reduce mu/union [schema:sizing
|
||||
schema:spacing
|
||||
schema:stroke-width
|
||||
schema:border-radius]))
|
||||
(-> (reduce mu/union [schema:sizing
|
||||
schema:spacing
|
||||
schema:stroke-width
|
||||
schema:border-radius])
|
||||
(mu/update-properties assoc :title "DimensionsTokenAttrs")))
|
||||
|
||||
(def dimensions-keys (schema-keys schema:dimensions))
|
||||
|
||||
@@ -135,22 +139,20 @@
|
||||
|
||||
(def axis-keys (schema-keys schema:axis))
|
||||
|
||||
|
||||
|
||||
(def ^:private schema:rotation
|
||||
[:map
|
||||
[:map {:title "RotationTokenAttrs"}
|
||||
[:rotation {:optional true} token-name-ref]])
|
||||
|
||||
(def rotation-keys (schema-keys schema:rotation))
|
||||
|
||||
(def ^:private schema:font-size
|
||||
[:map
|
||||
[:map {:title "FontSizeTokenAttrs"}
|
||||
[:font-size {:optional true} token-name-ref]])
|
||||
|
||||
(def font-size-keys (schema-keys schema:font-size))
|
||||
|
||||
(def ^:private schema:letter-spacing
|
||||
[:map
|
||||
[:map {:title "LetterSpacingTokenAttrs"}
|
||||
[:letter-spacing {:optional true} token-name-ref]])
|
||||
|
||||
(def letter-spacing-keys (schema-keys schema:letter-spacing))
|
||||
@@ -162,8 +164,9 @@
|
||||
(def ff-typography-keys (set/difference typography-keys font-size-keys))
|
||||
|
||||
(def ^:private schema:number
|
||||
(reduce mu/union [[:map [:line-height {:optional true} token-name-ref]]
|
||||
schema:rotation]))
|
||||
(-> (reduce mu/union [[:map [:line-height {:optional true} token-name-ref]]
|
||||
schema:rotation])
|
||||
(mu/update-properties assoc :title "NumberTokenAttrs")))
|
||||
|
||||
(def number-keys (schema-keys schema:number))
|
||||
|
||||
@@ -180,10 +183,10 @@
|
||||
number-keys))
|
||||
|
||||
(def ^:private schema:tokens
|
||||
[:map {:title "Applied Tokens"}])
|
||||
[:map {:title "GenericTokenAttrs"}])
|
||||
|
||||
(def schema:applied-tokens
|
||||
[:merge
|
||||
[:merge {:title "AppliedTokens"}
|
||||
schema:tokens
|
||||
schema:border-radius
|
||||
schema:sizing
|
||||
|
||||
@@ -186,6 +186,10 @@
|
||||
:modified-at modified-at
|
||||
:tokens tokens})])
|
||||
|
||||
#?@(:clj
|
||||
[json/JSONWriter
|
||||
(-write [this writter options] (json/-write (deref this) writter options))])
|
||||
|
||||
#?@(:cljs [cljs.core/IEncodeJS
|
||||
(-clj->js [_] (js-obj "id" (clj->js id)
|
||||
"name" (clj->js name)
|
||||
@@ -292,7 +296,9 @@
|
||||
(declare make-token-set)
|
||||
|
||||
(def schema:token-set
|
||||
(sm/required-keys schema:token-set-attrs))
|
||||
[:schema {:gen/gen (->> (sg/generator schema:token-set-attrs)
|
||||
(sg/fmap #(make-token-set %)))}
|
||||
(sm/required-keys schema:token-set-attrs)])
|
||||
|
||||
(sm/register! ::token-set schema:token-set) ;; need to register for the recursive schema of token-sets
|
||||
|
||||
@@ -466,18 +472,17 @@
|
||||
(get-ordered-set-names [_] "get an ordered sequence of all sets names in the library")
|
||||
(get-set [_ set-name] "get one set looking for name"))
|
||||
|
||||
(def schema:token-set-node
|
||||
[:schema {:registry {::node [:or [:fn token-set?]
|
||||
[:and
|
||||
[:map-of {:gen/max 5} :string [:ref ::node]]
|
||||
[:fn d/ordered-map?]]]}}
|
||||
(def ^:private schema:token-set-node
|
||||
[:schema {:registry {::node
|
||||
[:or [:fn token-set?]
|
||||
[:and
|
||||
[:map-of {:gen/max 5} :string [:ref ::node]]
|
||||
[:fn d/ordered-map?]]]}}
|
||||
[:ref ::node]])
|
||||
|
||||
(def schema:token-sets
|
||||
[:and
|
||||
[:map-of {:title "TokenSets"}
|
||||
:string
|
||||
schema:token-set-node]
|
||||
(def ^:private schema:token-sets
|
||||
[:and {:title "TokenSets"}
|
||||
[:map-of :string schema:token-set-node]
|
||||
[:fn d/ordered-map?]])
|
||||
|
||||
(def ^:private check-token-sets
|
||||
|
||||
@@ -125,7 +125,11 @@
|
||||
|
||||
(mf/defc menu-team-icon*
|
||||
[{:keys [subscription-type]}]
|
||||
[:span {:class (stl/css :subscription-icon) :data-testid "subscription-icon"}
|
||||
[:span {:class (stl/css :subscription-icon)
|
||||
:title (if (= subscription-type "unlimited")
|
||||
(tr "subscription.dashboard.power-up.unlimited-plan")
|
||||
(tr "subscription.dashboard.power-up.enterprise-plan"))
|
||||
:data-testid "subscription-icon"}
|
||||
(case subscription-type
|
||||
"unlimited" i/character-u
|
||||
"enterprise" i/character-e)])
|
||||
|
||||
@@ -74,42 +74,12 @@
|
||||
[:& c/navigation-bullets
|
||||
{:slide slide
|
||||
:navigate navigate
|
||||
:total 3}]
|
||||
:total 2}]
|
||||
|
||||
[: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.9-overrides.gif"
|
||||
:class (stl/css :start-image)
|
||||
:border "0"
|
||||
:alt "Component text overrides"}]
|
||||
|
||||
[:div {:class (stl/css :modal-content)}
|
||||
[:div {:class (stl/css :modal-header)}
|
||||
[:h1 {:class (stl/css :modal-title)}
|
||||
"Component text overrides"]]
|
||||
|
||||
[:div {:class (stl/css :feature)}
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"You can now edit the text content independently from its properties—such as color, effects, font size, or weight—allowing you to update the wording while preserving the styling."]
|
||||
|
||||
[:p {:class (stl/css :feature-content)}
|
||||
"This change (inspired by community feedback) greatly improves consistency, predictability, and control when working with texts in components."]]
|
||||
|
||||
[:div {:class (stl/css :navigation)}
|
||||
[:& c/navigation-bullets
|
||||
{:slide slide
|
||||
:navigate navigate
|
||||
:total 3}]
|
||||
|
||||
[:button {:on-click next
|
||||
:class (stl/css :next-btn)} "Continue"]]]]]]
|
||||
|
||||
2
|
||||
[:div {:class (stl/css-case :modal-overlay true)}
|
||||
[:div.animated {:class klass}
|
||||
[:div {:class (stl/css :modal-container)}
|
||||
@@ -135,7 +105,7 @@
|
||||
[:& c/navigation-bullets
|
||||
{:slide slide
|
||||
:navigate navigate
|
||||
:total 3}]
|
||||
:total 2}]
|
||||
|
||||
[:button {:on-click finish
|
||||
:class (stl/css :next-btn)} "Let's go"]]]]]])))
|
||||
|
||||
@@ -150,7 +150,16 @@
|
||||
:class (stl/css :input-field)}]]
|
||||
[:div {:class (stl/css :editors-cost)}
|
||||
[:span {:class (stl/css :modal-text-small)}
|
||||
(tr "subscription.settings.management.dialog.price-month" (or (get-in @form [:clean-data :min-members]) 0))]
|
||||
(when (> (get-in @form [:clean-data :min-members]) 25)
|
||||
[:> i18n/tr-html*
|
||||
{:class (stl/css :modal-text-cap)
|
||||
:tag-name "span"
|
||||
:content (tr "subscription.settings.management.dialog.price-month" "175")}])
|
||||
[:> i18n/tr-html*
|
||||
{:class (stl/css-case :text-strikethrough (> (get-in @form [:clean-data :min-members]) 25))
|
||||
:tag-name "span"
|
||||
:content (tr "subscription.settings.management.dialog.price-month"
|
||||
(* 7 (or (get-in @form [:clean-data :min-members]) 0)))}]]
|
||||
[:span {:class (stl/css :modal-text-small)}
|
||||
(tr "subscription.settings.management.dialog.payment-explanation")]]]
|
||||
|
||||
|
||||
@@ -199,6 +199,20 @@
|
||||
@include t.use-typography("body-small");
|
||||
}
|
||||
|
||||
.modal-text-cap {
|
||||
margin-inline-end: var(--sp-s);
|
||||
}
|
||||
|
||||
.text-strikethrough {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.modal-text-small strong,
|
||||
.text-strikethrough strong,
|
||||
.modal-text-cap strong {
|
||||
font-weight: $fw700;
|
||||
}
|
||||
|
||||
.modal-content,
|
||||
.modal-end {
|
||||
color: var(--color-foreground-secondary);
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
:type "text"
|
||||
:on-blur on-submit
|
||||
:on-key-down on-key-down
|
||||
:maxlength "256"
|
||||
:max-length "256"
|
||||
:auto-focus true
|
||||
:placeholder (tr "workspace.tokens.set-edit-placeholder")
|
||||
:default-value default-value}]))
|
||||
@@ -210,7 +210,7 @@
|
||||
|
||||
(mf/defc sets-tree-set*
|
||||
[{:keys [id set label tree-depth tree-path tree-index is-selected is-active is-draggable is-editing
|
||||
on-select on-drop on-toggle on-start-edition on-reset-edition on-edit-submit]}]
|
||||
on-select on-drop on-toggle on-start-edition on-reset-edition on-edit-submit is-new]}]
|
||||
|
||||
(let [set-name (ctob/get-name set)
|
||||
can-edit? (mf/use-ctx ctx/can-edit?)
|
||||
@@ -239,7 +239,11 @@
|
||||
:path tree-path})))))
|
||||
|
||||
on-double-click
|
||||
(mf/use-fn (mf/deps id) #(on-start-edition id))
|
||||
(mf/use-fn
|
||||
(mf/deps id is-new)
|
||||
(fn []
|
||||
(when-not is-new
|
||||
(on-start-edition id))))
|
||||
|
||||
on-checkbox-click
|
||||
(mf/use-fn
|
||||
@@ -392,7 +396,7 @@
|
||||
:is-editing true
|
||||
:is-active true
|
||||
:is-selected true
|
||||
|
||||
:is-new true
|
||||
:tree-path path
|
||||
:tree-depth depth
|
||||
:tree-index index
|
||||
@@ -416,6 +420,7 @@
|
||||
:tree-path path
|
||||
:tree-depth depth
|
||||
:tree-index index
|
||||
:is-new false
|
||||
:tree-parent-path parent-path
|
||||
:on-toggle on-toggle-set
|
||||
:edition-id edition-id
|
||||
|
||||
@@ -116,13 +116,17 @@
|
||||
(let [root? (contains? (:root-shapes options) (:id shape))]
|
||||
(if (and root? (ctl/any-layout? shape))
|
||||
:fill
|
||||
(get-shape-size shape objects :width))))
|
||||
;; Don't set fixed width for auto-width text shapes
|
||||
(when-not (and (cfh/text-shape? shape) (= (:grow-type shape) :auto-width))
|
||||
(get-shape-size shape objects :width)))))
|
||||
|
||||
(defmethod get-value :height
|
||||
[_ shape objects options]
|
||||
(let [root? (contains? (:root-shapes options) (:id shape))]
|
||||
(when-not (and root? (ctl/any-layout? shape))
|
||||
(get-shape-size shape objects :height))))
|
||||
;; Don't set fixed height for auto-height text shapes
|
||||
(when-not (and (cfh/text-shape? shape) (= (:grow-type shape) :auto-height))
|
||||
(get-shape-size shape objects :height)))))
|
||||
|
||||
(defmethod get-value :flex-grow
|
||||
[_ shape _ options]
|
||||
|
||||
@@ -4387,11 +4387,6 @@ msgstr "Subscription"
|
||||
msgid "subscription.settings.add-payment-to-continue"
|
||||
msgstr "Add a payment method to continue after your trial"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:82, src/app/main/ui/settings/subscription.cljs:115, src/app/main/ui/settings/subscription.cljs:127
|
||||
#, fuzzy, unused
|
||||
msgid "subscription.settings.benefits.all-professiona-benefits"
|
||||
msgstr ""
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:247, src/app/main/ui/settings/subscription.cljs:268, src/app/main/ui/settings/subscription.cljs:303, src/app/main/ui/settings/subscription.cljs:317
|
||||
msgid "subscription.settings.benefits.all-professional-benefits"
|
||||
msgstr "All Professional plan benefits and:"
|
||||
@@ -4446,8 +4441,10 @@ msgid "subscription.settings.management.dialog.payment-explanation"
|
||||
msgstr "(No payment will be made now)"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:124
|
||||
#, markdown
|
||||
msgid "subscription.settings.management.dialog.price-month"
|
||||
msgstr "$7 per editor/month x %s"
|
||||
msgstr ""
|
||||
"**$%s** per month"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:112
|
||||
msgid "subscription.settings.management.dialog.select-editors"
|
||||
|
||||
@@ -4474,8 +4474,10 @@ msgid "subscription.settings.management.dialog.payment-explanation"
|
||||
msgstr "(Ahora no se efectuará ningún pago)"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:124
|
||||
#, markdown
|
||||
msgid "subscription.settings.management.dialog.price-month"
|
||||
msgstr "$7 por editor/mes x %s"
|
||||
msgstr ""
|
||||
"**$%s** por mes"
|
||||
|
||||
#: src/app/main/ui/settings/subscription.cljs:112
|
||||
msgid "subscription.settings.management.dialog.select-editors"
|
||||
|
||||
Reference in New Issue
Block a user