Compare commits

..

1 Commits

Author SHA1 Message Date
Flatlogic Bot
30fe60f3ea Fazliddin 2026-01-29 11:42:42 +00:00
5692 changed files with 993633 additions and 3 deletions

View File

@ -1,4 +1,4 @@
WordPress Admin Credentials:
URL: http://localhost/wp-admin
Username: admin
Password: c59u3v2geHuIQMRP
Password: WK17kECWD9BPRGt7

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 KiB

1
wp-admin/test_access.php Normal file
View File

@ -0,0 +1 @@
<?php echo 'hello'; ?>

View File

@ -103,8 +103,7 @@ define( 'WP_DEBUG', false );
/* Add any custom values between this line and the "stop editing" line. */
define('FS_METHOD', 'direct');
/* That's all, stop editing! Happy publishing. */

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array('react', 'react-jsx-runtime'), 'version' => 'c0561fbc682c545702d0');

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
.lsq-block{padding:20px 10px}.lsq-block h4{margin-top:0}.lsq-block h4 img{margin-left:5px;vertical-align:-5px;width:30px}.lsq-block .lsq-link-text{border:1px solid var(--wp-components-color-gray-600,#949494);box-shadow:0 1px 1px rgba(10,10,11,.06);box-sizing:border-box;font-size:13px!important;font-weight:400;margin-top:8px;padding:5px 10px}.lsq-block .lsq-link-text span{font-size:13px;top:-2px}.lsq-block .components-input-control__input{height:32px!important;min-height:32px!important}.lsq-block .lemonsqueezy-custom-data-header{display:flex;justify-content:space-between}.lsq-block .lemonsqueezy-custom-data-header a{padding:0}.lsq-block .lemonsqueezy-custom-data-row{grid-gap:10px;display:grid;grid-template-columns:1fr 1fr 100px}.lsq-block .lemonsqueezy-custom-data-row button{align-self:end;height:30px}.lsq-block .lemonsqueezy-custom-data-row .components-base-control__field,.lsq-block .lemonsqueezy-custom-data-row button{margin-bottom:8px}.lsq-block .lsq-block-settings{display:grid;gap:10px;grid-template-columns:1fr 1fr;margin:20px 0}.lsq-block .components-base-control__label{margin-bottom:0}

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => '34c440f8635f24bc6ce0');

View File

@ -0,0 +1,2 @@
.lsq-block{padding:20px 10px}.lsq-block h4{margin-top:0}.lsq-block h4 img{margin-right:5px;vertical-align:-5px;width:30px}.lsq-block .lsq-link-text{border:1px solid var(--wp-components-color-gray-600,#949494);box-shadow:0 1px 1px rgba(10,10,11,.06);box-sizing:border-box;font-size:13px!important;font-weight:400;margin-top:8px;padding:5px 10px}.lsq-block .lsq-link-text span{font-size:13px;top:-2px}.lsq-block .components-input-control__input{height:32px!important;min-height:32px!important}.lsq-block .lemonsqueezy-custom-data-header{display:flex;justify-content:space-between}.lsq-block .lemonsqueezy-custom-data-header a{padding:0}.lsq-block .lemonsqueezy-custom-data-row{grid-gap:10px;display:grid;grid-template-columns:1fr 1fr 100px}.lsq-block .lemonsqueezy-custom-data-row button{align-self:end;height:30px}.lsq-block .lemonsqueezy-custom-data-row .components-base-control__field,.lsq-block .lemonsqueezy-custom-data-row button{margin-bottom:8px}.lsq-block .lsq-block-settings{display:grid;gap:10px;grid-template-columns:1fr 1fr;margin:20px 0}.lsq-block .components-base-control__label{margin-bottom:0}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array(), 'version' => '39139c5f5539244f2462');

View File

@ -0,0 +1 @@
(()=>{"use strict";var r,e={773:()=>{}},o={};function n(r){var t=o[r];if(void 0!==t)return t.exports;var a=o[r]={exports:{}};return e[r](a,a.exports,n),a.exports}n.m=e,r=[],n.O=(e,o,t,a)=>{if(!o){var i=1/0;for(u=0;u<r.length;u++){for(var[o,t,a]=r[u],l=!0,s=0;s<o.length;s++)(!1&a||i>=a)&&Object.keys(n.O).every(r=>n.O[r](o[s]))?o.splice(s--,1):(l=!1,a<i&&(i=a));if(l){r.splice(u--,1);var v=t();void 0!==v&&(e=v)}}return e}a=a||0;for(var u=r.length;u>0&&r[u-1][2]>a;u--)r[u]=r[u-1];r[u]=[o,t,a]},n.o=(r,e)=>Object.prototype.hasOwnProperty.call(r,e),(()=>{var r={910:0,919:0};n.O.j=e=>0===r[e];var e=(e,o)=>{var t,a,[i,l,s]=o,v=0;if(i.some(e=>0!==r[e])){for(t in l)n.o(l,t)&&(n.m[t]=l[t]);if(s)var u=s(n)}for(e&&e(o);v<i.length;v++)a=i[v],n.o(r,a)&&r[a]&&r[a][0](),r[a]=0;return n.O(u)},o=globalThis.webpackChunklemonsqueezy=globalThis.webpackChunklemonsqueezy||[];o.forEach(e.bind(null,0)),o.push=e.bind(null,o.push.bind(o))})();var t=n.O(void 0,[919],()=>n(773));t=n.O(t)})();

View File

@ -0,0 +1,2 @@

View File

@ -0,0 +1,2 @@

View File

@ -0,0 +1,6 @@
<svg width="20px" height="18px" viewBox="0 0 128 174" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M43.2867 106.795L90.2155 128.375C96.0319 131.051 100.138 135.542 102.355 140.694C107.963 153.739 100.298 167.081 88.2658 171.879C76.2316 176.676 63.4061 173.589 57.5744 160.023L37.1511 112.394C35.5684 108.702 39.5441 105.074 43.2867 106.795" fill="#FFC233"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M46.1054 92.8264L94.548 74.6126C110.648 68.5591 128.235 80.0127 127.998 96.6547C127.994 96.8719 127.99 97.0891 127.984 97.3081C127.636 113.514 110.539 124.406 94.7927 118.673L46.1513 100.965C42.2711 99.5535 42.2425 94.2786 46.1054 92.8264" fill="#FFC233"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M43.39 86.5175L91.0107 66.3914C106.835 59.7029 110.851 39.6283 98.4575 28.0294C98.2951 27.8766 98.1326 27.7257 97.9682 27.5747C85.8174 16.3567 65.7305 20.3065 58.8131 35.0822L37.4436 80.7328C35.7386 84.3733 39.592 88.1225 43.39 86.5175" fill="#FFC233"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M31.1356 78.5642L48.4491 31.3456C50.5956 25.4909 50.198 19.5202 47.9789 14.3686C42.3594 1.32848 27.1408 -2.8808 15.1104 1.92481C3.08191 6.73226 -3.71504 17.6502 2.12812 31.2112L22.6853 78.7888C24.2794 82.4753 29.7556 82.3299 31.1356 78.5642" fill="#FFC233"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,18 @@
<svg width="300" height="160" viewBox="0 0 1200 160" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M39.5904 98.2021L82.512 118.046C87.8317 120.507 91.5868 124.636 93.6147 129.373C98.7439 141.369 91.7337 153.638 80.7288 158.05C69.7222 162.46 57.9919 159.622 52.6582 147.147L33.9787 103.35C32.5312 99.9554 36.1675 96.6196 39.5904 98.2021Z" fill="#FFC233"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M42.1685 85.3576L86.4746 68.6093C101.2 63.0429 117.285 73.5749 117.068 88.8779C117.064 89.0776 117.061 89.2773 117.056 89.4787C116.738 104.381 101.1 114.396 86.6984 109.124L42.2105 92.8416C38.6616 91.5435 38.6354 86.693 42.1685 85.3576Z" fill="#FFC233"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M39.6849 79.5563L83.2393 61.0496C97.7126 54.8992 101.386 36.4398 90.0502 25.7741C89.9017 25.6336 89.7531 25.4949 89.6027 25.3561C78.4895 15.0407 60.1177 18.6727 53.791 32.2595L34.2463 74.237C32.6869 77.5847 36.2112 81.0321 39.6849 79.5563Z" fill="#FFC233"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M28.4769 72.243L44.312 28.8235C46.2752 23.4399 45.9116 17.9496 43.882 13.2125C38.7423 1.22159 24.8232 -2.64901 13.8201 1.76994C2.81875 6.19058 -3.39781 16.2301 1.9464 28.7L20.7482 72.4494C22.2062 75.8394 27.2147 75.7057 28.4769 72.243Z" fill="#FFC233"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M232.799 79.1658H268.818C266.42 70.0148 259.848 66.3049 251.845 66.3049C243.045 66.3049 235.993 71.1013 232.799 79.1658ZM289.95 94.8157H231.521C233.919 106.602 243.84 110.945 252.483 110.945C263.369 110.945 268.023 104.432 268.023 104.432H288.19C282.103 119.93 267.54 128.45 251.845 128.45C230.23 128.45 211.341 112.485 211.341 88.3151C211.341 64.2859 230.073 49.406 251.205 49.406C271.699 49.406 292.518 63.1994 289.95 94.8157Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M488.442 88.9337C488.442 76.8429 481.077 67.3907 468.913 67.3907C456.739 67.3907 448.576 76.8429 448.576 88.9337C448.576 101.024 456.739 110.477 468.913 110.477C481.077 110.477 488.442 101.024 488.442 88.9337ZM427.602 89.0843C427.602 64.2867 447.456 49.4068 468.913 49.4068C490.528 49.4068 509.417 64.4373 509.417 88.7695C509.417 113.418 489.876 128.449 468.263 128.449C446.491 128.449 427.602 113.418 427.602 89.0843Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M595.119 85.6778V127.679H573.817V90.3218C573.817 87.685 575.747 68.1594 560.377 67.391C552.842 66.9239 539.4 70.9485 539.4 91.2561V127.679H518.27V50.1756H537.668L537.731 60.9344C537.731 60.9344 546.477 49.4055 562.789 49.4055C583.439 49.4055 595.119 64.2854 595.119 85.6778Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M672.985 65.8379C666.258 65.8379 663.377 69.0941 663.377 72.3504C663.377 77.6138 670.586 79.1658 675.383 80.1C689.645 83.0398 704.05 87.2302 704.05 103.649C704.05 119.615 690.441 128.45 673.95 128.45C655.541 128.45 641.294 117.608 640.329 101.176H660.013C660.496 105.82 663.702 111.865 673.467 111.865C681.628 111.865 683.558 107.688 683.558 104.432C683.558 98.6897 677.951 96.9855 672.502 95.7483C663.064 93.7292 642.727 90.0194 642.727 72.3504C642.727 57.1557 657.784 49.406 673.31 49.406C691.236 49.406 703.085 59.9448 704.05 72.9681H684.352C683.713 70.3313 681.159 65.8379 672.985 65.8379Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M768.776 88.9336C768.776 76.0609 761.566 68.4754 751.165 68.4754C741.399 68.4754 731.622 75.2909 731.622 88.9336C731.622 102.564 741.399 109.392 751.165 109.392C761.566 109.392 768.776 101.794 768.776 88.9336ZM788.787 50.1769V158.676H768.776V120.081C763.652 125.659 756.444 128.449 748.114 128.449C727.79 128.449 710.816 112.333 710.816 88.9336C710.816 65.5222 727.79 49.4068 748.114 49.4068C764.089 49.4068 770.07 59.7865 770.07 59.7865L770.04 50.1769H788.787Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M903.194 79.1658H939.214C936.815 70.0148 930.244 66.3049 922.241 66.3049C913.44 66.3049 906.388 71.1013 903.194 79.1658ZM960.346 94.8157H901.904C904.315 106.602 914.236 110.945 922.879 110.945C933.765 110.945 938.418 104.432 938.418 104.432H958.585C952.498 119.93 937.936 128.45 922.241 128.45C900.626 128.45 881.737 112.485 881.737 88.3151C881.737 64.2859 900.469 49.406 921.601 49.406C942.095 49.406 962.914 63.1994 960.346 94.8157Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M988.257 79.1658H1024.28C1021.88 70.0148 1015.31 66.3049 1007.3 66.3049C998.503 66.3049 991.451 71.1013 988.257 79.1658ZM1045.41 94.8157H986.979C989.377 106.602 999.298 110.945 1007.94 110.945C1018.83 110.945 1023.48 104.432 1023.48 104.432H1043.65C1037.56 119.93 1023 128.45 1007.3 128.45C985.689 128.45 966.799 112.485 966.799 88.3151C966.799 64.2859 985.531 49.406 1006.66 49.406C1027.16 49.406 1047.98 63.1994 1045.41 94.8157Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M1116.69 110.325V127.678H1048.65V117.444L1087.24 67.5423H1050.26V50.1762H1115.1V60.4104L1076.51 110.325H1116.69Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M1199.99 50.1762V118.378V119.93C1199.99 140.855 1188.94 159.458 1161.56 159.458C1135.94 159.458 1122.02 143.177 1122.02 130.936H1142.03C1142.03 130.936 1145.07 141.322 1160.92 141.322C1174.38 141.322 1179.98 133.876 1179.98 123.034V119.778C1176.45 123.653 1169.74 128.45 1157.73 128.45C1136.75 128.45 1123.63 113.734 1123.63 92.1893L1123.46 50.1762H1144.27V87.5334C1144.27 98.0705 1148.12 110.478 1161.41 110.478C1168.29 110.478 1179.66 107.221 1179.66 86.5991V50.1762H1199.99Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M196.101 104.413C196.101 109.246 198.005 111.24 201.538 111.24C204.027 111.24 205.644 110.951 208.003 110.243L209.321 126.171C204.914 127.584 200.652 128.442 195.215 128.442C182.74 128.442 175.1 124.466 175.1 107.253V19.1799H196.101V104.413Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M418.567 85.6778V127.679H397.265V90.3218C397.265 79.6324 398.387 66.142 383.655 67.391C379.823 67.694 369.25 69.3966 369.25 91.2561V127.679H348.118V90.3218C348.118 79.6324 349.239 66.142 334.509 67.391C330.663 67.694 320.104 69.3966 320.104 91.2561V127.679H298.971V50.1756H318.371L318.389 60.9344C318.389 60.9344 325.803 49.4055 339.631 49.4055C356.295 49.4055 362.835 61.9566 362.835 61.9566C362.835 61.9566 370.009 49.2549 388.309 49.2549C409.116 49.2549 418.567 64.1348 418.567 85.6778Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M797.768 92.1772V50.176H819.07V87.5332C819.07 90.17 817.14 109.696 832.51 110.464C840.045 110.931 853.485 106.906 853.485 86.5989V50.176H874.617V127.679H855.245L855.156 116.921C855.156 116.921 846.41 128.449 830.097 128.449C809.448 128.449 797.768 113.57 797.768 92.1772Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -0,0 +1,582 @@
# Copyright (C) 2025 Lemon Squeezy
# This file is distributed under the GPL-2.0+.
msgid ""
msgstr ""
"Project-Id-Version: Lemon Squeezy — Sell Digital Products, Subscriptions, and Licenses 1.4.2\n"
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/lemon-squeezy\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"POT-Creation-Date: 2025-12-02T09:04:45+00:00\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"X-Generator: WP-CLI 2.12.0\n"
"X-Domain: lemon-squeezy\n"
#. Plugin Name of the plugin
#: lemonsqueezy.php
msgid "Lemon Squeezy — Sell Digital Products, Subscriptions, and Licenses"
msgstr ""
#. Plugin URI of the plugin
#: lemonsqueezy.php
msgid "https://www.lemonsqueezy.com"
msgstr ""
#. Description of the plugin
#: lemonsqueezy.php
msgid "Sell digital products the easy-peasy way directly from WordPress."
msgstr ""
#. Author of the plugin
#: lemonsqueezy.php
#: src/class-lsq-register-block.php:52
#: build/editor.js:424
#: src/blocks/button/index.js:577
#: build/editor.js:596
msgid "Lemon Squeezy"
msgstr ""
#. Author URI of the plugin
#: lemonsqueezy.php
msgid "https://www.lemonsqueezy.com/"
msgstr ""
#: src/class-lsq-oauth.php:134
msgid "Invalid oauth state/code"
msgstr ""
#: src/class-lsq-rest-controller.php:264
#: src/class-lsq-rest-controller.php:322
#: src/class-lsq-rest-controller.php:379
#: src/class-lsq-rest-controller.php:432
#: src/class-lsq-rest-controller.php:506
#: src/class-lsq-rest-controller.php:581
msgid "Unauthorized request"
msgstr ""
#: src/class-lsq-rest-controller.php:593
msgid "Missing license_key"
msgstr ""
#: src/class-lsq-rest-controller.php:607
msgid "Invalid license_key"
msgstr ""
#: src/class-lsq-rest-controller.php:619
msgid "Error fetching license_key"
msgstr ""
#: src/class-lsq-rest-controller.php:631
msgid "Invalid order item"
msgstr ""
#: src/class-lsq-rest-controller.php:643
msgid "Missing files"
msgstr ""
#: src/class-lsq-rest-controller.php:656
msgid "Missing file version"
msgstr ""
#: build/admin.js:308
#: src/admin/admin.js:175
#: build/admin.js:247
msgid "Connected to Lemon Squeezy"
msgstr ""
#: build/admin.js:308
#: build/admin.js:309
#: src/admin/admin.js:176
#: src/admin/admin.js:179
#: build/admin.js:248
#: build/admin.js:251
msgid "Connect to Lemon Squeezy"
msgstr ""
#: build/admin.js:309
#: src/admin/admin.js:178
#: build/admin.js:250
msgid "Checking..."
msgstr ""
#: build/admin.js:318
#: src/admin/admin.js:186
#: build/admin.js:258
msgid "LemonSqueezy.com"
msgstr ""
#: build/admin.js:321
#: src/admin/admin.js:189
#: build/admin.js:261
msgid "Want to make money with digital products?"
msgstr ""
#: build/admin.js:326
#: src/admin/admin.js:199
#: build/admin.js:271
msgid "Start selling today"
msgstr ""
#: build/admin.js:336
#: src/admin/admin.js:207
#: build/admin.js:279
msgid "Connect your store"
msgstr ""
#: build/admin.js:338
#: src/admin/admin.js:209
#: build/admin.js:281
msgid "The Lemon Squeezy plugin connects your Lemon Squeezy stores to your WordPress site to bring your products right into the block editor."
msgstr ""
#: build/admin.js:343
#: src/admin/admin.js:217
#: build/admin.js:289
msgid "1. Connect to Lemon Squeezy"
msgstr ""
#: build/admin.js:345
#: src/admin/admin.js:223
#: build/admin.js:295
msgid "To get started, use the \"Connect to Lemon Squeezy\" button on the right. When prompted, click \"Authorize\" to connect your Lemon Squeezy account with this WordPress site."
msgstr ""
#: build/admin.js:350
#: src/admin/admin.js:231
#: build/admin.js:303
msgid "2. Add the Lemon Squeezy block and start selling!"
msgstr ""
#: build/admin.js:352
#: src/admin/admin.js:237
#: build/admin.js:309
msgid "To add products to your posts or pages, simply add the Lemon Squeezy block and select which product you'd like to insert. Use the block settings to select a checkout link or a checkout overlay."
msgstr ""
#: build/editor.js:317
#: src/blocks/button/index.js:280
#: build/editor.js:299
msgid "Select Store"
msgstr ""
#: build/editor.js:326
#: build/editor.js:768
#: src/blocks/button/index.js:292
#: src/blocks/ls-button/edit.js:369
#: build/editor.js:311
#: build/editor.js:1040
msgid "Loading..."
msgstr ""
#: build/editor.js:328
#: build/editor.js:770
#: src/blocks/button/index.js:296
#: src/blocks/ls-button/edit.js:373
#: build/editor.js:315
#: build/editor.js:1044
msgid "Product"
msgstr ""
#: build/editor.js:337
#: build/editor.js:779
#: src/blocks/button/index.js:308
#: src/blocks/ls-button/edit.js:385
#: build/editor.js:327
#: build/editor.js:1056
msgid "No products found"
msgstr ""
#: build/editor.js:339
#: build/editor.js:790
#: src/blocks/button/index.js:315
#: src/blocks/ls-button/edit.js:407
#: build/editor.js:334
#: build/editor.js:1078
msgid "Quantity"
msgstr ""
#: build/editor.js:346
#: build/editor.js:799
#: src/blocks/button/index.js:326
#: src/blocks/ls-button/edit.js:419
#: build/editor.js:345
#: build/editor.js:1090
msgid "Use checkout overlay?"
msgstr ""
#: build/editor.js:348
#: build/editor.js:800
#: src/blocks/button/index.js:333
#: src/blocks/ls-button/edit.js:425
#: build/editor.js:352
#: build/editor.js:1096
msgid "Your checkout will be opened in a modal window."
msgstr ""
#: build/editor.js:348
#: build/editor.js:800
#: src/blocks/button/index.js:337
#: src/blocks/ls-button/edit.js:429
#: build/editor.js:356
#: build/editor.js:1100
msgid "Your customer will be redirected to your checkout page."
msgstr ""
#: build/editor.js:351
#: build/editor.js:804
#: src/blocks/button/index.js:345
#: src/blocks/ls-button/edit.js:438
#: build/editor.js:364
#: build/editor.js:1109
msgid "Pre-fill User Data"
msgstr ""
#: build/editor.js:353
#: build/editor.js:806
#: src/blocks/button/index.js:352
#: src/blocks/ls-button/edit.js:445
#: build/editor.js:371
#: build/editor.js:1116
msgid "If logged-in, pre-fill user's data on checkout."
msgstr ""
#: build/editor.js:353
#: build/editor.js:806
#: src/blocks/button/index.js:356
#: src/blocks/ls-button/edit.js:449
#: build/editor.js:375
#: build/editor.js:1120
msgid "It won't pre-fill user's data on checkout."
msgstr ""
#: build/editor.js:356
#: build/editor.js:809
#: src/blocks/button/index.js:364
#: src/blocks/ls-button/edit.js:457
#: build/editor.js:383
#: build/editor.js:1128
msgid "Pre-fill from URL"
msgstr ""
#: build/editor.js:358
#: build/editor.js:811
#: src/blocks/button/index.js:371
#: src/blocks/ls-button/edit.js:464
#: build/editor.js:390
#: build/editor.js:1135
msgid "If there are checkout query strings in URL, it'll pre-fill the checkout."
msgstr ""
#: build/editor.js:358
#: build/editor.js:811
#: src/blocks/button/index.js:375
#: src/blocks/ls-button/edit.js:468
#: build/editor.js:394
#: build/editor.js:1139
msgid "It won't pre-fill URL data on checkout."
msgstr ""
#: build/editor.js:361
#: build/editor.js:814
#: src/blocks/button/index.js:383
#: src/blocks/ls-button/edit.js:476
#: build/editor.js:402
#: build/editor.js:1147
msgid "Show Logo"
msgstr ""
#: build/editor.js:363
#: build/editor.js:816
#: src/blocks/button/index.js:387
#: src/blocks/ls-button/edit.js:480
#: build/editor.js:406
#: build/editor.js:1151
msgid "Show the Lemon Squeezy logo in the checkout."
msgstr ""
#: build/editor.js:363
#: build/editor.js:816
#: src/blocks/button/index.js:391
#: src/blocks/ls-button/edit.js:484
#: build/editor.js:410
#: build/editor.js:1155
msgid "It won't show the Lemon Squeezy logo in the checkout."
msgstr ""
#: build/editor.js:366
#: build/editor.js:819
#: src/blocks/button/index.js:402
#: src/blocks/ls-button/edit.js:495
#: build/editor.js:421
#: build/editor.js:1166
msgid "Show Media"
msgstr ""
#: build/editor.js:367
#: build/editor.js:820
#: src/blocks/button/index.js:405
#: src/blocks/ls-button/edit.js:501
#: build/editor.js:424
#: build/editor.js:1172
msgid "Show the product media in the checkout."
msgstr ""
#: build/editor.js:367
#: build/editor.js:820
#: src/blocks/button/index.js:409
#: src/blocks/ls-button/edit.js:505
#: build/editor.js:428
#: build/editor.js:1176
msgid "It won't show the product media in the checkout."
msgstr ""
#: build/editor.js:371
#: build/editor.js:824
#: src/blocks/button/index.js:421
#: src/blocks/ls-button/edit.js:517
#: build/editor.js:440
#: build/editor.js:1188
msgid "Show Description"
msgstr ""
#: build/editor.js:372
#: build/editor.js:825
#: src/blocks/button/index.js:427
#: src/blocks/ls-button/edit.js:523
#: build/editor.js:446
#: build/editor.js:1194
msgid "Show the product description in the checkout."
msgstr ""
#: build/editor.js:372
#: build/editor.js:825
#: src/blocks/button/index.js:431
#: src/blocks/ls-button/edit.js:527
#: build/editor.js:450
#: build/editor.js:1198
msgid "It won't show the product description in the checkout."
msgstr ""
#: build/editor.js:376
#: build/editor.js:829
#: src/blocks/button/index.js:443
#: src/blocks/ls-button/edit.js:539
#: build/editor.js:462
#: build/editor.js:1210
msgid "Show Discount"
msgstr ""
#: build/editor.js:377
#: build/editor.js:830
#: src/blocks/button/index.js:446
#: src/blocks/ls-button/edit.js:545
#: build/editor.js:465
#: build/editor.js:1216
msgid "Show the product discount in the checkout."
msgstr ""
#: build/editor.js:377
#: build/editor.js:830
#: src/blocks/button/index.js:450
#: src/blocks/ls-button/edit.js:549
#: build/editor.js:469
#: build/editor.js:1220
msgid "It won't show the product discount in the checkout."
msgstr ""
#: build/editor.js:381
#: build/editor.js:735
#: src/blocks/button/index.js:462
#: src/blocks/ls-button/edit.js:287
#: build/editor.js:481
#: build/editor.js:958
msgid "Checkout colors"
msgstr ""
#: build/editor.js:385
#: build/editor.js:732
#: build/editor.js:739
#: src/blocks/button/index.js:474
#: src/blocks/ls-button/edit.js:278
#: src/blocks/ls-button/edit.js:299
#: build/editor.js:493
#: build/editor.js:949
#: build/editor.js:970
msgid "Background"
msgstr ""
#: build/editor.js:389
#: build/editor.js:743
#: src/blocks/button/index.js:486
#: src/blocks/ls-button/edit.js:311
#: build/editor.js:505
#: build/editor.js:982
msgid "Links"
msgstr ""
#: build/editor.js:393
#: build/editor.js:747
#: src/blocks/button/index.js:495
#: src/blocks/ls-button/edit.js:323
#: build/editor.js:514
#: build/editor.js:994
msgid "Button"
msgstr ""
#: build/editor.js:397
#: build/editor.js:751
#: build/editor.js:781
#: build/editor.js:784
#: src/blocks/button/index.js:504
#: src/blocks/ls-button/edit.js:335
#: src/blocks/ls-button/edit.js:393
#: src/blocks/ls-button/edit.js:397
#: build/editor.js:523
#: build/editor.js:1006
#: build/editor.js:1064
#: build/editor.js:1068
msgid "Button text"
msgstr ""
#: build/editor.js:401
#: build/editor.js:755
#: src/blocks/button/index.js:516
#: src/blocks/ls-button/edit.js:347
#: build/editor.js:535
#: build/editor.js:1018
msgid "Terms + Privacy"
msgstr ""
#: build/editor.js:406
#: src/blocks/button/index.js:528
#: build/editor.js:547
msgid "Checking connection status"
msgstr ""
#: build/editor.js:408
#: build/editor.js:874
#: src/blocks/button/index.js:537
#: src/blocks/ls-button/edit.js:637
#: build/editor.js:556
#: build/editor.js:1308
msgid "Uh oh! Looks like you haven't connected your store yet! Please visit the"
msgstr ""
#: build/editor.js:410
#: build/editor.js:876
#: src/blocks/button/index.js:546
#: src/blocks/ls-button/edit.js:646
#: build/editor.js:565
#: build/editor.js:1317
msgid "Lemon Squeezy Settings"
msgstr ""
#: build/editor.js:411
#: build/editor.js:877
#: src/blocks/button/index.js:551
#: src/blocks/ls-button/edit.js:651
#: build/editor.js:570
#: build/editor.js:1322
msgid "and connect to Lemon Squeezy."
msgstr ""
#: build/editor.js:415
#: build/editor.js:881
#: src/blocks/button/index.js:563
#: src/blocks/ls-button/edit.js:662
#: build/editor.js:582
#: build/editor.js:1333
msgid "We're fetching your data, hold on for a second!"
msgstr ""
#: build/editor.js:429
#: src/blocks/button/index.js:583
#: build/editor.js:602
msgid "Apply Lemon Squeezy Checkout"
msgstr ""
#: build/editor.js:431
#: src/blocks/button/index.js:590
#: build/editor.js:609
msgid "Your button will be used for Lemon Squeezy Checkout."
msgstr ""
#: build/editor.js:431
#: src/blocks/button/index.js:594
#: build/editor.js:613
msgid "Your button will not be used for Lemon Squeezy Checkout."
msgstr ""
#: build/editor.js:720
#: src/blocks/ls-button/edit.js:254
#: build/editor.js:925
msgid "Lemon Squeezy Buy Button"
msgstr ""
#: build/editor.js:724
#: src/blocks/ls-button/edit.js:262
#: build/editor.js:933
msgid "Button colors"
msgstr ""
#: build/editor.js:728
#: src/blocks/ls-button/edit.js:270
#: build/editor.js:941
msgid "Text"
msgstr ""
#: build/editor.js:759
#: src/blocks/ls-button/edit.js:357
#: build/editor.js:1028
msgid "Store"
msgstr ""
#: build/editor.js:851
#: build/editor.js:852
#: src/blocks/ls-button/edit.js:588
#: src/blocks/ls-button/edit.js:592
#: build/editor.js:1259
#: build/editor.js:1263
msgid "Data Key"
msgstr ""
#: build/editor.js:858
#: build/editor.js:859
#: src/blocks/ls-button/edit.js:604
#: src/blocks/ls-button/edit.js:608
#: build/editor.js:1275
#: build/editor.js:1279
msgid "Data Value"
msgstr ""
#: build/editor.js:991
#: src/blocks/ls-button/index.js:83
#: build/editor.js:1429
msgid "The Lemon Squeezy Product Block"
msgstr ""
#: build/editor.js:1013
#: src/blocks/ls-button/index.js:112
#: build/editor.js:1458
msgid "ecommerce"
msgstr ""
#: build/editor.js:1013
#: src/blocks/ls-button/index.js:113
#: build/editor.js:1459
msgid "product"
msgstr ""
#: build/editor.js:1013
#: src/blocks/ls-button/index.js:114
#: build/editor.js:1460
msgid "digital"
msgstr ""
#: build/editor.js:1013
#: src/blocks/ls-button/index.js:115
#: build/editor.js:1461
msgid "digital products"
msgstr ""

View File

@ -0,0 +1,61 @@
<?php
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Plugin Name: Lemon Squeezy Sell Digital Products, Subscriptions, and Licenses
* Plugin URI: https://www.lemonsqueezy.com
* Description: Sell digital products the easy-peasy way directly from WordPress.
* Version: 1.4.3
* Requires at least: 5.3
* Requires PHP: 7.0
* Author: Lemon Squeezy
* Author URI: https://www.lemonsqueezy.com/
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
* Text Domain: lemon-squeezy
* Domain Path: /languages
*/
define( 'LSQ_PATH', plugin_dir_path( __FILE__ ) );
define( 'LSQ_URL', untrailingslashit( plugin_dir_url( __FILE__ ) ) );
if ( ! defined( 'LSQ_API_URL' ) ) {
define( 'LSQ_API_URL', 'https://api.lemonsqueezy.com' );
}
if ( ! defined( 'LSQ_APP_URL' ) ) {
define( 'LSQ_APP_URL', 'https://app.lemonsqueezy.com' );
}
if ( ! defined( 'LSQ_OAUTH_CLIENT_ID' ) ) {
define( 'LSQ_OAUTH_CLIENT_ID', '94d59e1b-7459-4371-a131-7ad050c8ca0d' );
}
// Bootmanager for Lemon Squeezy plugin.
if ( ! function_exists( 'lemonsqueezy_run_plugin' ) ) {
add_action( 'plugins_loaded', 'lemonsqueezy_run_plugin' );
if ( WP_DEBUG ) {
add_filter( 'https_ssl_verify', '__return_false' );
}
/**
* Run plugin
*
* @return void
*/
function lemonsqueezy_run_plugin() {
// Initialize classes.
include_once LSQ_PATH . 'src/class-lsq-oauth.php';
include_once LSQ_PATH . 'src/class-lsq-updater.php';
include_once LSQ_PATH . 'src/class-lsq-admin.php';
include_once LSQ_PATH . 'src/class-lsq-rest-controller.php';
include_once LSQ_PATH . 'src/class-lsq-register-block.php';
lemonsqueezy\LSQ_Admin::get_instance();
lemonsqueezy\LSQ_Rest_Controller::get_instance();
lemonsqueezy\LSQ_Register_Block::get_instance();
}
}

View File

@ -0,0 +1,195 @@
=== Lemon Squeezy — Sell Digital Products, Subscriptions, and Licenses ===
Contributors: lemonsqueezy, gilbitron, jamesckemp, patrickposner, mauryaratan
Donate link: https://lemonsqueezy.com
Tags: ecommerce, digital products, checkout, payments, subscriptions
Requires at least: 5.3
Tested up to: 6.8
Stable tag: 1.4.3
Requires PHP: 7.0
License: GPLv2 or later
License URI: [https://www.gnu.org/licenses/gpl-2.0.html](https://www.gnu.org/licenses/gpl-2.0.html)
Sell digital products, subscriptions, memberships, and software licenses on your WordPress website.
== Description ==
### Sell digital products on WordPress
If you want to sell digital products on WordPress today, its going to take a lot of tools, time, and effort to get something off the ground. Even if you have a simple product, it will often require bloated plugins to launch a store and start making sales.
**That is, until now.** [Lemon Squeezy](https://lemonsqueezy.com/) is our fresh take on digital commerce. Lemon Squeezy is focused on helping creators sell their digital products — everything from digital downloads (eBooks, PDFs, design assets, photos, audio, and videos), subscriptions, and software licenses — without the hassle. The ability to manage your products, customers, taxes and VAT, discounts, email lists, and more is all perfectly packaged into every Lemon Squeezy store.
Our all-in-one, no-code platform is everything you need to start making money with your digital products. Its blazing fast, super secure, and beautifully-designed with **you** in mind.
https://www.youtube.com/watch?v=wcFSb5EMiI0
### Relax, we got you covered
**Were also the merchant of record**, which means we take responsibility and liability for payment methods, complicated tax laws, fraud prevention, subscription billing, invoicing, secure file delivery, and virtually every other complicated aspect of running an online store. We make it easy-peasy so you dont have to think about any of it.
The icing on the cake? Lemon Squeezy supports 95 different [currencies](https://docs.lemonsqueezy.com/help/payments/currencies) and offers [payouts](https://docs.lemonsqueezy.com/help/getting-started/getting-paid) for over 280+ countries.
> When launching Iconic, Lemon Squeezy literally took care of everything. No need to think about taxes, VAT, license keys, etc. The setup really was easy-peasy. James McDonald / iconic.app
>
### Powerful checkout pages, anywhere you want them
No e-commerce software on your WordPress site? No problem. Each Lemon Squeezy store comes with a blazing-fast, secure checkout page for each of your products. You can either send customers directly to your hosted checkout page, or you can bring the beautiful Lemon Squeezy checkout experience to your website with our Checkout Overlay feature.
With Checkout Overlay, your customers can make purchases directly on your WordPress website, without installing any bloated e-commerce software.
### Sell your software the easy way
Selling software and apps is a piece of cake with Lemon Squeezy. With our powerful software licensing and subscription features, you can control access to your software and charge customers a regular fee to continue accessing your product.
### Why use Lemon Squeezy over WooCommerce or Easy Digital Downloads?
Glad you asked! Although these are powerful plugins, they both can be cumbersome to use, leaving WordPress creators to manage plugin updates, security, payments, taxes, customer accounts, extensions, and GDPR laws. On top of that, it can be difficult to manage customers, products, and orders via the often-crowded WordPress admin.
We created Lemon Squeezy specifically so you dont have to think about *any* of those headaches. Using the Lemon Squeezy app, you can launch your store, create & market products, manage customers & subscribers, and more all within a beautifully-designed interface tailor made for digital products.
When youre ready to sell on your WordPress site, you simply install the Lemon Squeezy WordPress plugin and add your products to any post, page, or content area to start generating sales. Easy-peasy!
### Auto Updates for your WordPress Themes and Plugins with Lemon Squeezy
Having the ability to release updates to your WordPress digital products is essential. This gives your customers the ability to get the latest features and bug fixes. When distributing your premium WordPress products, this is critical. Currently, this is very difficult to do, and few services are available to help you do it.
**With Lemon Squeezy**, these auto-updates are taken care of for you. The Lemon Squeezy team has worked hard to bring this advanced feature to our platform and it makes the entire process a breeze. With Lemon Squeezy, youll be able to sell your WordPress products, ship updates to paying customers and grow a thriving WordPress business.
[Check out our WordPress Plugin documentation](https://docs.lemonsqueezy.com/help/wordpress) for more detailed information.
### Ready to get started?
Lets get you set up on Lemon Squeezy so you can start selling your products!
1. Head over to [Lemon Squeezy](https://lemonsqueezy.com/) and pick a pricing plan. Our simple and affordable pricing plans are priced for first-time creators and up-and-coming WordPress businesses.
2. Set up your store details and create your first products. Well walk you through the whole process during onboarding.
3. Add the Lemon Squeezy WordPress plugin to any of your WordPress websites and start adding products and making sales!
### Testimonials
> I made my first $99/yr sale within the first hour of setup! Finally, an all-in-one solution for makers with multiple products, with the ability to sell with both subscription and one-off pricing. Incredible.
> Rob Hope / onepagelove.com
> Lemon Squeezy is exactly what I have been looking for. The license key management and recurring payments have streamlined my business, and I am looking forward to seeing the platform grow.
> UiPress / uipress.co
> Lemon Squeezy is the best option for selling digital products. I experienced the way things work, and wow, are you kidding me! Lemon squeezy is gonna change the industry!
> Eren T / @ertuken
> Imagine having a team of designers, developers, email marketers, and tax accountants behind you. Thats how Lemon Squeezy feels, letting you focus on creating your digital products.
> Shahadat Rahman / @HiShahadat
> Lemon Squeezy has surpassed my expectations, and Ive made the decision to move all my chips in on this platform for the long haul. The product is beautifully designed and a joy to use.
> Michael Riddering / figma.academy
> Ive never come across a platform that has made it SO easy-peasy to start selling. Lemon Squeezy is full of beautiful surprises, and its a genuine joy to use!
> Rachel Shillcock / @MissRachilli
> Its refreshing to see Lemon Squeezy focusing solely on digital products. Giving you all the necessary tools youll need to start selling your products and subscriptions quickly and easily.
> Ian Barnard / @ian_barnard
> Its so good to have a system focused on digital products, and it took me no time at all to allow customers to buy fonts straight from my website. Theres so much potential. I cant wait to see whats next!
> TypeHeist / typeheist.co
> Lemon Squeezy had the perfect combination of features for selling my first software product. Its been so easy to set up, and customer support has been amazing.
> Ross Wintle / turbo-admin.com
> Lemon Squeezy made setting up a store and selling digital products super easy and fun. No more clunky plugins to manage or taxes to worry about. Lemon Squeezy does everything I need and more.
> Mike McAlister / liftoffcourse.com
== Installation ==
This plugin can be installed directly from your site.
1. Log in and navigate to _Plugins → Add New.
2. Type “Lemon Squeezy” into the Search and hit Enter.
3. Locate the Lemon Squeezy plugin in the list of search results and click **Install Now**.
4. Once installed, click the Activate link.
== Frequently Asked Questions ==
= Can the Lemon Squeezy plugin be used with any theme? =
Absolutely! The Lemon Squeezy plugin integrates seamlessly with the WordPress block editor to bring your Lemon Squeezy products to any post or page.
= Do you need coding skills to Lemon Squeezy? =
Absolutely not. You can create and sell your digital products easy-peasy style. Within minutes you can add your products and start making money.
= What kind of products can I sell use Lemon Squeezy? =
Any digital product you can dream of. Digital downloads, licensed software, ebooks, themes, plugins, photos, video files, audio files, courses, memberships, and more.
== Screenshots ==
1. The Lemon Squeezy Dashboard
2. Viewing an order in Lemon Squeezy
3. Connecting your stores in WordPress
4. Using the Lemon Squeezy button block
== Changelog ==
= 1.4.3
= Improve sanitization and security
= 1.4.2 =
- Bump version for republish
= 1.4.1 =
- Fixed oAuth authentication flow
= 1.4.0 =
- Enhanced OAuth flow with improved security and user experience
- Replaced native `fetch` calls with `wp.apiFetch` for better WordPress integration and multisite support
- Improved Lemon Squeezy Buy Button block with enhanced customization options
- Added quantity fields to both Button and Lemon Squeezy blocks
- Added color controls for checkout customization (show logo, media, description, discount)
- Added proper form labels for better accessibility compliance
- Moved Lemon Squeezy menu item to bottom of admin menu for better organization
- Switched to CDN URL for checkout script to improve performance
- General code cleanup and formatting improvements
- Fixed deprecated function calls and improved error handling
- Updated translations and language files
= 1.3.0 =
- Improved performance of Lemon Squeezy in Block Editor on core Buttons
- Added option to pre-fill logged-in user's data on Checkout
- Added option to pre-fill data from URL query string following the same checkout pre-fill pattern
- Added option to define Custom Data when using LS button block
- Added option to define text and background colors for LS button block
- Added option to enter Test API key and with that enable Test Mode
= 1.2.2 =
- Minor bug fix
= 1.2.1 =
- Fixed issue fetching versions for products with lots of files
= 1.2.0 =
- Added support for activating and deactivating license keys
= 1.1.0 =
- Add error codes to REST responses
= 1.0.3 =
- Bug fix with "Connect to Lemon Squeezy" button
= 1.0.2 =
- Fixed paginated results in product selection
= 1.0.1 =
- Readme update
= 1.0 =
- Initial release.

View File

@ -0,0 +1,508 @@
import "./admin.scss";
import lsqIcon from "../../images/ls-icon.svg";
const lsqUrl = "https://www.lemonsqueezy.com/";
const { __ } = wp.i18n;
const {
BaseControl,
Button,
PanelBody,
PanelRow,
Card,
CardMedia,
CardBody,
Notice
} = wp.components;
const { render, Component, Fragment } = wp.element;
class AdminSettings extends Component {
constructor() {
super(...arguments);
this.state = {
isSettingsLoaded: false,
isAPILoading: false,
isAPISaving: false,
isTestAPISaving: false,
lsqApiKey: "",
lsqApiKeyTest: "",
showingTestInput: false,
enteredApiKeyTest: "",
lsqUser: null,
oauth: window.lsq_oauth || {}
};
}
async componentDidMount() {
wp.api.loadPromise.then(() => {
this.settings = new wp.api.models.Settings();
if (false === this.state.isSettingsLoaded) {
this.settings.fetch().then(response => {
this.setState({
lsqApiKey: response.lsq_api_key,
lsqApiKeyTest: response.lsq_api_key_test,
isSettingsLoaded: true
});
this.checkApi();
});
}
});
}
removeTestKey() {
this.setState({ isTestAPISaving: true });
return wp
.apiFetch({
path: "lsq/v1/delete_test_key",
method: "DELETE"
})
.then(response => {
if (true == response.success) {
this.setState({
lsqApiKeyTest: "",
isTestAPISaving: false
});
} else {
this.setState({
isTestAPISaving: false
});
if (response.error) {
alert(response.error);
}
}
});
}
saveTestApiKey() {
this.setState({ isTestAPISaving: true });
return wp
.apiFetch({
path: "lsq/v1/save_test_key",
method: "POST",
data: { test_key: this.state.enteredApiKeyTest }
})
.then(response => {
if (true == response.success) {
this.setState({
lsqApiKeyTest: this.state.enteredApiKeyTest,
isTestAPISaving: false
});
} else {
this.setState({
isTestAPISaving: false,
lsqApiKeyTest: ""
});
if (response.error) {
alert(response.error);
}
}
});
}
checkApi() {
this.setState({
isAPILoading: true
});
return wp
.apiFetch({
path: "lsq/v1/validate"
})
.then(response => {
if (true == response.success) {
this.setState({
isAPILoading: false,
lsqUser: response.user
});
} else {
this.setState({
isAPILoading: false,
lsqUser: null
});
}
})
.catch(() => {
this.setState({
isAPILoading: false,
lsqUser: null
});
});
}
changeOptions(option, value) {
this.setState({ isAPISaving: true });
const model = new wp.api.models.Settings({
// eslint-disable-next-line camelcase
[option]: value
});
return model.save().then(response => {
this.setState({
[option]: response[option],
isAPISaving: false
});
});
}
oauthAuthorize() {
window.location.href = window.Lemonsqueezy.oauth_url;
}
oauthDisconnect() {
this.changeOptions("lsq_api_key", "").then(() => {
this.setState({
lsqUser: null
});
});
}
saveTestKey() {
this.saveTestApiKey();
}
render() {
const panelLabel = this.state.lsqUser
? __("Connected to Lemon Squeezy", "lemon-squeezy")
: __("Connect to Lemon Squeezy", "lemon-squeezy");
let buttonLabel = this.state.isAPILoading
? __("Checking...", "lemon-squeezy")
: __("Connect to Lemon Squeezy", "lemon-squeezy");
return (
<Fragment>
<div className="lsq-header">
<div className="lsq-header__logo">
<img src={lsqIcon} className="lsq-header__logo-icon" />
{__("LemonSqueezy.com", "lemon-squeezy")}
</div>
<div className="lsq-header__cta">
{__(
"Want to make money with digital products?",
"lemon-squeezy"
)}
<a
href={lsqUrl}
target="_blank"
rel="noreferrer"
className="lsq-button lsq-button--secondary"
>
{__("Start selling today", "lemon-squeezy")}
</a>
</div>
</div>
<div className="lsq-main">
<div className="lsq-main__column lsq-main__column--left">
<div className="lsq-content lsq-content--intro">
<h1>{__("Connect your store", "lemon-squeezy")}</h1>
<p>
{__(
"The Lemon Squeezy plugin connects your Lemon Squeezy stores to your WordPress site to bring your products right into the block editor.",
"lemon-squeezy"
)}
</p>
</div>
<div className="lsq-content lsq-content--step">
<h2>
{__(
"1. Connect to Lemon Squeezy",
"lemon-squeezy"
)}
</h2>
<p>
{__(
'To get started, use the "Connect to Lemon Squeezy" button on the right. When prompted, click "Authorize" to connect your Lemon Squeezy account with this WordPress site.',
"lemon-squeezy"
)}
</p>
</div>
<div className="lsq-content lsq-content--step">
<h2>
{__(
"2. Add the Lemon Squeezy block and start selling!",
"lemon-squeezy"
)}
</h2>
<p>
{__(
"To add products to your posts or pages, simply add the Lemon Squeezy block and select which product you'd like to insert. Use the block settings to select a checkout link or a checkout overlay.",
"lemon-squeezy"
)}
</p>
</div>
</div>
<div className="lsq-main__column lsq-main__column--right">
<PanelBody className="lsq-panel">
<PanelRow className="lsq-panel__row">
<BaseControl
label={panelLabel}
id="lsq-options-lsq-api"
className="lsq-panel__control"
>
{this.state.oauth.error && (
<Notice
status="error"
className="lsq-notice"
>
An error occurred:&nbsp;
{this.state.oauth.error}
</Notice>
)}
{this.state.lsqUser && (
<Card size="small" className="lsq-card">
<CardMedia>
<div className="lsq-avatar">
<svg
xmlns="http://www.w3.org/2000/svg"
width="80px"
height="80px"
viewBox="0 0 80 80"
version="1.1"
>
<circle
fill={
this.state
.lsqUser
.attributes
.color
}
width="80"
height="80"
cx="40"
cy="40"
r="40"
/>
<text
x="50%"
y="50%"
alignmentBaseline="middle"
textAnchor="middle"
fontSize="32"
fontWeight="400"
dy=".1em"
dominantBaseline="middle"
fill="#ffffff"
>
{this.state.lsqUser.attributes.name
.charAt(0)
.toUpperCase()}
</text>
</svg>
{this.state.lsqUser
.attributes
.avatar_url && (
<img
src={
this.state
.lsqUser
.attributes
.avatar_url
}
/>
)}
</div>
</CardMedia>
<CardBody className="lsq-card__body">
<p>Connected as:</p>
<h3>
{
this.state.lsqUser
.attributes.name
}
</h3>
<div>
{
this.state.lsqUser
.attributes.email
}
</div>
</CardBody>
</Card>
)}
<div className="lsq-panel__buttons">
{this.state.lsqUser && (
<>
<Button
isPrimary
isBusy={
this.state.isAPISaving
}
disabled={
this.state.isAPISaving
}
onClick={() =>
this.oauthDisconnect()
}
className="lsq-button lsq-button--primary"
>
Disconnect from Lemon
Squeezy
</Button>
{!this.state.lsqApiKeyTest && (
<>
{!this.state
.showingTestInput && (
<Button
onClick={() =>
this.setState(
{
showingTestInput: true
}
)
}
isSmall
>
Need to Test?
Enter your Test
Key
</Button>
)}
{this.state
.showingTestInput && (
<>
<input
className={
"lsq-input"
}
onChange={el => {
this.setState(
{
enteredApiKeyTest:
el
.target
.value
}
);
}}
type={
"text"
}
placeholder={
"Enter your Test API Key"
}
/>
<Button
isBusy={
this
.state
.isTestAPISaving
}
isSecondary
onClick={() =>
this.saveTestKey()
}
>
Save Test
API Key
</Button>
<Button
onClick={() =>
this.setState(
{
showingTestInput: false
}
)
}
>
Cancel
</Button>
<div>
<br />
<Button
isLink
target={
"_blank"
}
href={
"https://docs.lemonsqueezy.com/help/getting-started/test-mode"
}
>
Read
about
the test
mode.
</Button>
</div>
</>
)}
</>
)}
{this.state.lsqApiKeyTest && (
<>
<p>
You&apos;re on Test
Mode.
</p>
<Button
isBusy={
this.state
.isTestAPISaving
}
isSecondary
onClick={() =>
this.removeTestKey()
}
>
Remove Test Mode
</Button>
</>
)}
</>
)}
{!this.state.lsqUser && (
<Button
isPrimary
isBusy={
this.state.isAPILoading ||
!this.state.isSettingsLoaded
}
disabled={
this.state.isAPILoading ||
!this.state.isSettingsLoaded
}
onClick={() =>
this.oauthAuthorize()
}
className="lsq-button lsq-button--primary"
>
{buttonLabel}
</Button>
)}
</div>
<div className="lsq-panel__footer">
<p>
&copy; {new Date().getFullYear()}{" "}
Lemon Squeezy, LLC{" "}
<span className="lsq-u-bullet-spacer">
&bull;
</span>{" "}
<a
target="blank"
rel="noreferrer"
href={lsqUrl}
>
LemonSqueezy.com
</a>
</p>
</div>
</BaseControl>
</PanelRow>
</PanelBody>
</div>
</div>
</Fragment>
);
}
}
render(<AdminSettings />, document.getElementById("lsq-plugin"));

View File

@ -0,0 +1,14 @@
@import "scss/vars";
@import "scss/mixins";
@import "scss/global";
@import "scss/header";
@import "scss/button";
@import "scss/main";
@import "scss/content";
@import "scss/panel";
@import "scss/field";
@import "scss/card";
@import "scss/avatar";
@import "scss/utilities";

View File

@ -0,0 +1,27 @@
.lsq-avatar {
position: relative;
width: 80px;
height: 80px;
svg,
img {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
}
svg text {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
color: #ffffff;
line-height: 1;
}
img {
display: block;
border-radius: 100%;
}
}

View File

@ -0,0 +1,89 @@
// Block.
.lsq-button {
position: relative;
background: $c-brand-1 !important;
color: #fff !important;
height: 40px;
line-height: 40px;
white-space: nowrap;
display: inline-block;
padding: 0 20px;
border-radius: $br-sm;
text-decoration: none;
box-shadow: none;
transition: box-shadow 0.25s ease-in-out;
&:hover {
box-shadow: 0 2px 7px rgba(0, 0, 0, 0.2), 0 3px 6px rgba(0, 0, 0, 0.13);
text-decoration: none !important;
}
&:disabled {
opacity: 0.5 !important;
}
&.is-busy::after {
content: "";
position: absolute;
width: 16px;
height: 16px;
top: 0;
right: 16px;
bottom: 0;
margin: auto;
border: 2px solid transparent;
border-top-color: #ffffff;
border-radius: 50%;
animation: button-loading-spinner 1s ease infinite;
}
}
// Modifier.
.lsq-button--secondary {
background: #fff !important;
color: $c-brand-1 !important;
position: relative;
padding-right: 60px;
border-radius: $br-md;
&:before,
&:after {
content: "";
position: absolute;
}
&:before {
right: 20px;
transform: rotate(45deg);
border: 2px solid $c-brand-1;
width: 6px;
height: 6px;
top: 16px;
border-bottom: none;
border-left: none;
}
&:after {
top: 19px;
right: 20px;
height: 2px;
width: 32px;
background: $c-brand-1;
display: block;
}
&:hover {
background: #fff;
color: $c-brand-1;
}
}
@keyframes button-loading-spinner {
from {
transform: rotate(0turn);
}
to {
transform: rotate(1turn);
}
}

View File

@ -0,0 +1,16 @@
.lsq-card {
margin-bottom: 40px;
.lsq-avatar {
margin: 16px auto 0;
}
.lsq-card__body {
p:first-child {
margin-top: 0;
}
h3 {
margin-bottom: 7px;
}
}
}

View File

@ -0,0 +1,50 @@
// Block.
.lsq-content {
margin-bottom: 30px;
&:last-child {
margin-bottom: 0;
}
p {
font-size: 16px;
}
h1 {
font-size: 34px;
font-weight: 400;
line-height: 1.2;
margin-top: 0;
@include breakpoint($bp-sm) {
font-size: 40px;
}
@include breakpoint($bp-md) {
font-size: 46px;
}
}
h2 {
font-size: 18px;
font-weight: 400;
line-height: 1.2;
@include breakpoint($bp-sm) {
font-size: 20px;
}
@include breakpoint($bp-md) {
font-size: 22px;
}
}
}
// Modifiers.
.lsq-content--intro {
margin-bottom: 50px;
p {
font-size: 18px;
}
}

View File

@ -0,0 +1,34 @@
// Block.
.lsq-field-wrapper {
position: relative;
}
// Elements.
.lsq-field-wrapper {
.lsq-field {
padding-right: 40px;
}
}
.lsq-field-wrapper__icon {
position: absolute;
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
border-radius: 10px;
top: 10px;
right: 10px;
font-size: 16px;
transition: none;
&.dashicons-yes {
background: $c-yes-1;
color: $c-yes-2;
}
&.dashicons-no {
background: $c-no-1;
color: $c-no-2;
}
}

View File

@ -0,0 +1,51 @@
body {
background: $c-background;
}
#wpbody-content {
padding-bottom: 0;
}
#lsq-plugin {
margin: 0 0 0 -10px;
font-size: 14px;
min-height: calc(100vh - 32px);
position: relative;
@include breakpoint($bp-sm) {
margin: 0 0 0 -20px;
}
.wp-responsive-open & {
margin: 0 0 0 -30px;
}
&:after {
content: "";
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 50%;
background: #fff;
z-index: -1;
display: none;
@include breakpoint($bp-md) {
display: block;
}
}
a {
color: $c-brand-1;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
#wpfooter {
display: none;
}

View File

@ -0,0 +1,51 @@
// Block.
.lsq-header {
background: $c-brand-1;
padding: 20px 50px 22px;
color: #fff;
display: flex;
align-items: center;
justify-content: space-between;
flex-direction: column;
@include breakpoint($bp-md) {
flex-direction: row;
}
}
// Elements.
.lsq-header__logo {
display: flex;
align-items: center;
margin: 0 0 30px;
@include breakpoint($bp-md) {
margin: 0;
}
}
.lsq-header__logo-icon {
width: 30px;
height: auto;
margin: 2px 10px 0 0;
}
.lsq-header__cta {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
@include breakpoint($bp-md) {
text-align: left;
display: block;
}
.lsq-button {
margin: 10px 0 0;
@include breakpoint($bp-md) {
margin: 0 0 0 20px;
}
}
}

View File

@ -0,0 +1,33 @@
// Block.
.lsq-main {
display: flex;
align-items: flex-start;
flex-direction: column-reverse;
@include breakpoint($bp-md) {
flex-direction: row;
}
}
// Elements.
.lsq-main__column {
width: 100%;
padding: 60px 50px;
box-sizing: border-box;
@include breakpoint($bp-md) {
width: 50%;
}
&--right {
display: flex;
align-items: center;
justify-content: center;
background: #fff;
@include breakpoint($bp-md) {
background: transparent;
height: calc(100vh - 114px);
}
}
}

View File

@ -0,0 +1,5 @@
@mixin breakpoint($breakpoint) {
@media screen and (min-width: $breakpoint) {
@content;
}
}

View File

@ -0,0 +1,66 @@
// Block.
.lsq-panel {
padding: 0 !important;
border: none;
text-align: center;
}
// Elements.
.lsq-panel {
.components-base-control__label {
color: $c-headings;
font-size: 26px;
margin: 0 0 40px;
line-height: 1.2;
max-width: 100%;
}
input[type="text"],
input[type="password"] {
box-sizing: border-box;
height: 40px;
border: 1px solid $c-border;
width: 100%;
line-height: 38px;
box-shadow: $shadow-fields;
border-radius: $br-sm;
text-overflow: ellipsis;
margin: 0 0 20px 0;
max-width: 420px;
}
.lsq-button {
margin: 0 0 20px;
}
.lsq-button {
width: 100%;
max-width: 420px;
}
.lsq-input {
display: block;
}
.error {
color: #f44e4d;
margin-top: -10px;
}
.success {
color: #24bf60;
margin-top: -10px;
}
.reset {
color: #7047eb;
cursor: pointer;
}
.reset:hover {
text-decoration: underline;
}
.lsq-notice {
margin-bottom: 20px;
}
}

View File

@ -0,0 +1,4 @@
.lsq-u-bullet-spacer {
margin: 0 4px;
display: inline-block;
}

View File

@ -0,0 +1,22 @@
// Colors.
$c-brand-1: #7047eb;
$c-background: #f7f7f8;
$c-headings: #1d2327;
$c-border: rgba(10, 10, 11, 0.16);
$c-yes-1: #e7f8f1;
$c-yes-2: #24bf60;
$c-no-1: #fff2f2;
$c-no-2: #f44e4d;
// Shadows.
$shadow-fields: 0 1px 1px rgba(10, 10, 11, 0.06);
// Border radii.
$br-sm: 8px;
$br-md: 20px;
// Breakpoints.
$bp-sm: 782px;
$bp-md: 850px;

View File

@ -0,0 +1 @@
// Silence is golden.

View File

@ -0,0 +1,649 @@
/**
* External Dependencies
*/
import "./styles.editor.scss";
/**
* WordPress Dependencies
*/
const { __ } = wp.i18n;
const { addFilter } = wp.hooks;
const { Fragment, Component } = wp.element;
const { InspectorControls, PanelColorSettings } = wp.editor;
const { createHigherOrderComponent } = wp.compose;
const { ToggleControl, PanelBody, SelectControl, __experimentalNumberControl } =
wp.components;
const NumberControl = __experimentalNumberControl;
// Restrict to specific block names.
const allowedBlocks = ["core/button"];
/**
* Add custom attributes for Lemon Squeezy product selection.
*
* @param {Object} settings Settings for the block.
*
* @return {Object} settings Modified settings.
*/
function extendAttributes(settings) {
/**
* check if object exists for old Gutenberg version compatibility.
* Add allowedBlocks restriction
*/
if (
typeof settings.attributes !== "undefined" &&
allowedBlocks.includes(settings.name)
) {
settings.attributes = Object.assign(settings.attributes, {
overlay: {
type: "boolean",
default: false
},
use_ls: {
type: "boolean",
default: false
},
prefillUserData: {
type: "boolean",
default: false
},
store: {
type: "string",
default: ""
},
product: {
type: "string",
default: ""
},
prefillFromURL: {
type: "boolean",
default: false
},
showLogo: {
type: "boolean",
default: true
},
showMedia: {
type: "boolean",
default: true
},
showDescription: {
type: "boolean",
default: true
},
showDiscount: {
type: "boolean",
default: true
},
quantity: {
type: "number",
default: 1
},
checkoutBackgroundColor: {
type: "string"
},
checkoutLinksColor: {
type: "string"
},
checkoutButtonColor: {
type: "string"
},
checkoutButtonTextColor: {
type: "string"
},
checkoutTermsPrivacyColor: {
type: "string"
}
});
}
return settings;
}
const extendControls = createHigherOrderComponent(BlockEdit => {
return class Edit extends Component {
componentDidMount() {
const { use_ls } = this.props.attributes;
// Set initial state if there is non available from higher order component.
this.setState({
products: [],
stores: [],
checkingApi: false
});
if (use_ls) {
this.getStores();
this.checkApi();
}
}
getStores() {
return wp
.apiFetch({
path: "lsq/v1/stores"
})
.then(response => {
if (true == response.success) {
this.setState({
stores: response.stores
});
if (response.stores.length) {
let selectedStoreIndex = response.stores.findIndex(
store =>
store.value == this.props.attributes.store
);
if (selectedStoreIndex === -1) {
selectedStoreIndex = 0;
}
this.getProducts(
response.stores[selectedStoreIndex].value
);
}
}
});
}
checkApi() {
this.setState({
checkingApi: true
});
return wp
.apiFetch({
path: "lsq/v1/validate"
})
.then(response => {
let isApiConnectable = false;
if (true == response.success) {
isApiConnectable = true;
}
this.setState({
isApiConnectable,
checkingApi: false
});
});
}
getProducts(store_id) {
this.setState({
products: [],
isLoadingProducts: true
});
return wp
.apiFetch({
path: `lsq/v1/products?store_id=${store_id}`
})
.then(response => {
if (true == response.success) {
this.setState({
products: response.products
});
if (response.products.length) {
let selectedProductIndex =
response.products.findIndex(
product =>
product.value ==
this.props.attributes.product
);
if (selectedProductIndex === -1) {
selectedProductIndex = 0;
}
this.props.setAttributes({
product:
response.products[selectedProductIndex]
.value
});
}
}
})
.finally(() => {
this.setState({
isLoadingProducts: false
});
});
}
onChangeProduct = product => {
this.props.setAttributes({ product: product });
};
onChangeStore = store => {
this.props.setAttributes({ store });
this.getProducts(store);
};
onChangeOverlay = overlay => {
this.props.setAttributes({ overlay: overlay });
};
onChangeUserData = prefillUserData => {
this.props.setAttributes({ prefillUserData });
};
changeUseLS = use_ls => {
this.props.setAttributes({ use_ls: use_ls });
if (use_ls && !this.state.stores.length) {
this.getStores();
this.checkApi();
}
};
onChangeURLData = prefillFromURL => {
this.props.setAttributes({ prefillFromURL });
};
onAttributeChange = (attribute, value) => {
this.props.setAttributes({ [attribute]: value });
};
render() {
const { attributes } = this.props;
const {
store,
product,
overlay,
use_ls,
prefillUserData,
prefillFromURL,
showLogo,
showMedia,
showDescription,
showDiscount,
quantity,
checkoutBackgroundColor,
checkoutLinksColor,
checkoutButtonColor,
checkoutButtonTextColor,
checkoutTermsPrivacyColor
} = attributes;
// If it's not a core button, do not include settings panel.
if (this.props.name !== "core/button") {
return <BlockEdit {...this.props} />;
}
const settings = () => {
return this.state ? (
[
this.state.isApiConnectable ? (
<Fragment>
<SelectControl
label={__("Select Store", "lemon-squeezy")}
value={store}
options={this.state.stores}
onChange={this.onChangeStore}
/>
{this.state.isLoadingProducts ? (
<p
style={{
fontSize: "14px",
color: "rgb(117, 117, 117)"
}}
>
{__("Loading...", "lemon-squeezy")}
</p>
) : this.state.products.length ? (
<SelectControl
label={__("Product", "lemon-squeezy")}
value={product}
options={this.state.products}
onChange={this.onChangeProduct}
/>
) : (
<p
style={{
fontSize: "14px",
color: "rgb(117, 117, 117)"
}}
>
{__(
"No products found",
"lemon-squeezy"
)}
</p>
)}
<NumberControl
label={__("Quantity", "lemon-squeezy")}
__next40pxDefaultSize
isShiftStepEnabled={true}
shiftStep={1}
value={quantity}
onChange={this.onAttributeChange.bind(
this,
"quantity"
)}
/>
<ToggleControl
label={__(
"Use checkout overlay?",
"lemon-squeezy"
)}
checked={overlay}
help={
overlay
? __(
"Your checkout will be opened in a modal window.",
"lemon-squeezy"
)
: __(
"Your customer will be redirected to your checkout page.",
"lemon-squeezy"
)
}
onChange={this.onChangeOverlay}
/>
<ToggleControl
label={__(
"Pre-fill User Data",
"lemon-squeezy"
)}
checked={prefillUserData}
help={
prefillUserData
? __(
"If logged-in, pre-fill user's data on checkout.",
"lemon-squeezy"
)
: __(
"It won't pre-fill user's data on checkout.",
"lemon-squeezy"
)
}
onChange={this.onChangeUserData}
/>
<ToggleControl
label={__(
"Pre-fill from URL",
"lemon-squeezy"
)}
checked={prefillFromURL}
help={
prefillFromURL
? __(
"If there are checkout query strings in URL, it'll pre-fill the checkout.",
"lemon-squeezy"
)
: __(
"It won't pre-fill URL data on checkout.",
"lemon-squeezy"
)
}
onChange={this.onChangeURLData}
/>
<ToggleControl
label={__("Show Logo", "lemon-squeezy")}
checked={showLogo}
help={
showLogo
? __(
"Show the Lemon Squeezy logo in the checkout.",
"lemon-squeezy"
)
: __(
"It won't show the Lemon Squeezy logo in the checkout.",
"lemon-squeezy"
)
}
onChange={this.onAttributeChange.bind(
this,
"showLogo"
)}
/>
<ToggleControl
label={__("Show Media", "lemon-squeezy")}
help={
showMedia
? __(
"Show the product media in the checkout.",
"lemon-squeezy"
)
: __(
"It won't show the product media in the checkout.",
"lemon-squeezy"
)
}
checked={showMedia}
onChange={this.onAttributeChange.bind(
this,
"showMedia"
)}
/>
<ToggleControl
label={__(
"Show Description",
"lemon-squeezy"
)}
help={
showDescription
? __(
"Show the product description in the checkout.",
"lemon-squeezy"
)
: __(
"It won't show the product description in the checkout.",
"lemon-squeezy"
)
}
checked={showDescription}
onChange={this.onAttributeChange.bind(
this,
"showDescription"
)}
/>
<ToggleControl
label={__("Show Discount", "lemon-squeezy")}
help={
showDiscount
? __(
"Show the product discount in the checkout.",
"lemon-squeezy"
)
: __(
"It won't show the product discount in the checkout.",
"lemon-squeezy"
)
}
checked={showDiscount}
onChange={this.onAttributeChange.bind(
this,
"showDiscount"
)}
/>
<PanelColorSettings
title={__(
"Checkout colors",
"lemon-squeezy"
)}
colorSettings={[
{
value: checkoutBackgroundColor,
onChange:
this.onAttributeChange.bind(
this,
"checkoutBackgroundColor"
),
label: __(
"Background",
"lemon-squeezy"
)
},
{
value: checkoutLinksColor,
onChange:
this.onAttributeChange.bind(
this,
"checkoutLinksColor"
),
label: __("Links", "lemon-squeezy")
},
{
value: checkoutButtonColor,
onChange:
this.onAttributeChange.bind(
this,
"checkoutButtonColor"
),
label: __("Button", "lemon-squeezy")
},
{
value: checkoutButtonTextColor,
onChange:
this.onAttributeChange.bind(
this,
"checkoutButtonTextColor"
),
label: __(
"Button text",
"lemon-squeezy"
)
},
{
value: checkoutTermsPrivacyColor,
onChange:
this.onAttributeChange.bind(
this,
"checkoutTermsPrivacyColor"
),
label: __(
"Terms + Privacy",
"lemon-squeezy"
)
}
]}
/>
</Fragment>
) : (
<p>
{this.state.checkingApi && (
<small>
{__(
"Checking connection status",
"lemon-squeezy"
)}
</small>
)}
{!this.state.checkingApi && (
<small>
{__(
"Uh oh! Looks like you haven't connected your store yet! Please visit the",
"lemon-squeezy"
)}{" "}
<a
href={
/*global lsData*/ /*eslint no-undef: "error"*/ lsData.settings_url
}
>
{__(
"Lemon Squeezy Settings",
"lemon-squeezy"
)}
</a>{" "}
{__(
"and connect to Lemon Squeezy.",
"lemon-squeezy"
)}
</small>
)}
</p>
)
]
) : (
<p>
<small>
{__(
"We're fetching your data, hold on for a second!",
"lemon-squeezy"
)}
</small>
</p>
);
};
return (
<Fragment>
<BlockEdit {...this.props} />
<InspectorControls>
<PanelBody
title={__("Lemon Squeezy", "lemon-squeezy")}
initialOpen={false}
>
<Fragment>
<p>
<ToggleControl
label={__(
"Apply Lemon Squeezy Checkout",
"lemon-squeezy"
)}
checked={use_ls}
help={
use_ls
? __(
"Your button will be used for Lemon Squeezy Checkout.",
"lemon-squeezy"
)
: __(
"Your button will not be used for Lemon Squeezy Checkout.",
"lemon-squeezy"
)
}
onChange={this.changeUseLS}
/>
</p>
</Fragment>
{use_ls && settings()}
</PanelBody>
</InspectorControls>
</Fragment>
);
}
};
}, "extendControls");
/**
* Add custom element class in save element.
*
* @param {Object} extraProps Block element.
* @param {Object} blockType Blocks object.
* @param {Object} attributes Blocks attributes.
*
* @return {Object} extraProps Modified block element.
*/
function saveExtendedOptions(extraProps, blockType, attributes) {
const { overlay, product } = attributes;
if (allowedBlocks.includes(blockType.name)) {
extraProps.overlay = overlay;
extraProps.product = product;
}
return extraProps;
}
//add filters
addFilter(
"blocks.registerBlockType",
"lemon-squeezy/custom-attributes",
extendAttributes
);
addFilter(
"editor.BlockEdit",
"lemon-squeezy/custom-advanced-control",
extendControls
);
addFilter(
"blocks.getSaveContent.extraProps",
"lemon-squeezy/saveExtendedOptions",
saveExtendedOptions
);

View File

@ -0,0 +1 @@
import "./style.scss";

View File

@ -0,0 +1,674 @@
import lsqIcon from "../../../images/ls-icon.svg";
import { Component, Fragment } from "@wordpress/element";
import {
RichText,
withColors,
PanelColorSettings,
InspectorControls
} from "@wordpress/block-editor";
import {
SelectControl,
ToggleControl,
TextControl,
__experimentalNumberControl as NumberControl,
BaseControl,
Button
} from "@wordpress/components";
import { __ } from "@wordpress/i18n";
class Edit extends Component {
constructor(props) {
super(props);
this.state = {
stores: [],
products: [],
isCheckingApi: true,
isApiConnectable: false,
isLoadingProducts: false,
newCustomDataKey: "",
newCustomDataValue: ""
};
}
componentDidMount() {
wp.apiFetch({
path: "lsq/v1/stores"
}).then(response => {
if (true == response.success) {
this.setState({
stores: response.stores
});
if (response.stores.length) {
let selectedStoreIndex = response.stores.findIndex(
store => store.value == this.props.attributes.store
);
if (selectedStoreIndex === -1) {
selectedStoreIndex = 0;
}
this.getProducts(response.stores[selectedStoreIndex].value);
}
}
});
this.checkApi();
}
checkApi() {
return wp
.apiFetch({
path: "lsq/v1/validate"
})
.then(response => {
if (true == response.success) {
this.setState({
isApiConnectable: true
});
} else {
this.setState({
isApiConnectable: false
});
}
})
.finally(() => {
this.setState({
isCheckingApi: false
});
});
}
getProducts(store_id) {
this.setState({
products: [],
isLoadingProducts: true
});
return wp
.apiFetch({
path: `lsq/v1/products?store_id=${store_id}`
})
.then(response => {
if (true == response.success) {
this.setState({
products: response.products
});
if (response.products.length) {
let selectedProductIndex = response.products.findIndex(
product =>
product.value == this.props.attributes.product
);
if (selectedProductIndex === -1) {
selectedProductIndex = 0;
}
this.props.setAttributes({
product:
response.products[selectedProductIndex].value
});
}
}
})
.finally(() => {
this.setState({
isLoadingProducts: false
});
});
}
onChangeContent = content => {
this.props.setAttributes({ content });
};
onChangeProduct = product => {
this.props.setAttributes({ product });
};
onChangeStore = store => {
this.props.setAttributes({ store });
this.getProducts(store);
};
onChangeOverlay = overlay => {
this.props.setAttributes({ overlay: overlay });
};
onChangeUserData = prefillUserData => {
this.props.setAttributes({ prefillUserData });
};
onAttributeChange = (attribute, value) => {
this.props.setAttributes({ [attribute]: value });
};
onChangeURLData = prefillFromURL => {
this.props.setAttributes({ prefillFromURL });
};
handleRemoveCustomData = index => {
const customData = [...this.props.attributes.customData];
customData.splice(index, 1);
this.props.setAttributes({ customData });
};
handleCustomDataKeyChange = (data, index) => {
const customData = [...this.props.attributes.customData];
customData[index].key = data;
this.props.setAttributes({ customData });
};
handleCustomDataValueChange = (data, index) => {
const customData = [...this.props.attributes.customData];
customData[index].value = data;
this.props.setAttributes({ customData });
};
handleAddCustomData() {
if (!this.state.newCustomDataKey || !this.state.newCustomDataValue) {
alert("Please Insert Key & Value");
return;
}
const customData = [...this.props.attributes.customData];
customData.push({
key: this.state.newCustomDataKey,
value: this.state.newCustomDataValue
});
this.setState({ newCustomDataKey: "", newCustomDataValue: "" });
this.props.setAttributes({ customData });
}
render() {
const {
attributes,
textColor,
setTextColor,
backgroundColor,
setBackgroundColor
} = this.props;
const {
content,
store,
product,
overlay,
prefillUserData,
prefillFromURL,
customData,
showLogo,
showMedia,
showDescription,
showDiscount,
quantity,
checkoutBackgroundColor,
checkoutLinksColor,
checkoutButtonColor,
checkoutButtonTextColor,
checkoutTermsPrivacyColor
} = attributes;
let customDataFields = [];
if (customData.length) {
customDataFields = customData.map((data, index) => {
return (
<Fragment key={index}>
<div className={"lemonsqueezy-custom-data-row"}>
<TextControl
placeholder="Examples: user_name, user_id"
value={data.key}
onChange={value =>
this.handleCustomDataKeyChange(value, index)
}
/>
<TextControl
placeholder="Examples: JoshSmith, 123"
value={data.value}
onChange={value =>
this.handleCustomDataValueChange(
value,
index
)
}
/>
<Button
onClick={() =>
this.handleRemoveCustomData(index)
}
variant="secondary"
size="small"
>
- Remove
</Button>
</div>
</Fragment>
);
});
}
return (
<div className="lsq-block">
<h4>
<img src={lsqIcon} />
{__("Lemon Squeezy Buy Button", "lemon-squeezy")}
</h4>
{this.state && !this.state.isCheckingApi ? (
[
this.state.isApiConnectable ? (
<Fragment>
<InspectorControls>
<PanelColorSettings
title={__(
"Button colors",
"lemon-squeezy"
)}
colorSettings={[
{
value: textColor.color,
onChange: setTextColor,
label: __(
"Text",
"lemon-squeezy"
)
},
{
value: backgroundColor.color,
onChange: setBackgroundColor,
label: __(
"Background",
"lemon-squeezy"
)
}
]}
/>
<PanelColorSettings
title={__(
"Checkout colors",
"lemon-squeezy"
)}
colorSettings={[
{
value: checkoutBackgroundColor,
onChange:
this.onAttributeChange.bind(
this,
"checkoutBackgroundColor"
),
label: __(
"Background",
"lemon-squeezy"
)
},
{
value: checkoutLinksColor,
onChange:
this.onAttributeChange.bind(
this,
"checkoutLinksColor"
),
label: __(
"Links",
"lemon-squeezy"
)
},
{
value: checkoutButtonColor,
onChange:
this.onAttributeChange.bind(
this,
"checkoutButtonColor"
),
label: __(
"Button",
"lemon-squeezy"
)
},
{
value: checkoutButtonTextColor,
onChange:
this.onAttributeChange.bind(
this,
"checkoutButtonTextColor"
),
label: __(
"Button text",
"lemon-squeezy"
)
},
{
value: checkoutTermsPrivacyColor,
onChange:
this.onAttributeChange.bind(
this,
"checkoutTermsPrivacyColor"
),
label: __(
"Terms + Privacy",
"lemon-squeezy"
)
}
]}
/>
</InspectorControls>
<SelectControl
label={__("Store", "lemon-squeezy")}
value={store}
options={this.state.stores}
onChange={this.onChangeStore}
/>
{this.state.isLoadingProducts ? (
<span
style={{
fontSize: "14px",
color: "rgb(117, 117, 117)"
}}
>
{__("Loading...", "lemon-squeezy")}
</span>
) : this.state.products.length ? (
<SelectControl
label={__("Product", "lemon-squeezy")}
value={product}
options={this.state.products}
onChange={this.onChangeProduct}
/>
) : (
<span
style={{
fontSize: "14px",
color: "rgb(117, 117, 117)"
}}
>
{__(
"No products found",
"lemon-squeezy"
)}
</span>
)}
<BaseControl
label={__("Button text", "lemon-squeezy")}
__nextHasNoMarginBottom
/>
<RichText
placeholder={__(
"Button text",
"lemon-squeezy"
)}
tagName="p"
className="lsq-link-text"
onChange={this.onChangeContent}
value={content}
/>
<NumberControl
label={__("Quantity", "lemon-squeezy")}
__next40pxDefaultSize
isShiftStepEnabled={true}
shiftStep={1}
value={quantity}
onChange={this.onAttributeChange.bind(
this,
"quantity"
)}
/>
<div className="lsq-block-settings">
<ToggleControl
label={__(
"Use checkout overlay?",
"lemon-squeezy"
)}
help={
overlay
? __(
"Your checkout will be opened in a modal window.",
"lemon-squeezy"
)
: __(
"Your customer will be redirected to your checkout page.",
"lemon-squeezy"
)
}
checked={overlay}
onChange={this.onChangeOverlay}
/>
<ToggleControl
label={__(
"Pre-fill User Data",
"lemon-squeezy"
)}
checked={prefillUserData}
help={
prefillUserData
? __(
"If logged-in, pre-fill user's data on checkout.",
"lemon-squeezy"
)
: __(
"It won't pre-fill user's data on checkout.",
"lemon-squeezy"
)
}
onChange={this.onChangeUserData}
/>
<ToggleControl
label={__(
"Pre-fill from URL",
"lemon-squeezy"
)}
checked={prefillFromURL}
help={
prefillFromURL
? __(
"If there are checkout query strings in URL, it'll pre-fill the checkout.",
"lemon-squeezy"
)
: __(
"It won't pre-fill URL data on checkout.",
"lemon-squeezy"
)
}
onChange={this.onChangeURLData}
/>
<ToggleControl
label={__("Show Logo", "lemon-squeezy")}
checked={showLogo}
help={
showLogo
? __(
"Show the Lemon Squeezy logo in the checkout.",
"lemon-squeezy"
)
: __(
"It won't show the Lemon Squeezy logo in the checkout.",
"lemon-squeezy"
)
}
onChange={this.onAttributeChange.bind(
this,
"showLogo"
)}
/>
<ToggleControl
label={__(
"Show Media",
"lemon-squeezy"
)}
help={
showMedia
? __(
"Show the product media in the checkout.",
"lemon-squeezy"
)
: __(
"It won't show the product media in the checkout.",
"lemon-squeezy"
)
}
checked={showMedia}
onChange={this.onAttributeChange.bind(
this,
"showMedia"
)}
/>
<ToggleControl
label={__(
"Show Description",
"lemon-squeezy"
)}
help={
showDescription
? __(
"Show the product description in the checkout.",
"lemon-squeezy"
)
: __(
"It won't show the product description in the checkout.",
"lemon-squeezy"
)
}
checked={showDescription}
onChange={this.onAttributeChange.bind(
this,
"showDescription"
)}
/>
<ToggleControl
label={__(
"Show Discount",
"lemon-squeezy"
)}
help={
showDiscount
? __(
"Show the product discount in the checkout.",
"lemon-squeezy"
)
: __(
"It won't show the product discount in the checkout.",
"lemon-squeezy"
)
}
checked={showDiscount}
onChange={this.onAttributeChange.bind(
this,
"showDiscount"
)}
/>
</div>
<p>
<small
className={
"lemonsqueezy-custom-data-header"
}
>
<strong>Custom Data</strong>
<br />
<Button
size="small"
variant="link"
href={
"https://docs.lemonsqueezy.com/help/checkout/passing-custom-data"
}
target={"_blank"}
>
Read more about custom data
</Button>
</small>
</p>
<div>
<div
className={
"lemonsqueezy-custom-data-row"
}
>
<TextControl
label={__(
"Data Key",
"lemon-squeezy"
)}
placeholder={__(
"Data Key",
"lemon-squeezy"
)}
value={this.state.newCustomDataKey}
onChange={val =>
this.setState({
newCustomDataKey: val
})
}
/>
<TextControl
label={__(
"Data Value",
"lemon-squeezy"
)}
placeholder={__(
"Data Value",
"lemon-squeezy"
)}
value={
this.state.newCustomDataValue
}
onChange={val =>
this.setState({
newCustomDataValue: val
})
}
/>
<Button
onClick={() =>
this.handleAddCustomData()
}
variant="secondary"
size="small"
>
+ Add Data
</Button>
</div>
{customDataFields}
</div>
</Fragment>
) : (
<p>
<small>
{__(
"Uh oh! Looks like you haven't connected your store yet! Please visit the",
"lemon-squeezy"
)}{" "}
<a
href={
/*global lsData*/ /*eslint no-undef: "error"*/ lsData.settings_url
}
>
{__(
"Lemon Squeezy Settings",
"lemon-squeezy"
)}
</a>{" "}
{__(
"and connect to Lemon Squeezy.",
"lemon-squeezy"
)}
</small>
</p>
)
]
) : (
<p>
<small>
{__(
"We're fetching your data, hold on for a second!",
"lemon-squeezy"
)}
</small>
</p>
)}
</div>
);
}
}
export default withColors("backgroundColor", { textColor: "color" })(Edit);

View File

@ -0,0 +1,195 @@
import "./styles.editor.scss";
import { registerBlockType } from "@wordpress/blocks";
import { getColorClassName } from "@wordpress/block-editor";
import { __ } from "@wordpress/i18n";
import Edit from "./edit";
const attributes = {
content: {
type: "string"
},
overlay: {
type: "boolean"
},
store: {
type: "string"
},
product: {
type: "string"
},
textColor: {
type: "string"
},
customTextColor: {
type: "string"
},
backgroundColor: {
type: "string"
},
customBackgroundColor: {
type: "string"
},
prefillUserData: {
type: "boolean",
default: false
},
prefillFromURL: {
type: "boolean",
default: false
},
showLogo: {
type: "boolean",
default: true
},
showMedia: {
type: "boolean",
default: true
},
showDescription: {
type: "boolean",
default: true
},
showDiscount: {
type: "boolean",
default: true
},
quantity: {
type: "number",
default: 1
},
customData: {
type: "array",
default: []
},
checkoutBackgroundColor: {
type: "string"
},
checkoutLinksColor: {
type: "string"
},
checkoutButtonColor: {
type: "string"
},
checkoutButtonTextColor: {
type: "string"
},
checkoutTermsPrivacyColor: {
type: "string"
}
};
registerBlockType("lemonsqueezy/ls-button", {
title: "Lemon Squeezy",
description: __("The Lemon Squeezy Product Block", "lemon-squeezy"),
category: "lemonsqueezy",
icon: (
<svg
width="118"
height="160"
viewBox="0 0 118 160"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M39.5904 98.2021L82.512 118.046C87.8317 120.507 91.5868 124.636 93.6147 129.373C98.7439 141.369 91.7337 153.638 80.7288 158.05C69.7222 162.46 57.9919 159.622 52.6582 147.147L33.9787 103.35C32.5312 99.9554 36.1675 96.6196 39.5904 98.2021"
fill="#000000"
/>
<path
d="M42.1685 85.3576L86.4746 68.6093C101.2 63.0429 117.285 73.5749 117.068 88.8779C117.064 89.0776 117.061 89.2773 117.056 89.4787C116.738 104.381 101.1 114.396 86.6984 109.124L42.2105 92.8416C38.6616 91.5435 38.6354 86.693 42.1685 85.3576"
fill="#000000"
/>
<path
d="M39.6849 79.5563L83.2393 61.0496C97.7126 54.8992 101.386 36.4398 90.0502 25.7741C89.9017 25.6336 89.7531 25.4949 89.6027 25.3561C78.4895 15.0407 60.1177 18.6727 53.791 32.2595L34.2463 74.237C32.6869 77.5847 36.2112 81.0321 39.6849 79.5563"
fill="#000000"
/>
<path
d="M28.4769 72.243L44.312 28.8235C46.2753 23.4399 45.9116 17.9496 43.882 13.2125C38.7423 1.22159 24.8232 -2.64901 13.8201 1.76994C2.81875 6.19058 -3.39781 16.2301 1.9464 28.7L20.7482 72.4494C22.2062 75.8394 27.2147 75.7057 28.4769 72.243"
fill="#000000"
/>
</svg>
),
keywords: [
__("ecommerce", "lemon-squeezy"),
__("product", "lemon-squeezy"),
__("digital", "lemon-squeezy"),
__("digital products", "lemon-squeezy")
],
attributes,
deprecated: [
{
attributes,
save: ({ attributes }) => {
const { content, overlay, product } = attributes;
let link = product;
let className = ["wp-block-button__link"];
if (overlay) {
className.push("lemonsqueezy-button");
link = product + "?embed=1";
}
return (
<div className="wp-block-buttons">
<div className="wp-block-button">
<a className={className.join(" ")} href={link}>
{content}
</a>
</div>
</div>
);
}
}
],
edit: Edit,
save: ({ attributes }) => {
const {
content,
overlay,
product,
textColor,
customTextColor,
backgroundColor,
customBackgroundColor
} = attributes;
let link = product;
let divStyles = {};
let className = ["wp-block-button__link"];
if (overlay) {
className.push("lemonsqueezy-button");
link = product + "?embed=1";
}
if (textColor != undefined) {
className.push(getColorClassName("color", textColor));
}
if (backgroundColor != undefined) {
className.push(
getColorClassName("background-color", backgroundColor)
);
}
if (customTextColor != undefined) {
divStyles.color = customTextColor;
}
if (customBackgroundColor != undefined) {
divStyles.backgroundColor = customBackgroundColor;
}
return (
<div className="wp-block-buttons">
<div className="wp-block-button">
<a
style={divStyles}
className={className.join(" ")}
href={link}
>
{content}
</a>
</div>
</div>
);
}
});

View File

@ -0,0 +1 @@
import "./style.scss";

View File

@ -0,0 +1,69 @@
.lsq-block {
padding: 20px 10px;
h4 {
margin-top: 0;
}
h4 img {
vertical-align: -5px;
width: 30px;
margin-right: 5px;
}
.lsq-link-text {
border: 1px solid var(--wp-components-color-gray-600, #949494);
box-sizing: border-box;
box-shadow: 0px 1px 1px rgba(10, 10, 11, 0.06);
font-size: 13px !important;
padding: 5px 10px;
font-weight: 400;
margin-top: 8px;
span {
font-size: 13px;
top: -2px;
}
}
.components-input-control__input {
height: 32px !important;
min-height: 32px !important;
}
.lemonsqueezy-custom-data-header {
display: flex;
justify-content: space-between;
a {
padding: 0;
}
}
.lemonsqueezy-custom-data-row {
display: grid;
grid-template-columns: 1fr 1fr 100px;
grid-gap: 10px;
button {
align-self: end;
height: 30px;
}
.components-base-control__field,
button {
margin-bottom: 8px;
}
}
.lsq-block-settings {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
margin: 20px 0;
}
.components-base-control__label {
margin-bottom: 0;
}
}

View File

@ -0,0 +1,172 @@
<?php
namespace lemonsqueezy;
/**
* Class to handle the admin area of the lemon squeezy plugin.
*/
class LSQ_Admin {
/**
* Contains instance or null
*
* @var object|null
*/
private static $instance = null;
/**
* Returns instance of LSQ_Admin.
*
* @return object
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor for LSQ_Admin.
*/
public function __construct() {
add_action( 'admin_menu', array( $this, 'add_option_menu' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'add_admin_assets' ) );
add_action( 'init', array( $this, 'register_settings' ) );
add_filter( 'option_lsq_api_key', array( $this, 'maybe_return_test_key' ) );
add_filter( 'allowed_redirect_hosts', array( $this, 'allowed_redirect_hosts' ) );
}
public function allowed_redirect_hosts( $hosts ) {
$hosts[] = wp_parse_url( LSQ_APP_URL, PHP_URL_HOST );
return $hosts;
}
/**
* Maybe return Test API key.
*
* @param string $api_key API Key.
*
* @return mixed
*/
public function maybe_return_test_key( $api_key ) {
$test_key = get_option( 'lsq_api_key_test' );
if ( ! $test_key ) {
return $api_key;
}
return $test_key;
}
/**
* Is this a LSQ admin page?
*
* @return bool
*/
public static function is_admin() {
global $current_screen;
if ( ! $current_screen ) {
return false;
}
return 'toplevel_page_lemonsqueezy' === $current_screen->id;
}
/**
* Enqueue admin assets.
*
* @return void
*/
public function add_admin_assets() {
if ( ! self::is_admin() ) {
return;
}
wp_enqueue_script( 'lemonsqueezy-admin-script' );
wp_enqueue_style( 'lemonsqueezy-admin-style' );
wp_localize_script(
'lemonsqueezy-admin-script',
'Lemonsqueezy',
array(
'oauth_url' => wp_nonce_url( admin_url( 'admin.php?page=lemonsqueezy&oauth_authorize=1' ), 'lsq_oauth_authorize' ),
)
);
}
/**
* Callback for outputting lemon squeezy options page.
*
* @return void
*/
public function menu_callback() {
?>
<div id="lsq-plugin"></div>
<style>
.lsq-logo { background-image: url("<?php echo esc_url( LSQ_URL . '/images/ls-logo.svg' ); ?>"); }
</style>
<?php
}
/**
* Register options page.
*
* @return void
*/
public function add_option_menu() {
$hook_suffix = add_menu_page(
'Lemon Squeezy',
'Lemon Squeezy',
'manage_options',
'lemonsqueezy',
array( $this, 'menu_callback' ),
LSQ_URL . '/images/ls-icon.svg',
90
);
wp_register_script( 'lemonsqueezy-admin-script', LSQ_URL . '/build/admin.js', array( 'wp-api', 'wp-i18n', 'wp-components', 'wp-element', 'wp-api-fetch' ), '1.4.0', true );
wp_register_style( 'lemonsqueezy-admin-style', LSQ_URL . '/build/admin.css', array( 'wp-edit-blocks' ), '1.4.0' );
add_action( 'load-' . $hook_suffix, array( $this, 'load_page_hook' ) );
}
/**
* Register settings fpr the otions page.
*
* @return void
*/
public function register_settings() {
register_setting(
'lsq_admin_settings',
'lsq_api_key',
array(
'type' => 'string',
'show_in_rest' => true,
'sanitize_callback' => 'sanitize_text_field',
)
);
register_setting(
'lsq_admin_settings',
'lsq_api_key_test',
array(
'type' => 'string',
'show_in_rest' => true,
'sanitize_callback' => 'sanitize_text_field',
)
);
}
/**
* Processing the settings page.
*
* @return void
*/
public function load_page_hook() {
$lsq_oauth = new LSQ_OAuth( LSQ_OAUTH_CLIENT_ID );
$lsq_oauth->handle_authorize();
$lsq_oauth->handle_callback();
}
}

View File

@ -0,0 +1,181 @@
<?php
namespace lemonsqueezy;
class LSQ_OAuth {
/**
* @var string
*/
protected $client_id;
/**
* @var string
*/
protected $redirect_uri;
/**
* @param string $client_id
* @param string $redirect_uri
*/
public function __construct( $client_id ) {
$this->client_id = $client_id;
$this->redirect_uri = LSQ_APP_URL . '/oauth/callback/wordpress';
}
/**
* Get transient key for OAuth state storage.
*
* @param string $type Type of transient (code or code_verifier).
* @return string
*/
private function get_transient_key( $type ) {
return 'lsq_oauth_' . $type . '_' . get_current_user_id();
}
/**
* Handle OAuth authorization
*
* @return void
*/
public function handle_authorize() {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verification is handled below.
if ( empty( $_GET['oauth_authorize'] ) ) {
return;
}
if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'lsq_oauth_authorize' ) ) {
return;
}
$oauth_code = get_transient( $this->get_transient_key( 'code' ) );
$code_verifier = get_transient( $this->get_transient_key( 'code_verifier' ) );
if ( empty( $oauth_code ) ) {
$oauth_code = wp_generate_password( 40, false );
set_transient( $this->get_transient_key( 'code' ), $oauth_code, HOUR_IN_SECONDS );
}
if ( empty( $code_verifier ) ) {
$code_verifier = wp_generate_password( 128, false );
set_transient( $this->get_transient_key( 'code_verifier' ), $code_verifier, HOUR_IN_SECONDS );
}
$code_challenge = strtr(
rtrim(
base64_encode( hash( 'sha256', $code_verifier, true ) ),
'='
),
'+/',
'-_'
);
$query = http_build_query(
array(
'client_id' => $this->client_id,
'redirect_uri' => $this->redirect_uri,
'response_type' => 'code',
'scope' => '',
'state' => $oauth_code,
'code_challenge' => $code_challenge,
'code_challenge_method' => 'S256',
'prompt' => 'consent',
'return_to' => admin_url( 'admin.php?page=lemonsqueezy&oauth_callback=1' ),
)
);
wp_safe_redirect( LSQ_APP_URL . '/oauth/authorize?' . $query );
exit;
}
/**
* Handle OAuth token exchange
*
* @return void
*/
public function handle_callback() {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- OAuth callback from external provider, state parameter provides CSRF protection.
if ( empty( $_GET['oauth_callback'] ) ) {
return;
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- OAuth callback from external provider, state parameter provides CSRF protection.
if ( ! empty( $_GET['error'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- OAuth callback from external provider.
$error = isset( $_GET['error'] ) ? sanitize_text_field( wp_unslash( $_GET['error'] ) ) : '';
wp_add_inline_script(
'lemonsqueezy-admin-script',
'window.lsq_oauth = ' . wp_json_encode(
array(
'error' => $error,
)
),
'before'
);
return;
}
$oauth_code = get_transient( $this->get_transient_key( 'code' ) );
$code_verifier = get_transient( $this->get_transient_key( 'code_verifier' ) );
if ( empty( $oauth_code ) || empty( $code_verifier ) ) {
return;
}
// phpcs:disable WordPress.Security.NonceVerification.Recommended -- OAuth callback from external provider, state parameter provides CSRF protection.
$code = isset( $_GET['code'] ) ? sanitize_text_field( wp_unslash( $_GET['code'] ) ) : null;
$state = isset( $_GET['state'] ) ? sanitize_text_field( wp_unslash( $_GET['state'] ) ) : null;
// phpcs:enable WordPress.Security.NonceVerification.Recommended
if ( $oauth_code !== $state || ! $code ) {
wp_add_inline_script(
'lemonsqueezy-admin-script',
'window.lsq_oauth = ' . wp_json_encode(
array(
'error' => __( 'Invalid oauth state/code', 'lemon-squeezy' ),
)
),
'before'
);
return;
}
$response = wp_remote_post(
LSQ_APP_URL . '/oauth/token',
array(
'body' => array(
'grant_type' => 'authorization_code',
'client_id' => $this->client_id,
'redirect_uri' => $this->redirect_uri,
'code_verifier' => $code_verifier,
'code' => $code,
),
)
);
// Clean up transients after use.
delete_transient( $this->get_transient_key( 'code' ) );
delete_transient( $this->get_transient_key( 'code_verifier' ) );
if ( is_wp_error( $response ) ) {
wp_add_inline_script(
'lemonsqueezy-admin-script',
'window.lsq_oauth = ' . wp_json_encode(
array(
'error' => $response->get_error_message(),
)
),
'before'
);
return;
}
$data = json_decode( $response['body'] );
if ( ! empty( $data->access_token ) ) {
update_option( 'lsq_api_key', $data->access_token );
}
if ( ! empty( $data->expires_in ) ) {
update_option( 'lsq_api_key_expires', time() + $data->expires_in );
}
}
}

View File

@ -0,0 +1,250 @@
<?php
namespace lemonsqueezy;
/**
* Class to handle rest api connections of the lemon squeezy plugin.
*/
class LSQ_Register_Block {
/**
* Contains instance or null
*
* @var object|null
*/
private static $instance = null;
/**
* Returns instance of LSQ_Rest.
*
* @return object
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor for LSQ_Register_Block.
*/
public function __construct() {
add_action( 'init', array( $this, 'register_blocks' ) );
add_filter( 'render_block', array( $this, 'filter_button_block_markup' ), 10, 2 );
add_filter( 'block_categories_all', array( $this, 'add_block_categories' ), 10, 2 );
}
/**
* Register block category.
*
* @param array $categories given categories.
* @param object $post current post.
* @return array
*/
public function add_block_categories( $categories ) {
return array_merge(
$categories,
array(
array(
'slug' => 'lemonsqueezy',
'title' => __( 'Lemon Squeezy', 'lemon-squeezy' ),
'icon' => 'wordpress',
),
)
);
}
/**
* Register block types.
*
* @param string $block current block.
* @param array $options list of options.
* @return void
*/
public function register_block_type( $block, $options = array() ) {
register_block_type(
'lemonsqueezy/' . $block,
array_merge(
array(
'editor_script' => 'lemonsqueezy-editor-script',
'editor_style' => 'lemonsqueezy-editor-style',
'script' => 'lemonsqueezy-script',
'style' => 'lemonsqueezy-style',
),
$options
)
);
}
/**
* Register lemon squeezy blocks and enqueue assets.
*
* @return void
*/
public function register_blocks() {
wp_register_script( 'lemonsqueezy-editor-script', LSQ_URL . '/build/editor.js', array( 'wp-blocks', 'wp-i18n', 'wp-element', 'wp-editor', 'wp-components', 'lodash', 'wp-blob', 'wp-data', 'wp-html-entities', 'wp-compose', 'wp-block-editor', 'wp-api-fetch' ), '1.4.0', true );
wp_add_inline_script( 'lemonsqueezy-editor-script', 'var lsData = ' . wp_json_encode( array( 'settings_url' => admin_url( 'admin.php?page=lemonsqueezy' ) ) ), 'before' );
wp_register_script( 'lemonsqueezy-script', LSQ_URL . '/build/script.js', array(), '1.4.0', true );
wp_register_style( 'lemonsqueezy-style', LSQ_URL . '/build/style-script.css', array(), '1.4.0' );
wp_register_style( 'lemonsqueezy-editor-style', LSQ_URL . '/build/editor.css', array( 'wp-edit-blocks' ), '1.4.0' );
$this->register_block_type( 'button' );
$this->register_block_type( 'ls-button' );
}
/**
* Add button size class.
*
* @param string $block_content Block content to be rendered.
* @param array $block Block attributes.
* @return string
*/
public function filter_button_block_markup( $block_content = '', $block = array() ) {
if ( isset( $block['blockName'] ) && 'core/button' === $block['blockName'] ) {
$args = wp_parse_args( $block['attrs'] );
if ( empty( $args['product'] ) ) {
return $block_content;
}
// If overlay is activated we have to include the script and add parameter to URL.
if ( ! empty( $args['overlay'] ) ) {
wp_enqueue_script( 'lemonsqueezy-checkout', 'https://assets.lemonsqueezy.com/lemon.js', array(), '1.4.3', true );
}
$purchase_link = $this->get_purchase_link( $args, $block );
$existing_href = $this->get_link_from_button( $block_content );
if ( $existing_href ) {
$block_content = str_replace( 'href="' . $existing_href . '"', 'href="' . $purchase_link . '"', $block_content );
} else {
// No href in sight.
$block_content = str_replace( 'class="wp-block-button__link', ' href="' . $purchase_link . '" class="wp-block-button__link', $block_content );
}
if ( ! empty( $args['overlay'] ) ) {
$block_content = str_replace( 'class="wp-block-button__link', 'class="wp-block-button__link lemonsqueezy-button ', $block_content );
}
}
if ( isset( $block['blockName'] ) && 'lemonsqueezy/ls-button' === $block['blockName'] ) {
$args = wp_parse_args( $block['attrs'] );
if ( ! empty( $args['overlay'] ) ) {
wp_enqueue_script( 'lemonsqueezy-checkout', 'https://assets.lemonsqueezy.com/lemon.js', array(), '1.4.3', true );
}
$existing_href = $this->get_link_from_button( $block_content );
$purchase_link = $this->get_purchase_link( $args, $block );
if ( $existing_href ) {
$block_content = str_replace( 'href="' . $existing_href . '"', 'href="' . $purchase_link . '"', $block_content );
} else {
// No href in sight.
$block_content = str_replace( 'class="wp-block-button__link', ' href="' . $purchase_link . '" class="wp-block-button__link', $block_content );
}
}
return $block_content;
}
protected function get_purchase_link( $args, $block ) {
if ( empty( $args['product'] ) ) {
return false;
}
$link = $args['product'];
if ( ! empty( $args['overlay'] ) && $args['overlay'] ) {
$link = add_query_arg( 'embed', '1', $link );
}
$args = apply_filters( 'lemonsqueezy_purchase_link_args', $args, $block );
if ( ! empty( $args['prefillUserData'] ) && $args['prefillUserData'] && is_user_logged_in() ) {
$user = wp_get_current_user();
$user_full_name = trim( $user->first_name . ' ' . $user->last_name );
$link = add_query_arg( 'checkout[email]', $user->user_email, $link );
if ( $user_full_name ) {
$link = add_query_arg( 'checkout[name]', $user_full_name, $link );
}
}
if ( ! empty( $args['customData'] ) && $args['customData'] ) {
foreach ( $args['customData'] as $custom_data ) {
$link = add_query_arg( 'checkout[custom][' . sanitize_text_field( $custom_data['key'] ) . ']', sanitize_text_field( $custom_data['value'] ), $link );
}
}
if ( isset( $args['showLogo'] ) ) {
$link = add_query_arg( 'logo', $args['showLogo'] ? '1' : '0', $link );
}
if ( isset( $args['showMedia'] ) ) {
$link = add_query_arg( 'media', $args['showMedia'] ? '1' : '0', $link );
}
if ( isset( $args['showDescription'] ) ) {
$link = add_query_arg( 'desc', $args['showDescription'] ? '1' : '0', $link );
}
if ( isset( $args['showDiscount'] ) ) {
$link = add_query_arg( 'discount', $args['showDiscount'] ? '1' : '0', $link );
}
if ( isset( $args['quantity'] ) ) {
$link = add_query_arg( 'quantity', $args['quantity'], $link );
}
$colors = array(
'checkoutBackgroundColor' => 'background_color',
'checkoutLinksColor' => 'links_color',
'checkoutButtonColor' => 'button_color',
'checkoutButtonTextColor' => 'button_text_color',
'checkoutTermsPrivacyColor' => 'terms_privacy_color',
);
foreach ( $colors as $color_key => $color_value ) {
if ( isset( $args[ $color_key ] ) && ! empty( $args[ $color_key ] ) ) {
$link = add_query_arg( $color_value, rawurlencode( $args[ $color_key ] ), $link );
}
}
// phpcs:disable WordPress.Security.NonceVerification.Recommended -- Frontend feature for prefilling checkout from URL params (marketing/affiliate links).
if ( ! empty( $args['prefillFromURL'] ) && $args['prefillFromURL']
&& isset( $_GET['checkout'] ) && is_array( $_GET['checkout'] ) ) {
$checkout_data = isset( $_GET['checkout'] ) ? map_deep( wp_unslash( $_GET['checkout'] ), 'sanitize_text_field' ) : array();
if ( is_array( $checkout_data ) ) {
foreach ( $checkout_data as $checkout_name => $checkout_value ) {
$checkout_name = sanitize_text_field( $checkout_name );
if ( ! is_array( $checkout_value ) ) {
$link = add_query_arg( 'checkout[' . $checkout_name . ']', $checkout_value, $link );
} else {
foreach ( $checkout_value as $sub_checkout_name => $sub_checkout_value ) {
$sub_checkout_name = sanitize_text_field( $sub_checkout_name );
$link = add_query_arg( 'checkout[' . $checkout_name . '][' . $sub_checkout_name . ']', $sub_checkout_value, $link );
}
}
}
}
}
// phpcs:enable WordPress.Security.NonceVerification.Recommended
return apply_filters( 'lemonsqueezy_purchase_link', $link, $args, $block );
}
protected function get_link_from_button( $block_content ) {
$pattern = '/href=["\']([^"\']+)["\']/';
if ( preg_match( $pattern, $block_content, $matches ) ) {
// The extracted href value will be in $matches[1]
return $matches[1];
}
return false;
}
}

View File

@ -0,0 +1,690 @@
<?php
namespace lemonsqueezy;
/**
* Class to handle the rest api requests of the lemon squeezy plugin.
*/
class LSQ_Rest_Controller {
/**
* Contains instance or null
*
* @var object|null
*/
private static $instance = null;
/**
* Returns instance of LSQ_Rest_Controller.
*
* @return object
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor for LSQ_Rest_Controller.
*/
public function __construct() {
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}
/**
* Register the routes for the objects of the controller.
*/
public function register_routes() {
$namespace = 'lsq/v1';
register_rest_route(
$namespace,
'/validate/',
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'validate_key' ),
'args' => array(),
'permission_callback' => function () {
return true;
},
)
);
register_rest_route(
$namespace,
'/delete_test_key/',
array(
'methods' => \WP_REST_Server::DELETABLE,
'callback' => array( $this, 'delete_test' ),
'args' => array(),
'permission_callback' => function () {
return current_user_can( 'manage_options' );
},
)
);
register_rest_route(
$namespace,
'/save_test_key/',
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'save_test' ),
'args' => array(
'test_key' => array(
'description' => 'Test API key.',
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
),
),
'permission_callback' => function () {
return current_user_can( 'manage_options' );
},
)
);
register_rest_route(
$namespace,
'/activate/',
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'activate_key' ),
'args' => array(
'license_key' => array(
'description' => 'License key.',
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
),
'instance_name' => array(
'description' => 'Instance name for the activation.',
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
),
),
'permission_callback' => function () {
return true;
},
)
);
register_rest_route(
$namespace,
'/deactivate/',
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'deactivate_key' ),
'args' => array(
'license_key' => array(
'description' => 'License key.',
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
),
'instance_id' => array(
'description' => 'Instance ID of the existing activation.',
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
),
),
'permission_callback' => function () {
return true;
},
)
);
register_rest_route(
$namespace,
'/stores/',
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_stores' ),
'args' => array(),
'permission_callback' => function () {
return true;
},
)
);
register_rest_route(
$namespace,
'/products/',
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_products' ),
'args' => array(),
'permission_callback' => function () {
return true;
},
)
);
register_rest_route(
$namespace,
'/update/',
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_update' ),
'args' => array(),
'permission_callback' => function () {
return true;
},
)
);
}
/**
* Delete Test API key.
*
* @param \WP_REST_Request $request Full data about the request.
* @return \WP_Error|\WP_REST_Response
*/
public function delete_test() {
$deleted = delete_option( 'lsq_api_key_test' );
return new \WP_REST_Response(
array(
'success' => $deleted,
),
$deleted ? 200 : 400
);
}
/**
* Save Test API key with Lemon Squeezy API.
*
* @param \WP_REST_Request $request Full data about the request.
* @return \WP_Error|\WP_REST_Response
*/
public function save_test( $request ) {
$test_key = $request->get_param( 'test_key' );
$response = wp_remote_get(
LSQ_API_URL . '/v1/users/me',
array(
'headers' => array(
'Authorization' => 'Bearer ' . $test_key,
'Accept' => 'application/vnd.api+json',
'Content-Type' => 'application/vnd.api+json',
'Cache-Control' => 'no-cache',
),
)
);
$is_valid = false;
if ( ! is_wp_error( $response ) ) {
if ( 200 === wp_remote_retrieve_response_code( $response ) ) {
$is_valid = true;
$body = json_decode( $response['body'] );
$user = $body->data;
update_option( 'lsq_api_key_test', $test_key );
} else {
$error_message = wp_remote_retrieve_response_message( $response );
}
} else {
$error_message = $response->get_error_message();
}
return new \WP_REST_Response(
array(
'success' => $is_valid,
'user' => $user,
'error' => $error_message,
),
$is_valid ? 200 : 400
);
}
/**
* Validate API key with Lemon Squeezy API.
*
* @param \WP_REST_Request $request Full data about the request.
* @return \WP_Error|\WP_REST_Response
*/
public function validate_key() {
// Check LS API connection.
$api_key = get_option( 'lsq_api_key' );
$is_valid = false;
$user = null;
$error_message = '';
if ( ! isset( $api_key ) || empty( $api_key ) ) {
return new \WP_REST_Response(
array(
'success' => $is_valid,
'user' => $user,
'error' => __( 'Unauthorized request', 'lemon-squeezy' ),
),
401
);
}
$response = wp_remote_get(
LSQ_API_URL . '/v1/users/me',
array(
'headers' => array(
'Authorization' => 'Bearer ' . $api_key,
'Accept' => 'application/vnd.api+json',
'Content-Type' => 'application/vnd.api+json',
'Cache-Control' => 'no-cache',
),
)
);
if ( ! is_wp_error( $response ) ) {
if ( 200 === wp_remote_retrieve_response_code( $response ) ) {
$is_valid = true;
$body = json_decode( $response['body'] );
$user = $body->data;
} else {
$error_message = wp_remote_retrieve_response_message( $response );
}
} else {
$error_message = $response->get_error_message();
}
return new \WP_REST_Response(
array(
'success' => $is_valid,
'user' => $user,
'error' => $error_message,
),
$is_valid ? 200 : 400
);
}
/**
* Activate license key through Lemon Squeezy API.
*
* @param WP_REST_Request $request Full data about the request.
* @return \WP_REST_Response|\WP_Error
*/
public function activate_key( $request ) {
$license_key = $request->get_param( 'license_key' );
$instance_name = $request->get_param( 'instance_name' );
$is_valid = false;
$error_message = '';
$api_key = get_option( 'lsq_api_key' );
if ( empty( $api_key ) ) {
return new \WP_REST_Response(
array(
'success' => false,
'error' => __( 'Unauthorized request', 'lemon-squeezy' ),
),
401
);
}
$response = wp_remote_post(
LSQ_API_URL . "/v1/licenses/activate?license_key={$license_key}&instance_name={$instance_name}",
array(
'headers' => array(
'Authorization' => 'Bearer ' . $api_key,
'Accept' => 'application/vnd.api+json',
'Content-Type' => 'application/vnd.api+json',
'Cache-Control' => 'no-cache',
),
)
);
$body = json_decode( $response['body'], true );
if ( ! is_wp_error( $response ) ) {
if ( 200 === wp_remote_retrieve_response_code( $response ) ) {
$is_valid = true;
} else {
$error_message = isset( $body['error'] ) ? $body['error'] : wp_remote_retrieve_response_message( $response );
}
} else {
$error_message = $response->get_error_message();
}
return new \WP_REST_Response(
array(
'success' => $is_valid,
'error' => $error_message,
'data' => $body,
),
$is_valid ? 200 : 400
);
}
/**
* Deactivate license key through Lemon Squeezy API.
*
* @param WP_REST_Request $request Full data about the request.
* @return \WP_REST_Response|\WP_Error
*/
public function deactivate_key( $request ) {
$license_key = $request->get_param( 'license_key' );
$instance_name = $request->get_param( 'instance_id' );
$is_valid = false;
$error_message = null;
$api_key = get_option( 'lsq_api_key' );
if ( empty( $api_key ) ) {
return new \WP_REST_Response(
array(
'success' => false,
'error' => __( 'Unauthorized request', 'lemon-squeezy' ),
),
401
);
}
$response = wp_remote_post(
LSQ_API_URL . "/v1/licenses/deactivate?license_key={$license_key}&instance_id={$instance_name}",
array(
'headers' => array(
'Authorization' => 'Bearer ' . $api_key,
'Accept' => 'application/vnd.api+json',
'Content-Type' => 'application/vnd.api+json',
'Cache-Control' => 'no-cache',
),
)
);
if ( ! is_wp_error( $response ) ) {
$body = json_decode( $response['body'], true );
if ( 200 === wp_remote_retrieve_response_code( $response ) ) {
$is_valid = $body['deactivated'];
} else {
$error_message = isset( $body['error'] ) ? $body['error'] : wp_remote_retrieve_response_message( $response );
}
} else {
$error_message = $response->get_error_message();
}
return new \WP_REST_Response(
array(
'success' => $is_valid,
'error' => $error_message,
),
$is_valid ? 200 : 400
);
}
/**
* Get products from the Lemon Squeezy API.
*
* @param \WP_REST_Request $request Full data about the request.
* @return \WP_Error|\WP_REST_Response
*/
public function get_stores() {
// Check LS API connection.
$api_key = get_option( 'lsq_api_key' );
$error_message = '';
if ( ! isset( $api_key ) || empty( $api_key ) ) {
return new \WP_REST_Response(
array(
'success' => false,
'error' => __( 'Unauthorized request', 'lemon-squeezy' ),
'error_code' => 'unauthorized',
),
401
);
}
// Get stores.
$response = wp_remote_get(
LSQ_API_URL . '/v1/stores/',
array(
'headers' => array(
'Authorization' => 'Bearer ' . $api_key,
'Accept' => 'application/vnd.api+json',
'Content-Type' => 'application/vnd.api+json',
'Cache-Control' => 'no-cache',
),
)
);
if ( ! is_wp_error( $response ) ) {
if ( 200 === wp_remote_retrieve_response_code( $response ) ) {
$store_data = json_decode( $response['body'] );
$stores = array();
// Build product list.
if ( isset( $store_data ) && ! empty( $store_data ) ) {
foreach ( $store_data->data as $store ) {
$stores[] = array(
'label' => $store->attributes->name,
'value' => $store->id,
);
}
}
return new \WP_REST_Response(
array(
'success' => true,
'stores' => $stores,
),
200
);
} else {
$error_message = wp_remote_retrieve_response_message( $response );
}
} else {
$error_message = $response->get_error_message();
}
return new \WP_REST_Response(
array(
'success' => false,
'error' => $error_message,
'error_code' => 'api_error',
),
400
);
}
/**
* Get products from the Lemon Squeezy API.
*
* @param \WP_REST_Request $request Full data about the request.
* @return \WP_Error|\WP_REST_Response
*/
public function get_products( $request ) {
// Check LS API connection.
$api_key = get_option( 'lsq_api_key' );
$error_message = '';
if ( ! isset( $api_key ) || empty( $api_key ) ) {
return new \WP_REST_Response(
array(
'success' => false,
'error' => __( 'Unauthorized request', 'lemon-squeezy' ),
'error_code' => 'unauthorized',
),
401
);
}
$store_id = filter_var( $request->get_param( 'store_id' ), FILTER_SANITIZE_FULL_SPECIAL_CHARS );
$page_size = rawurlencode( 'page[size]' );
$response = wp_remote_get(
LSQ_API_URL . "/v1/stores/{$store_id}/products?" . $page_size . '=100',
array(
'headers' => array(
'Authorization' => 'Bearer ' . $api_key,
'Accept' => 'application/vnd.api+json',
'Content-Type' => 'application/vnd.api+json',
'Cache-Control' => 'no-cache',
),
)
);
if ( ! is_wp_error( $response ) ) {
if ( 200 === wp_remote_retrieve_response_code( $response ) ) {
$product_data = json_decode( $response['body'] );
$products = array();
foreach ( $product_data->data as $product ) {
if ( 'published' !== $product->attributes->status ) {
continue;
}
$products[] = array(
'label' => $product->attributes->name,
'value' => $product->attributes->buy_now_url,
);
}
return new \WP_REST_Response(
array(
'success' => true,
'products' => $products,
),
200
);
} else {
$error_message = wp_remote_retrieve_response_message( $response );
}
} else {
$error_message = $response->get_error_message();
}
return new \WP_REST_Response(
array(
'success' => false,
'error' => $error_message,
'error_code' => 'api_error',
),
400
);
}
/**
* Validate and return a software update from the Lemon Squeezy API.
*
* @param \WP_REST_Request $request Full data about the request.
* @return \WP_Error|\WP_REST_Response
*/
public function get_update( $request ) {
$api_key = get_option( 'lsq_api_key' );
if ( empty( $api_key ) ) {
return new \WP_REST_Response(
array(
'success' => false,
'error' => __( 'Unauthorized request', 'lemon-squeezy' ),
'error_code' => 'unauthorized',
),
401
);
}
$license_key = filter_var( $request->get_param( 'license_key' ), FILTER_SANITIZE_FULL_SPECIAL_CHARS );
if ( empty( $license_key ) ) {
return new \WP_REST_Response(
array(
'success' => false,
'error' => __( 'Missing license_key', 'lemon-squeezy' ),
'error_code' => 'missing_license_key',
),
401
);
}
$lsq_updater = new LSQ_Updater();
$license = $lsq_updater->get_license( $license_key );
if ( empty( $license->valid ) || empty( $license->license_key->id ) ) {
return new \WP_REST_Response(
array(
'success' => false,
'error' => __( 'Invalid license_key', 'lemon-squeezy' ),
'error_code' => 'invalid_license_key',
),
401
);
}
$license_key_obj = $lsq_updater->get_license_key( $license->license_key->id );
if ( empty( $license_key_obj ) || empty( $license_key_obj->data->relationships->{'order-item'}->data ) ) {
return new \WP_REST_Response(
array(
'success' => false,
'error' => __( 'Error fetching license_key', 'lemon-squeezy' ),
'error_code' => 'error_fetching_license_key',
),
400
);
}
$order_item = $lsq_updater->relation_from_license_key( $license_key_obj, 'order-item' );
if ( ! $order_item ) {
return new \WP_REST_Response(
array(
'success' => false,
'error' => __( 'Invalid order item', 'lemon-squeezy' ),
'error_code' => 'invalid_order_item',
),
400
);
}
$files = $lsq_updater->get_files( $order_item->attributes->variant_id );
if ( empty( $files->data ) ) {
return new \WP_REST_Response(
array(
'success' => false,
'error' => __( 'Missing files', 'lemon-squeezy' ),
'error_code' => 'missing_files',
),
400
);
}
$sorted_files = $lsq_updater->sort_files_by_version( $files->data );
$latest_file = array_pop( $sorted_files );
if ( empty( $latest_file->attributes->version ) ) {
return new \WP_REST_Response(
array(
'success' => false,
'error' => __( 'Missing file version', 'lemon-squeezy' ),
'error_code' => 'missing_file_version',
),
400
);
}
$store = $lsq_updater->relation_from_license_key( $license_key_obj, 'store' );
$product = $lsq_updater->relation_from_license_key( $license_key_obj, 'product' );
return new \WP_REST_Response(
array(
'success' => true,
'error' => '',
'error_code' => '',
'update' => array(
'version' => $latest_file->attributes->version,
'tested' => null,
'requires' => null,
'author' => $store ? $store->attributes->name : null,
'author_profile' => $store ? $store->attributes->url : null,
'download_link' => $latest_file->attributes->download_url,
'trunk' => $latest_file->attributes->download_url,
'requires_php' => null,
'last_updated' => null,
'sections' => array(
'description' => $product ? $product->attributes->description : null,
'changelog' => $latest_file->attributes->version,
),
),
),
200
);
}
}

