From 1a6a680020a1f229bc4f2967f768ef5e4c6f35b5 Mon Sep 17 00:00:00 2001 From: liaoxuezhi <2betop.cn@gmail.com> Date: Tue, 16 Apr 2024 16:39:12 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E8=B0=83=E6=95=B4=E5=85=AC=E5=BC=8F?= =?UTF-8?q?=E8=BE=93=E5=85=A5=E4=BA=A4=E4=BA=92=E5=B9=B6=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=99=A8=E6=A8=A1=E7=89=88=E6=96=87=E6=A1=A3?= =?UTF-8?q?=20(#10034)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- amis.code-workspace | 9 + examples/doc.css | 765 +----------------- examples/index.html | 4 + examples/style.scss | 2 +- index.html | 4 + package.json | 5 + .../control/_expression-formula-control.scss | 10 +- packages/amis-editor/examples/App.tsx | 6 +- .../amis-editor/examples/component/Doc.tsx | 83 ++ .../examples/component/PanelPreview.tsx | 60 ++ packages/amis-editor/examples/route/Basic.md | 21 + .../amis-editor/examples/route/Formula.md | 117 +++ packages/amis-editor/examples/style.scss | 28 + packages/amis-editor/index.html | 1 + packages/amis-editor/index.tsx | 202 ++++- .../src/renderer/ExpressionFormulaControl.tsx | 11 +- .../src/renderer/FormulaControl.tsx | 5 +- .../src/renderer/TplFormulaControl.tsx | 23 +- packages/amis-editor/src/tpl/common.tsx | 5 +- .../amis-ui/scss/components/_formula.scss | 20 +- .../src/components/formula/CodeEditor.tsx | 10 +- .../amis-ui/src/components/formula/Picker.tsx | 30 +- .../amis-ui/src/components/formula/plugin.ts | 26 + packages/amis-ui/src/custom.d.ts | 6 +- scripts/markdownPlugin.ts | 2 + 25 files changed, 654 insertions(+), 801 deletions(-) create mode 100644 packages/amis-editor/examples/component/Doc.tsx create mode 100644 packages/amis-editor/examples/component/PanelPreview.tsx create mode 100644 packages/amis-editor/examples/route/Basic.md create mode 100644 packages/amis-editor/examples/route/Formula.md diff --git a/amis.code-workspace b/amis.code-workspace index 407500fb5..71f13097f 100644 --- a/amis.code-workspace +++ b/amis.code-workspace @@ -18,6 +18,15 @@ }, { "path": "./packages/office-viewer" + }, + { + "path": "./packages/amis-editor-core" + }, + { + "path": "./packages/amis-editor" + }, + { + "path": "./packages/amis-theme-editor-helper" } ] } diff --git a/examples/doc.css b/examples/doc.css index 9a32adb27..543d5aa10 100644 --- a/examples/doc.css +++ b/examples/doc.css @@ -1,751 +1,17 @@ -/* csshint-disable */ -@font-face { - font-family: octicons-link; - src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8IhnYXNwAAAGTAAAABAAAAAQABoAI2dseWYAAAFsAAABPAAAAZwcEq9taGVhZAAAAsgAAAA0AAAANgh4a91oaGVhAAADCAAAABoAAAAkCA8DRGhtdHgAAAL8AAAADAAAAAwGAACfbG9jYQAAAsAAAAAIAAAACABiATBtYXhwAAACqAAAABgAAAAgAA8ASm5hbWUAAAToAAABQgAAAlXu73sOcG9zdAAABiwAAAAeAAAAME3QpOBwcmVwAAAEbAAAAHYAAAB/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vWY/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7Vm1ozezUeLEaUjhaDSuXHwVRgvLJn1tQ7xiuVv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9JOS0nbaaYDCQfwCJ7Au3AHj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aUEd4Nd3CHD8NdvOLTsA2GL8M9PODbcL+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9Jyda6Sl1dUYhSCm1dyClfoeDve4qMYdLEbfqHf3O/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==) - format('woff'); -} - -.markdown { - padding: 25px 45px 25px; -} - .markdown-body { - -ms-text-size-adjust: 100%; - -webkit-text-size-adjust: 100%; - color: #333; - font-family: 'PingFang SC', 'Microsoft YaHei', 'Hiragino Sans GB', 'STHeiti', - 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif; - font-size: 16px; - line-height: 1.6; - word-wrap: break-word; box-sizing: border-box; min-width: 200px; - /* max-width: 980px; */ - /* margin: 0 auto; */ + max-width: 980px; } -.markdown-body a:not(.btn) { - background-color: transparent; - -webkit-text-decoration-skip: objects; -} - -.markdown-body a:active:not(.btn), -.markdown-body a:hover:not(.btn) { - outline-width: 0; -} - -.markdown-body strong { - font-weight: inherit; -} - -.markdown-body strong { - font-weight: bolder; -} - -.markdown-body > h1 { - font-size: 2em; - margin: 0.67em 0; -} - -.markdown-body img { - border-style: none; -} - -.markdown-body svg:not(:root) { - overflow: hidden; -} - -.markdown-body code, -.markdown-body kbd, -.markdown-body pre { - font-family: monospace, monospace; - font-size: 1em; -} - -.markdown-body hr { - box-sizing: content-box; - height: 0; - overflow: visible; -} - -.markdown-body input { - font: inherit; - margin: 0; -} - -.markdown-body input { - overflow: visible; -} - -.markdown-body button:-moz-focusring, -.markdown-body [type='button']:-moz-focusring, -.markdown-body [type='reset']:-moz-focusring, -.markdown-body [type='submit']:-moz-focusring { - outline: 1px dotted ButtonText; -} - -.markdown-body [type='checkbox'] { - box-sizing: border-box; - padding: 0; -} - -.markdown-body table:not(.table) { - border-spacing: 0; - border-collapse: collapse; -} - -.markdown-body table:not(.table) td, -.markdown-body table:not(.table) th { - padding: 0; -} - -.markdown-body * { - box-sizing: border-box; -} - -.markdown-body input { - font: 13px/1.4 Helvetica, arial, nimbussansl, liberationsans, freesans, clean, - sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; -} - -/* .markdown-body a:not(.btn) { - color: #4078c0; - text-decoration: none; -} - -.markdown-body a:hover:not(.btn), -.markdown-body a:active:not(.btn) { - color: #4078c0; - text-decoration: underline; -} */ - -.markdown-body hr { - height: 0; - margin: 15px 0; - overflow: hidden; - background: transparent; - border: 0; - border-bottom: 1px solid #ddd; -} - -.markdown-body hr::before { - display: table; - content: ''; -} - -.markdown-body hr::after { - display: table; - clear: both; - content: ''; -} - -.markdown-body > h1, -.markdown-body > h2, -.markdown-body > h3, -.markdown-body > h4, -.markdown-body > h5, -.markdown-body > h6 { - margin-top: 0; - margin-bottom: 0; - line-height: 1.5; -} - -.markdown-body > h1 { - font-size: 30px; -} - -.markdown-body > h2 { - font-size: 21px; -} - -.markdown-body > h3 { - font-size: 16px; -} - -.markdown-body > h4 { - font-size: 14px; -} - -.markdown-body > h5 { - font-size: 12px; -} - -.markdown-body > h6 { - font-size: 11px; -} - -.markdown-body p { - margin-top: 0; - margin-bottom: 10px; -} - -.markdown-body blockquote { - margin: 0; -} - -.markdown-body ul, -.markdown-body ol { - padding-left: 0; - margin-top: 0; - margin-bottom: 0; -} - -.markdown-body ol ol, -.markdown-body ul ol { - list-style-type: lower-roman; -} - -.markdown-body ul ul ol, -.markdown-body ul ol ol, -.markdown-body ol ul ol, -.markdown-body ol ol ol { - list-style-type: lower-alpha; -} - -.markdown-body dd { - margin-left: 0; -} - -.markdown-body code { - font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; - font-size: 12px; -} - -.markdown-body pre { - margin-top: 0; - margin-bottom: 0; - font: 12px Consolas, 'Liberation Mono', Menlo, Courier, monospace; -} - -.markdown-body .pl-0 { - padding-left: 0 !important; -} - -.markdown-body .pl-1 { - padding-left: 3px !important; -} - -.markdown-body .pl-2 { - padding-left: 6px !important; -} - -.markdown-body .pl-3 { - padding-left: 12px !important; -} - -.markdown-body .pl-4 { - padding-left: 24px !important; -} - -.markdown-body .pl-5 { - padding-left: 36px !important; -} - -.markdown-body .pl-6 { - padding-left: 48px !important; -} - -.markdown-body .form-select::-ms-expand { - opacity: 0; -} - -.markdown-body:before { - display: table; - content: ''; -} - -.markdown-body:after { - display: table; - clear: both; - content: ''; -} - -.markdown-body > *:first-child { - margin-top: 0 !important; -} - -.markdown-body > *:last-child { - margin-bottom: 0 !important; -} - -.markdown-body a:not([href]) { - color: inherit; - text-decoration: none; -} - -.markdown-body a.anchor { - display: inline-block; - padding-right: 2px; - margin-left: -18px; -} - -.markdown-body a.anchor:focus { - outline: none; -} - -.markdown-body > h1, -.markdown-body > h2, -.markdown-body > h3, -.markdown-body > h4, -.markdown-body > h5, -.markdown-body > h6 { - margin-top: 1em; - margin-bottom: 16px; - font-weight: bold; - line-height: 1.4; -} - -.markdown-body > h1 .octicon-link, -.markdown-body > h2 .octicon-link, -.markdown-body > h3 .octicon-link, -.markdown-body > h4 .octicon-link, -.markdown-body > h5 .octicon-link, -.markdown-body > h6 .octicon-link { - color: #000; - vertical-align: middle; - visibility: hidden; -} - -.markdown-body > h1:hover .anchor, -.markdown-body > h2:hover .anchor, -.markdown-body > h3:hover .anchor, -.markdown-body > h4:hover .anchor, -.markdown-body > h5:hover .anchor, -.markdown-body > h6:hover .anchor { - text-decoration: none; -} - -.markdown-body > h1:hover .anchor .octicon-link, -.markdown-body > h2:hover .anchor .octicon-link, -.markdown-body > h3:hover .anchor .octicon-link, -.markdown-body > h4:hover .anchor .octicon-link, -.markdown-body > h5:hover .anchor .octicon-link, -.markdown-body > h6:hover .anchor .octicon-link { - visibility: visible; -} - -.markdown-body > h1 { - padding-bottom: 0.3em; - font-size: 2.25em; - line-height: 1.2; - border-bottom: 1px solid #dee5e7; -} - -.markdown-body > h1 .anchor { - line-height: 1; -} - -.markdown-body > h2 { - padding-bottom: 0.3em; - font-size: 1.75em; - line-height: 1.225; - border-bottom: 1px solid #dee5e7; -} - -.markdown-body > h2 .anchor { - line-height: 1; -} - -.markdown-body > h3 { - font-size: 1.5em; - line-height: 1.43; -} - -.markdown-body > h3 .anchor { - line-height: 1.2; -} - -.markdown-body > h4 { - font-size: 1.25em; -} - -.markdown-body > h4 .anchor { - line-height: 1.2; -} - -.markdown-body > h5 { - font-size: 1em; -} - -.markdown-body > h5 .anchor { - line-height: 1.1; -} - -.markdown-body > h6 { - font-size: 1em; - color: #777; -} - -.markdown-body h6 .anchor { - line-height: 1.1; -} - -.markdown-body p, -.markdown-body blockquote, -.markdown-body ul, -.markdown-body ol, -.markdown-body dl, -.markdown-body table, -.markdown-body pre { - margin-top: 0; - margin-bottom: 16px; -} - -.markdown-body hr { - height: 4px; - padding: 0; - margin: 16px 0; - background-color: #e7e7e7; - border: 0 none; -} - -.markdown-body ul:not(.dropdown-menu):not(.nav), -.markdown-body ol { - padding-left: 2em; -} - -.markdown-body ul ul, -.markdown-body ul ol, -.markdown-body ol ol, -.markdown-body ol ul { - margin-top: 0; - margin-bottom: 0; -} - -.markdown-body li > p { - margin-top: 16px; -} - -.markdown-body dl { - padding: 0; -} - -.markdown-body dl dt { - padding: 0; - margin-top: 16px; - font-size: 1em; - font-style: italic; - font-weight: bold; -} - -.markdown-body dl dd { - padding: 0 16px; - margin-bottom: 16px; -} - -.markdown-body blockquote { - padding: 0 15px; - color: #777; - border-left: 4px solid #ddd; -} - -.markdown-body blockquote > :first-child { - margin-top: 0; -} - -.markdown-body blockquote > :last-child { - margin-bottom: 0; -} - -.markdown-body table:not(.table) { - display: block; - width: 100%; - overflow: auto; - word-break: normal; - /* word-break: keep-all; */ - border-left: 1px solid #ddd; -} - -.markdown-body table:not(.table) th { - font-weight: bold; -} - -.markdown-body table:not(.table) th, -.markdown-body table:not(.table) td { - padding: 6px 13px; - border: 1px solid #ddd; -} - -.markdown-body table:not(.table) tr { - border-top: 1px solid #ccc; -} - -.markdown-body table:not(.table) tr:nth-child(2n) { - background-color: var(--colors-neutral-fill-9); -} - -.markdown-body table td:first-child, -.markdown-body table th:first-child { - position: sticky; - left: 0; - z-index: 10; - background-color: var(--colors-neutral-fill-11); - border-left: 0px !important; -} - -.markdown-body table td:first-child::after, -.markdown-body table th:first-child::after { - box-shadow: inset 10px 0 8px -8px rgba(0, 0, 0, 0.1); - position: absolute; - top: 0; - right: 0; - bottom: 0px; - width: 30px; - transform: translate(100%); - transition: box-shadow 0.3s; - content: ''; - pointer-events: none; -} - -.markdown-body table tr:nth-child(2n) td:first-child { - background-color: var(--colors-neutral-fill-9); -} - -/* modified by zhangjun08 - * 更改文档中的图片展示样式 - */ -.markdown-body img { - max-width: 90%; - margin-left: 5%; - margin-right: 5%; - box-sizing: content-box; - background-color: #fff; - border-radius: 5px; - border: 1px solid #ddd; - box-shadow: 0 8px 18px 0 rgba(0, 0, 0, 0.3); -} - -@media (min-width: 1200px) { - .markdown-body img { - max-width: 800px; +@media (max-width: 767px) { + .markdown-body { + padding: 15px; } } -.markdown-body code { - padding: 0; - padding-top: 0.2em; - padding-bottom: 0.2em; - margin: 0; - font-size: 85%; - background-color: rgba(0, 0, 0, 0.04); - border-radius: 3px; -} - -.markdown-body code:before, -.markdown-body code:after { - letter-spacing: -0.2em; - content: '\00a0'; -} - -.markdown-body pre > code { - padding: 0; - margin: 0; - font-size: 100%; - word-break: normal; - white-space: pre; - background: transparent; - border: 0; -} - -.markdown-body .highlight { - margin-bottom: 16px; -} - -.markdown-body .highlight pre, -.markdown-body pre { - padding: 16px; - overflow: auto; - font-size: 85%; - line-height: 1.45; - background-color: #f7f7f7; - border-radius: 3px; -} - -.markdown-body .highlight pre { - margin-bottom: 0; - word-break: normal; -} - -.markdown-body pre { - word-wrap: normal; -} - -.markdown-body pre code { - display: inline; - max-width: initial; - padding: 0; - margin: 0; - overflow: initial; - line-height: inherit; - word-wrap: normal; - background-color: transparent; - border: 0; -} - -.markdown-body pre code:before, -.markdown-body pre code:after { - content: normal; -} - -.markdown-body kbd { - display: inline-block; - padding: 3px 5px; - font-size: 11px; - line-height: 10px; - color: #555; - vertical-align: middle; - background-color: #fcfcfc; - border: solid 1px #ccc; - border-bottom-color: #bbb; - border-radius: 3px; - box-shadow: inset 0 -1px 0 #bbb; -} - -.markdown-body .pl-c { - color: #969896; -} - -.markdown-body .pl-c1, -.markdown-body .pl-s .pl-v { - color: #0086b3; -} - -.markdown-body .pl-e, -.markdown-body .pl-en { - color: #795da3; -} - -.markdown-body .pl-s .pl-s1, -.markdown-body .pl-smi { - color: #333; -} - -.markdown-body .pl-ent { - color: #63a35c; -} - -.markdown-body .pl-k { - color: #a71d5d; -} - -.markdown-body .pl-pds, -.markdown-body .pl-s, -.markdown-body .pl-s .pl-pse .pl-s1, -.markdown-body .pl-sr, -.markdown-body .pl-sr .pl-cce, -.markdown-body .pl-sr .pl-sra, -.markdown-body .pl-sr .pl-sre { - color: #183691; -} - -.markdown-body .pl-v { - color: #ed6a43; -} - -.markdown-body .pl-id { - color: #b52a1d; -} - -.markdown-body .pl-ii { - background-color: #b52a1d; - color: #f8f8f8; -} - -.markdown-body .pl-sr .pl-cce { - color: #63a35c; - font-weight: bold; -} - -.markdown-body .pl-ml { - color: #693a17; -} - -.markdown-body .pl-mh, -.markdown-body .pl-mh .pl-en, -.markdown-body .pl-ms { - color: #1d3e81; - font-weight: bold; -} - -.markdown-body .pl-mq { - color: #008080; -} - -.markdown-body .pl-mi { - color: #333; - font-style: italic; -} - -.markdown-body .pl-mb { - color: #333; - font-weight: bold; -} - -.markdown-body .pl-md { - background-color: #ffecec; - color: #bd2c00; -} - -.markdown-body .pl-mi1 { - background-color: #eaffea; - color: #55a532; -} - -.markdown-body .pl-mdr { - color: #795da3; - font-weight: bold; -} - -.markdown-body .pl-mo { - color: #1d3e81; -} - -.markdown-body kbd { - display: inline-block; - padding: 3px 5px; - font: 11px Consolas, 'Liberation Mono', Menlo, Courier, monospace; - line-height: 10px; - color: #555; - vertical-align: middle; - background-color: #fcfcfc; - border: solid 1px #ccc; - border-bottom-color: #bbb; - border-radius: 3px; - box-shadow: inset 0 -1px 0 #bbb; -} - -.markdown-body .full-commit .btn-outline:not(:disabled):hover { - color: #4078c0; - border: 1px solid #4078c0; -} - -.markdown-body :checked + .radio-label { - position: relative; - z-index: 1; - border-color: #4078c0; -} - -.markdown-body .octicon { - display: inline-block; - vertical-align: text-top; - fill: currentColor; -} - -.markdown-body .task-list-item { - list-style-type: none; -} - -.markdown-body .task-list-item + .task-list-item { - margin-top: 3px; -} - -.markdown-body .task-list-item input { - margin: 0 0.2em 0.25em -1.6em; - vertical-align: middle; -} - -.markdown-body hr { - border-bottom-color: #eee; +.markdown { + padding: 25px 45px 0; } .doc-play-ground { @@ -765,25 +31,6 @@ margin-bottom: 0; } -.markdown-body .CodeMirror pre { - padding: 0 4px; - margin: 0; - background-color: transparent; -} - -.markdown-body .CodeMirror, -.markdown-body .CodeMirror * { - box-sizing: content-box; -} - -.markdown-body .CodeMirror-lines { - padding: 0; -} - -.markdown-body .tree-view ul { - padding-left: 0 !important; -} - .markdown-body > .amis-preview { margin-bottom: 15px; } diff --git a/examples/index.html b/examples/index.html index f1de0347d..c2a26371d 100644 --- a/examples/index.html +++ b/examples/index.html @@ -19,6 +19,10 @@ /> + diff --git a/examples/style.scss b/examples/style.scss index 74c185b8b..cc5ad60cb 100644 --- a/examples/style.scss +++ b/examples/style.scss @@ -333,7 +333,7 @@ body { a.anchor { padding-top: 100px; - margin-top: -100px; + margin-top: -94px; } &-nav, diff --git a/index.html b/index.html index 30a549dea..6a24a7f45 100644 --- a/index.html +++ b/index.html @@ -26,6 +26,10 @@ /> + diff --git a/package.json b/package.json index 5b3bbceb2..a666ea478 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "@types/prismjs": "^1.26.0", "@types/react": "^18.0.24", "@types/react-dom": "^18.0.8", + "@types/react-syntax-highlighter": "^15.5.11", "@vitejs/plugin-react": "^2.2.0", "amis-publish": "^1.0.1", "copy-to-clipboard": "3.3.1", @@ -82,6 +83,7 @@ "fis3-prepackager-stand-alone-pack": "^1.0.0", "fis3-preprocessor-js-require-css": "^0.1.3", "fis3-preprocessor-js-require-file": "^0.1.3", + "github-markdown-css": "^5.5.1", "husky": "^8.0.0", "jest": "^29.0.3", "jest-environment-jsdom": "^29.0.3", @@ -97,7 +99,10 @@ "prismjs": "^1.29.0", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-markdown": "^9.0.1", "react-overlays": "5.1.1", + "react-syntax-highlighter": "^15.5.0", + "remark-gfm": "^4.0.0", "rollup": "^2.79.1", "rollup-pluginutils": "^2.8.2", "setprototypeof": "^1.2.0", diff --git a/packages/amis-editor-core/scss/control/_expression-formula-control.scss b/packages/amis-editor-core/scss/control/_expression-formula-control.scss index b993a9db6..978703823 100644 --- a/packages/amis-editor-core/scss/control/_expression-formula-control.scss +++ b/packages/amis-editor-core/scss/control/_expression-formula-control.scss @@ -9,8 +9,11 @@ .btn-configured { position: relative; justify-content: left; - padding-right: 32px; - padding-left: 4px; + padding: var(--button-size-sm-paddingTop) 32px + var(--button-size-sm-paddingBottom) 4px; + line-height: var(--button-size-sm-lineHeight); + height: var(--button-size-sm-height); + & > span { max-width: 100%; text-overflow: ellipsis; @@ -28,7 +31,8 @@ bottom: 0; right: var(--button-size-default-paddingRight); margin: auto 0 !important; - font-size: 14px; + width: 12px; + height: 12px; fill: var(--Form-input-clearBtn-color); &:hover { fill: var(--Form-input-clearBtn-color-onHover); diff --git a/packages/amis-editor/examples/App.tsx b/packages/amis-editor/examples/App.tsx index 474b417ff..8f05860c9 100644 --- a/packages/amis-editor/examples/App.tsx +++ b/packages/amis-editor/examples/App.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import {AlertComponent, ToastComponent, ContextMenu} from 'amis'; // @ts-ignore import AMisSchemaEditor from './Editor'; +import {Link} from 'react-router-dom'; export default class App extends React.PureComponent { render() { // 备注: 如果需要改用antd主题,还需要将index.html换成index-antd.html @@ -9,7 +10,10 @@ export default class App extends React.PureComponent { return (
-
amis 可视化编辑器
+
+ amis 可视化编辑器  + 面板模版 +
diff --git a/packages/amis-editor/examples/component/Doc.tsx b/packages/amis-editor/examples/component/Doc.tsx new file mode 100644 index 000000000..03d6e59a6 --- /dev/null +++ b/packages/amis-editor/examples/component/Doc.tsx @@ -0,0 +1,83 @@ +import React from 'react'; +import Markdown from 'react-markdown'; +import remarkGfm from 'remark-gfm'; +import {Prism as SyntaxHighlighter} from 'react-syntax-highlighter'; +import {darcula} from 'react-syntax-highlighter/dist/esm/styles/prism'; +import {getSchemaTpl, tipedLabel} from 'amis-editor-core'; +import 'amis'; +import '../../src/index'; +import PanelPreview from './PanelPreview'; +export interface DocProps { + children?: string | null | undefined; +} + +export function mdComment(fun: Function) { + const txt = fun.toString(); + debugger; + return txt; +} + +function str2schema(code: string) { + const fn = new Function('getSchemaTpl', 'tipedLabel', `return [${code}]`); + return fn.call(null, getSchemaTpl, tipedLabel); +} + +export default function Doc({children}: DocProps) { + return ( +
+
+ {props.children}; + } + + return {props.children}; + }, + code(props) { + const {children, className, node, ref, ...rest} = props; + const match = /language-(\w+)/.exec(className || ''); + + if (match?.[1] === 'schema') { + const schema = str2schema(children as string); + + return ( +
+ + + + + +
+ ); + } + + return match ? ( + + ) : ( + + {children} + + ); + } + }} + /> +
+
+ ); +} diff --git a/packages/amis-editor/examples/component/PanelPreview.tsx b/packages/amis-editor/examples/component/PanelPreview.tsx new file mode 100644 index 000000000..981fc9c05 --- /dev/null +++ b/packages/amis-editor/examples/component/PanelPreview.tsx @@ -0,0 +1,60 @@ +import {JsonView, render} from 'amis'; +import cx from 'classnames'; +import React from 'react'; +export interface PanelPreviewProps { + schema: any; +} + +export default function (props: PanelPreviewProps) { + const schema = React.useMemo(() => { + return { + type: 'form', + mode: 'normal', + wrapWithPanel: false, + className: cx('config-form-content', 'ae-Settings-content'), + wrapperComponent: 'div', + body: Array.isArray(props.schema) ? props.schema : [props.schema], + submitOnChange: true, + submitOnInit: true + }; + }, [JSON.stringify(props.schema)]); + const [data, setData] = React.useState({}); + const onFinished = React.useCallback((data: any) => { + setData(data); + return false; + }, []); + const onJsonEdit = React.useCallback((e: any) => { + setData(e.updated_src); + }, []); + const dom = React.useRef(null); + // const popOverContainer = React.useCallback(() => { + // return dom.current; + // }, []); + + return ( +
+
+ {render( + schema, + { + data: data, + onFinished: onFinished + // popOverContainer + }, + { + // theme: 'cxd' // 右侧属性配置面板固定使用cxd主题展示 + } + )} +
+ +
+ ); +} diff --git a/packages/amis-editor/examples/route/Basic.md b/packages/amis-editor/examples/route/Basic.md new file mode 100644 index 000000000..bcff094b5 --- /dev/null +++ b/packages/amis-editor/examples/route/Basic.md @@ -0,0 +1,21 @@ +# 基本模版 + +## 表单项名字 + +`formItemName` + +```schema +getSchemaTpl('formItemName', { + value: 'name' +}) +``` + +## 表单项展示模式 + +`formItemMode` + +```schema +getSchemaTpl('formItemMode', { + +}) +``` diff --git a/packages/amis-editor/examples/route/Formula.md b/packages/amis-editor/examples/route/Formula.md new file mode 100644 index 000000000..675875e4b --- /dev/null +++ b/packages/amis-editor/examples/route/Formula.md @@ -0,0 +1,117 @@ +# 公式相关 + +公式输入相关组件规范说明。 + +## 显隐表达式 + +比如:`visibleOn`, `disabledOn` 因为存在两种表达式的写法,所以这里需要明确区分。 + +- 没有初始值时出现「点击编写表达式」按钮,点击会弹出一个表达式编辑器。 +- 初始值存在时,且为 js 表达式(即不是 `${` 和 `}`包裹的)时,直接用文本输入框展示与输入。 +- 初始值存在时,且为 `${` 和 `}`包裹的公式表达式时,用公式编辑器展示,同时点击后,会弹出一个表达式编辑器,能直接回显当前公式 +- 公式弹窗内部始终是公式语法,不存在模版拼接语法。 +- 当 js 表达式被删除后,只能用新版公式编辑器了。 + +```schema +getSchemaTpl('expressionFormulaControl', { + label: '无默认值', + name: 'var1' +}), + +getSchemaTpl('expressionFormulaControl', { + label: '默认值为旧语法', + name: 'var2', + value: 'data.a == 1' +}), + +getSchemaTpl('expressionFormulaControl', { + label: '默认值为新语法', + name: 'var3', + value: '\\${a == 1 ? "1" : a == 2 ? "二" : a == 3 ? "三" : "一个很长的表达式"}' +}) +``` + +## 文本输入框默认值 + +默认展示为文本输入框,通过点击 `+fx` 来添加公式片段,公式部分高亮展示,是整体高亮,而不是表达式内部 token 高亮(变量名、操作符、字面量等会用不同的方式高亮)。整体高亮内部不细化高亮,展示 tooltip 时再细化高亮,并且点击后开始编辑点击部分公式,注意这里是编辑局部公式,而不是整个默认值输入框。 + +值格式中如果没有出现 `${` 和 `}` 包裹的公式,则认为是普通文本,如果存在,则会做公式处理。当时用户直接通过文本输入框输入公式时,会当成时输入普通文本,如果用户输入了 `$` 符号,要将其转成 `\\$`,这样就不会被误认为是公式了。要添加公式片段,用户必须通过点击 `+fx` 按钮添加。`+fx` 可以添加多个片段。 + +```schema +getSchemaTpl('tplFormulaControl', { + name: 'value', + label: '默认值' +}), + +getSchemaTpl('tplFormulaControl', { + name: 'value2', + label: '默认值', + value: 'My name is \\${name}' +}) +``` + +## 多行文本输入框默认值 + +```schema +getSchemaTpl('textareaDefaultValue', { + name: 'var1', + value: 'My name is \\${name}' +}) +``` + +## 数字输入框默认值 + +默认展示为数字输入框,通过点击 `fx` 输入公式,因为不是文本,无法拼接,所以默认值要么是公式,要么是静态值。 + +```schema +getSchemaTpl('valueFormula', { + mode: 'vertical', + rendererSchema: (schema) => ({ + type: 'input-number', + ...schema, + displayMode: 'base' + }), + valueType: 'number' // 期望数值类型 +}) +``` + +## 日期输入框默认值 + +```schema +getSchemaTpl('valueFormula', { + mode: 'vertical', + rendererSchema: (schema) => ({ + type: 'input-date', + ...schema + }), + placeholder: '请选择静态值', + header: '表达式或相对值', + DateTimeType: 1, + label: tipedLabel('默认值', '支持例如: now、+3days、-2weeks、+1hour、+2years 等(minute|min|hour|day|week|month|year|weekday|second|millisecond)这种相对值用法') +}) +``` + +## 选项类输入框默认值 + +```schema +getSchemaTpl('valueFormula', { + rendererSchema: (schema) => ({ + ...schema, + type: 'select', + options: [ + { + label: '选项1', + value: '1' + }, + { + label: '选项2', + value: '2' + } + ] + }), + // 默认值组件设计有些问题,自动发起了请求,接口数据作为了默认值选项,接口形式应该是设置静态值或者FX + needDeleteProps: ['source'], + // 当数据源是自定义静态选项时,不额外配置默认值,在选项上直接勾选即可,放开会有个bug:当去掉勾选时,默认值配置组件不清空,只是schema清空了value + visibleOn: 'this.selectFirst !== true && this.source != null' +}) +``` diff --git a/packages/amis-editor/examples/style.scss b/packages/amis-editor/examples/style.scss index b684bb45f..9c45ea41a 100644 --- a/packages/amis-editor/examples/style.scss +++ b/packages/amis-editor/examples/style.scss @@ -286,3 +286,31 @@ $disabled-bg-color: #f7f7f9; // 禁用背景颜色 #root > .a-Select-popover { z-index: 1500; } + +.schema-tpl-preview { + display: flex; + flex-direction: row; + align-items: flex-start; + + > *:first-child { + flex: 1; + min-width: 0; + background-color: rgb(43, 43, 43); + } +} + +.PanelPreview { + background-color: #fff; + padding: 0 20px 20px 20px; + position: relative; + width: 400px; + flex-shrink: 0; + + > .editor-right-panel { + margin-bottom: 20px; + } + + > .react-json-view { + font-size: 12px; + } +} diff --git a/packages/amis-editor/index.html b/packages/amis-editor/index.html index 51d5a1274..c3f9e92eb 100644 --- a/packages/amis-editor/index.html +++ b/packages/amis-editor/index.html @@ -27,6 +27,7 @@ href="../../../node_modules/@fortawesome/fontawesome-free/css/v4-shims.css" /> + diff --git a/packages/amis-editor/index.tsx b/packages/amis-editor/index.tsx index b4cee5744..2a9df8dbb 100644 --- a/packages/amis-editor/index.tsx +++ b/packages/amis-editor/index.tsx @@ -2,11 +2,207 @@ * @file entry of this example. * @author fex */ -import * as React from 'react'; +import React from 'react'; import {createRoot} from 'react-dom/client'; -import App from './examples/App'; + +import {Layout, AsideNav, Spinner, NotFound} from 'amis-ui'; +import {eachTree, TreeArray, TreeItem} from 'amis-core'; +import { + HashRouter as Router, + Route, + Redirect, + Switch, + Link, + NavLink +} from 'react-router-dom'; +import Doc from './examples/component/Doc'; + +function MDComponent(fN: () => Promise<{default: {raw: string}}>) { + return React.lazy(() => + fN().then(ret => ({default: () => })) + ); +} + +const pages: TreeArray = [ + { + label: '面板模版', + children: [ + { + label: '基础', + path: '/basic', + component: MDComponent(() => import('./examples/route/Basic.md')) + }, + + { + label: '公式', + path: '/formula', + component: MDComponent(() => import('./examples/route/Formula.md')) + } + ] + } +]; + +function getPath(path: string) { + return path ? (path[0] === '/' ? path : `/${path}`) : ''; +} + +function isActive(link: any, location: any) { + return !!(link.path && getPath(link.path) === location.pathname); +} + +export function navigations2route( + navigations: any, + additionalProperties?: any +) { + let routes: any = []; + + navigations.forEach((root: any) => { + root.children && + eachTree(root.children, (item: any) => { + if (item.path && item.component) { + routes.push( + additionalProperties ? ( + ( + + )} + /> + ) : ( + + ) + ); + } + }); + }); + + return routes; +} + +export function Main() { + function renderAside() { + return ( + ({ + ...item, + children: item.children + ? item.children.map((item: any) => ({ + ...item, + className: 'is-top' + })) + : [] + }))} + renderLink={({ + link, + active, + toggleExpand, + classnames: cx, + depth + }: any) => { + let children: any[] = []; + + if (link.children && link.children.length) { + children.push( + toggleExpand(link, e)} + > + ); + } + + link.badge && + children.push( + + {link.badge} + + ); + + if (link.icon) { + children.push( + + ); + } + + children.push( + + {link.label} + + ); + + return link.path ? ( + /^https?\:/.test(link.path) ? ( + + {children} + + ) : ( + + {children} + + ) + ) : ( + toggleExpand(link) : undefined}> + {children} + + ); + }} + isActive={(link: any) => isActive(link, location)} + /> + ); + } + + return ( + + } + > + + import('./examples/App'))} + exact + path="/" + /> + +
编辑器面板示例
+ 回到编辑器 +
+ } + aside={renderAside()} + > + } + > + + {navigations2route(pages)} + } /> + + + + + + + ); +} export function bootstrap(mountTo: HTMLElement, initalState: any) { const root = createRoot(mountTo); - root.render(); + root.render(
); } diff --git a/packages/amis-editor/src/renderer/ExpressionFormulaControl.tsx b/packages/amis-editor/src/renderer/ExpressionFormulaControl.tsx index 2ae86c73f..f8f90d129 100644 --- a/packages/amis-editor/src/renderer/ExpressionFormulaControl.tsx +++ b/packages/amis-editor/src/renderer/ExpressionFormulaControl.tsx @@ -3,10 +3,10 @@ */ import React from 'react'; -import {autobind, FormControlProps} from 'amis-core'; +import {autobind, FormControlProps, isExpression} from 'amis-core'; import cx from 'classnames'; import {FormItem, Button, Icon, PickerContainer} from 'amis'; -import {FormulaCodeEditor, FormulaEditor} from 'amis-ui'; +import {FormulaCodeEditor, FormulaEditor, InputBox} from 'amis-ui'; import type {VariableItem} from 'amis-ui'; import {reaction} from 'mobx'; import {getVariables} from 'amis-editor-core'; @@ -139,6 +139,7 @@ export default class ExpressionFormulaControl extends React.Component< render() { const {value, className, variableMode, header, size, ...rest} = this.props; const {formulaPickerValue, variables} = this.state; + const isNewExpression = isExpression(value); // 自身字段 const selfName = this.props?.data?.name; @@ -171,7 +172,9 @@ export default class ExpressionFormulaControl extends React.Component< size={size ?? 'lg'} > {({onClick}: {onClick: (e: React.MouseEvent) => any}) => - formulaPickerValue ? ( + value && !isNewExpression ? ( + + ) : formulaPickerValue ? (