@livepreso/react-plugin-textfield 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.rush/temp/shrinkwrap-deps.json +32 -27
- package/CHANGELOG.json +29 -0
- package/CHANGELOG.md +15 -1
- package/components/InsertTokenDialog.js +82 -0
- package/components/InsertTokenDialog.module.scss +166 -0
- package/components/editor-toolbars/EditorMenu.module.scss +1 -0
- package/components/editor-toolbars/SimpleButton.js +34 -0
- package/components/editor-toolbars/SimpleButton.module.scss +36 -0
- package/components/tiptap/token/Token.js +142 -0
- package/components/tiptap/token/Token.module.scss +28 -0
- package/components/tiptap/token/TokenList.js +93 -0
- package/components/tiptap/token/TokenList.module.scss +58 -0
- package/components/tiptap/token/utils.js +92 -0
- package/configs/generate-toolbar-configuration.js +14 -2
- package/configs/generate-toolbar-options.js +4 -2
- package/configs/toolbar-configuration.js +15 -0
- package/constants.js +19 -1
- package/icons/HelpCenter.js +13 -0
- package/icons/MoreVert.js +13 -0
- package/icons/WandStars.js +13 -0
- package/icons/help_center.svg +1 -0
- package/icons/index.js +9 -1
- package/icons/more_vert.svg +1 -0
- package/icons/wand_stars.svg +1 -0
- package/index.js +48 -4
- package/index.module.scss +9 -8
- package/package.json +30 -27
- package/scripts/extract-svg.js +3 -1
- package/variables.scss +6 -0
- package/icons/format_color_text.svg +0 -5
- package/icons/format_color_text_ungrouped.svg +0 -6
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"../../content/react-plugin-textfield": "../../content/react-plugin-textfield:
|
|
2
|
+
"../../content/react-plugin-textfield": "../../content/react-plugin-textfield:s+ovoFo6pNPlWHs2F95bzMt1Z4kRJxtfv1FVmar0Dlk=:",
|
|
3
3
|
"/@ampproject/remapping@2.3.0": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
|
|
4
4
|
"/@babel/code-frame@7.26.2": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
|
|
5
5
|
"/@babel/code-frame@7.27.1": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
|
|
@@ -40,8 +40,10 @@
|
|
|
40
40
|
"/@eslint/object-schema@2.1.4": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==",
|
|
41
41
|
"/@eslint/plugin-kit@0.2.3": "sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==",
|
|
42
42
|
"/@floating-ui/core@1.7.2": "sha512-wNB5ooIKHQc+Kui96jE/n69rHFWAVoxn5CAzL1Xdd8FG03cgY3MLO+GF9U3W737fYDSgPWA6MReKhBQBop6Pcw==",
|
|
43
|
+
"/@floating-ui/core@1.7.3": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==",
|
|
43
44
|
"/@floating-ui/dom@1.7.2": "sha512-7cfaOQuCS27HD7DX+6ib2OrnW+b4ZBwDNnCcT0uTyidcmyWb03FnQqJybDBoCnpdxwBSfA94UAYlRCt7mV+TbA==",
|
|
44
|
-
"/@floating-ui/
|
|
45
|
+
"/@floating-ui/dom@1.7.4": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==",
|
|
46
|
+
"/@floating-ui/react-dom@2.1.6(react-dom@18.2.0)(react@18.2.0)": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==",
|
|
45
47
|
"/@floating-ui/utils@0.2.10": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
|
|
46
48
|
"/@humanfs/core@0.19.1": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
|
|
47
49
|
"/@humanfs/node@0.16.6": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
|
|
@@ -129,31 +131,33 @@
|
|
|
129
131
|
"/@svgr/core@8.1.0": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==",
|
|
130
132
|
"/@svgr/hast-util-to-babel-ast@8.0.0": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==",
|
|
131
133
|
"/@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0)": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==",
|
|
132
|
-
"/@tiptap/core@3.
|
|
133
|
-
"/@tiptap/extension-bold@3.
|
|
134
|
-
"/@tiptap/extension-bubble-menu@3.
|
|
135
|
-
"/@tiptap/extension-document@3.
|
|
136
|
-
"/@tiptap/extension-floating-menu@3.
|
|
137
|
-
"/@tiptap/extension-hard-break@3.
|
|
138
|
-
"/@tiptap/extension-heading@3.
|
|
139
|
-
"/@tiptap/extension-image@3.
|
|
140
|
-
"/@tiptap/extension-italic@3.
|
|
141
|
-
"/@tiptap/extension-link@3.
|
|
142
|
-
"/@tiptap/extension-list@3.
|
|
143
|
-
"/@tiptap/extension-
|
|
144
|
-
"/@tiptap/extension-
|
|
145
|
-
"/@tiptap/extension-
|
|
146
|
-
"/@tiptap/extension-
|
|
147
|
-
"/@tiptap/extension-table-
|
|
148
|
-
"/@tiptap/extension-table-
|
|
149
|
-
"/@tiptap/extension-table@3.
|
|
150
|
-
"/@tiptap/extension-
|
|
151
|
-
"/@tiptap/extension-text-
|
|
152
|
-
"/@tiptap/extension-text@3.
|
|
153
|
-
"/@tiptap/extension-
|
|
154
|
-
"/@tiptap/
|
|
155
|
-
"/@tiptap/pm@3.
|
|
156
|
-
"/@tiptap/
|
|
134
|
+
"/@tiptap/core@3.10.1(@tiptap/pm@3.10.1)": "sha512-YY/u+RsjLVhcUaIn+wv6vjMx8kldO7SzFFnRu0iuC+QW57VrlqUzqz5PR6CenphwJHuqGM5b3SCr4K2ZPjN8jQ==",
|
|
135
|
+
"/@tiptap/extension-bold@3.10.1(@tiptap/core@3.10.1)": "sha512-8TE9oFEonoAs0k3Vd1RGW1FiDBayJiBWyd+1eoH6EEmk1DD7quHcP1mBNZwPpjhONMITaSmizs2FjweWYibFwA==",
|
|
136
|
+
"/@tiptap/extension-bubble-menu@3.10.1(@tiptap/core@3.10.1)(@tiptap/pm@3.10.1)": "sha512-oNRXAupEeDCeI4nkIhCYSUuT9eZeHDWXcC5fQeWDzCPv3hOcm7W4jqUGJhWWD6qhcbmUSKmsGDTLkBfNk4NT4Q==",
|
|
137
|
+
"/@tiptap/extension-document@3.10.1(@tiptap/core@3.10.1)": "sha512-HM9lmPGKX1s9NJYQh1BD6oLqwh0gWylNmgkT6hEI7lm7DANxaYyMZue9anCDae+K6tln22BauXGAfbRb6Bs0Lw==",
|
|
138
|
+
"/@tiptap/extension-floating-menu@3.10.1(@tiptap/core@3.10.1)(@tiptap/pm@3.10.1)": "sha512-D5ociNnOI3OP4NxS8eKiiqjUdO7geOguK4ZhJo1CFiIXXoLyV20wqqu4fe8Hq9+4gbEyyJ55Tz/AzLiaXw/GPQ==",
|
|
139
|
+
"/@tiptap/extension-hard-break@3.10.1(@tiptap/core@3.10.1)": "sha512-kCz/ILEVr3jd4/adOfl9d62dEe9PQrHXAB5rBy1ZFoNC+C7Trq8cgpyqUYFAK7Z500nKmUgQh1GtqGN2vy338Q==",
|
|
140
|
+
"/@tiptap/extension-heading@3.10.1(@tiptap/core@3.10.1)": "sha512-udG4cG1pmumECEb6WDW/qYtuHcHscTMPCR6mG8hz0WpYk1S+LQWGPaQPdvHK6qYrMo/3YwQcYZv5vuQiB3dpjg==",
|
|
141
|
+
"/@tiptap/extension-image@3.10.1(@tiptap/core@3.10.1)": "sha512-89NU8LAcSW49mwKDW86I6jf4M9vWbHKMAo6Pj4cees5FPjCk/6XAImjlC3WPr+CfjmM1Lmy7+BnOrVayyUHyVg==",
|
|
142
|
+
"/@tiptap/extension-italic@3.10.1(@tiptap/core@3.10.1)": "sha512-/VbABhC20z/KWhKjcFUk7jJuOgD8Hp2V5lr6fOLFJaRpptoJhmbCRrPJzEZhs/Z55nv6aF7ZxVxtjzO0FpKneQ==",
|
|
143
|
+
"/@tiptap/extension-link@3.10.1(@tiptap/core@3.10.1)(@tiptap/pm@3.10.1)": "sha512-87OBwlU/ylPCDNhNyKPQaM0KiT0FscyAqh8/oErmI7gKVdrUNfO4zcqIOKHql32lEu9KsmpSum/jSeeUJMR4pA==",
|
|
144
|
+
"/@tiptap/extension-list@3.10.1(@tiptap/core@3.10.1)(@tiptap/pm@3.10.1)": "sha512-v1TqDqNq3RXwKXyCoObv+42qrxAEtpac3BRZKWwwUcxM55oP5HxeaiEo2usheLs3+fEFkKtWKof2I9gUW0HLvA==",
|
|
145
|
+
"/@tiptap/extension-mention@3.10.1(@tiptap/core@3.10.1)(@tiptap/pm@3.10.1)(@tiptap/suggestion@3.10.1)": "sha512-s7zC3gBQQL99vH37/WdagfLFIDmSJz1uV6fsouckIag0nHBxKTPsZy4LR8CRZZ6RECIyj2WGm71GoVqKUUSEBw==",
|
|
146
|
+
"/@tiptap/extension-paragraph@3.10.1(@tiptap/core@3.10.1)": "sha512-ocxyg947q5yOSyripEingN7SnsJ/4cYuxOg8BdNlSao8HzUTw5298/81Almf2pT0FNAJHMp8R4Xsii2oMlJ/yQ==",
|
|
147
|
+
"/@tiptap/extension-subscript@3.10.1(@tiptap/core@3.10.1)(@tiptap/pm@3.10.1)": "sha512-okDnD2aoPfNIWL1lHXS3skemHIa3C6wYsPsp8aZC8W2anlY3YiY7nL6qYqK92eZnPAyeMaysAJNI0otBccl/7A==",
|
|
148
|
+
"/@tiptap/extension-superscript@3.10.1(@tiptap/core@3.10.1)(@tiptap/pm@3.10.1)": "sha512-lmYxzjTOLUvRyW2MjQJUh2D6BFdv8vOVLe1k7UDSW1s+9dfuyJro6SAvOT9cVCB9JKLb28keoukEeXj4vRAXDg==",
|
|
149
|
+
"/@tiptap/extension-table-cell@3.10.1(@tiptap/extension-table@3.10.1)": "sha512-v0Q286PuFv/TVSAM8qcUb6qZff/z+/rlse2CN/ipUyteQOo6o5yawtplokfKMlDdGp9gSRK4DV2pfTkh2Xq8dA==",
|
|
150
|
+
"/@tiptap/extension-table-header@3.10.1(@tiptap/extension-table@3.10.1)": "sha512-fKGUELF5iCMBt7wgRkV27uE3/rAUnqzDB3Tyk7WivAkU8TtJq468wawatM32CV/PmK0j0cdcUMR0rmQEiJrgVg==",
|
|
151
|
+
"/@tiptap/extension-table-row@3.10.1(@tiptap/extension-table@3.10.1)": "sha512-kIrgawz7MfLU28LfGgSyUgw85R2ln8/JILhBJyjDEl5H83EXvsvOdCPiohUPy/3zsF42tfANzgxwcVLV3Pp9Ag==",
|
|
152
|
+
"/@tiptap/extension-table@3.10.1(@tiptap/core@3.10.1)(@tiptap/pm@3.10.1)": "sha512-i18t1wfVHQjJIMlqIB0SCpP78bsoZDTFhhZBOLYDM0Q4KHY+zVkiZADkiY5zA8UFZiBuWC4eviqajCvq4XOvQw==",
|
|
153
|
+
"/@tiptap/extension-text-align@3.10.1(@tiptap/core@3.10.1)": "sha512-6Pxgf5TuQr44lXbPi5REZxHQYCRTUm6VXiuC3oisvoJxe4rls0+2OFI8iaSRRQalceXsCPkUGUH+Pf5xljC61g==",
|
|
154
|
+
"/@tiptap/extension-text-style@3.10.1(@tiptap/core@3.10.1)": "sha512-WPpHNtcet6P23w7kQHvut3y3+ATd1/8Wwyk/nIhdEc6RuOerisRm2EPW+kvGHsQ5NdlaQOwY555zKjJkyv1igA==",
|
|
155
|
+
"/@tiptap/extension-text@3.10.1(@tiptap/core@3.10.1)": "sha512-Af0WBQJvjiTnEArutOZENCVNGuK7Ln3BwUH3jXsk4OUHxOyt5JK9qsDePsO46Dj9OlXHbnBi5hAnhJGI8zGLzw==",
|
|
156
|
+
"/@tiptap/extension-underline@3.10.1(@tiptap/core@3.10.1)": "sha512-U56hHqCSjwP8wAq28n6A+l+aNW/DxJXiaNwXs7YlC4IjRDkbsl5q53UcOlRCoVnYVY2mxj1L6Zmu2u6dhjeuSQ==",
|
|
157
|
+
"/@tiptap/extensions@3.10.1(@tiptap/core@3.10.1)(@tiptap/pm@3.10.1)": "sha512-tZZ1IGIcch4ezuoid3iPSirh0s2GQuSKY6ceWRJCVeZ2gT2LsN3i10tqfidcYrsmyQRMuM7QUfRmH5HOKJZ73Q==",
|
|
158
|
+
"/@tiptap/pm@3.10.1": "sha512-LhTRI+bECLFqitWN821A7faVFVw5OitFGWn45LIIRc/1Jg3lkqsaqx3LcLN1sjXd+f/vfoeXLKSD6VJvv/B/nQ==",
|
|
159
|
+
"/@tiptap/react@3.10.1(@tiptap/core@3.10.1)(@tiptap/pm@3.10.1)(react-dom@18.2.0)(react@18.2.0)": "sha512-skL1a+WorLKv+m0bkbPKIbavN2CSBueWqEWxYs1AxI0qk2v49oRj/cyvv7lLUC2sdzds9GqXHcSBDqsw8Th+hw==",
|
|
160
|
+
"/@tiptap/suggestion@3.10.1(@tiptap/core@3.10.1)(@tiptap/pm@3.10.1)": "sha512-QpSMsMtpsBSapCDytjdKXLcuPunnd00fGSrYp23C4BDI2Ph7JOYHsgv/wIKgpAYg2fpbJT6DIIbpSHhWluEFyw==",
|
|
157
161
|
"/@types/estree@1.0.6": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
|
158
162
|
"/@types/json-schema@7.0.15": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
|
159
163
|
"/@types/linkify-it@5.0.0": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==",
|
|
@@ -207,6 +211,7 @@
|
|
|
207
211
|
"/find-up@5.0.0": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
|
|
208
212
|
"/flat-cache@4.0.1": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
|
|
209
213
|
"/flatted@3.3.2": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==",
|
|
214
|
+
"/fuse.js@7.1.0": "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==",
|
|
210
215
|
"/gensync@1.0.0-beta.2": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
|
|
211
216
|
"/get-nonce@1.0.1": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
|
|
212
217
|
"/glob-parent@6.0.2": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
|
package/CHANGELOG.json
CHANGED
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@livepreso/react-plugin-textfield",
|
|
3
3
|
"entries": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"tag": "@livepreso/react-plugin-textfield_v0.2.0",
|
|
7
|
+
"date": "Wed, 19 Nov 2025 03:51:23 GMT",
|
|
8
|
+
"comments": {
|
|
9
|
+
"minor": [
|
|
10
|
+
{
|
|
11
|
+
"comment": "Add Tokens"
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"dependency": [
|
|
15
|
+
{
|
|
16
|
+
"comment": "Updating dependency \"@livepreso/content-react\" to `2.0.2`"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"version": "0.1.3",
|
|
23
|
+
"tag": "@livepreso/react-plugin-textfield_v0.1.3",
|
|
24
|
+
"date": "Tue, 28 Oct 2025 00:29:49 GMT",
|
|
25
|
+
"comments": {
|
|
26
|
+
"patch": [
|
|
27
|
+
{
|
|
28
|
+
"comment": "optimise table toolbar creation"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
},
|
|
4
33
|
{
|
|
5
34
|
"version": "0.1.2",
|
|
6
35
|
"tag": "@livepreso/react-plugin-textfield_v0.1.2",
|
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
# Change Log - @livepreso/react-plugin-textfield
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Wed, 19 Nov 2025 03:51:23 GMT and should not be manually modified.
|
|
4
|
+
|
|
5
|
+
## 0.2.0
|
|
6
|
+
Wed, 19 Nov 2025 03:51:23 GMT
|
|
7
|
+
|
|
8
|
+
### Minor changes
|
|
9
|
+
|
|
10
|
+
- Add Tokens
|
|
11
|
+
|
|
12
|
+
## 0.1.3
|
|
13
|
+
Tue, 28 Oct 2025 00:29:49 GMT
|
|
14
|
+
|
|
15
|
+
### Patches
|
|
16
|
+
|
|
17
|
+
- optimise table toolbar creation
|
|
4
18
|
|
|
5
19
|
## 0.1.2
|
|
6
20
|
Mon, 27 Oct 2025 00:19:05 GMT
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { Dialog } from "radix-ui";
|
|
3
|
+
import style from "./InsertTokenDialog.module.scss";
|
|
4
|
+
import tokenStyle from "./tiptap/token/Token.module.scss";
|
|
5
|
+
import classNames from "classnames";
|
|
6
|
+
import icons, { Close } from "../icons";
|
|
7
|
+
import { SimpleButton } from "./editor-toolbars/SimpleButton";
|
|
8
|
+
import { TOKEN_TRIGGER_CHAR } from "./tiptap/token/utils";
|
|
9
|
+
|
|
10
|
+
const InsertTokenDialog = ({ id, onChange, tokens }) => {
|
|
11
|
+
const div = window.Bridge.UI.overlay;
|
|
12
|
+
|
|
13
|
+
const [open, setOpen] = useState(false);
|
|
14
|
+
|
|
15
|
+
const setSelectedTokenId = (id) => {
|
|
16
|
+
const token = tokens.find((token) => token.id === id);
|
|
17
|
+
onChange(token);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Dialog.Root open={open} onOpenChange={setOpen}>
|
|
22
|
+
<Dialog.Trigger asChild>
|
|
23
|
+
<SimpleButton
|
|
24
|
+
key={id}
|
|
25
|
+
label="See all tokens"
|
|
26
|
+
showLabel={true}
|
|
27
|
+
icon={<icons.MoreVert />}
|
|
28
|
+
disabled={false}
|
|
29
|
+
/>
|
|
30
|
+
</Dialog.Trigger>
|
|
31
|
+
|
|
32
|
+
<Dialog.Portal container={div}>
|
|
33
|
+
<Dialog.Overlay className={style.overlay} />
|
|
34
|
+
<Dialog.Content className={style.content}>
|
|
35
|
+
<div className={style.titleRow}>
|
|
36
|
+
<Dialog.Title className={style.title}>Tokens</Dialog.Title>
|
|
37
|
+
|
|
38
|
+
<Dialog.Close asChild>
|
|
39
|
+
<button className={classNames(style.button, style.iconButton)}>
|
|
40
|
+
<Close />
|
|
41
|
+
</button>
|
|
42
|
+
</Dialog.Close>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<Dialog.Description className={style.description}>
|
|
46
|
+
Click to insert any of the following tokens into the text field, and
|
|
47
|
+
have them substituted with the corresponding preso-specific values
|
|
48
|
+
when the preso is viewed or a pdf is generated.
|
|
49
|
+
</Dialog.Description>
|
|
50
|
+
|
|
51
|
+
<fieldset className={style.fieldset}>
|
|
52
|
+
{tokens.map(({ id, label, description }, index) => (
|
|
53
|
+
<div key={index} className={style.tokenRow}>
|
|
54
|
+
<div className={style.tokenCell}>
|
|
55
|
+
<button
|
|
56
|
+
className={tokenStyle.token}
|
|
57
|
+
id={id}
|
|
58
|
+
onClick={(e) => {
|
|
59
|
+
let value = e.currentTarget.attributes.id.value;
|
|
60
|
+
setSelectedTokenId(value);
|
|
61
|
+
}}
|
|
62
|
+
>
|
|
63
|
+
{label}
|
|
64
|
+
</button>
|
|
65
|
+
</div>
|
|
66
|
+
<div className={style.tokenCell}>{description}</div>
|
|
67
|
+
</div>
|
|
68
|
+
))}
|
|
69
|
+
</fieldset>
|
|
70
|
+
|
|
71
|
+
<Dialog.Description className={style.description}>
|
|
72
|
+
You can also type <strong>'{TOKEN_TRIGGER_CHAR}'</strong> into the
|
|
73
|
+
field and then narrow down this list by entering part of any of the
|
|
74
|
+
labels you see.
|
|
75
|
+
</Dialog.Description>
|
|
76
|
+
</Dialog.Content>
|
|
77
|
+
</Dialog.Portal>
|
|
78
|
+
</Dialog.Root>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export default InsertTokenDialog;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
@import "./style.module.scss";
|
|
2
|
+
|
|
3
|
+
:global(.sp-presenter-overlay) {
|
|
4
|
+
.overlay {
|
|
5
|
+
background-color: var(--sp-toolbar-modal-bg-color);
|
|
6
|
+
position: fixed;
|
|
7
|
+
inset: 0;
|
|
8
|
+
animation: overlayShow 150ms cubic-bezier(0.16, 1, 0.3, 1);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Specificity below is required to beat the unset
|
|
12
|
+
// found in index.module.scss
|
|
13
|
+
.content {
|
|
14
|
+
@extend %root;
|
|
15
|
+
z-index: 1001;
|
|
16
|
+
position: fixed;
|
|
17
|
+
top: 50%;
|
|
18
|
+
left: 50%;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
transform: translate(-50%, -50%);
|
|
21
|
+
width: 90vw;
|
|
22
|
+
max-width: 720px;
|
|
23
|
+
max-height: 85vh;
|
|
24
|
+
padding: 15px;
|
|
25
|
+
animation: contentShow 150ms cubic-bezier(0.16, 1, 0.3, 1);
|
|
26
|
+
|
|
27
|
+
&:focus {
|
|
28
|
+
outline: none;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.title-row {
|
|
32
|
+
display: flex;
|
|
33
|
+
justify-content: space-between;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.title {
|
|
37
|
+
margin-bottom: 10px;
|
|
38
|
+
color: var(--sp-toolbar-color);
|
|
39
|
+
font-size: 20px;
|
|
40
|
+
line-height: 1.3em;
|
|
41
|
+
font-weight: 400;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.description {
|
|
45
|
+
margin-bottom: 15px;
|
|
46
|
+
color: var(--sp-toolbar-highlight-color);
|
|
47
|
+
font-size: 14px;
|
|
48
|
+
line-height: 1.3em;
|
|
49
|
+
font-weight: 400;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.fieldset {
|
|
53
|
+
display: flex;
|
|
54
|
+
flex-direction: column;
|
|
55
|
+
max-height: 300px;
|
|
56
|
+
overflow-x: auto;
|
|
57
|
+
border-top: 1px solid var(--sp-toolbar-separator-color);
|
|
58
|
+
border-bottom: 1px solid var(--sp-toolbar-separator-color);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.label {
|
|
62
|
+
color: var(--sp-toolbar-color);
|
|
63
|
+
font-size: 14px;
|
|
64
|
+
line-height: 1.3em;
|
|
65
|
+
font-weight: 400;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.token-row {
|
|
69
|
+
display: flex;
|
|
70
|
+
flex-direction: row;
|
|
71
|
+
font-size: 14px;
|
|
72
|
+
border-left: 1px solid var(--sp-toolbar-separator-color);
|
|
73
|
+
border-right: 1px solid var(--sp-toolbar-separator-color);
|
|
74
|
+
border-bottom: 1px solid var(--sp-toolbar-separator-color);
|
|
75
|
+
|
|
76
|
+
&:last-child {
|
|
77
|
+
border-bottom: none;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.token-cell {
|
|
82
|
+
flex: 3;
|
|
83
|
+
padding: 6px;
|
|
84
|
+
|
|
85
|
+
&:first-child {
|
|
86
|
+
flex: 2;
|
|
87
|
+
border-right: 1px solid var(--sp-toolbar-separator-color);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.button {
|
|
92
|
+
display: inline-flex;
|
|
93
|
+
align-items: center;
|
|
94
|
+
justify-content: center;
|
|
95
|
+
border-radius: 6px;
|
|
96
|
+
padding: 4px 16px;
|
|
97
|
+
font-size: 14px;
|
|
98
|
+
line-height: 24px;
|
|
99
|
+
font-weight: 700;
|
|
100
|
+
user-select: none;
|
|
101
|
+
color: var(--sp-toolbar-color);
|
|
102
|
+
background-color: var(--sp-toolbar-button);
|
|
103
|
+
cursor: pointer;
|
|
104
|
+
|
|
105
|
+
&:hover {
|
|
106
|
+
background-color: var(--sp-toolbar-button-hover);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
&:focus:not(:focus-visible) {
|
|
110
|
+
outline: 0;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
&:focus-visible {
|
|
114
|
+
outline: 2px solid var(--sp-toolbar-button);
|
|
115
|
+
outline-offset: 2px;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
&[data-disabled],
|
|
119
|
+
&[disabled] {
|
|
120
|
+
@extend %disabled;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
&.primary {
|
|
124
|
+
color: var(--sp-toolbar-color-white);
|
|
125
|
+
background-color: var(--sp-toolbar-button-primary);
|
|
126
|
+
|
|
127
|
+
&:focus-visible {
|
|
128
|
+
outline-color: var(--sp-toolbar-button-primary);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
&:hover {
|
|
132
|
+
background-color: var(--sp-toolbar-button-primary-hover);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
&.icon-button {
|
|
137
|
+
padding: 6px;
|
|
138
|
+
background-color: transparent;
|
|
139
|
+
|
|
140
|
+
&:hover {
|
|
141
|
+
background-color: var(--sp-toolbar-button-hover);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@keyframes overlayShow {
|
|
149
|
+
from {
|
|
150
|
+
opacity: 0;
|
|
151
|
+
}
|
|
152
|
+
to {
|
|
153
|
+
opacity: 1;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
@keyframes contentShow {
|
|
158
|
+
from {
|
|
159
|
+
opacity: 0;
|
|
160
|
+
transform: translate(-50%, -48%) scale(0.96);
|
|
161
|
+
}
|
|
162
|
+
to {
|
|
163
|
+
opacity: 1;
|
|
164
|
+
transform: translate(-50%, -50%) scale(1);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React, { forwardRef } from "react";
|
|
2
|
+
import classNames from "classnames";
|
|
3
|
+
import style from "./SimpleButton.module.scss";
|
|
4
|
+
|
|
5
|
+
// a radix button detached from the toolbar, but still useful as a dialog trigger
|
|
6
|
+
export const SimpleButton = forwardRef(
|
|
7
|
+
(
|
|
8
|
+
{
|
|
9
|
+
label,
|
|
10
|
+
showLabel = false,
|
|
11
|
+
icon,
|
|
12
|
+
className,
|
|
13
|
+
disabled,
|
|
14
|
+
onClick = () => {},
|
|
15
|
+
...props
|
|
16
|
+
},
|
|
17
|
+
forwardedRef,
|
|
18
|
+
) => {
|
|
19
|
+
return (
|
|
20
|
+
<button
|
|
21
|
+
ref={forwardedRef}
|
|
22
|
+
className={classNames(className, style.button)}
|
|
23
|
+
value={label}
|
|
24
|
+
aria-label={label}
|
|
25
|
+
disabled={disabled}
|
|
26
|
+
onClick={onClick}
|
|
27
|
+
{...props}
|
|
28
|
+
>
|
|
29
|
+
{icon}
|
|
30
|
+
{showLabel && label && <div className={style.label}>{label}</div>}
|
|
31
|
+
</button>
|
|
32
|
+
);
|
|
33
|
+
},
|
|
34
|
+
);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
@import "../style.module.scss";
|
|
2
|
+
|
|
3
|
+
:global(.sp-presenter-overlay) {
|
|
4
|
+
.button {
|
|
5
|
+
@extend %item;
|
|
6
|
+
flex: 0 0 auto;
|
|
7
|
+
padding: 6px 12px 6px 8px;
|
|
8
|
+
margin: 0px;
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
justify-content: flex-start;
|
|
12
|
+
|
|
13
|
+
&:hover {
|
|
14
|
+
@extend %hover;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
&:focus {
|
|
18
|
+
@extend %focus;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
&.toggle {
|
|
22
|
+
&[data-state="on"] {
|
|
23
|
+
@extend %active;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&[data-disabled],
|
|
28
|
+
&[disabled] {
|
|
29
|
+
@extend %disabled;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.label {
|
|
34
|
+
padding-left: 8px;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import Mention from "@tiptap/extension-mention";
|
|
2
|
+
import style from "./Token.module.scss";
|
|
3
|
+
import classNames from "classnames";
|
|
4
|
+
import { generateSuggestionConfiguration, TOKEN_TRIGGER_CHAR } from "./utils";
|
|
5
|
+
import { mergeAttributes } from "@tiptap/core";
|
|
6
|
+
|
|
7
|
+
const TYPE_TOKEN = "token";
|
|
8
|
+
|
|
9
|
+
const TokenBase = Mention.extend({
|
|
10
|
+
name: "token",
|
|
11
|
+
options: {
|
|
12
|
+
fieldIsEditable: null,
|
|
13
|
+
operationMode: null,
|
|
14
|
+
tokens: [],
|
|
15
|
+
},
|
|
16
|
+
addAttributes() {
|
|
17
|
+
return {
|
|
18
|
+
...this.parent?.(),
|
|
19
|
+
id: { default: null },
|
|
20
|
+
label: { default: "" },
|
|
21
|
+
// this marks the token with a persistent ref to the mode
|
|
22
|
+
// (cms/prep/unmanaged) in which it was created
|
|
23
|
+
mode: {
|
|
24
|
+
default: this.options.operationMode,
|
|
25
|
+
parseHTML: (element) => element.getAttribute("data-mode"),
|
|
26
|
+
renderHTML: (attributes) => {
|
|
27
|
+
return {
|
|
28
|
+
"data-mode": attributes.mode,
|
|
29
|
+
};
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
// we use a custom node view in order to be able to do the double-click action
|
|
36
|
+
// this negates the need for the plugin to define a renderHTML method
|
|
37
|
+
addNodeView() {
|
|
38
|
+
return ({ editor, node, getPos, HTMLAttributes }) => {
|
|
39
|
+
const options = this.options;
|
|
40
|
+
const tokenDOM = document.createElement("span");
|
|
41
|
+
const attribs = mergeAttributes(HTMLAttributes, {
|
|
42
|
+
class: options.fieldIsEditable ? classNames(style.token) : "",
|
|
43
|
+
});
|
|
44
|
+
// manually append all attributes
|
|
45
|
+
Object.entries(attribs).forEach(([key, value]) => {
|
|
46
|
+
tokenDOM.setAttribute(key, value);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const tokenSummary = `${TOKEN_TRIGGER_CHAR}${
|
|
50
|
+
node.attrs.label ?? node.attrs.id
|
|
51
|
+
}`;
|
|
52
|
+
const warningMessage = options.fieldIsEditable
|
|
53
|
+
? `[token ${node.attrs.id} not found]`
|
|
54
|
+
: "";
|
|
55
|
+
const { render = () => warningMessage } =
|
|
56
|
+
options.tokens.find((token) => token.id === node.attrs.id) || {};
|
|
57
|
+
|
|
58
|
+
// where possible, the token's content is its value, not the @summary
|
|
59
|
+
const content =
|
|
60
|
+
options.fieldIsEditable && options.usePlaceholder
|
|
61
|
+
? tokenSummary
|
|
62
|
+
: render();
|
|
63
|
+
|
|
64
|
+
const editableNode = document.createElement("span");
|
|
65
|
+
editableNode.setAttribute("contenteditable", true);
|
|
66
|
+
|
|
67
|
+
const dom = options.burstOnCreate ? editableNode : tokenDOM;
|
|
68
|
+
const contentDOM = dom.appendChild(document.createTextNode(content));
|
|
69
|
+
|
|
70
|
+
const convertToTextNode = () => {
|
|
71
|
+
// To reference this specific node in a command, get its position.
|
|
72
|
+
const pos = getPos();
|
|
73
|
+
const endPos = pos + node.nodeSize;
|
|
74
|
+
|
|
75
|
+
// convert the node to a text node and insert the content
|
|
76
|
+
// replacing the token in the process
|
|
77
|
+
editor
|
|
78
|
+
.chain()
|
|
79
|
+
.focus()
|
|
80
|
+
.setNodeSelection(pos)
|
|
81
|
+
.insertContentAt({ from: pos, to: endPos }, content)
|
|
82
|
+
.toggleNode(TYPE_TOKEN, "text")
|
|
83
|
+
.run();
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// Attach the double-click event listener in all modes where content is available.
|
|
87
|
+
if (!options.usePlaceholder) {
|
|
88
|
+
tokenDOM.addEventListener("dblclick", (event) => {
|
|
89
|
+
event.preventDefault(); // Prevent default browser behavior if needed
|
|
90
|
+
convertToTextNode();
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (options.burstOnCreate) {
|
|
95
|
+
// this will be run, once, after the node is created
|
|
96
|
+
// after which, the Token will no longer exist
|
|
97
|
+
setTimeout(() => convertToTextNode(), 50);
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
dom,
|
|
101
|
+
contentDOM,
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// returns an instance of our Token plugin, with a `configure()` with our options
|
|
108
|
+
export const generateTokenInstance = ({
|
|
109
|
+
tokens = [],
|
|
110
|
+
mode,
|
|
111
|
+
isEditable: fieldIsEditable,
|
|
112
|
+
usePlaceholder = false,
|
|
113
|
+
burstOnCreate = false,
|
|
114
|
+
fuse,
|
|
115
|
+
...otherOverrides
|
|
116
|
+
}) => {
|
|
117
|
+
// Not 100% sure whether we only want to pass the UI-required fields, or just pass `tokens`?
|
|
118
|
+
// description is here as it's used in the modal
|
|
119
|
+
const tokenSuggestions = tokens.map((token) => {
|
|
120
|
+
const { id, label, description } = token;
|
|
121
|
+
return { id, label, description };
|
|
122
|
+
});
|
|
123
|
+
return TokenBase.configure({
|
|
124
|
+
HTMLAttributes: {
|
|
125
|
+
// if you add a `class` here, it can't be overriden with mergeAttributes,
|
|
126
|
+
// only augmented with other classes.
|
|
127
|
+
},
|
|
128
|
+
suggestion: generateSuggestionConfiguration({
|
|
129
|
+
tokens: tokenSuggestions,
|
|
130
|
+
fuse,
|
|
131
|
+
isEditable: fieldIsEditable,
|
|
132
|
+
}),
|
|
133
|
+
// we can store these in the extension, and access them via this.options
|
|
134
|
+
// operationMode may not be used at the moment, but could be useful in the future
|
|
135
|
+
operationMode: mode,
|
|
136
|
+
usePlaceholder,
|
|
137
|
+
tokens,
|
|
138
|
+
fieldIsEditable,
|
|
139
|
+
burstOnCreate,
|
|
140
|
+
...otherOverrides,
|
|
141
|
+
});
|
|
142
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
@import "../../../variables.scss";
|
|
2
|
+
|
|
3
|
+
.token,
|
|
4
|
+
:global(.sp-presenter-overlay) .token {
|
|
5
|
+
position: relative;
|
|
6
|
+
// wanted this to be var(--brand-primary-light)
|
|
7
|
+
// but the branding definitions do not extend into the sp-presenter-overlay scope
|
|
8
|
+
background-color: $active-color;
|
|
9
|
+
color: $toolbar-color;
|
|
10
|
+
font-size: 0.9em;
|
|
11
|
+
line-height: 1em;
|
|
12
|
+
border-radius: 0.8rem;
|
|
13
|
+
box-decoration-break: clone;
|
|
14
|
+
padding: 0.2em 0.4em;
|
|
15
|
+
cursor: pointer;
|
|
16
|
+
|
|
17
|
+
// Hit area
|
|
18
|
+
&:after {
|
|
19
|
+
content: "";
|
|
20
|
+
position: absolute;
|
|
21
|
+
inset: -5px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// zero-width space to prevent collapse when empty
|
|
25
|
+
&::after {
|
|
26
|
+
content: "\200B";
|
|
27
|
+
}
|
|
28
|
+
}
|