View File

@ -0,0 +1,121 @@
<?php
namespace lemonsqueezy;
class LSQ_Updater {
/**
* @param string $license_key
* @return object
*/
public function get_license( $license_key ) {
$api_key = get_option( 'lsq_api_key' );
$response = wp_remote_post(
LSQ_API_URL . '/v1/licenses/validate/',
array(
'headers' => array(
'Authorization' => 'Bearer ' . $api_key,
'Accept' => 'application/json',
'Cache-Control' => 'no-cache',
),
'body' => array(
'license_key' => $license_key,
),
)
);
if ( is_wp_error( $response ) ||
200 !== wp_remote_retrieve_response_code( $response ) ) {
return array();
}
return json_decode( wp_remote_retrieve_body( $response ) );
}
/**
* @param string $license_key
* @return object
*/
public function get_license_key( $license_id ) {
$api_key = get_option( 'lsq_api_key' );
$response = wp_remote_get(
LSQ_API_URL . "/v1/license-keys/{$license_id}/?include=store,product,order-item",
array(
'headers' => array(
'Authorization' => 'Bearer ' . $api_key,
'Accept' => 'application/vnd.api+json',
'Content-Type' => 'application/vnd.api+json',
'Cache-Control' => 'no-cache',
),
)
);
if ( is_wp_error( $response ) ||
200 !== wp_remote_retrieve_response_code( $response ) ) {
return array();
}
return json_decode( wp_remote_retrieve_body( $response ) );
}
/**
* @param object $license_key
* @return object
*/
public function relation_from_license_key( $license_key, $relation_key ) {
$relation_type = $license_key->data->relationships->{$relation_key}->data->type;
$relation_id = $license_key->data->relationships->{$relation_key}->data->id;
foreach ( $license_key->included as $relation ) {
if ( $relation->type === $relation_type && $relation->id === $relation_id ) {
return $relation;
}
}
return null;
}
/**
* @param string $variant_id
* @return object
*/
public function get_files( $variant_id ) {
$api_key = get_option( 'lsq_api_key' );
$response = wp_remote_get(
LSQ_API_URL . "/v1/variants/{$variant_id}/files/?sort=-id&page[size]=100",
array(
'headers' => array(
'Authorization' => 'Bearer ' . $api_key,
'Accept' => 'application/vnd.api+json',
'Content-Type' => 'application/vnd.api+json',
'Cache-Control' => 'no-cache',
),
)
);
if ( is_wp_error( $response ) ||
200 !== wp_remote_retrieve_response_code( $response ) ) {
return array();
}
return json_decode( wp_remote_retrieve_body( $response ) );
}
/**
* @param array $files
* @return array
*/
public function sort_files_by_version( $files ) {
usort(
$files,
function ( $a, $b ) {
return version_compare( $a->attributes->version, $b->attributes->version );
}
);
return $files;
}
}

