diff --git a/.changeset/ninety-ghosts-shake.md b/.changeset/ninety-ghosts-shake.md new file mode 100644 index 000000000..0814dfe6c --- /dev/null +++ b/.changeset/ninety-ghosts-shake.md @@ -0,0 +1,5 @@ +--- +"@tabler/core": patch +--- + +Add Signature Pad feature and signatures page diff --git a/core/scss/_utilities.scss b/core/scss/_utilities.scss index eef28aecb..6eb9b1ad2 100644 --- a/core/scss/_utilities.scss +++ b/core/scss/_utilities.scss @@ -43,8 +43,9 @@ $utilities: ( v-text: vertical-text, grab: grab, grabbing: grabbing, + crosshair: crosshair, ), - ), + ), "border": ( property: border, values: $border-values, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6b6519c26..6e8eb87dc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -147,6 +147,9 @@ importers: plyr: specifier: ^3.7.8 version: 3.7.8 + signature_pad: + specifier: ^5.0.4 + version: 5.0.4 star-rating.js: specifier: ^4.3.1 version: 4.3.1 @@ -3777,6 +3780,10 @@ packages: engines: {node: '>=14'} dev: true + /signature_pad@5.0.4: + resolution: {integrity: sha512-nngOixbwLAUOuH3QnZwlgwmynQblxmo4iWacKFwfymJfiY+Qt+9icNtcIe/okqXKun4hJ5QTFmHyC7dmv6lf2w==} + dev: false + /simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} dependencies: diff --git a/preview/eleventy.config.mjs b/preview/eleventy.config.mjs index 14b52d228..61b7adc3c 100644 --- a/preview/eleventy.config.mjs +++ b/preview/eleventy.config.mjs @@ -33,7 +33,7 @@ const getCopyList = () => { files.forEach((file) => { if (!file.match(/^https?/)) { - copy[`node_modules/${dirname(file)}`] = `libs/${dirname(file) }`; + copy[`node_modules/${dirname(file)}`] = `libs/${dirname(file)}`; } }) @@ -91,7 +91,7 @@ export default function (eleventyConfig) { return { url: file.replace(/^pages\//, '/') } -}); + }); }); eleventyConfig.addGlobalData("site", { @@ -413,12 +413,12 @@ export default function (eleventyConfig) { /** * Filters */ - eleventyConfig.addFilter("miliseconds_to_minutes", function (value) { + eleventyConfig.addFilter("miliseconds_to_minutes", function (value) { // Raturn 3:45 time format const minutes = Math.floor(value / 60000); const seconds = ((value % 60000) / 1000).toFixed(0); return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`; - }); + }); eleventyConfig.addFilter("relative", (page) => { const segments = (page.url || '').replace(/^\//).split('/'); @@ -577,7 +577,7 @@ export default function (eleventyConfig) { /** * Shortcodes */ - const tags = ["capture_global", "endcapture_global", "highlight", "endhighlight"]; + const tags = ["highlight", "endhighlight"]; tags.forEach(tag => { eleventyConfig.addLiquidTag(tag, function (liquidEngine) { return { @@ -591,6 +591,31 @@ export default function (eleventyConfig) { }); }); + ['script', 'modal'].forEach((tag) => { + eleventyConfig.addPairedShortcode(`capture_${tag}`, function (content) { + if (!this.page[tag]) { + this.page[tag] = [] + } + + if (!this.page[tag][this.page.url]) { + this.page[tag][this.page.url] = []; + } + + this.page[tag][this.page.url].push(content); + + return '' + }) + + eleventyConfig.addShortcode(`${tag}s`, function () { + + if (this.page[tag]) { + return this.page[tag][this.page.url] ? `\n${this.page[tag][this.page.url].join('\n').trim()}\n` : ''; + } + + return '' + }); + }); + /** * Transforms */ diff --git a/preview/package.json b/preview/package.json index cbae03ea0..e216816f4 100644 --- a/preview/package.json +++ b/preview/package.json @@ -16,7 +16,7 @@ "js-compile": "rollup --config build/rollup.config.mjs --sourcemap", "js-minify": "pnpm run js-minify-demo && pnpm run js-minify-theme", "js-minify-demo": "terser --compress passes=2 --mangle --comments \"/^!/\" --source-map \"content=dist/preview/js/demo.js.map,includeSources,url=demo.min.js.map\" --output dist/preview/js/demo.min.js dist/preview/js/demo.js", - "js-minify-theme": "terser --compress passes=2 --mangle --comments \"/^!/\" --source-map \"content=dist/preview/js/demo-theme.js.map,includeSources,url=demo-theme.min.js.map\" --output dist/preview/js/demo-theme.min.js dist/preview/js/demo-theme.js", + "js-minify-theme": "terser --compress passes=2 --mangle --comments \"/^!/\" --source-map \"content=dist/preview/js/demo-theme.js.map,includeSources,url=demo-theme.min.js.map\" --output dist/preview/js/demo-theme.min.js dist/preview/js/demo-theme.js", "clean": "shx rm -rf dist demo", "html": "pnpm run html-build && pnpm run html-prettify", "html-build": "eleventy", @@ -31,32 +31,33 @@ "zip": "mkdir -p packages-zip && zip -r packages-zip/tabler-$(node -p \"require('./package.json').version\").zip demo/*" }, "dependencies": { + "@melloware/coloris": "^0.24.0", "@tabler/core": "workspace:*", "@tabler/icons": "^3.29.0", - "@melloware/coloris": "^0.24.0", "apexcharts": "^4.4.0", - "star-rating.js": "^4.3.1", - "tinymce": "^7.6.1", - "tom-select": "^2.4.2", - "typed.js": "^2.1.0", + "autosize": "^6.0.1", + "choices.js": "^11.0.3", + "countup.js": "^2.8.0", + "dropzone": "^6.0.0-beta.2", + "flatpickr": "^4.6.13", + "fslightbox": "^3.4.2", "imask": "^7.6.1", "jsvectormap": "^1.6.0", "list.js": "^2.3.1", "litepicker": "^2.0.12", "nouislider": "^15.8.1", "plyr": "^3.7.8", - "dropzone": "^6.0.0-beta.2", - "flatpickr": "^4.6.13", - "fslightbox": "^3.4.2", - "choices.js": "^11.0.3", - "countup.js": "^2.8.0", - "autosize": "^6.0.1" + "star-rating.js": "^4.3.1", + "tinymce": "^7.6.1", + "tom-select": "^2.4.2", + "typed.js": "^2.1.0", + "signature_pad": "^5.0.4" }, "devDependencies": { - "request": "^2.88.2", - "imageoptim-cli": "^3.1.9", "@11ty/eleventy": "^3.0.0", - "@repo/banner": "workspace:*" + "@repo/banner": "workspace:*", + "imageoptim-cli": "^3.1.9", + "request": "^2.88.2" }, "prettier": { "tabWidth": 2, diff --git a/preview/pages/2-step-verification-code.html b/preview/pages/2-step-verification-code.html index db6b0048e..6d8376fed 100644 --- a/preview/pages/2-step-verification-code.html +++ b/preview/pages/2-step-verification-code.html @@ -53,7 +53,7 @@ permalink: 2-step-verification-code.html It may take a minute to receive your code. Haven't received it? Resend a new code. -{% capture_global scripts %} +{% capture_script %} -{% endcapture_global %} \ No newline at end of file +{% endcapture_script %} \ No newline at end of file diff --git a/preview/pages/_data/libs.json b/preview/pages/_data/libs.json index 6bbc17297..65d9982f3 100644 --- a/preview/pages/_data/libs.json +++ b/preview/pages/_data/libs.json @@ -24,7 +24,8 @@ "dropzone": "dropzone/dist/dropzone-min.js", "star-rating.js": "star-rating.js/dist/star-rating.min.js", "coloris.js": "@melloware/coloris/dist/umd/coloris.min.js", - "typed.js": "typed.js/dist/typed.umd.js" + "typed.js": "typed.js/dist/typed.umd.js", + "signature_pad": "signature_pad/dist/signature_pad.umd.min.js" }, "css": { "mapbox": "https://api.mapbox.com/mapbox-gl-js/v1.8.0/mapbox-gl.css", diff --git a/preview/pages/_data/menu.json b/preview/pages/_data/menu.json index 9692d463b..8a16f6dc3 100644 --- a/preview/pages/_data/menu.json +++ b/preview/pages/_data/menu.json @@ -281,6 +281,11 @@ "title": "Settings", "url": "settings.html" }, + "signatures": { + "title": "Signatures", + "url": "signatures.html", + "badge": "New" + }, "tasks": { "title": "Tasks", "url": "tasks.html" diff --git a/preview/pages/_includes/layout/js.html b/preview/pages/_includes/layout/js.html index 08a799fc2..e825de966 100644 --- a/preview/pages/_includes/layout/js.html +++ b/preview/pages/_includes/layout/js.html @@ -1,10 +1,10 @@ - {% assign google-maps-key = site.googleMapsDevKey -%} {% if environment != 'development' -%} - {% assign google-maps-key = site.googleMapsKey -%} +{% assign google-maps-key = site.googleMapsKey -%} {% endif -%} {% if page-libs -%} + {% for lib in libs.js -%} {% if page-libs contains lib[0] or libs.global-libs contains lib[0] -%} {% for file in lib[1] -%} @@ -12,8 +12,8 @@ {% endfor -%} {% endif -%} {% endfor -%} + {% endif -%} - @@ -23,13 +23,7 @@ -{% for script in site.captured_global.scripts %} -{{ script }} -{% endfor %} - -{% for script in site.captured_once.scripts %} -{{ script }} -{% endfor %} +{% scripts %} {% assign libs = page-libs | default: layout.page-libs %} {% for lib in libs.js-files %} diff --git a/preview/pages/_includes/layout/modals-capture.html b/preview/pages/_includes/layout/modals-capture.html deleted file mode 100644 index 16615019d..000000000 --- a/preview/pages/_includes/layout/modals-capture.html +++ /dev/null @@ -1,3 +0,0 @@ -{% for modal in site.captured_global.modals %} -{{ modal }} -{% endfor %} diff --git a/preview/pages/_includes/layout/modals.html b/preview/pages/_includes/layout/modals.html deleted file mode 100644 index e69de29bb..000000000 diff --git a/preview/pages/_includes/ui/chart-heatmap.html b/preview/pages/_includes/ui/chart-heatmap.html index 991c9fef1..06839e0ea 100644 --- a/preview/pages/_includes/ui/chart-heatmap.html +++ b/preview/pages/_includes/ui/chart-heatmap.html @@ -8,87 +8,85 @@ {% capture script %} {% assign colors = include.colors | default: 1 %} {% endcapture %} -{% capture_global scripts %} +{% capture_script %} {{ script }} -{% endcapture_global %} +{% endcapture_script %} diff --git a/preview/pages/_includes/ui/chart-sparkline.html b/preview/pages/_includes/ui/chart-sparkline.html index 1935d28db..55d59b358 100644 --- a/preview/pages/_includes/ui/chart-sparkline.html +++ b/preview/pages/_includes/ui/chart-sparkline.html @@ -14,9 +14,8 @@ {% if id %}
- {% capture_global scripts %} + {% capture_script %} - {% endcapture_global %} + {% endcapture_script %} {% endif %} \ No newline at end of file diff --git a/preview/pages/_includes/ui/chart.html b/preview/pages/_includes/ui/chart.html index ee5019fa7..7dc8eb40b 100644 --- a/preview/pages/_includes/ui/chart.html +++ b/preview/pages/_includes/ui/chart.html @@ -21,7 +21,6 @@ {% capture script %} {% assign chart-type = data.type | default: 'bar' %} {% endcapture %} -{% capture_global scripts %} +{% capture_script %} {{ script }} -{% endcapture_global %} +{% endcapture_script %} {% endif %} diff --git a/preview/pages/_includes/ui/colorpicker.html b/preview/pages/_includes/ui/colorpicker.html index 5b3539568..4d5ca5fe4 100644 --- a/preview/pages/_includes/ui/colorpicker.html +++ b/preview/pages/_includes/ui/colorpicker.html @@ -4,9 +4,8 @@ -{% capture_global scripts %} +{% capture_script %} -{% endcapture_global %} +{% endcapture_script %} diff --git a/preview/pages/_includes/ui/datepicker.html b/preview/pages/_includes/ui/datepicker.html index 132e227c2..bf1d64b31 100644 --- a/preview/pages/_includes/ui/datepicker.html +++ b/preview/pages/_includes/ui/datepicker.html @@ -26,7 +26,6 @@ {% capture script %} {% endcapture %} {% if include.show-scripts %} {{ script }} {% else %} -{% capture_global scripts %} +{% capture_script %} {{ script }} -{% endcapture_global %} +{% endcapture_script %} {% endif %} {% endif %} \ No newline at end of file diff --git a/preview/pages/_includes/ui/dropzone.html b/preview/pages/_includes/ui/dropzone.html index 237ae3d6b..4d808d27c 100644 --- a/preview/pages/_includes/ui/dropzone.html +++ b/preview/pages/_includes/ui/dropzone.html @@ -14,13 +14,12 @@ {% endif %} -{% capture_global scripts %} +{% capture_script %} -{% endcapture_global %} \ No newline at end of file +{% endcapture_script %} \ No newline at end of file diff --git a/preview/pages/_includes/ui/inline-player.html b/preview/pages/_includes/ui/inline-player.html index 7e66599db..ed3009442 100644 --- a/preview/pages/_includes/ui/inline-player.html +++ b/preview/pages/_includes/ui/inline-player.html @@ -3,17 +3,15 @@ {% if id and include.embed-id %}
-{% capture_global scripts %} +{% capture_script %} -{% endcapture_global %} +{% endcapture_script %} {% endif %} \ No newline at end of file diff --git a/preview/pages/_includes/ui/map-vector.html b/preview/pages/_includes/ui/map-vector.html index 408fe52a5..9fb756370 100644 --- a/preview/pages/_includes/ui/map-vector.html +++ b/preview/pages/_includes/ui/map-vector.html @@ -11,7 +11,6 @@ {% capture script %} {% endcapture %} {% if include.show-scripts %} {{ script }} {% else %} - {% capture_global scripts %} + {% capture_script %} {{ script }} - {% endcapture_global %} + {% endcapture_script %} {% endif %} {% endif %} diff --git a/preview/pages/_includes/ui/map.html b/preview/pages/_includes/ui/map.html index 5efcee2c5..e03158c10 100644 --- a/preview/pages/_includes/ui/map.html +++ b/preview/pages/_includes/ui/map.html @@ -8,9 +8,8 @@ - {% capture_global scripts %} + {% capture_script %} - {% endcapture_global %} + {% endcapture_script %} {% endif %} \ No newline at end of file diff --git a/preview/pages/_includes/ui/modal.html b/preview/pages/_includes/ui/modal.html index e5c071999..1319aa62a 100644 --- a/preview/pages/_includes/ui/modal.html +++ b/preview/pages/_includes/ui/modal.html @@ -2,7 +2,7 @@ {% assign modal-id = include.modal-id | default: 'simple' %} {% assign size = include['size'] %} -{% capture_global modals %} +{% capture_modal %} -{% endcapture_global %} +{% endcapture_modal %} \ No newline at end of file diff --git a/preview/pages/_includes/ui/range.html b/preview/pages/_includes/ui/range.html index 06d7c2a99..f640a3b96 100644 --- a/preview/pages/_includes/ui/range.html +++ b/preview/pages/_includes/ui/range.html @@ -7,9 +7,8 @@ {% if id %}
- {% capture_global scripts %} + {% capture_script %} - {% endcapture_global %} + {% endcapture_script %} {% else %} {% endif %} \ No newline at end of file diff --git a/preview/pages/_includes/ui/rating.html b/preview/pages/_includes/ui/rating.html index 91725a1ce..129f4a2d8 100644 --- a/preview/pages/_includes/ui/rating.html +++ b/preview/pages/_includes/ui/rating.html @@ -20,9 +20,8 @@ {% assign star = star | replace_regex: "[\n\t]{2,}", " " | strip %} {% assign star = star | replace_regex: "", "" | strip %} -{% capture_global scripts %} +{% capture_script %} -{% endcapture_global %} \ No newline at end of file +{% endcapture_script %} \ No newline at end of file diff --git a/preview/pages/_includes/ui/select.html b/preview/pages/_includes/ui/select.html index 52f6b5592..f09070e53 100644 --- a/preview/pages/_includes/ui/select.html +++ b/preview/pages/_includes/ui/select.html @@ -56,7 +56,6 @@ {% capture script %} {% endcapture %} @@ -96,9 +94,9 @@ {% if include.show-scripts %} {{ script }} {% else %} -{% capture_global scripts %} +{% capture_script %} {{ script }} -{% endcapture_global %} +{% endcapture_script %} {% endif %} {% endif %} diff --git a/preview/pages/_includes/ui/signature.html b/preview/pages/_includes/ui/signature.html new file mode 100644 index 000000000..3f1929646 --- /dev/null +++ b/preview/pages/_includes/ui/signature.html @@ -0,0 +1,52 @@ +{% assign id = include.id | default: 'default' %} + +
+ {% if include.clear %} +
+
+ {% include "ui/icon.html" icon="trash" %} +
+
+ {% endif %} + +
+ +{% capture_script %} + + +{% endcapture_script %} \ No newline at end of file diff --git a/preview/pages/_includes/ui/tinymce.html b/preview/pages/_includes/ui/tinymce.html index f4ffdf858..92cd4e755 100644 --- a/preview/pages/_includes/ui/tinymce.html +++ b/preview/pages/_includes/ui/tinymce.html @@ -4,9 +4,8 @@ -{% capture_global scripts %} +{% capture_script %} -{% endcapture_global %} \ No newline at end of file +{% endcapture_script %} \ No newline at end of file diff --git a/preview/pages/_includes/ui/typed.html b/preview/pages/_includes/ui/typed.html index 2eb077368..32a37c7e8 100644 --- a/preview/pages/_includes/ui/typed.html +++ b/preview/pages/_includes/ui/typed.html @@ -2,7 +2,7 @@ {% assign id = include.id | default: "typed" %} {{ strings | first }} -{% capture_global scripts %} +{% capture_script %} -{% endcapture_global %} \ No newline at end of file +{% endcapture_script %} \ No newline at end of file diff --git a/preview/pages/_layouts/base.html b/preview/pages/_layouts/base.html index 4e6fa5eec..1b1c81bfd 100644 --- a/preview/pages/_layouts/base.html +++ b/preview/pages/_layouts/base.html @@ -46,7 +46,7 @@ {{ content }} - {% include "layout/modals-capture.html" %} + {% modals %} {% include "layout/js.html" %} diff --git a/preview/pages/datatables.html b/preview/pages/datatables.html index 60c495875..f4de0f335 100644 --- a/preview/pages/datatables.html +++ b/preview/pages/datatables.html @@ -49,7 +49,7 @@ permalink: datatables.html -{% capture_global scripts %} +{% capture_script %} -{% endcapture_global %} \ No newline at end of file +{% endcapture_script %} \ No newline at end of file diff --git a/preview/pages/emails.html b/preview/pages/emails.html index 8c7776f36..e0c0eca58 100644 --- a/preview/pages/emails.html +++ b/preview/pages/emails.html @@ -78,7 +78,7 @@ permalink: emails.html -{% capture_global scripts %} +{% capture_script %} -{% endcapture_global %} +{% endcapture_script %} diff --git a/preview/pages/illustrations.html b/preview/pages/illustrations.html index 3f1908d94..07eac6278 100644 --- a/preview/pages/illustrations.html +++ b/preview/pages/illustrations.html @@ -128,7 +128,7 @@ permalink: illustrations.html -{% capture_global scripts %} +{% capture_script %} -{% endcapture_global %} +{% endcapture_script %} diff --git a/preview/pages/map-fullsize.html b/preview/pages/map-fullsize.html index eb32db4d9..2babeaf6a 100644 --- a/preview/pages/map-fullsize.html +++ b/preview/pages/map-fullsize.html @@ -12,9 +12,8 @@ permalink: map-fullsize.html
-{% capture_global scripts %} +{% capture_script %} -{% endcapture_global %} \ No newline at end of file +{% endcapture_script %} \ No newline at end of file diff --git a/preview/pages/signatures.html b/preview/pages/signatures.html new file mode 100644 index 000000000..8486a63bb --- /dev/null +++ b/preview/pages/signatures.html @@ -0,0 +1,162 @@ +--- +title: Signatures +layout: default +permalink: signatures.html +page-header: Signatures +page-libs: [signature_pad] +page-menu: extra.signatures +--- + +{% capture simple-js %} +signaturePad.fromDataURL("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA1OTIgMjAwIj4KICA8ZyBjbGlwLXBhdGg9InVybCgjYSkiPgogICAgPHBhdGggZmlsbD0iIzAwMCIgZD0iTTEzMi4wOTIgNzkuMDY1YzAgLjMwNC0uMzU1IDEuNDAzLTEuMDYzIDMuMjk4LS42OTQgMS44OTQtMS4xNDIgMy4wMjItMS4zNDUgMy4zODQtMi4zNDIgMy44NDctNi43NiA3LjE4LTEzLjI1MiAxMC4wMDEtNS4zNjUgMi4yMjctMTMuNDU1IDUuNTktMjQuMjcgMTAuMDg4YTE0OC4xOSAxNDguMTkgMCAwIDAtMTAuMzQ3IDMuMTI0Yy0yLjY5Ljg4Mi02LjU4NiAyLjk1LTExLjY5IDYuMjA0YTE4Ny42NiAxODcuNjYgMCAwIDAtMS4wNjMgMTAuMTk2IDQwNy40OSA0MDcuNDkgMCAwIDEtMS40MzIgMTUuMzM4Yy0uODgyIDEuMTg2LTEuOTg4IDEuNzc5LTMuMzE4IDEuNzc5LjExNSAwIC4xNzMtLjAxNS4xNzMtLjA0NC0uMjAyLS4xMDEtLjg5Ni0uMjgyLTIuMDgyLS41NDJ2LTIuODg1YzAtMi43MDUuMjMxLTUuNDYuNjk0LTguMjY2IDAtLjA1Ny4yNTMtLjc3My43Ni0yLjE0Ny41MDUtMS4zMzEuNzU4LTIuMTQxLjc1OC0yLjQzIDAtMS42MDUtLjI5Ni0zLjI0LS44ODktNC45MDMtLjM5IDEuMTI4LTEuMTEzIDEuODU5LTIuMTY5IDIuMTkxLTEuMjQ0LS43MjMtMS44NjUtMS45ODgtMS44NjUtMy43OTYgMC0uMjAzIDEuMDQ4LTEuNzI5IDMuMTQ1LTQuNTc4IDIuMTQtMi45NjUgMy4zODMtNS4wMDQgMy43My02LjExNy4yNzUtLjgxLjc2Ny0zLjQ1IDEuNDc1LTcuOTE5IDEuMDQxLTYuNjEgMS45Ni0xMS40NCAyLjc1NS0xNC40OTEgMS42OTItNi42MzkgMy42OTQtMTAuODYyIDYuMDA4LTEyLjY3bDIuNDMgMS44MjN2MS44NjVjLTEuNTA1IDEuMTU3LTIuNTY3IDMuMjYyLTMuMTkgNi4zMTMtLjE4Ny45NC0uNjM2IDMuMzQxLTEuMzQ0IDcuMjAzLS4xNDUuNzA4LS43MjMgMi41NDUtMS43MzUgNS41MS0uOTExIDIuNjAzLTEuMzY3IDQuMTg3LTEuMzY3IDQuNzUxdjUuNDI0Yy4yNi4yNDUuNS4zNjguNzE2LjM2OCAxLjIxNSAwIDMuMTA5LS41MDYgNS42ODMtMS41MTggMy4wOC0xLjE1NyA1LjAxNy0xLjg1MSA1LjgxMy0yLjA4MyAxMy4wNzEtMy4zODQgMjMuMTUtNy4yMzggMzAuMjM1LTExLjU2MyA2LjIxOC0zLjc0NiA5Ljk5Mi02LjI5OCAxMS4zMjItNy42NTggMS41NzYtMS41NjIgMi4zNjQtMy42NjYgMi4zNjQtNi4zMTMgMC00LjY3MS0yLjEwNC04LjU2OS02LjMxMi0xMS42OTMtMy44Ni0yLjkwNy04LjE5MS00LjM2LTEyLjk5Mi00LjM2LTMuNzg4IDAtOC4yNzEuNDYyLTEzLjQ0NyAxLjM4OC02LjY2NiAxLjIxNS0xMi45MiAyLjkwNy0xOC43NjIgNS4wNzYtOC44NjQgMy4yODQtMTMuNzM2IDYuODM0LTE0LjYxOCAxMC42NTJsLTEuMDg1LjgwM0M1OC44MzkgNzguNDIyIDU4IDc3LjA2MiA1OCA3NS43OWMwLTEuODA4IDEuODgtNC4wMTQgNS42NC02LjYxNyAzLjA4LTIuMTQgNS44Mi0zLjU2NSA4LjIyLTQuMjc0IDE1Ljk0OS00LjkxNyAyNy44NjQtNy4zNzYgMzUuNzQ0LTcuMzc2IDcuNDYxIDAgMTMuNDEyIDEuOTUzIDE3Ljg1MSA1Ljg1NyA0LjQyNCAzLjg2MiA2LjYzNyA5LjA5IDYuNjM3IDE1LjY4NVptMzIuMjk1IDU1LjQwN3YxLjkwOWMtLjU5Mi44MjQtMS4yNDMgMS4yMzYtMS45NTIgMS4yMzYtLjQ0OCAwLTEuOTczLTEuMzU5LTQuNTc2LTQuMDc4LTIuNjAzLTIuNzMzLTQuMzM4LTQuMS01LjIwNi00LjEgMCAuMDU4LTMuMDggMS4yNDQtOS4yMzkgMy41NTgtNi4zMDUgMi4zNDMtMTAuMzE3IDMuNTE0LTEyLjAzOCAzLjUxNC0xLjQxNyAwLTIuOTg2LS42OTQtNC43MDctMi4wODMtMS43Mi0xLjM3NC0yLjU4MS0yLjY2OC0yLjU4MS0zLjg4MyAwLTMuMTM4IDMuNDM0LTYuNzk3IDEwLjMwMy0xMC45NzcgNi40MzQtMy45NjMgMTEuMzQzLTUuOTQ0IDE0LjcyNy01Ljk0NCAxLjQxNyAwIDIuNjkuODEgMy44MTcgMi40M3YxLjgyMmMtLjU2NC44MS0xLjIxNCAxLjIxNS0xLjk1MiAxLjIxNS0uMTMgMC0uNjE0LS4xODEtMS40NTMtLjU0My0uODM5LS4zNzYtMS4zMzctLjU2NC0xLjQ5Ni0uNTY0LTEuMTI4IDAtMy43MTcgMS4xNjUtNy43NjUgMy40OTMtMy44MzIgMi4xNjktNi4zOTkgMy43ODktNy43IDQuODYtMS4zMDIgMS4xMjgtMi4xMzMgMi40MTUtMi40OTQgMy44NjEuOTgzLjkyNiAyLjE1NCAxLjM4OCAzLjUxMyAxLjM4OC43MDkgMCA0LjEwNy0xLjE3MSAxMC4xOTQtMy41MTQgNi4wNzMtMi4zNzIgOS43NDYtMy41NTggMTEuMDE5LTMuNTU4IDEuODY1IDAgMy4yMS40NyA0LjAzNCAxLjQxLjE4OC4yMTcuOTA0IDEuNDkgMi4xNDcgMy44MThhMjEuOTAyIDIxLjkwMiAwIDAgMCAzLjQwNSA0LjczWm02OS44ODQtMTkuNzQydjEuOTUzYy0yLjk5MyAyLjQ1OC01Ljg5OSA1LjIxMy04LjcxOSA4LjI2NS04Ljc2MiA5LjQ1OS0xNC42NjIgMTQuMTg4LTE3LjY5OSAxNC4xODgtMi40NTggMC01LjE5OC0yLjIyLTguMjItNi42NmwtNi41MjgtOS42NTRjLTEuMjQ0LjIwMy0zLjQ5MiAyLjQ2Ni02Ljc0NiA2Ljc5LTMuMDUxIDQuMTIyLTUuODQyIDYuMTgzLTguMzcyIDYuMTgzbC0xLjE5My0uNjI5Yy0uODgyLTEuNjItMi41MzgtNS4xNy00Ljk2Ny0xMC42NTItMi42NDYtNS45MjktMy45NjktOS4zMDYtMy45NjktMTAuMTMxIDAtMS40MzIuODQ2LTIuNjE4IDIuNTM4LTMuNTU4IDEuNjkxIDIuMDQgMy4zNTQgNC44NjcgNC45ODggOC40ODMgMi40NTggNS4zMzYgMy44NzUgOC4zMyA0LjI1MSA4Ljk4MWgyLjA2MWMuNTY0LTEuMDQxIDEuODk0LTIuNjU0IDMuOTkxLTQuODM4LjczNy0xLjEyOCAxLjgyMi0yLjY5IDMuMjUzLTQuNjg2IDEuNjc3LTIuMzcyIDMuMDk1LTMuNTU3IDQuMjUxLTMuNTU3IDEuMDcgMCAxLjk3NC41OTIgMi43MTEgMS43NzggMS4wNzEgMS42OTMgMi45ODYgNC43MyA1Ljc0OCA5LjExMiAzLjA1MSA0Ljc0NCA1LjMgNy4xMTYgNi43NDYgNy4xMTYgMS4wNyAwIDUuMDgyLTMuMDgxIDEyLjAzNy05LjI0MiA2Ljk3LTYuMTYxIDEwLjc5NS05LjI0MiAxMS40NzQtOS4yNDJoMi4zNjRabTQ0LjU3MyAxOS41MjVjLTEuMDQyIDEuMjQ0LTIuNDAxIDEuODY2LTQuMDc4IDEuODY2aC0xNC45ODhjLTMuNDcgMC03LjMzOC0uNTIxLTExLjYwNC0xLjU2Mi01LjU5NS0xLjM2LTguNzYyLTMuMDY3LTkuNS01LjEyLS44MDktMi4zMTQtMS4yMTQtNC41MzQtMS4yMTQtNi42NiAwLTQuMjY3IDEuODM2LTcuNTQzIDUuNTA5LTkuODI4IDMuMDk0LTEuOTgxIDYuODc2LTIuOTcyIDExLjM0NC0yLjk3MiAzLjg0NiAwIDYuODk3LjgzMiA5LjE1MyAyLjQ5NSAyLjI1NSAxLjY0OSAzLjM4MyAzLjg5OCAzLjM4MyA2Ljc0NyAwIDEuNTkxLTIuNzExIDMuMzI2LTguMTMzIDUuMjA2LTQuNDgzIDEuNjItNy43NDQgMi40My05Ljc4MiAyLjQzYTQuNDkgNC40OSAwIDAgMS0uNjczLS4wNDNjMCAuMzktLjMxMS44NjgtLjkzMiAxLjQzMi4zMzIuNTY0IDEuOTgxIDEuMjE0IDQuOTQ1IDEuOTUyIDIuNjYuNjggNC41NTUgMS4wMiA1LjY4MiAxLjAyaDEzLjQ3YzAgLjAyOSAxLjY5OS4yODIgNS4wOTcuNzU5IDEuMDcuNjggMS44NDMgMS40MzkgMi4zMjEgMi4yNzhabS0xNy40NjEtMTYuOWMtMS41NzYtMS42MDUtNC4xMTMtMi40MDgtNy42MTMtMi40MDgtMi40NTggMC00LjczNS40NzctNi44MzIgMS40MzItMi43MDQgMS4yNDQtNC4wNTYgMi45MjktNC4wNTYgNS4wNTUgMCAuNzUyLjI1MyAxLjI4Ny43NTkgMS42MDVoMi43MTFjLjk1NSAwIDMuNTUtLjgwMyA3Ljc4Ny0yLjQwOCA0LjIzNy0xLjYyIDYuNjUyLTIuNzEyIDcuMjQ0LTMuMjc2Wm0zMi40OTEtNTMuMzAyLTIuNDA3IDUzLjU2M2MtLjE0NS4xMTUtLjIxNy40NTUtLjIxNyAxLjAxOSAwIC41NjQuMDcyIDEuMzM4LjIxNyAyLjMyMS4zMDQgMi42NjIgMS4wNDEgNy42OTUgMi4yMTIgMTUuMDk5LS4wNTguMjQ2LS41NDIuNTI4LTEuNDUzLjg0N2EyLjkyIDIuOTIgMCAwIDEtLjQ1NS4wNDNjLTIuOTY1IDAtNC44ODgtMy40MjEtNS43Ny0xMC4yNjEtLjAyOS0uMTQ1LS4wNDMtLjQyNy0uMDQzLS44NDYgMC0xLjMzMS4wNzItNC4wNTcuMjE3LTguMTc5LjIwMi01LjMwOC40NDEtMTAuODYyLjcxNS0xNi42NjEuMDg3LTIuMTk4LjQxMi02LjI5MS45NzYtMTIuMjc5LjUzNS01LjQ4MS44MDMtOS41NTIuODAzLTEyLjIxNCAwLTguMDk5LjUzNS0xMy43NiAxLjYwNS0xNi45ODZsLjY1MS0uMDQzaC4xOTVjLjk2OSAwIDEuNjE5LjUzNSAxLjk1MiAxLjYwNS4yNi43MDkuNTI4IDEuNy44MDIgMi45NzJabTExNC4yMTggNjguMTg0Yy0uNjggMS4zMDItMS41MTEgMS45NTMtMi40OTQgMS45NTMtLjQ5MiAwLTEuNjQyLS4zNjktMy40NDktMS4xMDctMi4xNjktLjg4Mi0zLjQzNC0xLjM4MS0zLjc5Ni0xLjQ5Ny0xLjU5LS4zOS0zLjk3Ni0uNzM3LTcuMTU3LTEuMDQxLTMuODQ3LS4zNzYtNi4yMzItLjY4Ny03LjE1OC0uOTMzLTQuNDk3LTEuMTEzLTEwLjAyLTIuNC0xNi41NzEtMy44NjEtMy4wOC0uNjgtNy4wMi0yLjMyMS0xMS44MjEtNC45MjUtNS44Ny0zLjE4Mi04LjgwNi01LjgwNy04LjgwNi03Ljg3NSAwLS40MTkgMy42OC0zLjgxMSAxMS4wNC0xMC4xNzQgOC4wMjYtNi45MTMgMTIuMjc3LTEwLjYwOSAxMi43NTQtMTEuMDg2LjQ2My0uNzA5IDEuMi0xLjcxNCAyLjIxMi0zLjAxNS4yNzUtLjI2IDIuNTc0LTIuMzY1IDYuODk4LTYuMzEzIDMuNDg0LTMuMTk3IDYuMzY5LTUuNzEzIDguNjU0LTcuNTUgMy41NTctMi44NzggNi43MTYtNC45NjggOS40NzgtNi4yNy40MDUuMzc3Ljg0Ni41ODYgMS4zMjMuNjN2My4xMDJsLS4zOS4yMTdhNTkuMDEgNTkuMDEgMCAwIDAtNi4zMTIgNC40NDdjLTYuOTEyIDUuNjI2LTE5LjczIDE3LjgwNC0zOC40NTYgMzYuNTMzIDUuNTM4IDMuOTQ4IDEzLjE3MyA2Ljg4NCAyMi45MDUgOC44MDggMS4wMjYuMTg4IDcuMTg2IDEuNzI4IDE4LjQ3OSA0LjYyMSAxLjM4OC4zMzIgNC4wNDIuOTc2IDcuOTYgMS45My4yODkuMDg3IDEuODU4IDEuMjIyIDQuNzA3IDMuNDA2Wm0tNTguNTQtNTMuMzQ1LTYuNjU5IDU3LjIyOWMtLjQ0OC40NjItMS4yNjUuNjk0LTIuNDUxLjY5NC0yLjAxIDAtMy4wMTUtLjcyMy0zLjAxNS0yLjE3IDAtLjU2NC40NDEtNC4yODEgMS4zMjMtMTEuMTUuMzYyLTIuNTYgMS40NDYtOS45NzIgMy4yNTQtMjIuMjM3LjMxOC0yLjUxNi45MTEtNy4wMjEgMS43NzgtMTMuNTE1LjczOC01LjEyIDEuOC05LjUxIDMuMTg5LTEzLjE2OCAxLjc0OS4zNjEgMi42MjQgMS41MTggMi42MjQgMy40NyAwIC4zMDQtLjAxNC41ODYtLjA0My44NDdabTk5LjQyNSAzMy43MTJjMCAxLjE4Ni0yLjE0NyA0LjE1OC02LjQ0MiA4LjkxNi0zLjc4OCA0LjE4LTYuNjAxIDYuOTQzLTguNDM3IDguMjg4LS45MjYuNjc5LTIuOTE0IDIuMTU1LTUuOTY1IDQuNDI1LTEuMjcyLjg5Ny0zLjIyNCAxLjc4Ni01Ljg1NiAyLjY2OS0yLjY3NS44NjctNC43NzkgMS4zMDEtNi4zMTIgMS4zMDEtMi44NzcgMC01LjI2My0xLjg1MS03LjE1Ny01LjU1NC0xLjU0OC0zLjAyMi0yLjMyMS02LjE2OC0yLjMyMS05LjQzNiAwLTIuNzE5LjU2NC01LjUwMyAxLjY5Mi04LjM1My40MTkgMCAuODUzLS4xOTUgMS4zMDEtLjU4NS41MzUuMzAzIDEuMjcyLjg5NiAyLjIxMiAxLjc3OS0uMjg5IDIuMjI3LS40MzMgNC4xNzItLjQzMyA1LjgzNSAwIDYuODQxIDIuMjE5IDEwLjI2MiA2LjY1OCAxMC4yNjIgNC4yOTUgMCA5LjQ1LTIuNjY5IDE1LjQ2NS04LjAwNi45NTQtLjg1MyA1LjQ3My01LjA3NiAxMy41NTYtMTIuNjY5aC42NzJjLjkxMSAwIDEuMzY3LjM3NiAxLjM2NyAxLjEyOFptMzguNDEyIDEuMDJjMCAuNTkzLS4yOTYgMy45Ny0uODg5IDEwLjEzMWE3MjIuMzI4IDcyMi4zMjggMCAwIDEtMS44NjUgMTYuNzA0Yy0uMDU4LjQ0OS0uNTA3LjY3My0xLjM0NS42NzMtMS4wOTkgMC0yLjAwMy0xLjM4OS0yLjcxMS00LjE2NS0uNTM1LTIuMTEyLS44MDMtMy45ODUtLjgwMy01LjYxOSAwLS42MjIuMzU0LTIuODU3IDEuMDYzLTYuNzA0LjcyMy0zLjgzMiAxLjA4NC02LjA1MiAxLjA4NC02LjY2IDAtMS42NjMtLjQ0OC0yLjQ5NC0xLjM0NC0yLjQ5NC0xLjE1NyAwLTMuNjMgMS4wMDUtNy40MTggMy4wMTUtMy4yODMgMS43NS01LjY2OSAzLjE3NS03LjE1OCA0LjI3NC0yLjg0OCAyLjA5Ny02LjA4IDUuMjUtOS42OTUgOS40NTgtLjU5My42OC0xLjc1NyAxLjk3NC0zLjQ5MiAzLjg4NC0uNjY1LjcwOC0yLjAwMyAxLjA3Ny00LjAxMyAxLjEwNnYtMi44NDJjMC0xLjMxNiAyLjU5Ni00LjIzOCA3Ljc4Ny04Ljc2NGExMTMuMjg2IDExMy4yODYgMCAwIDEgMTMuMDU3LTkuODI4YzYuMzc3LTQuMTUxIDExLjEyLTYuMjI2IDE0LjIyOC02LjIyNi44MjUgMCAxLjYxMy40NDggMi4zNjUgMS4zNDUuNzY2LjkxMSAxLjE0OSAxLjgxNSAxLjE0OSAyLjcxMlpNNTM0IDEzNC40NzJ2MS45MDljLS41OTMuODI0LTEuMjQzIDEuMjM2LTEuOTUyIDEuMjM2LS40NDggMC0xLjk3NC0xLjM1OS00LjU3Ny00LjA3OC0yLjYwMi0yLjczMy00LjMzNy00LjEtNS4yMDUtNC4xIDAgLjA1OC0zLjA4IDEuMjQ0LTkuMjQgMy41NTgtNi4zMDQgMi4zNDMtMTAuMzE3IDMuNTE0LTEyLjAzOCAzLjUxNC0xLjQxNyAwLTIuOTg1LS42OTQtNC43MDYtMi4wODMtMS43MjEtMS4zNzQtMi41ODEtMi42NjgtMi41ODEtMy44ODMgMC0zLjEzOCAzLjQzNC02Ljc5NyAxMC4zMDItMTAuOTc3IDYuNDM1LTMuOTYzIDExLjM0NC01Ljk0NCAxNC43MjgtNS45NDQgMS40MTcgMCAyLjY4OS44MSAzLjgxNyAyLjQzdjEuODIyYy0uNTY0LjgxLTEuMjE1IDEuMjE1LTEuOTUyIDEuMjE1LS4xMyAwLS42MTUtLjE4MS0xLjQ1My0uNTQzLS44MzktLjM3Ni0xLjMzOC0uNTY0LTEuNDk3LS41NjQtMS4xMjggMC0zLjcxNiAxLjE2NS03Ljc2NSAzLjQ5My0zLjgzMiAyLjE2OS02LjM5OCAzLjc4OS03LjcgNC44Ni0xLjMwMSAxLjEyOC0yLjEzMiAyLjQxNS0yLjQ5NCAzLjg2MS45ODMuOTI2IDIuMTU1IDEuMzg4IDMuNTE0IDEuMzg4LjcwOCAwIDQuMTA2LTEuMTcxIDEwLjE5NC0zLjUxNCA2LjA3My0yLjM3MiA5Ljc0Ni0zLjU1OCAxMS4wMTgtMy41NTggMS44NjYgMCAzLjIxLjQ3IDQuMDM1IDEuNDEuMTg3LjIxNy45MDMgMS40OSAyLjE0NyAzLjgxOGEyMS45MDIgMjEuOTAyIDAgMCAwIDMuNDA1IDQuNzNaIi8+CiAgPC9nPgogIDxkZWZzPgogICAgPGNsaXBQYXRoIGlkPSJhIj4KICAgICAgPHBhdGggZmlsbD0iI2ZmZiIgZD0iTTU4IDQ5aDQ3NnYxMDJINTh6Ii8+CiAgICA8L2NsaXBQYXRoPgogIDwvZGVmcz4KPC9zdmc+"); +{% endcapture %} + + +{% capture advanced-js %} +function randomColor() { + const r = Math.round(Math.random() * 255); + const g = Math.round(Math.random() * 255); + const b = Math.round(Math.random() * 255); + return `rgb(${r},${g},${b})`; +} + +function download(dataURL, filename) { + const blob = dataURLToBlob(dataURL); + const url = window.URL.createObjectURL(blob); + + const a = document.createElement("a"); + a.style = "display: none"; + a.href = url; + a.download = filename; + + document.body.appendChild(a); + a.click(); + + window.URL.revokeObjectURL(url); +} + +function dataURLToBlob(dataURL) { + const parts = dataURL.split(';base64,'); + const contentType = parts[0].split(":")[1]; + const raw = window.atob(parts[1]); + const rawLength = raw.length; + const uInt8Array = new Uint8Array(rawLength); + + for (let i = 0; i < rawLength; ++i) { + uInt8Array[i] = raw.charCodeAt(i); + } + + return new Blob([uInt8Array], { type: contentType }); +} + + +document.querySelector("#signature-advanced-color").addEventListener("click", function () { + signaturePad.penColor = randomColor(); +}); + +document.querySelector("#signature-advanced-svg").addEventListener("click", function () { + const dataURL = signaturePad.toDataURL('image/svg+xml'); + download(dataURL, "signature.svg"); +}); + +document.querySelector("#signature-advanced-png").addEventListener("click", function () { + const dataURL = signaturePad.toDataURL(); + download(dataURL, "signature.png"); +}); +{% endcapture %} + +
+
+
+
+

Confirm transfer

+

Please confirm the transfer of funds by signing below.

+
+
+ + +
+
+ + +
+
+ + {% include "ui/signature.html" sample clear extra-js=simple-js %} +
+
+
+ I agree that the signature and initials will be the electronic representation of my signature and initials for all purposes when I (or my agent) use + them on documents, including legally binding contracts - just the same as a pen-and-paper signature or initial. +
+ +
+
+ + +
+
+
+
+
+ +
+
+
+
+
+

Advanced demo

+ + {% include "ui/signature.html" id="advanced" clear extra-js=advanced-js %} + +
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+
+ {% include "ui/button.html" text="Open signature modal" modal-id="signature" %} +
+
+
+
+
+
+ + +{% capture_modal %} + +{% endcapture_modal %}