View File

@ -0,0 +1,2 @@
import "./blocks/button";
import "./blocks/ls-button";

View File

@ -0,0 +1,2 @@
import "./blocks/button/script";
import "./blocks/ls-button/script";

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -0,0 +1,60 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="216px" height="136px" viewBox="0 0 216 136" version="1.1">
<defs>
<clipPath id="clip1">
<path d="M 0.515625 0 L 215.484375 0 L 215.484375 136 L 0.515625 136 Z M 0.515625 0 "/>
</clipPath>
<clipPath id="clip2">
<path d="M 211 131 L 215.484375 131 L 215.484375 136 L 211 136 Z M 211 131 "/>
</clipPath>
</defs>
<g id="surface1">
<g clip-path="url(#clip1)" clip-rule="nonzero">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 0.515625 0 L 215.484375 0 L 215.484375 136 L 0.515625 136 Z M 0.515625 0 "/>
</g>
<g clip-path="url(#clip2)" clip-rule="nonzero">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 215.453125 131.578125 L 211.273438 131.578125 L 211.273438 135.660156 L 215.453125 135.660156 Z M 215.453125 131.578125 "/>
</g>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(74.509804%,62.745098%,94.901961%);fill-opacity:1;" d="M 200.851562 14.28125 L 200.851562 48.28125 L 204.335938 48.28125 L 204.335938 14.28125 Z M 200.851562 14.28125 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(74.509804%,62.745098%,94.901961%);fill-opacity:1;" d="M 207.820312 4.078125 L 207.820312 48.28125 L 211.304688 48.28125 L 211.304688 4.078125 Z M 207.820312 4.078125 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(74.509804%,62.745098%,94.901961%);fill-opacity:1;" d="M 193.882812 24.140625 L 193.882812 48.28125 L 197.367188 48.28125 L 197.367188 24.140625 Z M 193.882812 24.140625 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(74.509804%,62.745098%,94.901961%);fill-opacity:1;" d="M 88.550781 128.679688 L 96.972656 106.078125 L 118.679688 106.078125 L 127.101562 128.679688 L 143.363281 128.679688 L 143.363281 131.921875 L 72.289062 131.921875 L 72.289062 128.679688 Z M 88.550781 128.679688 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(74.509804%,62.745098%,94.901961%);fill-opacity:1;" d="M 92.394531 38.125 L 33.164062 38.125 L 33.164062 95.925781 L 92.394531 95.925781 Z M 92.394531 38.125 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 47.980469 67.867188 L 40.960938 70.34375 C 38.378906 71.253906 38.132812 72.867188 38.796875 73.964844 C 39.601562 75.285156 41.523438 75.160156 43.621094 73.792969 C 45.574219 72.519531 48.570312 70.480469 49.542969 69.796875 Z M 47.980469 67.867188 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 77.574219 67.867188 C 77.574219 67.867188 83.425781 69.929688 84.59375 70.34375 C 87.175781 71.253906 87.421875 72.867188 86.757812 73.964844 C 85.953125 75.285156 84.03125 75.160156 81.933594 73.792969 C 79.980469 72.519531 76.984375 70.480469 76.011719 69.796875 Z M 77.574219 67.867188 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 46.425781 61.804688 L 55.042969 73.023438 L 55.398438 72.824219 L 53.09375 60.066406 Z M 46.425781 61.804688 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(74.509804%,62.745098%,94.901961%);fill-opacity:1;" d="M 52.082031 72.761719 C 48.261719 72.761719 45.695312 69.460938 45.695312 66.152344 C 45.695312 62.539062 49.035156 61.121094 52.148438 61.121094 C 55.265625 61.121094 58.792969 62.710938 58.792969 65.921875 C 58.792969 69.609375 56.019531 72.761719 52.082031 72.761719 Z M 52.082031 72.761719 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 54.28125 72.40625 C 54.527344 72.324219 54.757812 72.230469 54.984375 72.121094 L 53.003906 61.164062 C 52.71875 61.136719 52.429688 61.121094 52.148438 61.121094 C 50.238281 61.121094 48.238281 61.660156 46.984375 62.90625 Z M 54.28125 72.40625 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(74.509804%,62.745098%,94.901961%);fill-opacity:1;" d="M 66.761719 65.921875 C 66.761719 62.710938 70.292969 61.121094 73.40625 61.121094 C 76.519531 61.121094 79.859375 62.539062 79.859375 66.152344 C 79.859375 69.464844 77.289062 72.761719 73.472656 72.761719 C 69.535156 72.761719 66.761719 69.609375 66.761719 65.921875 Z M 66.761719 65.921875 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 71.273438 72.40625 C 71.03125 72.324219 70.796875 72.230469 70.570312 72.121094 L 72.550781 61.164062 C 72.839844 61.136719 73.125 61.121094 73.40625 61.121094 C 75.320312 61.121094 77.316406 61.660156 78.570312 62.90625 Z M 71.273438 72.40625 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 73.539062 59.15625 C 66.585938 59.15625 64.664062 64.078125 62.777344 64.078125 C 60.886719 64.078125 58.972656 59.15625 52.011719 59.15625 C 47.609375 59.15625 43.007812 61.921875 40.617188 63.042969 L 40.617188 66.414062 L 43.183594 66.414062 C 43.539062 68.570312 45.328125 74.804688 52.078125 74.804688 C 59.625 74.804688 59.792969 67.304688 62.773438 67.304688 C 65.75 67.304688 65.921875 74.804688 73.464844 74.804688 C 80.21875 74.804688 82.003906 68.570312 82.359375 66.414062 L 84.929688 66.414062 L 84.929688 63.042969 C 82.539062 61.921875 77.933594 59.15625 73.53125 59.15625 Z M 52.082031 72.761719 C 48.261719 72.761719 45.695312 69.460938 45.695312 66.152344 C 45.695312 62.539062 49.035156 61.121094 52.148438 61.121094 C 55.265625 61.121094 58.792969 62.710938 58.792969 65.921875 C 58.792969 69.609375 56.019531 72.761719 52.082031 72.761719 Z M 73.472656 72.761719 C 69.535156 72.761719 66.761719 69.609375 66.761719 65.921875 C 66.761719 62.710938 70.292969 61.121094 73.40625 61.121094 C 76.519531 61.121094 79.859375 62.539062 79.859375 66.152344 C 79.859375 69.464844 77.289062 72.761719 73.472656 72.761719 Z M 73.472656 72.761719 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 155.867188 44.960938 L 96.636719 44.960938 L 96.636719 48.363281 L 155.867188 48.363281 Z M 155.867188 44.960938 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 126.253906 51.613281 L 96.636719 51.613281 L 96.636719 55.011719 L 126.253906 55.011719 Z M 126.253906 51.613281 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 155.867188 38.160156 L 96.636719 38.160156 L 96.636719 41.5625 L 155.867188 41.5625 Z M 155.867188 38.160156 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 159.304688 71.523438 L 159.304688 80.863281 L 175.355469 80.863281 C 175.355469 80.863281 173.632812 84.292969 173.632812 88.132812 C 173.632812 91.96875 176.171875 95.824219 181.066406 95.824219 C 185.960938 95.824219 188.5 91.839844 188.5 88.132812 C 188.5 84.421875 186.777344 80.863281 186.777344 80.863281 L 198.511719 80.863281 L 198.511719 71.523438 C 204.359375 74.753906 211.207031 73.65625 211.207031 66.953125 C 211.207031 60.25 204.359375 59.152344 198.511719 62.382812 L 198.511719 53.042969 L 186.777344 53.042969 C 186.777344 53.042969 188.5 49.613281 188.5 45.773438 C 188.5 41.9375 185.960938 38.082031 181.066406 38.082031 C 176.171875 38.082031 173.632812 42.066406 173.632812 45.773438 C 173.632812 49.484375 175.355469 53.042969 175.355469 53.042969 L 159.304688 53.042969 L 159.304688 62.382812 C 165.152344 59.152344 172 60.25 172 66.953125 C 172 73.65625 165.152344 74.753906 159.304688 71.523438 Z M 159.304688 71.523438 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(74.509804%,62.745098%,94.901961%);fill-opacity:1;" d="M 155.867188 87.378906 L 96.636719 87.378906 L 96.636719 95.878906 L 155.867188 95.878906 Z M 155.867188 87.378906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 34.308594 119.105469 L 34.308594 115.152344 L 30.957031 114.726562 C 30.65625 113.351562 30.105469 112.070312 29.34375 110.929688 L 31.402344 108.3125 L 28.539062 105.515625 L 25.855469 107.527344 C 24.6875 106.78125 23.375 106.246094 21.96875 105.953125 L 21.527344 102.679688 L 17.476562 102.679688 L 17.039062 105.953125 C 15.632812 106.246094 14.320312 106.78125 13.148438 107.527344 L 10.464844 105.515625 L 7.601562 108.3125 L 9.660156 110.929688 C 8.898438 112.070312 8.347656 113.351562 8.046875 114.726562 L 4.695312 115.152344 L 4.695312 119.105469 L 8.046875 119.535156 C 8.351562 120.90625 8.90625 122.1875 9.660156 123.332031 L 7.601562 125.949219 L 10.464844 128.742188 L 13.148438 126.734375 C 14.320312 127.476562 15.632812 128.015625 17.042969 128.308594 L 17.476562 131.578125 L 21.527344 131.578125 L 21.96875 128.308594 C 23.375 128.015625 24.6875 127.476562 25.855469 126.734375 L 28.539062 128.742188 L 31.402344 125.949219 L 29.34375 123.332031 C 30.105469 122.1875 30.65625 120.90625 30.957031 119.535156 Z M 19.5625 123.417969 C 15.832031 123.417969 12.804688 120.464844 12.804688 116.820312 C 12.804688 113.179688 15.832031 110.226562 19.5625 110.226562 C 23.296875 110.226562 26.324219 113.179688 26.324219 116.820312 C 26.324219 120.464844 23.296875 123.417969 19.5625 123.417969 Z M 19.5625 123.417969 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 182.777344 24.164062 L 33.164062 24.164062 L 33.164062 34.363281 L 182.777344 34.363281 Z M 182.777344 24.164062 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 37.308594 30.75 C 38.214844 30.75 38.953125 30.03125 38.953125 29.144531 C 38.953125 28.257812 38.214844 27.539062 37.308594 27.539062 C 36.398438 27.539062 35.664062 28.257812 35.664062 29.144531 C 35.664062 30.03125 36.398438 30.75 37.308594 30.75 Z M 37.308594 30.75 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 43.269531 30.75 C 44.175781 30.75 44.914062 30.03125 44.914062 29.144531 C 44.914062 28.257812 44.175781 27.539062 43.269531 27.539062 C 42.359375 27.539062 41.625 28.257812 41.625 29.144531 C 41.625 30.03125 42.359375 30.75 43.269531 30.75 Z M 43.269531 30.75 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;" d="M 49.234375 30.75 C 50.140625 30.75 50.878906 30.03125 50.878906 29.144531 C 50.878906 28.257812 50.140625 27.539062 49.234375 27.539062 C 48.324219 27.539062 47.589844 28.257812 47.589844 29.144531 C 47.589844 30.03125 48.324219 30.75 49.234375 30.75 Z M 49.234375 30.75 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(74.509804%,62.745098%,94.901961%);fill-opacity:1;" d="M 33.265625 100.394531 L 33.265625 101.214844 C 33.265625 104.140625 35.769531 106.515625 38.863281 106.515625 L 177.277344 106.515625 C 180.371094 106.515625 182.878906 104.144531 182.878906 101.214844 L 182.878906 100.394531 Z M 33.265625 100.394531 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(74.509804%,62.745098%,94.901961%);fill-opacity:1;" d="M 182.878906 20.398438 L 182.878906 19.582031 C 182.878906 16.65625 180.371094 14.28125 177.277344 14.28125 L 38.863281 14.28125 C 35.773438 14.28125 33.265625 16.652344 33.265625 19.582031 L 33.265625 20.398438 Z M 182.878906 20.398438 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(74.509804%,62.745098%,94.901961%);fill-opacity:1;" d="M 211.210938 123.40625 C 211.210938 127.878906 207.53125 131.511719 202.96875 131.578125 L 167.679688 131.578125 C 163.054688 131.578125 159.304688 127.921875 159.304688 123.40625 C 159.304688 118.890625 163.054688 115.234375 167.679688 115.234375 L 202.984375 115.234375 C 207.542969 115.234375 211.214844 118.941406 211.214844 123.40625 Z M 211.210938 123.40625 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 202.792969 129.21875 C 206.082031 129.21875 208.746094 126.617188 208.746094 123.40625 C 208.746094 120.195312 206.082031 117.597656 202.792969 117.597656 C 199.503906 117.597656 196.839844 120.195312 196.839844 123.40625 C 196.839844 126.617188 199.503906 129.21875 202.792969 129.21875 Z M 202.792969 129.21875 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(74.509804%,62.745098%,94.901961%);fill-opacity:1;" d="M 116.382812 63.886719 L 96.636719 63.886719 L 96.636719 83.152344 L 116.382812 83.152344 Z M 116.382812 63.886719 "/>
<path style="fill:none;stroke-width:0.908286;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(15.294118%,10.588235%,23.921569%);stroke-opacity:1;stroke-miterlimit:10;" d="M 98.346354 73.519531 L 108.755968 73.519531 " transform="matrix(1.028571,0,0,1,0,0)"/>
<path style="fill:none;stroke-width:0.908286;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(15.294118%,10.588235%,23.921569%);stroke-opacity:1;stroke-miterlimit:10;" d="M 103.549262 68.296875 L 103.549262 78.742188 " transform="matrix(1.028571,0,0,1,0,0)"/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(74.509804%,62.745098%,94.901961%);fill-opacity:1;" d="M 8.046875 98.058594 C 6.214844 98.058594 4.722656 96.625 4.695312 94.839844 L 4.695312 7.351562 C 4.695312 5.546875 6.195312 4.082031 8.046875 4.082031 C 9.898438 4.082031 11.398438 5.546875 11.398438 7.351562 L 11.398438 94.847656 C 11.398438 96.625 9.878906 98.058594 8.046875 98.058594 Z M 8.046875 98.058594 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 11.398438 33.148438 L 11.398438 29.839844 L 4.695312 25.332031 L 4.695312 28.640625 Z M 11.398438 33.148438 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 11.398438 39.578125 L 11.398438 36.269531 L 4.695312 31.757812 L 4.695312 35.070312 Z M 11.398438 39.578125 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 11.398438 46.003906 L 11.398438 42.699219 L 4.695312 38.1875 L 4.695312 41.5 Z M 11.398438 46.003906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 11.398438 52.433594 L 11.398438 49.125 L 4.695312 44.617188 L 4.695312 47.929688 Z M 11.398438 52.433594 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 11.398438 58.863281 L 11.398438 55.554688 L 4.695312 51.046875 L 4.695312 54.359375 Z M 11.398438 58.863281 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 11.398438 65.292969 L 11.398438 61.984375 L 4.695312 57.476562 L 4.695312 60.785156 Z M 11.398438 65.292969 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 11.398438 71.722656 L 11.398438 68.410156 L 4.695312 63.90625 L 4.695312 67.214844 Z M 11.398438 71.722656 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 11.398438 78.152344 L 11.398438 74.839844 L 4.695312 70.335938 L 4.695312 73.644531 Z M 11.398438 78.152344 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 11.398438 84.582031 L 11.398438 81.269531 L 4.695312 76.765625 L 4.695312 80.074219 Z M 11.398438 84.582031 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 11.398438 91.011719 L 11.398438 87.699219 L 4.695312 83.191406 L 4.695312 86.503906 Z M 11.398438 91.011719 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(15.294118%,10.588235%,23.921569%);fill-opacity:1;" d="M 4.695312 89.621094 L 4.695312 92.933594 L 10.609375 96.910156 C 11.101562 96.351562 11.398438 95.636719 11.398438 94.847656 L 11.398438 94.128906 Z M 4.695312 89.621094 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array('wc-components', 'wp-components', 'wp-element'), 'version' => '092d36684bd43b3c307d');

View File

@ -0,0 +1 @@
(()=>{"use strict";var e={d:(t,o)=>{for(var r in o)e.o(o,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:o[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{LayoutContext:()=>_,LayoutContextProvider:()=>w,WC_FOOTER_SLOT_NAME:()=>l,WC_HEADER_NAVIGATION_SLOT_NAME:()=>m,WC_HEADER_PAGE_TITLE_SLOT_NAME:()=>u,WC_HEADER_SLOT_NAME:()=>i,WooFooterItem:()=>a,WooHeaderItem:()=>c,WooHeaderNavigationItem:()=>s,WooHeaderPageTitle:()=>E,getLayoutContextValue:()=>y,useAdminSidebarWidth:()=>O,useExtendLayout:()=>f,useLayoutContext:()=>p});const o=window.wp.components,r=window.wp.element,n=window.wc.components,l="woocommerce_footer_item",a=({children:e,order:t=1})=>(0,r.createElement)(o.Fill,{name:l},(o=>(0,n.createOrderedChildren)(e,t,o)));a.Slot=({fillProps:e})=>(0,r.createElement)(o.Slot,{name:l,fillProps:e},n.sortFillsByOrder);const i="woocommerce_header_item",d=e=>e&&e.length?`${i}/${e}`:i,c=({children:e,order:t=1,name:l=""})=>(0,r.createElement)(o.Fill,{name:d(l)},(o=>(0,n.createOrderedChildren)(e,t,o)));c.Slot=({fillProps:e,name:t=""})=>(0,r.createElement)(o.Slot,{name:d(t),fillProps:e},n.sortFillsByOrder);const m="woocommerce_header_navigation_item",s=({children:e,order:t=1})=>(0,r.createElement)(o.Fill,{name:m},(o=>(0,n.createOrderedChildren)(e,t,o)));s.Slot=({fillProps:e})=>(0,r.createElement)(o.Slot,{name:m,fillProps:e},n.sortFillsByOrder);const u="woocommerce_header_page_title",E=({children:e})=>(0,r.createElement)(o.Fill,{name:u},e);E.Slot=({fillProps:e})=>(0,r.createElement)(o.Slot,{name:u,fillProps:e},(e=>(0,r.createElement)(r.Fragment,null,[...e].pop())));const _=(0,r.createContext)(void 0),y=(e=[])=>({layoutParts:[...e],extendLayout:t=>{const o=[...e,t];return{...y(o),layoutParts:o}},layoutString:e.join("/"),isDescendantOf:t=>e.includes(t)}),w=({children:e,value:t})=>(0,r.createElement)(_.Provider,{value:t},e),p=()=>{const e=(0,r.useContext)(_);if(void 0===e)throw new Error("useLayoutContext must be used within a LayoutContextProvider");return e},f=e=>{const{extendLayout:t}=p();return(0,r.useMemo)((()=>t(e)),[t,e])};function O(){const[e,t]=(0,r.useState)(0);return(0,r.useEffect)((()=>{const e=new ResizeObserver((e=>{t(e[0].contentRect.width)})),o=document.getElementById("adminmenu");return o&&e.observe(o),()=>{o&&e.unobserve(o)}}),[]),e}(window.wc=window.wc||{}).adminLayout=t})();

View File

@ -0,0 +1 @@
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}

View File

@ -0,0 +1 @@
<?php return array('version' => '34c76045af18baf00602');

View File

@ -0,0 +1 @@
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array('lodash', 'moment', 'react', 'react-dom', 'wc-admin-layout', 'wc-components', 'wc-csv', 'wc-currency', 'wc-customer-effort-score', 'wc-date', 'wc-experimental', 'wc-explat', 'wc-navigation', 'wc-notices', 'wc-number', 'wc-product-editor', 'wc-remote-logging', 'wc-sanitize', 'wc-settings', 'wc-store-data', 'wc-tracks', 'wp-a11y', 'wp-api-fetch', 'wp-blob', 'wp-block-editor', 'wp-block-library', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-data-controls', 'wp-date', 'wp-deprecated', 'wp-dom', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-keyboard-shortcuts', 'wp-keycodes', 'wp-media-utils', 'wp-notices', 'wp-plugins', 'wp-preferences', 'wp-primitives', 'wp-private-apis', 'wp-router', 'wp-url', 'wp-warning'), 'version' => '311846ae4291f8628515');

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,20 @@
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* React Router v6.3.0
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
<?php return array('version' => '9d3241446f1b42b214a9');

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}.woocommerce-beta-features-tracking-modal__actions{text-align:left;margin-top:24px}.woocommerce-beta-features-tracking-modal__actions .components-button.is-primary{margin-right:16px}.woocommerce-beta-features-tracking-modal__checkbox{padding:16px 0}

View File

@ -0,0 +1 @@
<?php return array('version' => '04d3d3fb2590fd7d4779');

View File

@ -0,0 +1 @@
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}.woocommerce-beta-features-tracking-modal__actions{text-align:right;margin-top:24px}.woocommerce-beta-features-tracking-modal__actions .components-button.is-primary{margin-left:16px}.woocommerce-beta-features-tracking-modal__checkbox{padding:16px 0}

View File

@ -0,0 +1,47 @@
<svg width="216" height="140" viewBox="0 0 216 140" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="216" height="140" fill="white"/>
<path d="M148.084 4.2002H83.3193V25.2002H148.084V4.2002Z" fill="#BEA0F2"/>
<path d="M67.9157 4.2002H25.5559V7.7002H67.9157V4.2002Z" fill="#271B3D"/>
<path d="M57.7634 18.2002H25.5559V21.7002H57.7634V18.2002Z" fill="#271B3D"/>
<path d="M79.1183 11.2002H25.906V14.7002H79.1183V11.2002Z" fill="#271B3D"/>
<path d="M12.953 21.7002C17.7866 21.7002 21.705 17.7827 21.705 12.9502C21.705 8.1177 17.7866 4.2002 12.953 4.2002C8.11939 4.2002 4.20097 8.1177 4.20097 12.9502C4.20097 17.7827 8.11939 21.7002 12.953 21.7002Z" fill="#271B3D"/>
<path d="M38.782 106.05C38.782 101.264 42.4788 97.3726 47.0649 97.2998H108.76C113.409 97.2998 117.176 101.216 117.176 106.05C117.176 110.883 113.409 114.8 108.76 114.8H47.0509C42.4718 114.8 38.782 110.829 38.782 106.05Z" fill="#BEA0F2"/>
<path d="M47.0509 114.8H85.6613V97.2998H47.0649C42.4788 97.3726 38.782 101.264 38.782 106.05C38.782 110.832 42.4683 114.8 47.0509 114.8Z" fill="#271B3D"/>
<path d="M211.733 67.9004H152.219V71.4004H211.733V67.9004Z" fill="#271B3D"/>
<path d="M181.976 74.9004H152.219V78.4004H181.976V74.9004Z" fill="#271B3D"/>
<path d="M143.852 17.237L144.223 8.09502L129.565 22.851L128.84 22.1265L143.586 7.48602L134.477 7.85702L134.358 6.86302L145.07 6.54102L145.154 6.62502L144.85 17.3525L143.855 17.2335L143.852 17.237Z" fill="black"/>
<path d="M211.799 98.3496H124.279V135.8H211.799V98.3496Z" fill="#BEA0F2"/>
<path d="M211.733 4.2002H152.219V63.7002H211.733V4.2002Z" fill="#271B3D"/>
<path d="M201.241 32.3874V25.8438H198.128V32.3874H194.382V29.1156H191.268V32.3874H179.04C178.289 27.5312 174.095 23.7998 169.049 23.7998C163.475 23.7998 158.937 28.3509 158.937 33.9498C158.937 39.5487 163.471 44.0998 169.049 44.0998C174.095 44.0998 178.289 40.3721 179.04 35.5122H204.797V32.3874H201.245H201.241ZM169.045 40.975C165.189 40.975 162.05 37.8245 162.05 33.9535C162.05 30.0824 165.189 26.9319 169.045 26.9319C172.902 26.9319 176.04 30.0824 176.04 33.9535C176.04 37.8245 172.902 40.975 169.045 40.975Z" fill="white"/>
<path d="M83.0707 76.6992C94.1881 76.6992 103.2 67.689 103.2 56.5742C103.2 45.4595 94.1881 36.4492 83.0707 36.4492C71.9534 36.4492 62.9411 45.4595 62.9411 56.5742C62.9411 67.689 71.9534 76.6992 83.0707 76.6992Z" fill="#BEA0F2"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M86.1727 56.9742C88.1989 55.7385 90.6081 53.6502 90.6081 50.1974C90.6081 45.6377 87.1231 42.7871 83.0707 42.7871C79.0184 42.7871 75.5334 45.6377 75.5334 50.1974C75.5334 53.6467 77.9391 55.7385 79.9688 56.9742L74.5203 69.5636H91.6246L86.1762 56.9742H86.1727Z" fill="#271B3D"/>
<path d="M196.98 121.093C195.415 122.636 190.78 126.423 188.165 125.429C187.853 125.31 187.64 125.1 187.5 124.775C186.835 123.231 187.717 119.521 190.122 113.743L188.883 112.959C188.648 113.218 184.185 118.156 180.691 122.612L183.106 113.862L181.752 113.277C181.731 113.309 179.728 116.599 177.155 119.728C173.938 123.644 171.207 125.632 169.478 125.335C168.995 125.251 168.61 124.988 168.329 124.551C168.074 124.148 167.916 123.62 167.857 123C171.823 121.887 175.272 119.469 176.101 116.76C176.437 115.661 176.315 114.597 175.758 113.848C175.377 113.33 174.617 112.714 173.168 112.714C170.024 112.714 167.682 116.189 166.751 119.637C166.541 120.41 166.415 121.152 166.366 121.842C165.413 122.041 164.454 122.146 163.523 122.16C163.81 121.583 164.065 120.984 164.283 120.389C165.315 117.568 165.693 114.159 163.659 113.046C162.424 112.371 160.267 112.651 157.754 115.139L158.209 113.442L157.036 112.661C155.748 113.659 154.218 114.443 152.653 114.968C152.828 114.331 152.975 113.694 153.083 113.071C153.861 108.633 152.712 105.437 149.936 104.296C147.972 103.491 145.63 103.936 143.827 105.462C141.807 107.173 140.904 109.795 141.471 112.304C141.958 114.457 143.299 115.983 145.35 116.718C146.869 117.264 148.62 117.323 150.381 117.05C148.585 121.485 145.501 125.184 143.078 125.286C142.182 125.321 141.45 124.953 140.88 124.187C139.43 122.241 139.388 118.38 140.778 114.345L139.371 113.858C137.802 118.412 137.921 122.71 139.686 125.072C140.558 126.241 141.748 126.826 143.141 126.766C146.603 126.619 150.262 121.789 152.107 116.672C153.584 116.27 155.016 115.664 156.266 114.947L151.963 130.987L153.402 131.372L155.457 123.718C155.59 124.383 155.807 124.999 156.136 125.506C156.588 126.199 157.207 126.63 157.974 126.784C158.146 126.819 158.314 126.836 158.482 126.836C160.015 126.836 161.51 125.464 162.69 123.623C163.911 123.676 165.168 123.571 166.401 123.333C166.499 124.106 166.723 124.782 167.076 125.338C167.584 126.133 168.326 126.633 169.226 126.791C171.578 127.197 174.638 125.135 178.317 120.652C179.098 119.703 179.819 118.748 180.453 117.873L178.202 126.031L179.532 126.651C181.514 123.774 184.874 119.784 187.251 117.047C185.827 121.131 185.473 123.812 186.138 125.349C186.439 126.052 186.947 126.542 187.643 126.808C188.116 126.987 188.617 127.067 189.128 127.067C192.919 127.067 197.467 122.703 198.034 122.139L196.987 121.079L196.98 121.093ZM168.186 120.022C168.942 117.218 170.822 114.201 173.164 114.201C173.623 114.201 174.235 114.292 174.557 114.73C174.83 115.097 174.872 115.678 174.676 116.322C174.228 117.789 172.551 119.357 170.192 120.522C169.453 120.886 168.683 121.194 167.899 121.439C167.958 120.988 168.053 120.515 168.186 120.022ZM151.617 112.815C151.463 113.687 151.242 114.565 150.969 115.43C149.079 115.832 147.251 115.825 145.854 115.325C144.286 114.761 143.299 113.638 142.924 111.982C142.392 109.63 143.537 107.66 144.79 106.603C145.735 105.805 146.824 105.385 147.885 105.385C148.392 105.385 148.896 105.479 149.373 105.675C152.212 106.837 151.998 110.649 151.617 112.815ZM158.265 125.338C157.894 125.261 157.61 125.062 157.375 124.705C156.378 123.179 156.819 119.623 157.106 118.191C159.217 115.325 161.713 113.676 162.945 114.355C163.89 114.873 163.866 117.197 162.886 119.882C161.685 123.165 159.609 125.618 158.265 125.342V125.338Z" fill="#271B3D"/>
<path d="M126.229 99.9846L167.993 86.6426" stroke="#261B3C" stroke-width="0.99" stroke-miterlimit="10"/>
<path d="M209.408 99.9846L167.993 86.6426" stroke="#261B3C" stroke-width="0.99" stroke-miterlimit="10"/>
<path d="M167.892 88.2942C168.804 88.2942 169.544 87.5546 169.544 86.6422C169.544 85.7299 168.804 84.9902 167.892 84.9902C166.979 84.9902 166.239 85.7299 166.239 86.6422C166.239 87.5546 166.979 88.2942 167.892 88.2942Z" fill="#271B3D"/>
<path d="M201.997 11.4323L207.248 17.5002V4.2002H196.746V17.5002L201.997 11.4323Z" fill="#BEA0F2"/>
<path d="M22.6852 56.8189C12.0953 56.8189 4.32 65.0649 4.32 75.1799C4.32 80.8919 6.69705 85.9599 11.4862 89.5719C15.3335 92.4734 17.483 93.5969 17.483 98.6089V131.712L22.6082 135.74V135.8L22.6467 135.768L22.6852 135.8V135.74L27.8104 131.712V125.062L24.1381 121.39L27.3903 118.139L24.1381 114.887L27.3903 111.636L24.1381 108.384L27.8104 104.713V98.6054C27.8104 93.5934 29.9599 92.4699 33.8073 89.5684C38.5929 85.9564 40.9735 80.8884 40.9735 75.1764C40.9735 65.0614 33.2752 56.8154 22.6888 56.8154L22.6852 56.8189ZM22.6467 73.9654C19.6255 73.9654 17.1785 71.5189 17.1785 68.4984C17.1785 65.4779 19.6255 63.0314 22.6467 63.0314C25.6679 63.0314 28.115 65.4779 28.115 68.4984C28.115 71.5189 25.6679 73.9654 22.6467 73.9654Z" fill="#271B3D"/>
<path d="M19.1354 64.3087L19.1389 64.3052V64.3018L19.1354 64.3087Z" fill="#BEA0F2"/>
<path d="M37.8893 36.4453C26.7112 36.4453 17.6476 45.5068 17.6476 56.6823C17.6476 56.9483 17.6546 57.2143 17.6651 57.4768C18.9254 57.1373 20.2452 56.9203 21.6175 56.8468C21.6175 56.7908 21.614 56.7383 21.614 56.6823C21.614 47.7118 28.9132 40.4143 37.8858 40.4143C46.8583 40.4143 54.1575 47.7118 54.1575 56.6823C54.1575 65.6528 46.8583 72.9503 37.8858 72.9503C31.1677 72.9503 25.3914 68.8623 22.9093 63.0418C22.8218 63.0383 22.7343 63.0278 22.6432 63.0278C21.3094 63.0278 20.0876 63.5073 19.1389 64.3018C22.1496 71.7008 29.4068 76.9193 37.8893 76.9193C49.0674 76.9193 58.131 67.8578 58.131 56.6823C58.131 45.5068 49.0674 36.4453 37.8893 36.4453Z" fill="#BEA0F2"/>
<g clip-path="url(#clip0_1946_297)">
<path d="M127.879 46.2583C133.735 46.2583 138.5 51.0193 138.5 56.8767C138.5 62.7341 133.738 67.4952 127.879 67.4952C122.021 67.4952 117.258 62.7341 117.258 56.8767C117.258 51.0193 122.021 46.2583 127.879 46.2583ZM127.879 36.75C116.764 36.75 107.751 45.7606 107.751 56.8733C107.751 67.9859 116.764 76.9965 127.879 76.9965C138.995 76.9965 148.007 67.9859 148.007 56.8733C148.007 45.7606 138.998 36.75 127.879 36.75Z" fill="#271B3D"/>
<path d="M117.92 39.3881L122.71 47.6051C124.242 46.749 126.003 46.2548 127.879 46.2548V36.75C124.256 36.75 120.858 37.7141 117.92 39.3881Z" fill="#BEA0F2"/>
</g>
<g clip-path="url(#clip1_1946_297)">
<path d="M38.859 127.048C38.859 122.263 42.5558 118.376 47.1419 118.3H108.837C113.486 118.3 117.253 122.215 117.253 127.048C117.253 131.881 113.486 135.796 108.837 135.796H47.1279C42.5453 135.796 38.859 131.83 38.859 127.048Z" fill="#BEA0F2"/>
<path d="M38.859 127.048C38.859 122.263 42.5558 118.376 47.1419 118.3H108.837C113.486 118.3 117.253 122.215 117.253 127.048C117.253 131.881 113.486 135.796 108.837 135.796H47.1279C42.5453 135.796 38.859 131.83 38.859 127.048Z" fill="#BEA0F2"/>
<path d="M57.6443 135.796H63.3857L70.3033 118.3H64.5619L57.6443 135.796Z" fill="#271B3D"/>
<path d="M80.5186 135.796H86.26L93.1776 118.3H87.4362L80.5186 135.796Z" fill="#271B3D"/>
<path d="M75.9991 118.3L69.0815 135.796H74.8228L81.7404 118.3H75.9991Z" fill="#271B3D"/>
<path d="M58.8661 118.3H53.1248L46.2282 135.742C46.5223 135.774 46.8233 135.796 47.1279 135.796H51.9485L58.8661 118.3Z" fill="#271B3D"/>
<path d="M41.4566 133.402L47.429 118.3H47.1454C44.0017 118.351 41.2816 120.192 39.8742 122.881L39.1951 124.595C38.978 125.374 38.859 126.196 38.859 127.048C38.859 129.533 39.8567 131.797 41.4566 133.398V133.402Z" fill="#271B3D"/>
</g>
<defs>
<clipPath id="clip0_1946_297">
<rect width="40.2593" height="40.25" fill="white" transform="translate(107.751 36.75)"/>
</clipPath>
<clipPath id="clip1_1946_297">
<rect width="78.3936" height="17.5" fill="white" transform="translate(38.859 118.3)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

@ -0,0 +1 @@
<?php return array('dependencies' => array('wc-settings', 'wp-block-editor', 'wp-blocks', 'wp-core-data', 'wp-data', 'wp-element'), 'version' => 'b3e63b3af3204f8c7929');

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}

View File

@ -0,0 +1 @@
<?php return array('version' => '34c76045af18baf00602');

View File

@ -0,0 +1 @@
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,9 @@
/**
* @license React
* use-sync-external-store-shim.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

View File

@ -0,0 +1,2 @@
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}.woocommerce-dashboard__chart-block-wrapper{cursor:pointer}.woocommerce-dashboard__chart-block-wrapper:hover .woocommerce-chart,.woocommerce-dashboard__chart-block-wrapper:hover .woocommerce-card__header{background:#f8f9f9}.woocommerce-dashboard__chart-block-wrapper:hover .woocommerce-legend__item button{background:rgba(0,0,0,0)}.woocommerce-dashboard__chart-block-wrapper .woocommerce-chart{margin-top:0;margin-bottom:0;border:0}.woocommerce-dashboard__chart-block-wrapper .woocommerce-chart__footer{position:relative}.woocommerce-dashboard__chart-block-wrapper .woocommerce-chart__footer::after{content:"";position:absolute;width:100%;height:100%;right:0;top:0;cursor:pointer;z-index:1}.woocommerce-dashboard__chart-block{overflow:hidden}.woocommerce-dashboard__chart-block .woocommerce-card__body{padding:0;position:relative}.woocommerce-dashboard__chart-block .woocommerce-card__body .woocommerce-chart{border:none;margin:0}.woocommerce-dashboard__chart-block .woocommerce-card__body .woocommerce-chart .woocommerce-legend__item>button{cursor:default}.woocommerce-dashboard__chart-block .woocommerce-card__body .woocommerce-chart .woocommerce-legend__item>button:hover{background:#f0f0f0}.woocommerce-dashboard__chart-block .woocommerce-card__body .woocommerce-chart .woocommerce-legend__item>button .woocommerce-legend__item-container{cursor:default}.woocommerce-dashboard__chart-block .woocommerce-card__body .woocommerce-chart .woocommerce-legend__item>button .woocommerce-legend__item-container .woocommerce-legend__item-checkmark.woocommerce-legend__item-checkmark-checked::after{display:none}.woocommerce-dashboard__chart-block .woocommerce-card__body .woocommerce-chart:hover{background:#f0f0f0}.woocommerce-dashboard__chart-block .woocommerce-card__body .woocommerce-chart:hover .woocommerce-legend__item>button{background:#f0f0f0}.woocommerce-dashboard__chart-block:hover{background:#f0f0f0}.woocommerce-dashboard__chart-block .screen-reader-text:focus{clip:auto;clip-path:none;z-index:1;right:6px;top:7px;height:auto;width:auto;display:block;font-size:14px;font-size:0.875rem;font-weight:600;padding:15px 23px 14px;background:#f1f1f1;color:#0073aa;text-decoration:none;box-shadow:0 0 2px 2px rgba(0,0,0,.6)}
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}.woocommerce-dashboard__dashboard-charts{border-bottom:0;border-left:0}.woocommerce-dashboard__dashboard-charts .woocommerce-section-header__actions{flex-grow:0}.woocommerce-dashboard__dashboard-charts .woocommerce-card__body{padding:0}.woocommerce-dashboard__dashboard-charts .woocommerce-summary{margin:0}

View File

@ -0,0 +1,2 @@
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}.woocommerce-dashboard__chart-block-wrapper{cursor:pointer}.woocommerce-dashboard__chart-block-wrapper:hover .woocommerce-chart,.woocommerce-dashboard__chart-block-wrapper:hover .woocommerce-card__header{background:#f8f9f9}.woocommerce-dashboard__chart-block-wrapper:hover .woocommerce-legend__item button{background:rgba(0,0,0,0)}.woocommerce-dashboard__chart-block-wrapper .woocommerce-chart{margin-top:0;margin-bottom:0;border:0}.woocommerce-dashboard__chart-block-wrapper .woocommerce-chart__footer{position:relative}.woocommerce-dashboard__chart-block-wrapper .woocommerce-chart__footer::after{content:"";position:absolute;width:100%;height:100%;left:0;top:0;cursor:pointer;z-index:1}.woocommerce-dashboard__chart-block{overflow:hidden}.woocommerce-dashboard__chart-block .woocommerce-card__body{padding:0;position:relative}.woocommerce-dashboard__chart-block .woocommerce-card__body .woocommerce-chart{border:none;margin:0}.woocommerce-dashboard__chart-block .woocommerce-card__body .woocommerce-chart .woocommerce-legend__item>button{cursor:default}.woocommerce-dashboard__chart-block .woocommerce-card__body .woocommerce-chart .woocommerce-legend__item>button:hover{background:#f0f0f0}.woocommerce-dashboard__chart-block .woocommerce-card__body .woocommerce-chart .woocommerce-legend__item>button .woocommerce-legend__item-container{cursor:default}.woocommerce-dashboard__chart-block .woocommerce-card__body .woocommerce-chart .woocommerce-legend__item>button .woocommerce-legend__item-container .woocommerce-legend__item-checkmark.woocommerce-legend__item-checkmark-checked::after{display:none}.woocommerce-dashboard__chart-block .woocommerce-card__body .woocommerce-chart:hover{background:#f0f0f0}.woocommerce-dashboard__chart-block .woocommerce-card__body .woocommerce-chart:hover .woocommerce-legend__item>button{background:#f0f0f0}.woocommerce-dashboard__chart-block:hover{background:#f0f0f0}.woocommerce-dashboard__chart-block .screen-reader-text:focus{clip:auto;clip-path:none;z-index:1;left:6px;top:7px;height:auto;width:auto;display:block;font-size:14px;font-size:0.875rem;font-weight:600;padding:15px 23px 14px;background:#f1f1f1;color:#0073aa;text-decoration:none;box-shadow:0 0 2px 2px rgba(0,0,0,.6)}
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}.woocommerce-dashboard__dashboard-charts{border-bottom:0;border-right:0}.woocommerce-dashboard__dashboard-charts .woocommerce-section-header__actions{flex-grow:0}.woocommerce-dashboard__dashboard-charts .woocommerce-card__body{padding:0}.woocommerce-dashboard__dashboard-charts .woocommerce-summary{margin:0}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,14 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
"use strict";(globalThis.webpackChunk_wcAdmin_webpackJsonp=globalThis.webpackChunk_wcAdmin_webpackJsonp||[]).push([[2363],{77728:(e,s,t)=>{t.r(s),t.d(s,{Products:()=>L});var o=t(27723),c=t(7081),i=t(14908),n=t(92279),r=t(86087),a=t(56427),l=t(15703),d=t(24148),p=t(56537),m=t(90700),u=t(83306),k=t(52619),_=t(40314),w=t(47143),g=t(98467),h=t(11911),x=t(89001),A=t(8852),C=t(68273),b=t(23984),j=t(93614),y=t(36753),P=t(83085),v=t(56288),f=t(79406),S=t(39793);const T=({isExpanded:e,onClick:s})=>(0,S.jsxs)(a.Button,{className:"woocommerce-task-products__button-view-less-product-types",onClick:s,children:[e?(0,o.__)("View less product types","woocommerce"):(0,o.__)("View more product types","woocommerce"),(0,S.jsx)(d.A,{icon:e?p.A:m.A})]}),L=()=>{const[e,s]=(0,r.useState)(!1),[t,c]=(0,r.useState)(!1),{installedPlugins:n,isRequestingPlugins:a}=(0,w.useSelect)((e=>{const{getInstalledPlugins:s,isPluginsRequesting:t}=e(_.pluginsStore);return{isRequestingPlugins:t("installPlugins"),installedPlugins:s()}}),[]),d=(0,h.p)((()=>{const e=(0,g.Qk)("onboarding");return e?.profile&&e?.profile.product_types||["physical"]})()),{productTypes:p,isRequesting:m}=(0,x.A)((0,h.h)(),d),{recordCompletionTime:L}=(0,y.A)("products"),E=(0,r.useMemo)((()=>p.map((e=>({...e,onClick:()=>{e.onClick(),L()}})))),[L,p]),{loadSampleProduct:N,isLoadingSampleProducts:F}=(0,b.A)({redirectUrlAfterSuccess:(0,l.getAdminLink)("edit.php?post_type=product&wc_onboarding_active_task=products")}),O=(0,r.useMemo)((()=>{const s=E.filter((e=>d.includes(e.key)));return e&&E.forEach((e=>!s.includes(e)&&s.push(e))),(0,k.applyFilters)(P.j1,s)}),[d,e,E]),q=(0,r.useMemo)((()=>{const e=[{...P.p3,onClick:()=>{P.p3.onClick(),L()}}];return!window.wcAdminFeatures?.printful||a||n.includes("printful-shipping-for-woocommerce")||e.push(P.tF),e}),[L,a,n]);return(0,S.jsxs)("div",{className:"woocommerce-task-products",children:[(0,S.jsx)(i.Text,{variant:"title",as:"h2",className:"woocommerce-task-products__title",children:(0,o.__)("What product do you want to add?","woocommerce")}),(0,S.jsxs)("div",{className:"woocommerce-product-content",children:[(0,S.jsx)(A.A,{items:O,onClickLoadSampleProduct:()=>c(!0),showOtherOptions:e,isTaskListItemClicked:m}),(0,S.jsx)(T,{isExpanded:e,onClick:()=>{e||(0,u.recordEvent)("tasklist_view_more_product_types_click"),s(!e)}}),(0,S.jsx)(A.A,{items:q,showOtherOptions:!1,isTaskListItemClicked:m}),(0,S.jsx)(v.d,{textProps:{className:"woocommerce-products-marketplace-link"},message:(0,o.__)("Visit {{Link}}the WooCommerce Marketplace{{/Link}} to enhance your store with additional options such as Subscriptions, Gift Cards, and more.","woocommerce"),eventName:"tasklist_add_product_visit_marketplace_click",targetUrl:(0,f.isFeatureEnabled)("marketplace")?(0,l.getAdminLink)("admin.php?page=wc-admin&tab=extensions&path=/extensions&category=merchandising"):"https://woocommerce.com/product-category/woocommerce-extensions/merchandising/",linkType:(0,f.isFeatureEnabled)("marketplace")?"wc-admin":"external"})]}),F?(0,S.jsx)(C.A,{}):t&&(0,S.jsx)(j.A,{onCancel:()=>{c(!1),(0,u.recordEvent)("tasklist_cancel_load_sample_products_click")},onImport:()=>{c(!1),N()}})]})},E=()=>(0,S.jsx)(c.WooOnboardingTask,{id:"products",children:(0,S.jsx)(L,{})});(0,n.registerPlugin)("wc-admin-onboarding-task-products",{scope:"woocommerce-tasks",render:()=>(0,S.jsx)(E,{})})}}]);

View File

@ -0,0 +1,4 @@
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}.woocommerce-task-products{display:flex;flex-direction:column;align-items:center}.woocommerce-task-products a{text-decoration:none;color:#007cba}.woocommerce-task-products .woocommerce-task-products__title{font-size:24px;text-align:center}.woocommerce-task-products .woocommerce-product-content{display:flex;flex-direction:column}.woocommerce-task-products .woocommerce-task-products__button-view-less-product-types{color:#007cba;padding:0;height:fit-content;margin-top:21px;justify-content:center}.woocommerce-task-products .woocommerce-task-products__button-view-less-product-types svg{margin-right:8px}.woocommerce-task-products .woocommerce-task-products__button-view-less-product-types:focus{color:#007cba;outline:none;box-shadow:none}.woocommerce-task-products .woocommerce-products-footer{margin-top:53px;display:flex;flex-direction:column}.woocommerce-task-products .woocommerce-products-footer__selling-somewhere-else{text-transform:uppercase;color:#757575;font-weight:500;font-size:11px;line-height:16px;margin-bottom:8px}.woocommerce-task-products .woocommerce-products-stack,.woocommerce-task-products .woocommerce-products-marketplace-link{max-width:550px;margin-top:24px}.woocommerce-task-products .woocommerce-products-stack:first-child,.woocommerce-task-products .woocommerce-products-marketplace-link:first-child{margin-top:32px}.woocommerce-task-products .woocommerce-list__item-before>svg{fill:var(--wp-admin-theme-color)}.woocommerce-task-products .woocommerce-list__item-before>svg .stroke-admin-theme{stroke:var(--wp-admin-theme-color)}@media(max-width: 600px){.woocommerce-task-products .woocommerce-products-marketplace-link{padding:0 16px}}
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}.woocommerce-products-stack{width:550px;position:relative}@media(max-width: 550px){.woocommerce-products-stack{width:100%}}.woocommerce-products-stack a{text-decoration:none;color:#007cba}.woocommerce-products-stack .woocommerce-list__item{margin-top:8px;border-radius:3px;border:1.5px solid #dcdcde}.woocommerce-products-stack .woocommerce-list__item:hover{background-color:#fff;border:1.5px solid #007cba}.woocommerce-products-stack .woocommerce-list__item:hover .woocommerce-list__item-title{color:#1e1e1e}.woocommerce-products-stack .woocommerce-list__item:not(.transitions-disabled).woocommerce-list__item-enter{transform:none}.woocommerce-products-stack .woocommerce-list__item:not(.transitions-disabled).woocommerce-list__item-enter-active{transform:none}.woocommerce-products-stack .woocommerce-list__item:not(.transitions-disabled).woocommerce-list__item-exit-active{display:none}.woocommerce-products-stack .woocommerce-list__item:first-child{margin-top:0}.woocommerce-products-stack .woocommerce-list__item.woocommerce-products-list__item-advert .woocommerce-list__item-before{background:none;border-radius:0;padding:0}.woocommerce-products-stack .woocommerce-list__item.woocommerce-products-list__item-advert .woocommerce-list__item-title span.printful-sponsored__text{display:flex;flex-direction:row;align-items:center;gap:8px}.woocommerce-products-stack .woocommerce-list__item.woocommerce-products-list__item-advert .woocommerce-label{background-color:rgba(var(--wp-admin-theme-color--rgb), 0.1);color:var(--wp-admin-theme-color, #000);border-radius:2px;padding:4px 8px;font-size:12px;font-weight:400;line-height:16px}.woocommerce-products-stack .woocommerce-list__item-inner{padding:20px}.woocommerce-products-stack .woocommerce-list__item-inner:focus{box-shadow:none}.woocommerce-products-stack .woocommerce-list__item-before{background:#f0f6fc;padding:8px;border-radius:50%}.woocommerce-products-stack .woocommerce-list__item-title{color:#1e1e1e;line-height:16px;font-weight:600}.woocommerce-products-stack .woocommerce-list__item-content{color:#757575;line-height:16px;font-weight:400}.woocommerce-products-stack .woocommerce-list__item-after svg{fill:#949494}.woocommerce-products-stack .woocommerce-stack__other-options{display:block;margin-top:20px;margin-bottom:4px;color:#757575;line-height:16px}.woocommerce-products-stack .woocommerce-stack__overlay-spinner{position:absolute;top:0;right:0;left:0;bottom:0;background-color:rgba(255,255,255,.8);display:flex;justify-content:center;align-items:center;z-index:999}.woocommerce-products-stack .woocommerce-stack__overlay-spinner .list-overlay{position:relative}
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}.woocommerce-products-load-sample-product-modal-overlay{top:0;background:rgba(255,255,255,.8)}@media(min-width: 783px){.woocommerce-products-load-sample-product-modal-overlay{right:35px}}@media(min-width: 960px){.woocommerce-products-load-sample-product-modal-overlay{right:160px}}.woocommerce-products-load-sample-product-modal{background:rgba(0,0,0,0);box-shadow:none}.woocommerce-products-load-sample-product-modal .components-modal__header{display:none}.woocommerce-products-load-sample-product-modal .components-modal__content,.woocommerce-products-load-sample-product-modal .components-modal__header+div{display:flex;flex-direction:column;align-items:center;justify-content:center;margin:0}.woocommerce-products-load-sample-product-modal .woocommerce-load-sample-product-modal__title{color:#1e1e1e;font-weight:400;font-size:24px;line-height:32px;margin-top:32px}.woocommerce-products-load-sample-product-modal .woocommerce-load-sample-product-modal__description{color:#757575;font-weight:400;font-size:16px;line-height:24px;margin-top:12px}
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}@media(min-width: 783px){.woocommerce-products-load-sample-product-confirm-modal-overlay{right:35px}}@media(min-width: 960px){.woocommerce-products-load-sample-product-confirm-modal-overlay{right:160px}}.woocommerce-products-load-sample-product-confirm-modal .components-truncate.components-text.woocommerce-confirmation-modal__message{color:#50575e}.woocommerce-products-load-sample-product-confirm-modal .woocommerce-confirmation-modal-actions{display:flex;justify-content:flex-end;margin-top:16px}.woocommerce-products-load-sample-product-confirm-modal .woocommerce-confirmation-modal-actions button{margin-right:16px}

View File

@ -0,0 +1,4 @@
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}.woocommerce-task-products{display:flex;flex-direction:column;align-items:center}.woocommerce-task-products a{text-decoration:none;color:#007cba}.woocommerce-task-products .woocommerce-task-products__title{font-size:24px;text-align:center}.woocommerce-task-products .woocommerce-product-content{display:flex;flex-direction:column}.woocommerce-task-products .woocommerce-task-products__button-view-less-product-types{color:#007cba;padding:0;height:fit-content;margin-top:21px;justify-content:center}.woocommerce-task-products .woocommerce-task-products__button-view-less-product-types svg{margin-left:8px}.woocommerce-task-products .woocommerce-task-products__button-view-less-product-types:focus{color:#007cba;outline:none;box-shadow:none}.woocommerce-task-products .woocommerce-products-footer{margin-top:53px;display:flex;flex-direction:column}.woocommerce-task-products .woocommerce-products-footer__selling-somewhere-else{text-transform:uppercase;color:#757575;font-weight:500;font-size:11px;line-height:16px;margin-bottom:8px}.woocommerce-task-products .woocommerce-products-stack,.woocommerce-task-products .woocommerce-products-marketplace-link{max-width:550px;margin-top:24px}.woocommerce-task-products .woocommerce-products-stack:first-child,.woocommerce-task-products .woocommerce-products-marketplace-link:first-child{margin-top:32px}.woocommerce-task-products .woocommerce-list__item-before>svg{fill:var(--wp-admin-theme-color)}.woocommerce-task-products .woocommerce-list__item-before>svg .stroke-admin-theme{stroke:var(--wp-admin-theme-color)}@media(max-width: 600px){.woocommerce-task-products .woocommerce-products-marketplace-link{padding:0 16px}}
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}.woocommerce-products-stack{width:550px;position:relative}@media(max-width: 550px){.woocommerce-products-stack{width:100%}}.woocommerce-products-stack a{text-decoration:none;color:#007cba}.woocommerce-products-stack .woocommerce-list__item{margin-top:8px;border-radius:3px;border:1.5px solid #dcdcde}.woocommerce-products-stack .woocommerce-list__item:hover{background-color:#fff;border:1.5px solid #007cba}.woocommerce-products-stack .woocommerce-list__item:hover .woocommerce-list__item-title{color:#1e1e1e}.woocommerce-products-stack .woocommerce-list__item:not(.transitions-disabled).woocommerce-list__item-enter{transform:none}.woocommerce-products-stack .woocommerce-list__item:not(.transitions-disabled).woocommerce-list__item-enter-active{transform:none}.woocommerce-products-stack .woocommerce-list__item:not(.transitions-disabled).woocommerce-list__item-exit-active{display:none}.woocommerce-products-stack .woocommerce-list__item:first-child{margin-top:0}.woocommerce-products-stack .woocommerce-list__item.woocommerce-products-list__item-advert .woocommerce-list__item-before{background:none;border-radius:0;padding:0}.woocommerce-products-stack .woocommerce-list__item.woocommerce-products-list__item-advert .woocommerce-list__item-title span.printful-sponsored__text{display:flex;flex-direction:row;align-items:center;gap:8px}.woocommerce-products-stack .woocommerce-list__item.woocommerce-products-list__item-advert .woocommerce-label{background-color:rgba(var(--wp-admin-theme-color--rgb), 0.1);color:var(--wp-admin-theme-color, #000);border-radius:2px;padding:4px 8px;font-size:12px;font-weight:400;line-height:16px}.woocommerce-products-stack .woocommerce-list__item-inner{padding:20px}.woocommerce-products-stack .woocommerce-list__item-inner:focus{box-shadow:none}.woocommerce-products-stack .woocommerce-list__item-before{background:#f0f6fc;padding:8px;border-radius:50%}.woocommerce-products-stack .woocommerce-list__item-title{color:#1e1e1e;line-height:16px;font-weight:600}.woocommerce-products-stack .woocommerce-list__item-content{color:#757575;line-height:16px;font-weight:400}.woocommerce-products-stack .woocommerce-list__item-after svg{fill:#949494}.woocommerce-products-stack .woocommerce-stack__other-options{display:block;margin-top:20px;margin-bottom:4px;color:#757575;line-height:16px}.woocommerce-products-stack .woocommerce-stack__overlay-spinner{position:absolute;top:0;left:0;right:0;bottom:0;background-color:rgba(255,255,255,.8);display:flex;justify-content:center;align-items:center;z-index:999}.woocommerce-products-stack .woocommerce-stack__overlay-spinner .list-overlay{position:relative}
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}.woocommerce-products-load-sample-product-modal-overlay{top:0;background:rgba(255,255,255,.8)}@media(min-width: 783px){.woocommerce-products-load-sample-product-modal-overlay{left:35px}}@media(min-width: 960px){.woocommerce-products-load-sample-product-modal-overlay{left:160px}}.woocommerce-products-load-sample-product-modal{background:rgba(0,0,0,0);box-shadow:none}.woocommerce-products-load-sample-product-modal .components-modal__header{display:none}.woocommerce-products-load-sample-product-modal .components-modal__content,.woocommerce-products-load-sample-product-modal .components-modal__header+div{display:flex;flex-direction:column;align-items:center;justify-content:center;margin:0}.woocommerce-products-load-sample-product-modal .woocommerce-load-sample-product-modal__title{color:#1e1e1e;font-weight:400;font-size:24px;line-height:32px;margin-top:32px}.woocommerce-products-load-sample-product-modal .woocommerce-load-sample-product-modal__description{color:#757575;font-weight:400;font-size:16px;line-height:24px;margin-top:12px}
:root{--wp-admin-theme-color: #007cba;--wp-admin-theme-color--rgb: 0, 124, 186;--wp-admin-theme-color-darker-10: #006ba1;--wp-admin-theme-color-darker-10--rgb: 0, 107, 161;--wp-admin-theme-color-darker-20: #005a87;--wp-admin-theme-color-darker-20--rgb: 0, 90, 135;--wp-admin-border-width-focus: 2px;--wp-block-synced-color: #7a00df;--wp-block-synced-color--rgb: 122, 0, 223;--wp-bound-block-color: var(--wp-block-synced-color)}@media(min-resolution: 192dpi){:root{--wp-admin-border-width-focus: 1.5px}}@media(min-width: 783px){.woocommerce-products-load-sample-product-confirm-modal-overlay{left:35px}}@media(min-width: 960px){.woocommerce-products-load-sample-product-confirm-modal-overlay{left:160px}}.woocommerce-products-load-sample-product-confirm-modal .components-truncate.components-text.woocommerce-confirmation-modal__message{color:#50575e}.woocommerce-products-load-sample-product-confirm-modal .woocommerce-confirmation-modal-actions{display:flex;justify-content:flex-end;margin-top:16px}.woocommerce-products-load-sample-product-confirm-modal .woocommerce-confirmation-modal-actions button{margin-left:16px}

Some files were not shown because too many files have changed in this diff Show More