├── module-gutenberg ├── src │ ├── products.sass │ ├── shop-editor.sass │ ├── shop-editor.js │ ├── featured-category.sass │ ├── products.jsx │ └── featured-category.jsx ├── dist │ ├── h-products.css │ ├── h-shop-editor.css │ ├── h-shop-editor.asset.php │ ├── h-products.asset.php │ ├── h-featured-category.asset.php │ ├── h-featured-category.css │ ├── h-shop-editor.js │ ├── h-products.js │ └── h-featured-category.js ├── _index.php ├── package.json └── webpack.config.js ├── src ├── js │ ├── hwc-admin.js │ └── hwc-public.js ├── images │ ├── spinner.gif │ └── thankyou-card.jpg └── sass │ ├── hwc-admin.sass │ ├── hwc-admin-profile.scss │ ├── _settings.scss │ ├── edje │ ├── _utility.scss │ ├── _utility-h.scss │ ├── _functional-vars.scss │ └── _output.scss │ └── hwc-myaccount.sass ├── dist ├── hwc-admin.css ├── hwc-admin.asset.php ├── hwc-public.asset.php ├── hwc-variations.asset.php ├── hwc-admin.js ├── hwc-public.js ├── hwc-variations.css └── hwc-variations.js ├── README.md ├── admin ├── _general.php └── locate-template.php ├── .gitattributes ├── composer.json ├── frontend ├── alert.php ├── my-account.php ├── cart.php ├── thank-you.php ├── products.php ├── my-account-register.php └── checkout.php ├── .eslintrc ├── package.json ├── module-widgets ├── widget--template.php ├── acf-json │ ├── group_61c67d8a280df.json │ └── group_62e8a1ac395ff.json ├── widget-myaccount.php ├── _index.php └── widget-cart.php ├── .gitignore ├── LICENSE.md ├── templates ├── page-checkout.php ├── checkout │ └── form-coupon.php ├── single-product │ ├── review.php │ └── tabs │ │ └── tabs.php ├── myaccount │ ├── form-lost-password.php │ ├── form-reset-password.php │ └── form-login.php └── cart │ └── cart.php ├── webpack.config.js ├── module-variations-ui ├── src │ ├── _settings.scss │ ├── hwc-variations.sass │ └── hwc-variations.js └── _index.php └── edje-wc-library.php /module-gutenberg/src/products.sass: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /module-gutenberg/dist/h-products.css: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /module-gutenberg/dist/h-shop-editor.css: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /module-gutenberg/src/shop-editor.sass: -------------------------------------------------------------------------------- 1 | ///// REVIEW 2 | -------------------------------------------------------------------------------- /src/js/hwc-admin.js: -------------------------------------------------------------------------------- 1 | import '../sass/hwc-admin.sass'; 2 | -------------------------------------------------------------------------------- /module-gutenberg/src/shop-editor.js: -------------------------------------------------------------------------------- 1 | import './shop-editor.sass'; 2 | -------------------------------------------------------------------------------- /dist/hwc-admin.css: -------------------------------------------------------------------------------- 1 | #widget-list [id*=woocommerce_widget_cart],#widget-list [id*=_block-]{display:none} 2 | -------------------------------------------------------------------------------- /src/images/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrsetyono/edje-wc-library/HEAD/src/images/spinner.gif -------------------------------------------------------------------------------- /src/images/thankyou-card.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrsetyono/edje-wc-library/HEAD/src/images/thankyou-card.jpg -------------------------------------------------------------------------------- /dist/hwc-admin.asset.php: -------------------------------------------------------------------------------- 1 | array('wp-polyfill'), 'version' => 'b447e3885e91d185d9b3eb4f63c62293'); -------------------------------------------------------------------------------- /dist/hwc-public.asset.php: -------------------------------------------------------------------------------- 1 | array('wp-polyfill'), 'version' => '48566b6bb36dcd3590b8df6585bae31d'); -------------------------------------------------------------------------------- /dist/hwc-variations.asset.php: -------------------------------------------------------------------------------- 1 | array('wp-polyfill'), 'version' => 'b08665b126a3b14e2f00813ea6a6926b'); -------------------------------------------------------------------------------- /module-gutenberg/dist/h-shop-editor.asset.php: -------------------------------------------------------------------------------- 1 | array('wp-polyfill'), 'version' => 'aabc2b439597fbd5af4a18d2970232a9'); -------------------------------------------------------------------------------- /src/sass/hwc-admin.sass: -------------------------------------------------------------------------------- 1 | ///// WIDGET Selection 2 | 3 | #widget-list 4 | [id*="woocommerce_widget_cart"], 5 | [id*="_block-"] 6 | display: none -------------------------------------------------------------------------------- /module-gutenberg/dist/h-products.asset.php: -------------------------------------------------------------------------------- 1 | array('lodash', 'wp-block-editor', 'wp-element', 'wp-hooks', 'wp-polyfill'), 'version' => 'd6ef043c2693dc04fe34dfc3e9bc8ed9'); -------------------------------------------------------------------------------- /module-gutenberg/dist/h-featured-category.asset.php: -------------------------------------------------------------------------------- 1 | array('lodash', 'wp-block-editor', 'wp-data', 'wp-element', 'wp-hooks', 'wp-polyfill'), 'version' => '5db98d1d580bec0163caf0ddac7fc53e'); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Edje WooCommerce Library 2 | 3 | This repo has been moved to https://github.com/pixelstudio-id/pixel-woo-library in order to fix the versioning. 4 | 5 | We are planning to follow WooCOmmerce version. So if the library's version is 7.6.x that means it's for WooCommerce 7.6.x 6 | -------------------------------------------------------------------------------- /admin/_general.php: -------------------------------------------------------------------------------- 1 | =7.0.0", 17 | "composer/installers": "~1.0" 18 | } 19 | } -------------------------------------------------------------------------------- /module-gutenberg/dist/h-featured-category.css: -------------------------------------------------------------------------------- 1 | .wc-block-featured-category .wc-block-featured-category__description, 2 | .wc-block-featured-product .wc-block-featured-product__description { 3 | margin-top: 1rem; 4 | } 5 | 6 | .wc-block-featured-category .wc-block-featured-category__wrapper:hover, 7 | .wc-block-featured-product .wc-block-featured-product__wrapper:hover { 8 | opacity: 1; 9 | transform: none; 10 | box-shadow: none; 11 | } 12 | 13 | .wc-block-featured-category .wc-block-featured-category__link, 14 | .wc-block-featured-product .wc-block-featured-product__link { 15 | display: none; 16 | } 17 | -------------------------------------------------------------------------------- /module-gutenberg/_index.php: -------------------------------------------------------------------------------- 1 | /', '', $message); // without tag 13 | 14 | $checkout_link = esc_url(wc_get_page_permalink('checkout')); 15 | $checkout_text = __('Checkout'); 16 | 17 | $button = "$checkout_text"; 18 | return $button . $real_message; 19 | } -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "env": { 4 | "node": true, 5 | "browser": true, 6 | "es6": true 7 | }, 8 | "extends": [ 9 | "airbnb-base" 10 | ], 11 | "parserOptions": { 12 | "parser": "babel-eslint" 13 | }, 14 | "plugins": [], 15 | "rules": { 16 | "max-len": 0, 17 | "linebreak-style": 0, 18 | "no-alert": "off", 19 | "no-param-reassign": [2, { "props": false }], 20 | "no-use-before-define": "off", 21 | "no-underscore-dangle": "off", 22 | "prefer-destructuring": [ 23 | "error", 24 | { 25 | "VariableDeclarator": { 26 | "array": false, 27 | "object": true 28 | }, 29 | "AssignmentExpression": { 30 | "array": false, 31 | "object": false 32 | } 33 | }, 34 | { 35 | "enforceForRenamedProperties": false 36 | } 37 | ] 38 | } 39 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "edje-wc-library", 3 | "private": true, 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/hrsetyono/edje-wc-library.git" 7 | }, 8 | "dependencies": {}, 9 | "devDependencies": { 10 | "@wordpress/components": "^11.1.1", 11 | "@wordpress/scripts": "^12.5.0", 12 | "css-loader": "^4.3.0", 13 | "eslint": "^7.32.0", 14 | "eslint-config-airbnb-base": "^14.2.1", 15 | "eslint-plugin-import": "^2.24.2", 16 | "file-loader": "^6.1.0", 17 | "mini-css-extract-plugin": "^0.11.2", 18 | "sass": "^1.53.0", 19 | "sass-loader": "^10.0.2", 20 | "url-loader": "^4.1.0" 21 | }, 22 | "scripts": { 23 | "build": "webpack --mode production", 24 | "dev": "webpack --mode development --watch" 25 | }, 26 | "babel": { 27 | "presets": [ 28 | "@wordpress/babel-preset-default" 29 | ] 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /module-gutenberg/src/featured-category.sass: -------------------------------------------------------------------------------- 1 | .wc-block-featured-category .wc-block-featured-category__wrapper, 2 | .wc-block-featured-product .wc-block-featured-product__wrapper 3 | &:hover 4 | opacity: 1 5 | transform: none 6 | box-shadow: none 7 | 8 | .wc-block-featured-category .wc-block-featured-category__link, 9 | .wc-block-featured-product .wc-block-featured-product__link 10 | display: none 11 | 12 | // .wc-block-featured-category .wc-block-featured-category__link, 13 | // .wc-block-featured-product .wc-block-featured-product__link 14 | // display: block 15 | // padding: 0 16 | // padding-top: 1rem 17 | 18 | // .wp-block-button 19 | // margin: 0 20 | 21 | // .wp-block-button .wp-block-button__link 22 | // position: static 23 | // padding: 0 0.5rem 24 | // background-color: var(--text) 25 | // font-size: 0 26 | 27 | // &::before 28 | // content: "Change Link" 29 | // font-size: var(--fontSize) -------------------------------------------------------------------------------- /dist/hwc-admin.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=1)}([,function(e,t,r){"use strict";r.r(t);r(2)},function(e,t,r){}]); -------------------------------------------------------------------------------- /module-widgets/widget--template.php: -------------------------------------------------------------------------------- 1 | __('Short description here') 9 | ]); 10 | } 11 | 12 | function widget($args, $instance) { 13 | $widget_id = 'widget_' . $args['widget_id']; 14 | $data = [ 15 | 'acf_field' => get_field('acf_field', $widget_id), 16 | ]; 17 | 18 | $custom_render = apply_filters('h_widget_name', '', $data); 19 | 20 | echo $args['before_widget']; 21 | echo $custom_render ? $custom_render : $this->render_widget($data); 22 | echo $args['after_widget']; 23 | } 24 | 25 | function render_widget($data) { 26 | [ 27 | 'acf_field' => $acf_field, 28 | ] = $data; 29 | ob_start(); ?> 30 | 31 |
32 | 33 |
34 | 35 | 2 | class="no-js"> 3 | 4 | 5 | 6 | 7 | 8 | 9 | <?php wp_title(''); ?> 10 | 11 | 12 | 13 | > 14 | ID); 18 | if ($thumbnail_url): ?> 19 |
20 | 21 |
22 | 23 | 24 |
25 | 28 |
29 |
30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /frontend/my-account.php: -------------------------------------------------------------------------------- 1 | customer->get_downloadable_products()) { 17 | unset($items['downloads']); 18 | } 19 | 20 | return $items; 21 | } 22 | 23 | /** 24 | * @action woocommerce_after_customer_login_form 25 | */ 26 | function h_myaccount_add_login_toggle() { 27 | ?> 28 |
29 |
30 | 31 | 32 | 33 |
34 |
35 | 36 | 37 | 38 |
39 |
40 | 14 |
15 | ' . esc_html__( 'Click here to enter your code', 'woocommerce' ) . '' ), 'notice' ); ?> 16 |
17 | 18 | 32 | -------------------------------------------------------------------------------- /module-gutenberg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "edje-wc-library--gutenberg", 3 | "license": "MIT", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/hrsetyono/edje-wc-library.git" 7 | }, 8 | "dependencies": { 9 | "@babel/polyfill": "^7.11.5" 10 | }, 11 | "devDependencies": { 12 | "@babel/cli": "^7.14.5", 13 | "@babel/core": "^7.14.6", 14 | "@babel/plugin-transform-runtime": "^7.14.5", 15 | "@babel/preset-env": "^7.14.5", 16 | "@wordpress/components": "^11.1.5", 17 | "@wordpress/scripts": "^12.6.1", 18 | "autoprefixer": "^10.2.6", 19 | "babel-core": "^7.0.0-bridge.0", 20 | "css-loader": "^4.3.0", 21 | "file-loader": "^6.1.0", 22 | "litepicker": "^1.5.7", 23 | "lodash": "^4.17.21", 24 | "mini-css-extract-plugin": "^0.11.2", 25 | "node-sass": "^4.14.1", 26 | "postcss": "^8.3.5", 27 | "postcss-loader": "^4.3.0", 28 | "sass-loader": "^10.2.0", 29 | "url-loader": "^4.1.0", 30 | "webpack": "^4.44.1", 31 | "webpack-cli": "^3.3.12" 32 | }, 33 | "scripts": { 34 | "prod": "webpack --mode production", 35 | "dev": "webpack --mode development --watch" 36 | }, 37 | "browserslist": [ 38 | "last 2 versions" 39 | ], 40 | "babel": { 41 | "presets": [ 42 | "@babel/preset-env", 43 | "@wordpress/babel-preset-default" 44 | ] 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /module-widgets/acf-json/group_61c67d8a280df.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": "group_61c67d8a280df", 3 | "title": "Edje Widget - Cart", 4 | "fields": [ 5 | { 6 | "key": "field_61c67e72cb76f", 7 | "label": "Cart Style", 8 | "name": "cart_style", 9 | "type": "button_group", 10 | "instructions": "", 11 | "required": 0, 12 | "conditional_logic": 0, 13 | "wrapper": { 14 | "width": "", 15 | "class": "", 16 | "id": "" 17 | }, 18 | "choices": { 19 | "default": "Default", 20 | "offcanvas": "Offcanvas" 21 | }, 22 | "allow_null": 0, 23 | "other_choice": 0, 24 | "default_value": "", 25 | "layout": "horizontal", 26 | "return_format": "value", 27 | "save_other_choice": 0 28 | } 29 | ], 30 | "location": [ 31 | [ 32 | { 33 | "param": "widget", 34 | "operator": "==", 35 | "value": "hwc_cart" 36 | } 37 | ] 38 | ], 39 | "menu_order": 0, 40 | "position": "normal", 41 | "style": "default", 42 | "label_placement": "top", 43 | "instruction_placement": "label", 44 | "hide_on_screen": "", 45 | "active": true, 46 | "description": "", 47 | "show_in_rest": 0, 48 | "modified": 1640399465 49 | } -------------------------------------------------------------------------------- /templates/single-product/review.php: -------------------------------------------------------------------------------- 1 | ` 5 | */ 6 | if ( ! defined( 'ABSPATH' ) ) { 7 | exit; // Exit if accessed directly 8 | } 9 | ?> 10 | 11 |
  • id="li-comment-"> 12 |
    13 | 14 |
    15 | 21 |
    22 | 33 |
    34 |
    35 |
    36 | 46 |
    47 |
    -------------------------------------------------------------------------------- /frontend/cart.php: -------------------------------------------------------------------------------- 1 | {$message}

    "; 22 | } 23 | 24 | 25 | /** 26 | * Change the thumbnail size of product image in cart 27 | * 28 | * @filter woocommerce_cart_item_thumbnail 29 | */ 30 | function h_cart_change_thumbnail_size($img, $cart_item) { 31 | if(isset($cart_item['product_id'])) { 32 | return get_the_post_thumbnail($cart_item['product_id'], 'thumbnail'); 33 | } 34 | 35 | return $img; 36 | } 37 | 38 | /** 39 | * Add button to increment and decrement the Order Form 40 | * 41 | * @action woocommerce_before_quantity_input_field 42 | */ 43 | function h_add_order_quantity_control() { 44 | echo ''; 45 | echo ''; 46 | } -------------------------------------------------------------------------------- /templates/myaccount/form-lost-password.php: -------------------------------------------------------------------------------- 1 | 11 | 12 |
    13 | 14 |

    15 | 16 |

    17 | 18 | 19 |

    20 | 21 |
    22 | 23 | 24 | 25 |

    26 | 27 | 28 |

    29 | 30 | 31 | 32 |
    33 | "; 11 | } 12 | 13 | /** 14 | * 15 | */ 16 | function h_thankyou_add_closing_wrapper() { 17 | echo ""; 18 | } 19 | 20 | /* 21 | Functions for Thank You page 22 | */ 23 | class Checkout_Thankyou { 24 | 25 | function __construct() { 26 | add_action( 'woocommerce_before_thankyou', array($this, 'before_thankyou'), 1 ); 27 | add_action( 'woocommerce_thankyou', array($this, 'between_thankyou'), 1 ); 28 | add_action( 'woocommerce_thankyou', array($this, 'after_thankyou'), 1000 ); 29 | } 30 | 31 | /* 32 | Add wrapper for Thank you page 33 | 34 | @action woocommerce_before_thankyou 35 | @action woocommerce_thankyou 36 | */ 37 | function before_thankyou( $order_id ) { 38 | echo '
    '; 39 | echo '
    '; 40 | // jetpack_breadcrumbs(); 41 | } 42 | 43 | function between_thankyou( $order_id ) { 44 | $order = wc_get_order( $order_id ); 45 | $show_customer_details = is_user_logged_in() && $order->get_user_id() === get_current_user_id(); 46 | if( $show_customer_details ) { 47 | wc_get_template( 'order/order-details-customer.php', array('order' => $order) ); 48 | } 49 | 50 | echo '
    '; 51 | echo '
    '; 52 | } 53 | 54 | function after_thankyou( $order_id ) { 55 | echo '
    '; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const DependencyExtractionWebpackPlugin = require('@wordpress/dependency-extraction-webpack-plugin'); 2 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 3 | const path = require('path'); 4 | 5 | const jsPath = './src/js'; 6 | const outputPath = 'dist'; 7 | const entryPoints = { 8 | 'hwc-public': `${jsPath}/hwc-public.js`, 9 | 'hwc-admin': `${jsPath}/hwc-admin.js`, 10 | 'hwc-variations': './module-variations-ui/src/hwc-variations.js', 11 | }; 12 | 13 | module.exports = { 14 | entry: entryPoints, 15 | output: { 16 | path: path.resolve(__dirname, outputPath), 17 | filename: '[name].js', 18 | }, 19 | plugins: [ 20 | new MiniCssExtractPlugin({ 21 | filename: '[name].css', 22 | }), 23 | 24 | new DependencyExtractionWebpackPlugin({ 25 | injectPolyfill: true, 26 | }), 27 | ], 28 | module: { 29 | rules: [ 30 | { 31 | test: /\.s?[ac]ss$/i, 32 | use: [ 33 | MiniCssExtractPlugin.loader, 34 | 'css-loader', 35 | 'sass-loader', 36 | ], 37 | }, 38 | { 39 | test: /\.(jpg|jpeg|png|gif|woff|woff2|eot|ttf|svg)$/i, 40 | use: 'url-loader?limit=1024', 41 | }, 42 | { 43 | test: /\.jsx$/i, 44 | use: [ 45 | require.resolve('thread-loader'), 46 | { 47 | loader: require.resolve('babel-loader'), 48 | options: { 49 | cacheDirectory: process.env.BABEL_CACHE_DIRECTORY || true, 50 | babelrc: false, 51 | configFile: false, 52 | presets: [ 53 | require.resolve('@wordpress/babel-preset-default'), 54 | ], 55 | }, 56 | }, 57 | ], 58 | }, 59 | ], 60 | }, 61 | }; 62 | -------------------------------------------------------------------------------- /admin/locate-template.php: -------------------------------------------------------------------------------- 1 | template_url; 14 | } 15 | 16 | $plugin_path = HWC_PATH . '/templates/'; 17 | 18 | // Look within passed path within the theme - this is priority 19 | $template = locate_template( 20 | array($template_path . $template_name, $template_name) 21 | ); 22 | 23 | if(!$template && file_exists( $plugin_path . $template_name ) ) { 24 | $template = $plugin_path . $template_name; 25 | } 26 | 27 | if(!$template ) { 28 | $template = $_template; 29 | } 30 | 31 | return $template; 32 | } 33 | 34 | /** 35 | * Locate the called template in /plugins/your-plugin/templates/$template_name. 36 | * http://jeroensormani.com/how-to-add-template-files-in-your-plugin/ 37 | * 38 | * @param string $template_name - Template to load. 39 | * @param string $default_path - Default path to template files. 40 | * @return string - Path to the template file. 41 | */ 42 | function hoo_locate_template( $template_name, $default_path = '' ) { 43 | // Set default plugin templates path. 44 | if(!$default_path) { 45 | $default_path = $_SERVER['DOCUMENT_ROOT'] . '/wp-content/plugins/edje-wc-library/templates/'; // Path to the template folder 46 | } 47 | 48 | $template = $default_path . $template_name; 49 | 50 | return apply_filters( 'hoo_locate_template', $template, $template_name, $default_path ); 51 | } -------------------------------------------------------------------------------- /module-gutenberg/webpack.config.js: -------------------------------------------------------------------------------- 1 | const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' ); 2 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 3 | // const BrowserSyncPlugin = require('browser-sync-webpack-plugin'); 4 | var path = require('path'); 5 | 6 | const outputPath = 'dist'; 7 | // const localDomain = 'http://shop.test/'; 8 | const entryPoints = { 9 | 'h-shop-editor': './src/shop-editor.js', 10 | 'h-featured-category': './src/featured-category.jsx', 11 | 'h-products': './src/products.jsx', 12 | }; 13 | 14 | module.exports = { 15 | entry: entryPoints, 16 | output: { 17 | path: path.resolve(__dirname, outputPath), 18 | filename: '[name].js', 19 | }, 20 | plugins: [ 21 | new MiniCssExtractPlugin({ 22 | filename: '[name].css', 23 | }), 24 | 25 | new DependencyExtractionWebpackPlugin( { 26 | injectPolyfill: true 27 | } ), 28 | ], 29 | module: { 30 | rules: [ 31 | { 32 | test: /\.s?[ac]ss$/i, 33 | use: [ 34 | MiniCssExtractPlugin.loader, 35 | 'css-loader', 36 | 'sass-loader', 37 | ] 38 | }, 39 | { 40 | test: /\.(jpg|jpeg|png|gif|woff|woff2|eot|ttf|svg)$/i, 41 | use: 'url-loader?limit=1024' 42 | }, 43 | { 44 | test: /\.jsx$/i, 45 | use: [ 46 | require.resolve( 'thread-loader' ), 47 | { 48 | loader: require.resolve( 'babel-loader' ), 49 | options: { 50 | cacheDirectory: process.env.BABEL_CACHE_DIRECTORY || true, 51 | babelrc: false, 52 | configFile: false, 53 | presets: [ 54 | require.resolve( '@wordpress/babel-preset-default' ), 55 | ], 56 | }, 57 | }, 58 | ], 59 | } 60 | ] 61 | }, 62 | 63 | }; -------------------------------------------------------------------------------- /module-variations-ui/src/_settings.scss: -------------------------------------------------------------------------------- 1 | $version: 0; 2 | 3 | $text: #333; 4 | $text-dim: #5c6c7a; 5 | $text-invert: #ebeef0; 6 | 7 | $border: #eee; 8 | $panel: #fafafa; 9 | 10 | $red : #e35950; 11 | $yellow : #edc200; 12 | $green : #4caf50; 13 | $blue: #47c1bf; 14 | 15 | $purple: #763eaf; 16 | $orange: #ff9517; 17 | 18 | $red-light : #ffc58b; 19 | $yellow-light : #ffea8a; 20 | $green-light : #c8e6c9; 21 | $blue-light: #cae9f7; 22 | 23 | $g-radius: 4px; 24 | $g-transition: all .25s ease-in-out; 25 | 26 | @mixin variation-select($color) { 27 | color: $color; 28 | 29 | &:hover { background-color: rgba($color, .2); } 30 | } 31 | 32 | @mixin wp-button() { 33 | cursor: pointer; 34 | display: inline-block; 35 | background: #f7f7f7; 36 | height: 28px; 37 | width: 28px; 38 | margin: 0; 39 | padding: 0; 40 | border: 1px solid #ccc; 41 | 42 | white-space: nowrap; 43 | text-decoration: none; 44 | font-size: 13px; 45 | line-height: 26px; 46 | color: #555; 47 | border-color: #ccc; 48 | vertical-align: top; 49 | 50 | -webkit-appearance: none; 51 | border-radius: 3px; 52 | box-sizing: border-box; 53 | box-shadow: 0 1px 0 #ccc; 54 | 55 | &:hover { 56 | background: #fafafa; 57 | border-color: #999; 58 | color: #23282d; 59 | } 60 | 61 | &:active { 62 | background: #eee; 63 | background-color: white; 64 | border-color: #999; 65 | 66 | box-shadow: inset 0 2px 5px -3px rgba(0,0,0,.5); 67 | -webkit-transform: translateY(1px); 68 | transform: translateY(1px); 69 | } 70 | } 71 | 72 | @mixin wp-button-error-on-hover() { 73 | &:hover { 74 | background: #e35950; 75 | border-color: #ba281e; 76 | color: #fff; 77 | box-shadow: 0 1px 0 #ba281e; 78 | } 79 | 80 | &:active { 81 | background: #d02c21; 82 | border-color: #ba281e; 83 | box-shadow: inset 0 2px 0 #ba281e; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /module-widgets/acf-json/group_62e8a1ac395ff.json: -------------------------------------------------------------------------------- 1 | { 2 | "key": "group_62e8a1ac395ff", 3 | "title": "Edje Widget - My Account Button", 4 | "fields": [ 5 | { 6 | "key": "field_62e8a1be39d2e", 7 | "label": "Label Logged Out", 8 | "name": "label_logged_out", 9 | "type": "text", 10 | "instructions": "Leave empty to not have a label", 11 | "required": 0, 12 | "conditional_logic": 0, 13 | "wrapper": { 14 | "width": "", 15 | "class": "", 16 | "id": "" 17 | }, 18 | "default_value": "Login", 19 | "placeholder": "", 20 | "prepend": "", 21 | "append": "", 22 | "maxlength": "" 23 | }, 24 | { 25 | "key": "field_62e8a1c939d2f", 26 | "label": "Label Logged In", 27 | "name": "label_logged_in", 28 | "type": "text", 29 | "instructions": "", 30 | "required": 0, 31 | "conditional_logic": 0, 32 | "wrapper": { 33 | "width": "", 34 | "class": "", 35 | "id": "" 36 | }, 37 | "default_value": "View Profile", 38 | "placeholder": "", 39 | "prepend": "", 40 | "append": "", 41 | "maxlength": "" 42 | } 43 | ], 44 | "location": [ 45 | [ 46 | { 47 | "param": "widget", 48 | "operator": "==", 49 | "value": "hwc_myaccount" 50 | } 51 | ] 52 | ], 53 | "menu_order": 0, 54 | "position": "normal", 55 | "style": "default", 56 | "label_placement": "top", 57 | "instruction_placement": "label", 58 | "hide_on_screen": "", 59 | "active": true, 60 | "description": "", 61 | "show_in_rest": 0, 62 | "modified": 1662369364 63 | } -------------------------------------------------------------------------------- /templates/single-product/tabs/tabs.php: -------------------------------------------------------------------------------- 1 | 23 | 24 |
    25 |
      26 | $product_tab ) : ?> 27 | 32 | 33 |
    34 | $product_tab ) : ?> 35 |
    39 | 40 | 41 | 42 |
    43 |
    44 | 49 |
    50 | 51 | 52 | 53 |
    54 | 55 | 56 | -------------------------------------------------------------------------------- /edje-wc-library.php: -------------------------------------------------------------------------------- 1 | 11 | 12 |
    13 | 14 |

    15 | 16 |

    17 | 18 | 19 |

    20 |

    21 | 22 | 23 |

    24 | 25 | 26 | 27 | 28 |
    29 | 30 | 31 | 32 |

    33 | 34 | 35 |

    36 | 37 | 38 | 39 |
    40 | __('Create a link to My Account page') 10 | ]); 11 | } 12 | 13 | function widget($args, $instance) { 14 | $widget_id = 'widget_' . $args['widget_id']; 15 | 16 | $label_logged_out = get_field('label_logged_out', $widget_id); 17 | $label_logged_in = get_field('label_logged_in', $widget_id); 18 | 19 | $data = apply_filters('hwc_widget_myaccount_args', [ 20 | 'label_logged_out' => $label_logged_out ? $label_logged_out : 'Login', 21 | 'label_logged_in' => $label_logged_in ? $label_logged_in : 'View Profile', 22 | 'icon' => '', 23 | ]); 24 | 25 | $custom_render = apply_filters('hwc_widget_myaccount', '', $data); 26 | 27 | echo $args['before_widget']; 28 | echo $custom_render ? $custom_render : $this->render_widget($data); 29 | echo $args['after_widget']; 30 | } 31 | 32 | function render_widget($data) { 33 | [ 34 | 'label_logged_out' => $label_logged_out, 35 | 'label_logged_in' => $label_logged_in, 36 | 'icon' => $icon, 37 | ] = $data; 38 | ob_start(); ?> 39 | 40 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | { 37 | // abort if not our targetted block 38 | let targetBlocks = [ 'woocommerce/handpicked-products' ]; 39 | if ( !targetBlocks.includes( props.name ) ) { 40 | return ( 41 | 42 | ); 43 | } 44 | 45 | let atts = props.attributes; 46 | 47 | return ( 48 | 49 | 50 | 51 | 54 | 55 | 56 | ); 57 | 58 | // 59 | function updateAlignment( newValue ) { 60 | newValue = newValue || ''; 61 | props.setAttributes({ textAlign: newValue }); 62 | 63 | // remove existing alignment class 64 | if( atts.className ) { 65 | atts.className = atts.className.replace( /has-text-align-\w+/, '' ).trim(); 66 | } else { 67 | atts.className = ''; // initialize 68 | } 69 | 70 | // add Align class 71 | if( newValue ) { 72 | props.setAttributes({ className: `${atts.className} has-text-align-${ newValue }` }); 73 | } 74 | } 75 | }; 76 | } -------------------------------------------------------------------------------- /module-widgets/_index.php: -------------------------------------------------------------------------------- 1 | __('Create a Cart dropdown menu') 13 | ]); 14 | } 15 | 16 | /** 17 | * 18 | */ 19 | function widget($args, $instance) { 20 | $widget_id = 'widget_' . $args['widget_id']; 21 | $data = [ 22 | 'cart_style' => get_field('cart_style', $widget_id), 23 | ]; 24 | 25 | $custom_render = apply_filters('hwc_widget_cart', '', $data); 26 | 27 | echo $args['before_widget']; 28 | echo $custom_render ? $custom_render : $this->render_widget($data); 29 | echo $args['after_widget']; 30 | } 31 | 32 | /** 33 | * 34 | */ 35 | function render_widget($data) { 36 | [ 37 | 'cart_style' => $cart_style, 38 | ] = $data; 39 | ob_start(); ?> 40 | 41 |
    42 | 43 | 44 |
    45 | 46 | cart->get_cart_contents_count(); 56 | $count = $count > 0 ? "{$count}" : ''; 57 | 58 | $extra_class = $woocommerce->cart->is_empty() ? 'is-cart-empty' : 'is-cart-filled'; 59 | 60 | $args = apply_filters('hwc_cart_button_args', [ 61 | 'label' => '' . __('Cart') . '', 62 | 'icon' => '', 63 | ]); 64 | 65 | $button = " 66 | {$args['icon']} {$count} {$args['label']} 67 | "; 68 | return $button; 69 | } 70 | 71 | /** 72 | * @filter woocommerce_add_to_cart_fragments 73 | */ 74 | function _hwc_cart_button_fragment($fragments) { 75 | $fragments['.is-cart-button'] = _hwc_cart_button(); 76 | return $fragments; 77 | } -------------------------------------------------------------------------------- /dist/hwc-public.js: -------------------------------------------------------------------------------- 1 | !function(e){var t={};function o(n){if(t[n])return t[n].exports;var c=t[n]={i:n,l:!1,exports:{}};return e[n].call(c.exports,c,c.exports,o),c.l=!0,c.exports}o.m=e,o.c=t,o.d=function(e,t,n){o.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},o.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},o.t=function(e,t){if(1&t&&(e=o(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var c in e)o.d(n,c,function(t){return e[t]}.bind(null,c));return n},o.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return o.d(t,"a",t),t},o.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},o.p="",o(o.s=0)}([function(e,t){const o={init(){document.querySelectorAll(".woocommerce-cart .woocommerce, form.cart").forEach(e=>{e.addEventListener("click",this.changeQuantity)})},changeQuantity(e){if(!e.target.classList.contains("quantity__h-spin"))return;e.preventDefault();const t=e.target.closest(".quantity").querySelector('input[type="number"]'),o=e.target.classList.contains("is-plus")?1:-1,n=parseInt(t.value,10)+o;if(n<=0)return;t.value=n;const c=new Event("input",{bubbles:!0});t.dispatchEvent(c)}},n={init(){[...document.querySelectorAll(".h-cart")].forEach(e=>{e.addEventListener("click",this.openPopup)}),document.addEventListener("click",this.closePopup)},openPopup(e){(e.target.classList.contains("is-cart-button")||e.target.closest(".is-cart-button"))&&(e.preventDefault(),e.target.closest(".h-cart").classList.toggle("is-active"))},closePopup(e){if(e.target.closest(".widget_shopping_cart")||e.target.closest(".is-cart-button"))return;const t=document.querySelector(".h-cart.is-active");t&&t.classList.remove("is-active")}},c={init(){if(!document.querySelector("body").classList.contains("woocommerce-checkout"))return;const e=document.querySelectorAll(".showcoupon, .showlogin"),t=document.querySelectorAll(".woocommerce-form-coupon, .woocommerce-form-login"),o=document.querySelector(".woocommerce-form-coupon");[...e].forEach(e=>{e.addEventListener("click",this.openForm)}),[...t].forEach(e=>{e.addEventListener("click",e=>e.stopPropagation())}),document.addEventListener("click",this.closeForm),o&&o.addEventListener("submit",this.closeForm)},openForm(e){e.preventDefault(),e.stopPropagation();const t=e.target.classList.contains("showcoupon")?".woocommerce-form-coupon":".woocommerce-form-login",o=document.querySelector(t);o&&(o.classList.toggle("is-open"),document.querySelector("body").classList.toggle("has-checkout-form-open"))},closeForm(){const e=document.querySelector(".woocommerce-form-coupon.is-open, .woocommerce-form-login.is-open");e&&(document.querySelector("body").classList.remove("has-checkout-form-open"),e.classList.remove("is-open"))}},r={init(){[...document.querySelectorAll(".h-tab-mobile a")].forEach(e=>{e.addEventListener("click",this.onClick)})},onClick(e){e.preventDefault();const t=e.currentTarget.getAttribute("href"),o=document.querySelector(t),n=e.currentTarget.closest(".h-tab-mobile");o&&(n.classList.contains("active")?o.style.display="none":o.style.display="",n.classList.toggle("active"))}};document.addEventListener("DOMContentLoaded",(function(){o.init(),n.init(),c.init(),r.init()})),document.addEventListener("load",(function(){}))}]); -------------------------------------------------------------------------------- /src/sass/hwc-admin-profile.scss: -------------------------------------------------------------------------------- 1 | @import "setting-admin"; 2 | @import "edje-v15"; 3 | 4 | ///// USER PROFILE 5 | 6 | #your-profile { 7 | 8 | @include display-flex; 9 | flex-wrap: wrap; 10 | 11 | *, 12 | *::before, 13 | *::after { 14 | box-sizing: border-box; 15 | } 16 | 17 | .form-table { 18 | display: block; 19 | width: 40%; 20 | background-color: white; 21 | padding: 1.25em; 22 | margin-bottom: 1.5em; 23 | border: 1px solid rgba(black, .15); 24 | border-radius: $g-radius; 25 | 26 | @include below( small ) { 27 | width: 80%; 28 | } 29 | 30 | @include below( mini ) { 31 | width: 100%; 32 | } 33 | } 34 | 35 | h2 { 36 | width: 100%; 37 | margin-top: 0.5rem; 38 | margin-bottom: 0.5rem; 39 | line-height: 1.3; 40 | 41 | font-size: 28px; 42 | font-weight: 400; 43 | 44 | @include below( small ) { 45 | width: 20%; 46 | margin-bottom: 0; 47 | } 48 | 49 | @include below( mini ) { 50 | width: 100%; 51 | padding-left: 0; 52 | font-size: 22px; 53 | } 54 | } 55 | 56 | tbody { 57 | @include display-flex; 58 | flex-wrap: wrap; 59 | margin: 0 -0.5em; 60 | } 61 | 62 | tr { 63 | width: 50%; 64 | padding: 0 0.5em; 65 | 66 | @include below( mini ) { 67 | width: 100%; 68 | margin-bottom: 0.5em; 69 | } 70 | } 71 | 72 | th, td { 73 | display: block; 74 | padding: 0; 75 | } 76 | 77 | th { 78 | color: $color-passive; 79 | } 80 | 81 | td { 82 | margin-bottom: 12px; 83 | } 84 | 85 | // field size 86 | 87 | input[type="text"], 88 | input[type="email"], 89 | input[type="url"], 90 | select, 91 | .form-table textarea, { 92 | width: 100%; 93 | padding: 5px 10px; 94 | } 95 | 96 | .select2-container { 97 | width: 100% !important; 98 | } 99 | 100 | .user-description-wrap, 101 | .user-profile-picture { 102 | width: 100%; 103 | 104 | p { display: none; } 105 | img { width: 75px; height: auto; } 106 | td { margin-bottom: 0; } 107 | } 108 | 109 | .user-sessions-wrap { 110 | width: 100%; 111 | } 112 | } 113 | 114 | #your-profile { 115 | ///// field order 116 | 117 | // ADMIN COLOR 118 | table:first-of-type, 119 | h2:first-of-type { 120 | display: none; 121 | } 122 | 123 | // NAME 124 | h2:nth-of-type(2), 125 | table:nth-of-type(2) { 126 | order: 1; 127 | } 128 | 129 | // CONTACT INFO 130 | h2:nth-of-type(3), 131 | table:nth-of-type(3) { 132 | order: 3; 133 | } 134 | 135 | // ABOUT THE USER 136 | h2:nth-of-type(4), 137 | table:nth-of-type(4) { 138 | order: 2; 139 | } 140 | 141 | // ACCOUNT MANAGEMENT 142 | h2:nth-of-type(5), 143 | table:nth-of-type(5) { 144 | order: 4; 145 | } 146 | 147 | // BILLING ADDRESS 148 | h2:nth-of-type(6), 149 | table:nth-of-type(6) { 150 | order: 5; 151 | } 152 | 153 | // BILLING ADDRESS 154 | h2:nth-of-type(7), 155 | table:nth-of-type(7) { 156 | order: 6; 157 | } 158 | 159 | .submit { 160 | order: 7; 161 | width: 100%; 162 | } 163 | 164 | 165 | ///// field design 166 | 167 | table:nth-of-type(4), 168 | table:nth-of-type(5) { 169 | background-color: $panel-bg; 170 | } 171 | 172 | } 173 | 174 | // Shipping and Billing 175 | 176 | #your-profile { 177 | #fieldset-billing, 178 | #fieldset-shipping { 179 | br { display: none; } 180 | } 181 | 182 | #fieldset-billing { 183 | tr:nth-child(1), 184 | tr:nth-child(2), 185 | tr:nth-child(3) { 186 | width: 33.333%; 187 | } 188 | } 189 | 190 | #fieldset-shipping { 191 | tr:nth-child(1) { 192 | width: 100%; 193 | } 194 | 195 | tr:nth-child(2), 196 | tr:nth-child(3), 197 | tr:nth-child(4) { 198 | width: 33.333%; 199 | } 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /module-gutenberg/src/featured-category.jsx: -------------------------------------------------------------------------------- 1 | // Add Vertical Alignment to woocommerce/featured-category block 2 | 3 | import './featured-category.sass'; 4 | 5 | import { assign } from 'lodash'; 6 | import { addFilter } from '@wordpress/hooks'; 7 | import { select } from '@wordpress/data'; 8 | import { Fragment } from '@wordpress/element'; 9 | import { 10 | BlockControls, 11 | BlockVerticalAlignmentToolbar, 12 | getColorObjectByColorValue, 13 | InspectorControls, 14 | PanelColorSettings } from '@wordpress/block-editor'; 15 | 16 | 17 | addFilter( 'blocks.registerBlockType', 'wc-featured-category/attributes', addAttribute ); 18 | addFilter( 'editor.BlockEdit', 'wc-featured-category/edit', addControl ); 19 | 20 | 21 | /** 22 | * Add the Vertical Align attribute 23 | */ 24 | function addAttribute( settings, name ) { 25 | // abort if not our targetted block 26 | let targetBlocks = [ 'woocommerce/featured-category', 'woocommerce/featured-product' ]; 27 | if ( !targetBlocks.includes( name ) ) { 28 | return settings; 29 | } 30 | 31 | settings.attributes = assign( settings.attributes, { 32 | verticalAlignment: { type: 'string', default: 'center' }, 33 | textColor: { type: 'string', default: 'white' }, 34 | } ); 35 | 36 | return settings; 37 | } 38 | 39 | 40 | /** 41 | * Add the Vertical Align option to the toolbar 42 | */ 43 | function addControl( BlockEdit ) { 44 | return ( props ) => { 45 | // abort if not our targetted block 46 | let targetBlocks = [ 'woocommerce/featured-category', 'woocommerce/featured-product' ]; 47 | if ( !targetBlocks.includes( props.name ) ) { 48 | return ( 49 | 50 | ); 51 | } 52 | 53 | let atts = props.attributes; 54 | 55 | return ( 56 | 57 | 58 | 59 | 63 | 64 | 65 | 75 | 76 | 77 | 78 | ); 79 | 80 | 81 | // 82 | function updateAlignment( newValue ) { 83 | newValue = newValue || ''; 84 | props.setAttributes( { verticalAlignment: newValue } ); 85 | 86 | // remove existing VAlign class 87 | if( atts.className ) { 88 | atts.className = atts.className.replace( /is-vertically-aligned-\w+/, '' ); 89 | } else { 90 | atts.className = ''; // initialize 91 | } 92 | 93 | // add VAlign class 94 | if( newValue ) { 95 | props.setAttributes({ className: `${atts.className} is-vertically-aligned-${ newValue }` }); 96 | } 97 | } 98 | 99 | /** 100 | * 101 | */ 102 | function updateTextColor( newColor ) { 103 | newColor = newColor || 'white'; 104 | props.setAttributes({ textColor: newColor }); 105 | 106 | // remove existing color class 107 | if( atts.className ) { 108 | atts.className = atts.className.replace( /has-text-color has-[\w-]+-color/, '' ).trim(); 109 | } else { 110 | atts.className = ''; // initialize 111 | } 112 | 113 | // if none selected 114 | if( newColor === 'white' ) { 115 | props.setAttributes({ className: atts.className.trim() }); 116 | } 117 | else { 118 | const settings = select( 'core/editor' ).getEditorSettings(); 119 | const colorObject = getColorObjectByColorValue( settings.colors, newColor ); 120 | 121 | props.setAttributes({ className: `${atts.className} has-text-color has-${colorObject.slug}-color` }); 122 | } 123 | } 124 | }; 125 | } -------------------------------------------------------------------------------- /frontend/products.php: -------------------------------------------------------------------------------- 1 | 73 | 74 | {$data->image} 75 | {$data->title} 76 | 77 | {$new_badge} 78 | {$data->price} 79 | {$data->rating} 80 | {$data->button} 81 |
  • "; 82 | } 83 | 84 | 85 | /** 86 | * Get a Sale badge saying "% Off" 87 | * 88 | * @param WC_Product $product 89 | * @return string - HTML of the badge 90 | */ 91 | function _h_get_sale_badge($product) : string { 92 | $percentage = 100; 93 | 94 | if ($product->is_type('variable')) { 95 | $percentages = []; 96 | 97 | $prices = $product->get_variation_prices(); 98 | 99 | foreach ($prices['price'] as $key => $price) { 100 | if ($prices['regular_price'][$key] !== $price) { 101 | $percentages[] = round( 102 | 100 - ( 103 | $prices['sale_price'][$key] / $prices['regular_price'][$key] * 100 104 | ) 105 | ); 106 | } 107 | } 108 | 109 | if (count($percentages) >= 1) { 110 | $percentage = max($percentages); 111 | } 112 | } else { 113 | $regular_price = (float) $product->get_regular_price(); 114 | $sale_price = (float) $product->get_sale_price(); 115 | 116 | if ($regular_price > 0) { 117 | $percentage = round(100 - ($sale_price / $regular_price * 100)); 118 | } 119 | } 120 | 121 | // if has discount 122 | if ($percentage < 100) { 123 | $label = sprintf(__('%s%% Off'), $percentage); 124 | $label = apply_filters('h_product_onsale_label', $label, $percentage); 125 | return "{$label}"; 126 | } 127 | 128 | return ''; 129 | } 130 | 131 | /** 132 | * Get an "Out of Stock" badge 133 | */ 134 | function _h_get_outofstock_badge($product) : string { 135 | if (!$product->is_in_stock()) { 136 | $label = __('Out of Stock'); 137 | return "{$label}"; 138 | } 139 | 140 | return ''; 141 | } -------------------------------------------------------------------------------- /frontend/my-account-register.php: -------------------------------------------------------------------------------- 1 | fields = $this->_set_fields(); 15 | } 16 | 17 | /* 18 | @action woocommerce_register_form_start 19 | */ 20 | function add_extra_register_fields() { 21 | foreach ($this->fields as $name => $field) { 22 | woocommerce_form_field($name, $field); 23 | } 24 | } 25 | 26 | /* 27 | @action woocommerce_register_post 28 | */ 29 | function validate_extra_register_fields( $username, $email, $validation_errors ) { 30 | foreach($this->fields as $name => $field) { 31 | 32 | $required_isset = isset( $field['required'] ); 33 | // if required arg doesn't exist OR exist but false 34 | if( !$required_isset || ( $required_isset && !$field['required'] ) ) { 35 | continue; 36 | } 37 | 38 | // if field not empty 39 | if( isset( $_POST[ $name ] ) && empty( $_POST[ $name ] ) ) { 40 | $validation_errors->add( 41 | $name . '_error', 42 | printf( __('%l is required ', 'h'), $field['label'] ) 43 | ); 44 | } 45 | } 46 | 47 | return $validation_errors; 48 | } 49 | 50 | 51 | /* 52 | @woocommerce_created_customer 53 | */ 54 | function save_extra_register_fields( $user_id ) { 55 | foreach( $this->fields as $name => $field ) { 56 | if( !isset( $_POST[ $name ] ) ) { continue; } 57 | 58 | $value = sanitize_text_field( $_POST[ $name ] ); 59 | update_user_meta( $user_id, $name, $value ); 60 | 61 | switch( $name ) { 62 | case 'billing_first_name': 63 | update_user_meta( $user_id, 'first_name', $value ); 64 | break; 65 | 66 | case 'billing_last_name': 67 | update_user_meta( $user_id, 'last_name', $value ); 68 | break; 69 | } 70 | } 71 | } 72 | 73 | ///// 74 | 75 | function _set_fields() { 76 | global $woocommerce; 77 | $wc_countries = new \WC_Countries(); 78 | $countries = $wc_countries->get_shipping_countries(); 79 | 80 | // TODO: need to make ajax to change state when country is changed 81 | reset( $countries ); 82 | $states = $wc_countries->get_states( key( $countries ) ); 83 | 84 | $fields = array( 85 | 'billing_first_name' => [ 86 | 'type' => 'text', 87 | 'label' => __('First name'), 88 | 'required' => true, 89 | ], 90 | 'billing_last_name' => [ 91 | 'type' => 'text', 92 | 'label' => __('Last name'), 93 | 'required' => true, 94 | ], 95 | // 96 | 'billing_address_1' => [ 97 | 'type' => 'text', 98 | 'label' => __('Address'), 99 | 'required' => true, 100 | 'placeholder' => __('Street Address'), 101 | ], 102 | 'billing_address_2' => [ 103 | 'type' => 'text', 104 | 'label' => __('Address 2'), 105 | 'placeholder' => __('Apartment, Suite, Unit No.'), 106 | ], 107 | // 108 | 'billing_country' => [ 109 | 'type' => 'select', 110 | 'label' => __('Country'), 111 | 'required' => true, 112 | 'options' => $countries, 113 | ], 114 | 'billing_state' => [ 115 | 'type' => 'select', 116 | 'label' => __('Province / State'), 117 | 'required' => true, 118 | 'options' => $states 119 | ], 120 | 'billing_postcode' => [ 121 | 'type' => 'text', 122 | 'label' => __('Postcode'), 123 | 'required' => true, 124 | ], 125 | // 126 | 'billing_city' => [ 127 | 'type' => 'text', 128 | 'label' => __('Town / City'), 129 | 'required' => true, 130 | ], 131 | 'billing_phone' => [ 132 | 'type' => 'text', 133 | 'label' => __('Phone'), 134 | ], 135 | ); 136 | 137 | // prepopulate fields 138 | foreach( $fields as $name => $f ) { 139 | if( isset( $_POST[ $name ] ) ) { 140 | $fields[ $name ]['default'] = $_POST[ $name ]; 141 | } 142 | } 143 | 144 | return $fields; 145 | } 146 | 147 | } 148 | 149 | 150 | new H_WooCommerce_Register(); -------------------------------------------------------------------------------- /src/sass/_settings.scss: -------------------------------------------------------------------------------- 1 | // EDJE Functional Sass 2 | // - Single-file version 3 | // - v3.0.0 4 | 5 | @charset "UTF-8"; 6 | 7 | ///// COLORS 8 | 9 | // Palette 10 | $red : #d32f2f; 11 | $red-light: #ffcdd2; 12 | $yellow : #ffee58; 13 | $yellow-light: #fff9c4; 14 | $green : #4caf50; 15 | $green-light: #c8e6c9; 16 | $blue: #1976d2; 17 | $blue-light: #bbdefb; 18 | 19 | // Named colors 20 | $main : #2196f3; 21 | $main-dark : darken($main, 20%); 22 | $main-light : lighten($main, 10%); 23 | 24 | $sub : #607d8b; 25 | $sub-dark: darken($sub, 15%); 26 | $sub-light: lighten($sub, 10%); 27 | 28 | $gray : #b0bcc4; 29 | $gray-light: #f3f6f8; 30 | $gray-dark: #93a3ae; 31 | 32 | $body-background: #fff; 33 | 34 | // Media Query 35 | $size-xs : 480px; 36 | $size-s : 767px; 37 | $size-m : 960px; 38 | $size-l : 1120px; 39 | 40 | $below-xs: "max-width:#{ $size-xs }"; 41 | $above-xs: "min-width:#{ $size-xs + 1px }"; 42 | $below-s: "max-width:#{ $size-s }"; 43 | $above-s: "min-width:#{ $size-s + 1px }"; 44 | $below-m: "max-width:#{ $size-m }"; 45 | $above-m: "min-width:#{ $size-m + 1px }"; 46 | $below-l: "max-width:#{ $size-l }"; 47 | $above-l: "min-width:#{ $size-l + 1px }"; 48 | 49 | $below-nav: $below-s; // small navigation breakpoint 50 | $above-nav: $above-s; 51 | 52 | $portrait: "orientation: portrait"; 53 | $landscape: "orientation: landscape"; 54 | $retina: "min-resolution: 192dpi"; 55 | 56 | // Typography 57 | $font-family : -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 58 | $font-family-header : "Apple Garamond", "Baskerville", "Times New Roman", "Droid Serif", "Times","Source Serif Pro", serif; 59 | $font-family-monospace: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; 60 | 61 | // Put file in /assets/fonts directory 62 | $font-faces: ( 63 | // "Open Sans": ( 64 | // ( "opensans.woff", 400 ), 65 | // ( "opensans-italic.woff", 400, italic ), 66 | // ( "opensans-bold.woff", 700 ) 67 | // ) 68 | ); 69 | 70 | $font-color : #222; 71 | $font-passive : #888; 72 | $font-weight : 400; 73 | $font-line : 1.65; 74 | $font-size : 16px; 75 | 76 | $color-link : inherit; 77 | $color-link-hover : inherit; 78 | 79 | // Typography - Header 80 | $header-color : $font-color; 81 | $header-weight : 700; 82 | $header-line : 1.25; 83 | $header-spacing : 0; 84 | $header-transform : none; 85 | 86 | $h1: (base: 42px, s: 30px); 87 | $h2: (base: 36px, s: 26px); 88 | $h3: (base: 30px, s: 22px); 89 | $h4: (base: 24px, s: 20px); 90 | $h5: (base: 20px, s: 18px); 91 | $h6: (base: $font-size, s: $font-size); 92 | 93 | // Typography List 94 | $ul-parent : disc; 95 | $ul-child : circle; 96 | $ol-parent : decimal; 97 | $ol-child : lower-alpha; 98 | 99 | // Grid 100 | $grid-columns : 12; 101 | $grid-gap : 20px; 102 | $grid-rim : 16px; 103 | $grid-max-width : $size-l; 104 | 105 | // Tile 106 | $tile-max : 8; 107 | $tile-gap : 20px; 108 | 109 | // Shadow 110 | $shadow-z0: 0 0.5px 2px rgba(black, .18), 0 1.5px 6px rgba(black, .08); 111 | $shadow-z1: 0 1.5px 4px rgba(black, .24), 0 1.5px 6px rgba(black, .12); 112 | $shadow-z2: 0 3px 12px rgba(black, .23), 0 3px 12px rgba(black, .16); 113 | $shadow-z3: 0 6px 12px rgba(black, .23), 0 10px 40px rgba(black, .19); 114 | 115 | // Other 116 | $g-radius : 4px; 117 | $g-transition : all .25s ease-out; 118 | 119 | $image-url: '../images/'; 120 | $font-url: '../fonts/'; 121 | 122 | // Blog 123 | $blog-width: 650px; 124 | $blog-font-size: 18px; 125 | 126 | 127 | // ---------------- 128 | // FUNCTIONAL SASS 129 | // ---------------- 130 | 131 | // COLORS for FUNCTIONAL SASS 132 | // - Accessible by these shorthand styles: bg, bc, c 133 | // - You can add transparency by adding underscore and number between 1-99 134 | // - Example: bg-main, c-black_10 135 | $h-colors: ( 136 | 'main': $main, 137 | 'main-dark': $main-dark, 138 | 'main-light': $main-light, 139 | 140 | 'sub': $sub, 141 | 'sub-dark': $sub-dark, 142 | 'sub-light': $sub-light, 143 | 144 | 'red': $red, 145 | 'red-light': $red-light, 146 | 'yellow': $yellow, 147 | 'yellow-light': $yellow-light, 148 | 'green': $green, 149 | 'green-light': $green-light, 150 | 'blue': $blue, 151 | 'blue-light': $blue-light, 152 | 153 | 'black': black, 154 | 'white': white, 155 | 'gray': $gray, 156 | 'gray-light': $gray-light, 157 | 'gray-dark': $gray-dark, 158 | 159 | 'text': $font-color, 160 | 'passive': $font-passive, 161 | 'header': $header-color, 162 | 163 | 'body-bg': $body-background 164 | ); 165 | 166 | 167 | // If the CSS doesn't fit in any variable, put it here 168 | $h-custom: ( 169 | m0-auto: ( margin: 0 auto ), 170 | content-empty: ( content: '' ), 171 | ); 172 | 173 | 174 | @import "edje/utility-h"; 175 | @import "edje/utility"; 176 | @import "edje/functional-vars"; 177 | @import "edje/output"; -------------------------------------------------------------------------------- /module-gutenberg/dist/h-shop-editor.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | /******/ 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | /******/ 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) { 10 | /******/ return installedModules[moduleId].exports; 11 | /******/ } 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ i: moduleId, 15 | /******/ l: false, 16 | /******/ exports: {} 17 | /******/ }; 18 | /******/ 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | /******/ 22 | /******/ // Flag the module as loaded 23 | /******/ module.l = true; 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | /******/ 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | /******/ 36 | /******/ // define getter function for harmony exports 37 | /******/ __webpack_require__.d = function(exports, name, getter) { 38 | /******/ if(!__webpack_require__.o(exports, name)) { 39 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 40 | /******/ } 41 | /******/ }; 42 | /******/ 43 | /******/ // define __esModule on exports 44 | /******/ __webpack_require__.r = function(exports) { 45 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 46 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 47 | /******/ } 48 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 49 | /******/ }; 50 | /******/ 51 | /******/ // create a fake namespace object 52 | /******/ // mode & 1: value is a module id, require it 53 | /******/ // mode & 2: merge all properties of value into the ns 54 | /******/ // mode & 4: return value when already ns object 55 | /******/ // mode & 8|1: behave like require 56 | /******/ __webpack_require__.t = function(value, mode) { 57 | /******/ if(mode & 1) value = __webpack_require__(value); 58 | /******/ if(mode & 8) return value; 59 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 60 | /******/ var ns = Object.create(null); 61 | /******/ __webpack_require__.r(ns); 62 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 63 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 64 | /******/ return ns; 65 | /******/ }; 66 | /******/ 67 | /******/ // getDefaultExport function for compatibility with non-harmony modules 68 | /******/ __webpack_require__.n = function(module) { 69 | /******/ var getter = module && module.__esModule ? 70 | /******/ function getDefault() { return module['default']; } : 71 | /******/ function getModuleExports() { return module; }; 72 | /******/ __webpack_require__.d(getter, 'a', getter); 73 | /******/ return getter; 74 | /******/ }; 75 | /******/ 76 | /******/ // Object.prototype.hasOwnProperty.call 77 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 78 | /******/ 79 | /******/ // __webpack_public_path__ 80 | /******/ __webpack_require__.p = ""; 81 | /******/ 82 | /******/ 83 | /******/ // Load entry module and return exports 84 | /******/ return __webpack_require__(__webpack_require__.s = "./src/shop-editor.js"); 85 | /******/ }) 86 | /************************************************************************/ 87 | /******/ ({ 88 | 89 | /***/ "./src/shop-editor.js": 90 | /*!****************************!*\ 91 | !*** ./src/shop-editor.js ***! 92 | \****************************/ 93 | /*! no exports provided */ 94 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 95 | 96 | "use strict"; 97 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _shop_editor_sass__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./shop-editor.sass */ \"./src/shop-editor.sass\");\n/* harmony import */ var _shop_editor_sass__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_shop_editor_sass__WEBPACK_IMPORTED_MODULE_0__);\n\r\n\n\n//# sourceURL=webpack:///./src/shop-editor.js?"); 98 | 99 | /***/ }), 100 | 101 | /***/ "./src/shop-editor.sass": 102 | /*!******************************!*\ 103 | !*** ./src/shop-editor.sass ***! 104 | \******************************/ 105 | /*! no static exports found */ 106 | /***/ (function(module, exports, __webpack_require__) { 107 | 108 | eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./src/shop-editor.sass?"); 109 | 110 | /***/ }) 111 | 112 | /******/ }); -------------------------------------------------------------------------------- /src/js/hwc-public.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Added (+) and (-) button to Quantity box. This is the listener for it. 3 | */ 4 | const hQuantity = { 5 | init() { 6 | const $cartForms = document.querySelectorAll('.woocommerce-cart .woocommerce, form.cart'); 7 | $cartForms.forEach(($f) => { 8 | $f.addEventListener('click', this.changeQuantity); 9 | }); 10 | }, 11 | 12 | changeQuantity(e) { 13 | if (!e.target.classList.contains('quantity__h-spin')) { return; } 14 | 15 | e.preventDefault(); 16 | const $field = e.target.closest('.quantity').querySelector('input[type="number"]'); 17 | const change = e.target.classList.contains('is-plus') ? 1 : -1; 18 | const result = parseInt($field.value, 10) + change; 19 | 20 | if (result <= 0) { return; } 21 | 22 | $field.value = result; 23 | 24 | // trigger change event for future use 25 | // const changeEvent = new Event('change'); 26 | // $field.dispatchEvent(changeEvent); 27 | 28 | // trigger input event to enable "Update Cart" button in Cart page 29 | const event = new Event('input', { bubbles: true }); 30 | $field.dispatchEvent(event); 31 | }, 32 | }; 33 | 34 | /** 35 | * Added custom Mini Cart widget. This is the listener to keep it open. 36 | */ 37 | const hMiniCart = { 38 | init() { 39 | const $minicarts = document.querySelectorAll('.h-cart'); 40 | 41 | [...$minicarts].forEach(($cart) => { 42 | $cart.addEventListener('click', this.openPopup); 43 | }); 44 | 45 | document.addEventListener('click', this.closePopup); 46 | }, 47 | 48 | openPopup(e) { 49 | if (!e.target.classList.contains('is-cart-button') && !e.target.closest('.is-cart-button')) { return; } 50 | 51 | e.preventDefault(); 52 | e.target.closest('.h-cart').classList.toggle('is-active'); 53 | }, 54 | 55 | closePopup(e) { 56 | if (e.target.closest('.widget_shopping_cart') || e.target.closest('.is-cart-button')) { return; } 57 | 58 | const $openMinicart = document.querySelector('.h-cart.is-active'); 59 | 60 | if ($openMinicart) { 61 | $openMinicart.classList.remove('is-active'); 62 | } 63 | }, 64 | }; 65 | 66 | /** 67 | * Changed the coupon and login form in Checkout into Popup 68 | */ 69 | const hCheckoutForm = { 70 | init() { 71 | if (!document.querySelector('body').classList.contains('woocommerce-checkout')) { return; } 72 | 73 | const $formLinks = document.querySelectorAll('.showcoupon, .showlogin'); 74 | const $forms = document.querySelectorAll('.woocommerce-form-coupon, .woocommerce-form-login'); 75 | const $couponForm = document.querySelector('.woocommerce-form-coupon'); 76 | 77 | [...$formLinks].forEach(($link) => { 78 | $link.addEventListener('click', this.openForm); 79 | }); 80 | 81 | // prevent closing when clicking inside the form 82 | [...$forms].forEach(($form) => { 83 | $form.addEventListener('click', (e) => e.stopPropagation()); 84 | }); 85 | 86 | // close the form when clicking outside 87 | document.addEventListener('click', this.closeForm); 88 | 89 | if ($couponForm) { 90 | $couponForm.addEventListener('submit', this.closeForm); 91 | } 92 | }, 93 | 94 | /** 95 | * 96 | */ 97 | openForm(e) { 98 | e.preventDefault(); 99 | e.stopPropagation(); 100 | const formTarget = e.target.classList.contains('showcoupon') 101 | ? '.woocommerce-form-coupon' 102 | : '.woocommerce-form-login'; 103 | 104 | const $form = document.querySelector(formTarget); 105 | 106 | if ($form) { 107 | $form.classList.toggle('is-open'); 108 | document.querySelector('body').classList.toggle('has-checkout-form-open'); 109 | } 110 | }, 111 | 112 | /** 113 | * 114 | */ 115 | closeForm() { 116 | const $openedForm = document.querySelector('.woocommerce-form-coupon.is-open, .woocommerce-form-login.is-open'); 117 | 118 | if ($openedForm) { 119 | document.querySelector('body').classList.remove('has-checkout-form-open'); 120 | $openedForm.classList.remove('is-open'); 121 | } 122 | }, 123 | }; 124 | 125 | /** 126 | * Listener for custom Mobile tab in Single Product page 127 | */ 128 | const hMobileTabs = { 129 | init() { 130 | const $tabButtons = document.querySelectorAll('.h-tab-mobile a'); 131 | 132 | [...$tabButtons].forEach(($b) => { 133 | $b.addEventListener('click', this.onClick); 134 | }); 135 | }, 136 | 137 | onClick(e) { 138 | e.preventDefault(); 139 | const tabId = e.currentTarget.getAttribute('href'); 140 | const $tab = document.querySelector(tabId); 141 | const $button = e.currentTarget.closest('.h-tab-mobile'); 142 | 143 | if (!$tab) { return; } 144 | 145 | if ($button.classList.contains('active')) { 146 | $tab.style.display = 'none'; 147 | } else { 148 | $tab.style.display = ''; 149 | } 150 | 151 | $button.classList.toggle('active'); 152 | }, 153 | }; 154 | 155 | function onReady() { 156 | hQuantity.init(); 157 | hMiniCart.init(); 158 | hCheckoutForm.init(); 159 | hMobileTabs.init(); 160 | } 161 | 162 | function onLoad() { 163 | 164 | } 165 | 166 | document.addEventListener('DOMContentLoaded', onReady); 167 | document.addEventListener('load', onLoad); 168 | -------------------------------------------------------------------------------- /dist/hwc-variations.css: -------------------------------------------------------------------------------- 1 | .metaboxes .wc-metabox{border:none;border-bottom:1px solid #eee}body:not(.is-product-type-variable) .attribute_tab{display:none !important}#product_attributes h3,#variable_product_options h3{display:flex;align-items:center}#product_attributes a.delete,#variable_product_options a.delete{order:4;width:27px;height:27px;margin-top:0 !important;border-radius:4px;visibility:visible;text-align:center;font-size:0;color:#5c6c7a}#product_attributes a.delete::before,#variable_product_options a.delete::before{content:"";font-family:dashicons;font-size:initial;vertical-align:top;-webkit-font-smoothing:antialiased}#product_attributes a.delete:hover,#variable_product_options a.delete:hover{color:#e35950;background-color:rgba(227,89,80,.1)}#product_attributes .sort,#variable_product_options .sort{order:2;margin:0;padding:.5rem;margin-left:auto}#product_attributes div.handlediv,#variable_product_options div.handlediv{order:3}#product_attributes .woocommerce_attribute:nth-child(1){--color: #4caf50}#product_attributes .woocommerce_attribute:nth-child(2){--color: #763eaf}#product_attributes .woocommerce_attribute:nth-child(3){--color: #ff9517}#product_attributes .wc-metaboxes{border-bottom:none}#product_attributes .wc-metabox{border:none;border-bottom:1px solid #eee}#product_attributes .toolbar.toolbar-top{background-color:#fafafa}#product_attributes .toolbar .expand-close{display:none}#product_attributes h3{padding:.75rem 1rem !important;cursor:default}#product_attributes h3>label{display:none}#product_attributes strong.attribute_name,#product_attributes input.attribute_name{display:inline-block;width:75px;margin-right:1rem;color:var(--color, #333)}#product_attributes .wc-metabox:not(.taxonomy) strong.attribute_name{display:none}#product_attributes .select2-container,#product_attributes textarea{min-width:300px}#product_attributes .select2-selection,#product_attributes textarea{border-color:#eee}#product_attributes textarea{max-height:4rem}#product_attributes button.select_all_attributes,#product_attributes button.select_no_attributes{display:none}#product_attributes button.add_new_attribute{padding:0 .5rem;border:1px solid rgba(0,0,0,.1);font-size:12px;line-height:1}#product_attributes div.handlediv{display:none}#product_attributes .wc-metabox-content{display:none !important}#variable_product_options h3 select:nth-of-type(1),#variable_product_options .variations-defaults select:nth-of-type(1){--color: #4caf50}#variable_product_options h3 select:nth-of-type(2),#variable_product_options .variations-defaults select:nth-of-type(2){--color: #763eaf}#variable_product_options h3 select:nth-of-type(3),#variable_product_options .variations-defaults select:nth-of-type(3){--color: #ff9517}#variable_product_options .toolbar-variations-defaults{display:flex;background-color:#fafafa}#variable_product_options .toolbar-variations-defaults .woocommerce-help-tip{display:none}#variable_product_options .toolbar-variations-defaults select[name*=default_attribute]{max-width:100px;border:none;color:var(--color)}#variable_product_options .toolbar-variations-defaults .variation_actions{order:2;margin-left:auto;width:150px;margin-right:.25rem}#variable_product_options .toolbar-variations-defaults .variation_actions optgroup:nth-of-type(4){display:none}#variable_product_options .toolbar-variations-defaults .button.bulk_edit{order:3;display:flex;align-items:center}#variable_product_options .toolbar-top{display:flex}#variable_product_options .toolbar-top .variations-pagenav{display:none !important}#variable_product_options .h-variation-buttons{display:flex;column-gap:.5rem;width:100%}#variable_product_options .h-variation-buttons .button{display:flex;align-items:center;column-gap:.5rem;margin:0}#variable_product_options .h-variation-buttons svg{height:1rem;width:auto}#variable_product_options .h-variation-buttons path{fill:currentColor}#variable_product_options .h-variation-buttons [data-action=set-stock]{margin-right:auto}#variable_product_options .toolbar-variations-defaults[style*=none]~.toolbar-top .h-variation-buttons [data-action=set-price],#variable_product_options .toolbar-variations-defaults[style*=none]~.toolbar-top .h-variation-buttons [data-action=set-sale-price],#variable_product_options .toolbar-variations-defaults[style*=none]~.toolbar-top .h-variation-buttons [data-action=set-stock]{display:none}#variable_product_options h3>strong{display:none}#variable_product_options h3 select{color:var(--color);border:none;padding:0 .5rem;background:none}#variable_product_options h3 div.handlediv{display:flex;align-items:center;justify-content:center;visibility:visible !important;margin-top:0;padding:0 .5rem 0 0;border-radius:4px;width:auto;height:27px}#variable_product_options h3 div.handlediv:hover{background-color:rgba(0,0,0,.1)}#variable_product_options h3 div.handlediv::before{position:static;padding:0}#variable_product_options h3 div.handlediv::after{content:"Edit"}#variable_product_options .form-row.hide_if_variation_virtual.form-row-full,#variable_product_options .form-row[class*=variable_tax_class]{display:none !important}#variable_product_options .woocommerce_variable_attributes .data{background-color:#fafafa}.h-variation-overview{display:flex;column-gap:1rem;row-gap:1rem;margin-left:2rem;color:#5c6c7a}.h-variation-overview svg{height:1rem;width:auto;opacity:.5}.h-variation-overview path{fill:#5c6c7a}.h-variation-overview p{display:flex;align-items:center;column-gap:.5rem;margin:0}.h-variation-overview p.hidden{display:none}.h-variation-overview span{line-height:1} 2 | -------------------------------------------------------------------------------- /frontend/checkout.php: -------------------------------------------------------------------------------- 1 |
    "; 36 | } 37 | 38 | function h_before_checkout_add_middle_wrapper() { 39 | echo "
    "; 40 | } 41 | 42 | /** 43 | * @filter woocommerce_before_checkout_form - 15 44 | */ 45 | function h_before_checkout_add_closing_wrapper() { 46 | echo "
    "; 47 | } 48 | 49 | /** 50 | * @action woocommerce_checkout_before_order_review_heading 51 | */ 52 | function h_order_review_add_wrapper() { 53 | echo "
    "; 54 | } 55 | 56 | /** 57 | * @action woocommerce_checkout_after_order_review 58 | */ 59 | function h_order_review_add_closing_wrapper() { 60 | echo "
    "; 61 | } 62 | 63 | /** 64 | * Add thumbnail to CART and ORDER table 65 | * @filter woocommerce_cart_item_name 66 | * 67 | * @param $name 68 | * @param $cart_item - The product data 69 | * @param $cart_item_key 70 | * @return - The HTML tag for item name 71 | */ 72 | function h_order_review_add_thumbnail(string $name, $cart_item, $cart_item_key) : string { 73 | if (is_checkout() || is_wc_endpoint_url('view-order')) { 74 | $image = get_the_post_thumbnail($cart_item['product_id'], 'thumbnail'); 75 | $image = $image ? $image : sprintf("", wc_placeholder_img_src()); 76 | 77 | return "
    {$image}
    {$name}"; 78 | } 79 | 80 | return $name; 81 | } 82 | 83 | /** 84 | * @filter woocommerce_checkout_cart_item_quantity 85 | */ 86 | function h_order_review_add_thumb_closing_wrapper($qty) { 87 | return "{$qty}
    "; 88 | } 89 | 90 | /** 91 | * @filter woocommerce_checkout_fields 92 | */ 93 | function h_checkout_reorder_fields($fields) { 94 | $fields['billing']['billing_email']['priority'] = 4; 95 | 96 | $fields['billing']['billing_phone']['required'] = false; 97 | $fields['shipping']['shipping_phone'] = [ 98 | 'type' => 'text', 99 | 'label' => __('Phone'), 100 | 'required' => false, 101 | 'priority' => 100, 102 | ]; 103 | return $fields; 104 | } 105 | 106 | /** 107 | * @filter woocommerce_default_address_fields 108 | */ 109 | function h_checkout_reorder_fields_locale( $fields ) { 110 | $fields['address_1']['priority'] = 40; 111 | $fields['address_2']['priority'] = 41; 112 | $fields['address_2']['label'] = __('Unit no.'); 113 | $fields['address_2']['label_class'] = []; 114 | 115 | $fields['country']['priority'] = 62; 116 | $fields['state']['priority'] = 64; 117 | $fields['city']['priority'] = 91; // after postcode (90) 118 | 119 | return $fields; 120 | } 121 | 122 | /** 123 | * @filter woocommerce_checkout_coupon_message 124 | */ 125 | function h_coupon_change_toggle_message($message) { 126 | $new_text = __('Have a coupon?', 'woocommerce') . ' ' . __('Click here') . ''; 127 | return $new_text; 128 | } 129 | 130 | /** 131 | * @action woocommerce_checkout_after_customer_details 132 | */ 133 | function h_checkout_add_legal_message() { 134 | global $post; 135 | $tnc_url = get_permalink(wc_get_page_id('terms')); 136 | $privacy_url = get_permalink(get_option('wp_page_for_privacy_policy', 0)); 137 | ?> 138 | 156 | {this.addTypeClass(e.currentTarget)}))},addTypeClass(e){const t=e.value,o=document.querySelector("body");if(!o)return;const i=new RegExp(/is-product-type-\w+/,"g");o.className.match(i)?o.className=o.className.replace(i,"is-product-type-"+t):o.classList.add("is-product-type-"+t)}},r={init(){this.onAdded(),this.onSaved(),this.moveFields()},onAdded(){i("body").on("woocommerce_added_attribute",()=>{[...document.querySelectorAll('#product_attributes [name*="attribute_variation["]')].forEach(e=>{e.checked=!0,e.dispatchEvent(new Event("change")),this.moveField(e.closest(".wc-metabox"))})})},onSaved(){i("#variable_product_options").on("reload",()=>{this.moveFields()})},moveFields(){[...document.querySelectorAll("#product_attributes .wc-metabox")].forEach(e=>{this.moveField(e)})},moveField(e){const t=e.querySelector("h3");if(!e.classList.contains("taxonomy")){const o=e.querySelector("td.attribute_name");o&&t.append(...o.childNodes)}const o=e.querySelector('td[rowspan="3"]');o&&t.append(...o.childNodes)}},a={init(){this.changeNoticeButton(),this.initSetPrice(),this.initSetSalePrice(),this.initSetStock(),this.initCreateVariations(),i("#woocommerce-product-data").on("woocommerce_variations_loaded",()=>{this.moveActionSelect(),this.renderToolbarButtons()})},moveActionSelect(){if(document.querySelector(".toolbar-variations-defaults .variation_actions"))return;const e=document.querySelector(".variation_actions"),t=document.querySelector(".do_variation_action"),o=document.querySelector(".toolbar-variations-defaults");e&&o&&(o.appendChild(e),o.appendChild(t))},renderToolbarButtons(){const e=document.querySelector("#variable_product_options .toolbar-top");if(!e)return;if(e.querySelector(".h-variation-buttons"))return;const t=document.querySelector("#h-variation-buttons");t&&(e.innerHTML+=t.innerHTML)},changeNoticeButton(){i("#variable_product_options").on("click","#variable_product_options_inner > .woocommerce-message a",(function(e){e.preventDefault();document.querySelector(".wc-tabs .attribute_tab a").dispatchEvent(new MouseEvent("click",{view:window,bubbles:!0,cancelable:!0}))}))},initSetPrice(){i("#variable_product_options").on("click",'.button[data-action="set-price"]',function(){this.doAction("variable_regular_price")}.bind(this))},initSetSalePrice(){i("#variable_product_options").on("click",'.button[data-action="set-sale-price"]',function(){const e=prompt("Enter the discounted price (leave empty to remove sale)");if(null===e)return;this.fillFields('input[name*="variable_sale_price"]',e)}.bind(this))},initSetStock(){i("#variable_product_options").on("click",'.button[data-action="set-stock"]',function(){const e=prompt("Enter stock amount (leave empty if not managing stock)");if(null===e)return;const t=""!==e;if(this.tickCheckboxes('[name*="variable_manage_stock"]',t),""===e)return;this.fillFields('[name*="variable_stock"]',e)}.bind(this))},initCreateVariations(){i("#variable_product_options").on("click",'.button[data-action="create-variations"]',function(){this.doAction("link_all_variations")}.bind(this))},doAction(e){const t=document.querySelector("#variable_product_options #field_to_edit"),o=document.querySelector("#variable_product_options .do_variation_action");t.value=e,o.dispatchEvent(new MouseEvent("click",{view:window,bubbles:!0,cancelable:!0}))},fillFields(e,t){[...document.querySelectorAll(e)].forEach(e=>{e.value=t,i(e).trigger("change")})},tickCheckboxes(e,t){[...document.querySelectorAll(e)].forEach(e=>{e.checked=t,i(e).trigger("change")})}},c={init(){i("#woocommerce-product-data").on("woocommerce_variations_loaded",this.render),i("#woocommerce-product-data").on("woocommerce_variations_added",this.render);[{field:'[name*="regular_price["]',overview:'[data-info="price"]'},{field:'[name*="sale_price["]',overview:'[data-info="sale-price"]'},{field:'[name*="variable_stock["]',overview:'[data-info="stock"]'}].forEach(e=>{i("#variable_product_options").on("change",e.field,t=>{this._updateOverview(t.currentTarget,e.overview)}),i("#woocommerce-product-data").on("woocommerce_variations_loaded",()=>{[...document.querySelectorAll(e.field)].forEach(t=>{this._updateOverview(t,e.overview)})})}),i("#variable_product_options").on("change",'[name*="variable_manage_stock["]',e=>{e.currentTarget.checked||this._updateOverview(e.currentTarget,'[data-info="stock"]')})},render(){const e=document.querySelectorAll("#variable_product_options .wc-metabox h3"),t=document.querySelector("#h-variation-overview").innerHTML;[...e].forEach(e=>{e.innerHTML.match(/h-variation-overview/)||(e.innerHTML+=t)})},_updateOverview(e,t){const o=e.closest(".wc-metabox").querySelector(".h-variation-overview");if(!o)return;const i=o.querySelector(t);e.value>0?i.classList.remove("hidden"):i.classList.add("hidden"),i.querySelector("span").textContent=e.value}};document.addEventListener("DOMContentLoaded",(function(){n.init(),r.init(),a.init(),c.init()})),window.addEventListener("load",(function(){}))},function(e,t,o){}]); -------------------------------------------------------------------------------- /templates/myaccount/form-login.php: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 |
    20 | 21 |
    22 | 23 | 24 | 25 |

    26 | 27 |
    > 28 | 29 | 30 | 31 | 32 | 33 |

    34 | 35 | 36 |

    37 | 38 | 39 | 40 |

    41 | 42 | 43 |

    44 | 45 | 46 | 47 |

    48 | 49 | 50 |

    51 | 52 | 53 | 54 |

    55 | 56 | 57 | 58 | 59 | 60 |

    61 | 62 | 63 |

    64 | 65 | 66 | 67 |
    68 | 69 | 70 | 71 |
    72 | 73 |
    74 | 75 |

    76 | 77 | 106 | 107 | 108 |
    109 | 110 | 111 | 112 |
    113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /module-variations-ui/src/hwc-variations.sass: -------------------------------------------------------------------------------- 1 | @import "settings" 2 | 3 | .metaboxes .wc-metabox 4 | border: none 5 | border-bottom: 1px solid $border 6 | 7 | body:not(.is-product-type-variable) .attribute_tab 8 | display: none !important 9 | 10 | // Buttons 11 | #product_attributes, 12 | #variable_product_options 13 | h3 14 | display: flex 15 | align-items: center 16 | 17 | a.delete 18 | order: 4 19 | width: 27px 20 | height: 27px 21 | margin-top: 0 !important 22 | border-radius: $g-radius 23 | visibility: visible 24 | text-align: center 25 | font-size: 0 26 | color: $text-dim 27 | 28 | &::before 29 | content: "\f182" 30 | font-family: dashicons 31 | font-size: initial 32 | vertical-align: top 33 | -webkit-font-smoothing: antialiased 34 | 35 | &:hover 36 | color: $red 37 | background-color: rgba($red, .1) 38 | 39 | .sort 40 | order: 2 41 | margin: 0 42 | padding: 0.5rem 43 | margin-left: auto 44 | 45 | div.handlediv 46 | order: 3 47 | 48 | ///// ATTRIBUTES 49 | 50 | // Color 51 | #product_attributes .woocommerce_attribute 52 | &:nth-child(1) 53 | --color: #{$green} 54 | 55 | &:nth-child(2) 56 | --color: #{$purple} 57 | 58 | &:nth-child(3) 59 | --color: #{$orange} 60 | 61 | #product_attributes 62 | .wc-metaboxes 63 | border-bottom: none 64 | 65 | .wc-metabox 66 | border: none 67 | border-bottom: 1px solid $border 68 | 69 | // Toolbar 70 | #product_attributes .toolbar 71 | &.toolbar-top 72 | background-color: $panel 73 | 74 | .expand-close 75 | display: none 76 | 77 | // Heading 78 | #product_attributes 79 | h3 80 | padding: 0.75rem 1rem !important 81 | cursor: default 82 | 83 | h3 > label 84 | display: none 85 | 86 | strong.attribute_name, 87 | input.attribute_name 88 | display: inline-block 89 | width: 75px 90 | margin-right: 1rem 91 | color: var(--color, #{$text}) 92 | 93 | .wc-metabox:not(.taxonomy) strong.attribute_name 94 | display: none 95 | 96 | .select2-container, 97 | textarea 98 | min-width: 300px 99 | 100 | .select2-selection, 101 | textarea 102 | border-color: $border 103 | 104 | textarea 105 | max-height: 4rem 106 | 107 | button.select_all_attributes, 108 | button.select_no_attributes 109 | display: none 110 | 111 | button.add_new_attribute 112 | padding: 0 0.5rem 113 | border: 1px solid rgba(black, .1) 114 | font-size: 12px 115 | line-height: 1 116 | 117 | div.handlediv 118 | display: none 119 | 120 | // Content 121 | #product_attributes .wc-metabox-content 122 | display: none !important 123 | 124 | ///// VARIATIONS 125 | 126 | // Color 127 | #variable_product_options h3 select, 128 | #variable_product_options .variations-defaults select 129 | &:nth-of-type(1) 130 | --color: #{$green} 131 | 132 | &:nth-of-type(2) 133 | --color: #{$purple} 134 | 135 | &:nth-of-type(3) 136 | --color: #{$orange} 137 | 138 | // Defaults 139 | #variable_product_options .toolbar-variations-defaults 140 | display: flex 141 | background-color: $panel 142 | 143 | .woocommerce-help-tip 144 | display: none 145 | 146 | select[name*="default_attribute"] 147 | max-width: 100px 148 | border: none 149 | color: var(--color) 150 | 151 | .variation_actions 152 | order: 2 153 | margin-left: auto 154 | width: 150px 155 | margin-right: 0.25rem 156 | 157 | optgroup:nth-of-type(4) 158 | display: none 159 | 160 | .button.bulk_edit 161 | order: 3 162 | display: flex 163 | align-items: center 164 | 165 | // Toolbars 166 | #variable_product_options .toolbar-top 167 | display: flex 168 | 169 | .variations-pagenav 170 | display: none !important 171 | 172 | #variable_product_options .h-variation-buttons 173 | display: flex 174 | column-gap: 0.5rem 175 | width: 100% 176 | 177 | .button 178 | display: flex 179 | align-items: center 180 | column-gap: 0.5rem 181 | margin: 0 182 | 183 | svg 184 | height: 1rem 185 | width: auto 186 | 187 | path 188 | fill: currentColor 189 | 190 | [data-action="set-stock"] 191 | margin-right: auto 192 | 193 | // Hide the Set price button when there is no variations 194 | #variable_product_options .toolbar-variations-defaults[style*="none"] 195 | ~ .toolbar-top .h-variation-buttons 196 | [data-action="set-price"], 197 | [data-action="set-sale-price"], 198 | [data-action="set-stock"] 199 | display: none 200 | 201 | // Heading 202 | #variable_product_options h3 203 | > strong 204 | display: none 205 | 206 | select 207 | color: var(--color) 208 | border: none 209 | padding: 0 0.5rem 210 | background: none 211 | 212 | div.handlediv 213 | display: flex 214 | align-items: center 215 | justify-content: center 216 | 217 | visibility: visible !important 218 | margin-top: 0 219 | padding: 0 0.5rem 0 0 220 | border-radius: $g-radius 221 | width: auto 222 | height: 27px 223 | 224 | &:hover 225 | background-color: rgba(black, .1) 226 | 227 | &::before 228 | position: static 229 | padding: 0 230 | 231 | &::after 232 | content: "Edit" 233 | 234 | // Content 235 | #variable_product_options 236 | // hide shipping class and tax class 237 | .form-row.hide_if_variation_virtual.form-row-full, 238 | .form-row[class*="variable_tax_class"] 239 | display: none !important 240 | 241 | .woocommerce_variable_attributes .data 242 | background-color: $panel 243 | 244 | 245 | ///// VARIATION OVERVIEW 246 | 247 | .h-variation-overview 248 | display: flex 249 | column-gap: 1rem 250 | row-gap: 1rem 251 | margin-left: 2rem 252 | 253 | color: $text-dim 254 | 255 | svg 256 | height: 1rem 257 | width: auto 258 | opacity: .5 259 | 260 | path 261 | fill: $text-dim 262 | 263 | p 264 | display: flex 265 | align-items: center 266 | column-gap: 0.5rem 267 | margin: 0 268 | 269 | p.hidden 270 | display: none 271 | 272 | span 273 | line-height: 1 -------------------------------------------------------------------------------- /module-variations-ui/_index.php: -------------------------------------------------------------------------------- 1 | base !== 'post' || $screen->post_type !== 'product') { return; } 27 | 28 | wp_enqueue_style('hwc-variations', HWC_DIST . '/hwc-variations.css', [], HWC_VERSION); 29 | wp_enqueue_script('hwc-variations', HWC_DIST . '/hwc-variations.js', ['jquery'], HWC_VERSION); 30 | } 31 | 32 | /** 33 | * Output template to be use by the JS 34 | * 35 | * @filter admin_footer 36 | */ 37 | function h_variations_js_template($views) { 38 | ?> 39 | 40 | 61 | 62 | 84 | 85 | ... '); 121 | // Result: 122 | // background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E% ... %3C/svg%3E"); 123 | 124 | @function svg-encode( $svg ) { 125 | $encoded: ''; 126 | $slice: 2000; 127 | $index: 0; 128 | $loops: ceil(str-length($svg) / $slice); 129 | 130 | @for $i from 1 through $loops { 131 | $chunk: str-slice($svg, $index, $index + $slice - 1); 132 | $chunk: _str-replace($chunk, '"', "'"); 133 | $chunk: _str-replace($chunk, '<', '%3C'); 134 | $chunk: _str-replace($chunk, '>', '%3E'); 135 | $chunk: _str-replace($chunk, '&', '%26'); 136 | $chunk: _str-replace($chunk, '#', '%23'); 137 | $encoded: #{$encoded}#{$chunk}; 138 | $index: $index + $slice; 139 | } 140 | 141 | @return url("data:image/svg+xml;charset=utf8,#{$encoded}"); 142 | } 143 | 144 | /// Replace `$search` with `$replace` in `$string` 145 | @function _str-replace( $string, $search, $replace: '' ) { 146 | $index: str-index($string, $search); 147 | 148 | @if $index { 149 | @return str-slice($string, 1, $index - 1) + $replace + _str-replace(str-slice($string, $index + str-length($search)), $search, $replace); 150 | } 151 | 152 | @return $string; 153 | } 154 | 155 | 156 | // ------------- 157 | // TRIANGLE 158 | // ------------- 159 | 160 | // Create triangle shape using border. Mostly applied in ::before / ::after pseudoselecter. 161 | // 162 | // Usage: 163 | // @include triangle( n, #333, 20px, 12px ); 164 | @mixin triangle( 165 | $direction, 166 | $color, 167 | $width, 168 | $height: false) { 169 | 170 | // If height is not specified, make the triangle equalateral 171 | @if not $height { 172 | @if $direction in (n, e, s, w) { 173 | $height : ($width / 2) * 1.732; 174 | } 175 | @else if $direction in (ne, se, sw, nw) { 176 | $height : $width; 177 | } 178 | } 179 | 180 | width: 0; 181 | height: 0; 182 | font-size: 0; 183 | line-height: 0%; 184 | border-style: solid; 185 | border-color: transparent; 186 | 187 | 188 | @if $direction == n { 189 | border-width: 0 $width/2 $height $width/2; 190 | border-bottom-color: $color; 191 | } 192 | @else if $direction == e { 193 | border-width: $width/2 0 $width/2 $height; 194 | border-left-color : $color; 195 | } 196 | @else if $direction == s { 197 | border-width: $height $width/2 0 $width/2; 198 | border-top-color: $color; 199 | } 200 | @else if $direction == w { 201 | border-width: $width/2 $height $width/2 0; 202 | border-right-color: $color; 203 | } 204 | 205 | @else if $direction == ne { 206 | border-width: 0 $width $height 0; 207 | border-right-color: $color; 208 | } 209 | @else if $direction == se { 210 | border-width: 0 0 $height $width; 211 | border-bottom-color: $color; 212 | } 213 | @else if $direction == sw { 214 | border-width: $height 0 0 $width; 215 | border-left-color: $color; 216 | } 217 | @else if $direction == nw { 218 | border-width: $height $width 0 0; 219 | border-top-color: $color; 220 | } 221 | } 222 | 223 | // ------------ 224 | // PLACEHOLDER 225 | // ------------ 226 | 227 | @mixin placeholder($base: false) { 228 | @if $base { 229 | ::-webkit-input-placeholder { @content; } 230 | ::-moz-placeholder { @content; } 231 | :-ms-input-placeholder { @content; } 232 | :-moz-placeholder { @content; } 233 | } @else { 234 | &::-webkit-input-placeholder { @content; } 235 | &::-moz-placeholder { @content; } 236 | &:-ms-input-placeholder { @content; } 237 | &:-moz-placeholder { @content; } 238 | } 239 | } 240 | 241 | // ----------- 242 | // ASSET URL 243 | // ----------- 244 | 245 | @function font-url( $file ) { 246 | @return url( $font-url + $file); 247 | } 248 | 249 | @function image-url( $file ) { 250 | @return url( $image-url + $file); 251 | } 252 | 253 | 254 | // CLEARFIX ----- 255 | 256 | @mixin clearfix() { 257 | &::before, 258 | &::after { 259 | content: ""; 260 | display: table; 261 | } 262 | 263 | &::after { 264 | clear: both; 265 | } 266 | } -------------------------------------------------------------------------------- /templates/cart/cart.php: -------------------------------------------------------------------------------- 1 | 10 | 11 |
    12 | 13 | 14 | 15 | 16 | 17 | 20 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | cart->get_cart() as $cart_item_key => $cart_item ) { 35 | $_product = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key ); 36 | $product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key ); 37 | 38 | if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_cart_item_visible', true, $cart_item, $cart_item_key ) ) { 39 | $product_permalink = apply_filters( 'woocommerce_cart_item_permalink', $_product->is_visible() ? $_product->get_permalink( $cart_item ) : '', $cart_item, $cart_item_key ); 40 | ?> 41 | 42 | 53 | 54 | 55 | 78 | 79 | 100 | 101 | 106 | 107 | 123 | 124 | 128 | 129 | 130 | 131 | 132 | 147 | 148 | 149 | 150 | 151 |
    18 | 19 | 21 | 22 | 24 | 25 |  
    43 | get_image(), $cart_item, $cart_item_key ); 45 | 46 | if ( ! $product_permalink ) { 47 | echo $thumbnail; // PHPCS: XSS ok. 48 | } else { 49 | printf( '%s', esc_url( $product_permalink ), $thumbnail ); // PHPCS: XSS ok. 50 | } 51 | ?> 52 | 56 | get_name(), $cart_item, $cart_item_key ) . ' ' ); 59 | } else { 60 | echo wp_kses_post( apply_filters( 'woocommerce_cart_item_name', sprintf( '%s', esc_url( $product_permalink ), $_product->get_name() ), $cart_item, $cart_item_key ) ); 61 | } 62 | 63 | do_action( 'woocommerce_after_cart_item_name', $cart_item, $cart_item_key ); 64 | 65 | // Meta data. 66 | echo wc_get_formatted_cart_item_data( $cart_item ); // PHPCS: XSS ok. 67 | 68 | // Backorder notification. 69 | if ( $_product->backorders_require_notification() && $_product->is_on_backorder( $cart_item['quantity'] ) ) { 70 | echo wp_kses_post( apply_filters( 'woocommerce_cart_item_backorder_notification', '

    ' . esc_html__( 'Available on backorder', 'woocommerce' ) . '

    ', $product_id ) ); 71 | } 72 | ?> 73 | 74 | cart->get_product_price( $_product ), $cart_item, $cart_item_key ); // PHPCS: XSS ok. 76 | ?> 77 |
    80 | is_sold_individually() ) { 82 | $product_quantity = sprintf( '1 ', $cart_item_key ); 83 | } else { 84 | $product_quantity = woocommerce_quantity_input( 85 | array( 86 | 'input_name' => "cart[{$cart_item_key}][qty]", 87 | 'input_value' => $cart_item['quantity'], 88 | 'max_value' => $_product->get_max_purchase_quantity(), 89 | 'min_value' => '0', 90 | 'product_name' => $_product->get_name(), 91 | ), 92 | $_product, 93 | false 94 | ); 95 | } 96 | 97 | echo apply_filters( 'woocommerce_cart_item_quantity', $product_quantity, $cart_item_key, $cart_item ); // PHPCS: XSS ok. 98 | ?> 99 | 102 | cart->get_product_subtotal( $_product, $cart_item['quantity'] ), $cart_item, $cart_item_key ); // PHPCS: XSS ok. 104 | ?> 105 | 108 | ×', 113 | esc_url( wc_get_cart_remove_url( $cart_item_key ) ), 114 | esc_html__( 'Remove this item', 'woocommerce' ), 115 | esc_attr( $product_id ), 116 | esc_attr( $_product->get_sku() ), 117 | __('Remove this item'), 118 | ), 119 | $cart_item_key 120 | ); 121 | ?> 122 |
    133 | 134 | 135 |
    136 | 137 | 138 |
    139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 |
    152 | 153 |
    154 | 155 | 156 | 157 |
    158 | 164 |
    165 | 166 | 172 | -------------------------------------------------------------------------------- /src/sass/edje/_utility-h.scss: -------------------------------------------------------------------------------- 1 | @mixin h( $bits ) { 2 | @each $b in $bits { 3 | $prop-key: getPropKey( $b ); 4 | $value-raw: str-slice( $b, str-length( $prop-key ) + 1 ); 5 | 6 | $prop: false; 7 | $value: false; 8 | 9 | // If color 10 | @if map-has-key( $h-props-color, $prop-key ) { 11 | $prop: map-get( $h-props-color, $prop-key ); 12 | $value: getColorValue( $value-raw ); 13 | } 14 | // If measurement 15 | @else if map-has-key( $h-props-measurement, $prop-key ) { 16 | $prop: map-get( $h-props-measurement, $prop-key ); 17 | $value: getMeasurementValue( $value-raw ); 18 | } 19 | // Else, it's static prop 20 | @else { 21 | $prop: map-get( $_h-all, $b ); 22 | 23 | @if $prop == null { 24 | @warn "The bit '#{ $b }' doesn't exist"; 25 | } 26 | } 27 | 28 | // If static prop 29 | @if type-of( $prop ) == map { 30 | @each $p, $v in $prop { 31 | // if first char is %, extend it 32 | @if type-of( $v ) == string and str-index( $v, '%') == 1 { 33 | @extend #{ $v }; 34 | } 35 | @else { 36 | #{ $p } : $v; 37 | } 38 | } 39 | } 40 | // if dynamic multiple prop 41 | @else if type-of( $prop ) == list { 42 | @each $p in $prop { 43 | #{ $p } : $value; 44 | } 45 | } 46 | // if dynamic single prop 47 | @else { 48 | #{ $prop } : $value; 49 | } 50 | } 51 | } 52 | 53 | 54 | 55 | // --------------- 56 | // DYNAMIC STYLE 57 | // --------------- 58 | 59 | // Property that can use color from $h-palette and allow opacity prefix 60 | // Example: c-red >>> color: $red 61 | // bg-main_10 >>> background-color: rgba($main, .10) 62 | $h-props-color: ( 63 | bg: background-color, 64 | bc: border-color, 65 | c: color 66 | ); 67 | 68 | // Property that can accept any number and allow unit prefix 69 | // Example: p1_5 >>> padding: 1.5rem 70 | // h50p >>> height: 50% 71 | // top70px >>> top: 70px 72 | $h-props-measurement: ( 73 | top: top, 74 | right: right, 75 | bottom: bottom, 76 | left: left, 77 | 78 | p: padding, 79 | pt: padding-top, 80 | pr: padding-right, 81 | pb: padding-bottom, 82 | pl: padding-left, 83 | pv: ( padding-top, padding-bottom ), 84 | ph: ( padding-right, padding-left ), 85 | 86 | m: margin, 87 | mt: margin-top, 88 | mr: margin-right, 89 | mb: margin-bottom, 90 | ml: margin-left, 91 | mv: ( margin-top, margin-bottom ), 92 | mh: ( margin-right, margin-left ), 93 | 94 | h: height, 95 | minh: min-height, 96 | maxh: max-height, 97 | w: width, 98 | minw: min-width, 99 | maxw: max-width, 100 | 101 | bw: border-width, 102 | btw: border-top-width, 103 | brw: border-right-width, 104 | bbw: border-bottom-width, 105 | blw: border-left-width, 106 | ); 107 | 108 | 109 | // Get property name, indicated by the letters before number or dash 110 | // 111 | @function getPropKey( $bit ) { 112 | $separator: ( '-': '-', '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9); 113 | $prop-key: ''; 114 | 115 | @for $i from 1 through str-length( $bit ) { 116 | $char: str-slice( $bit, $i, $i ); 117 | 118 | @if map-has-key( $separator, $char ) { 119 | @return $prop-key; 120 | } @else { 121 | $prop-key: $prop-key + $char; 122 | } 123 | } 124 | 125 | @return $prop-key; 126 | } 127 | 128 | 129 | // Get color value and its transparency (if any) 130 | // 131 | @function getColorValue( $raw ) { 132 | $raw: str-slice( $raw, 2 ); // remove the initial dash 133 | 134 | $alpha-index: str-index( $raw, '_' ); 135 | 136 | // if has transparency 137 | @if $alpha-index { 138 | $alpha: '0.' + str-slice( $raw, $alpha-index + 1 ); 139 | $color-key: str-slice( $raw, 1, $alpha-index - 1 ); 140 | @return rgba( var(--#{ $color-key }RGB), unquote($alpha) ); 141 | } 142 | 143 | // if not in map, return as is 144 | @if not map-has-key( $h-colors, $raw ) { 145 | @return $raw; 146 | } 147 | 148 | // default 149 | @return var(--#{ $raw }); 150 | } 151 | 152 | 153 | 154 | // Get measurement value with its unit (use 'rem' by default) 155 | // 156 | @function getMeasurementValue( $raw ) { 157 | $numbers: ('0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9 ); 158 | 159 | // if already number 160 | @if type-of( $raw ) == 'number' { @return $raw; } 161 | 162 | $len: str-length( $raw ); 163 | $first-char: str-slice( $raw, 1, 1 ); 164 | $second-char: str-slice( $raw, 2, 2 ); 165 | $last-char: str-slice( $raw, $len, $len ); 166 | 167 | // If found underscore, replace it with dot. 168 | $number: str-replace( $raw, '_' , '.' ); 169 | 170 | // If last char is "p", change to % 171 | @if $last-char == 'p' { 172 | @return str-replace( $number, 'p', '%'); 173 | } 174 | // If first char is '-' but second is not number, it's a string value 175 | @else if $first-char == '-' AND not map-has-key( $numbers, $second-char) { 176 | @return str-slice( $raw, 2 ); 177 | } 178 | // If last char is not number, return as is 179 | @else if not map-has-key( $numbers, $last-char ) { 180 | @return $number; 181 | } 182 | 183 | // if zero or $add-rem is false, no need to add unit 184 | @if ($len == 1 AND $first-char == '0') { 185 | @return $number; 186 | } 187 | 188 | @return $number + rem; 189 | } 190 | 191 | 192 | // -------------- 193 | // STATIC STYLE 194 | //--------------- 195 | 196 | // Merge multiple Functional maps into one 197 | @function _merge( $maps... ) { 198 | $collection: (); 199 | 200 | @each $map in $maps { 201 | @if map-get( $map, names ) { 202 | $collection: map-merge( $collection, _format-classes( $map ) ); 203 | } @else { 204 | $collection: map-merge( $collection, $map ); 205 | } 206 | } 207 | 208 | @return $collection; 209 | } 210 | 211 | 212 | // Format classes mapping by pairing each name to the values 213 | // 214 | // @param $raw (map) - Containing two items: names and values. Each will be paired against each other to create classes 215 | @function _format-classes( $raw ) { 216 | $classes: (); 217 | 218 | // loop the name 219 | @each $name, $props in map-get( $raw, 'names' ) { 220 | @each $postfix, $value in map-get( $raw, 'values' ) { 221 | 222 | $_name: #{ $name }#{ $postfix }; // format the name like "pt05" 223 | $new-item: ( $_name: _format-values( $props, $value ) ); 224 | 225 | // add the new item 226 | $classes: map-merge( $classes, $new-item ); 227 | } 228 | } 229 | 230 | @return $classes; 231 | } 232 | 233 | 234 | // Format the values of an Item 235 | // Expected format: ( padding-top: 0.5em ) 236 | // 237 | // If $styles is a list, pair each with the value 238 | // Example: ( padding-top: 0.5em, padding-bottom: 0.5em ) 239 | @function _format-values( $props, $value ) { 240 | $values: (); 241 | 242 | // If has multiple styles, combine them 243 | @if type-of( $props ) == 'list' { 244 | 245 | // combine the multiple styles 246 | @each $p in $props { 247 | $values: map-merge( $values, ( #{ $p }: #{ $value } ) ); 248 | } 249 | } 250 | // If single style, just format it normally 251 | @else { 252 | $values: ( #{ $props }: #{ $value } ); 253 | } 254 | 255 | @return $values; 256 | } 257 | 258 | 259 | 260 | 261 | // -------- 262 | // SASS HELPER 263 | // -------- 264 | 265 | // Replace part of string 266 | // 267 | @function str-replace( $string, $search, $replace: '' ) { 268 | $index: str-index( $string, $search ); 269 | 270 | @if $index { 271 | @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); 272 | } 273 | 274 | @return $string; 275 | } -------------------------------------------------------------------------------- /module-gutenberg/dist/h-products.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | /******/ 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | /******/ 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) { 10 | /******/ return installedModules[moduleId].exports; 11 | /******/ } 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ i: moduleId, 15 | /******/ l: false, 16 | /******/ exports: {} 17 | /******/ }; 18 | /******/ 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | /******/ 22 | /******/ // Flag the module as loaded 23 | /******/ module.l = true; 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | /******/ 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | /******/ 36 | /******/ // define getter function for harmony exports 37 | /******/ __webpack_require__.d = function(exports, name, getter) { 38 | /******/ if(!__webpack_require__.o(exports, name)) { 39 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 40 | /******/ } 41 | /******/ }; 42 | /******/ 43 | /******/ // define __esModule on exports 44 | /******/ __webpack_require__.r = function(exports) { 45 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 46 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 47 | /******/ } 48 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 49 | /******/ }; 50 | /******/ 51 | /******/ // create a fake namespace object 52 | /******/ // mode & 1: value is a module id, require it 53 | /******/ // mode & 2: merge all properties of value into the ns 54 | /******/ // mode & 4: return value when already ns object 55 | /******/ // mode & 8|1: behave like require 56 | /******/ __webpack_require__.t = function(value, mode) { 57 | /******/ if(mode & 1) value = __webpack_require__(value); 58 | /******/ if(mode & 8) return value; 59 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 60 | /******/ var ns = Object.create(null); 61 | /******/ __webpack_require__.r(ns); 62 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 63 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 64 | /******/ return ns; 65 | /******/ }; 66 | /******/ 67 | /******/ // getDefaultExport function for compatibility with non-harmony modules 68 | /******/ __webpack_require__.n = function(module) { 69 | /******/ var getter = module && module.__esModule ? 70 | /******/ function getDefault() { return module['default']; } : 71 | /******/ function getModuleExports() { return module; }; 72 | /******/ __webpack_require__.d(getter, 'a', getter); 73 | /******/ return getter; 74 | /******/ }; 75 | /******/ 76 | /******/ // Object.prototype.hasOwnProperty.call 77 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 78 | /******/ 79 | /******/ // __webpack_public_path__ 80 | /******/ __webpack_require__.p = ""; 81 | /******/ 82 | /******/ 83 | /******/ // Load entry module and return exports 84 | /******/ return __webpack_require__(__webpack_require__.s = "./src/products.jsx"); 85 | /******/ }) 86 | /************************************************************************/ 87 | /******/ ({ 88 | 89 | /***/ "./src/products.jsx": 90 | /*!**************************!*\ 91 | !*** ./src/products.jsx ***! 92 | \**************************/ 93 | /*! no exports provided */ 94 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 95 | 96 | "use strict"; 97 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/element */ \"@wordpress/element\");\n/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _products_sass__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./products.sass */ \"./src/products.sass\");\n/* harmony import */ var _products_sass__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_products_sass__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var lodash__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! lodash */ \"lodash\");\n/* harmony import */ var lodash__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(lodash__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _wordpress_hooks__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @wordpress/hooks */ \"@wordpress/hooks\");\n/* harmony import */ var _wordpress_hooks__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_wordpress_hooks__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @wordpress/block-editor */ \"@wordpress/block-editor\");\n/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_4__);\n\n// Add Text Alignment to all Products block\n\n\n\n\n\nObject(_wordpress_hooks__WEBPACK_IMPORTED_MODULE_3__[\"addFilter\"])('blocks.registerBlockType', 'wc-products/attributes', addAttributes);\nObject(_wordpress_hooks__WEBPACK_IMPORTED_MODULE_3__[\"addFilter\"])('editor.BlockEdit', 'wc-products/edit', addControl);\n/**\r\n * \r\n */\n\nfunction addAttributes(settings, name) {\n // abort if not our targetted block\n var targetBlocks = ['woocommerce/handpicked-products'];\n\n if (!targetBlocks.includes(name)) {\n return settings;\n } // Use Lodash's assign to gracefully handle if attributes are undefined\n\n\n settings.attributes = Object(lodash__WEBPACK_IMPORTED_MODULE_2__[\"assign\"])(settings.attributes, {\n textAlign: {\n type: 'string',\n default: ''\n }\n });\n return settings;\n}\n/**\r\n * \r\n */\n\n\nfunction addControl(BlockEdit) {\n return function (props) {\n // abort if not our targetted block\n var targetBlocks = ['woocommerce/handpicked-products'];\n\n if (!targetBlocks.includes(props.name)) {\n return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__[\"createElement\"])(BlockEdit, props);\n }\n\n var atts = props.attributes;\n return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__[\"createElement\"])(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__[\"Fragment\"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__[\"createElement\"])(BlockEdit, props), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__[\"createElement\"])(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_4__[\"BlockControls\"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__[\"createElement\"])(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_4__[\"AlignmentToolbar\"], {\n onChange: updateAlignment,\n value: atts.textAlign\n }))); //\n\n function updateAlignment(newValue) {\n newValue = newValue || '';\n props.setAttributes({\n textAlign: newValue\n }); // remove existing alignment class\n\n if (atts.className) {\n atts.className = atts.className.replace(/has-text-align-\\w+/, '').trim();\n } else {\n atts.className = ''; // initialize\n } // add Align class\n\n\n if (newValue) {\n props.setAttributes({\n className: \"\".concat(atts.className, \" has-text-align-\").concat(newValue)\n });\n }\n }\n };\n}\n\n//# sourceURL=webpack:///./src/products.jsx?"); 98 | 99 | /***/ }), 100 | 101 | /***/ "./src/products.sass": 102 | /*!***************************!*\ 103 | !*** ./src/products.sass ***! 104 | \***************************/ 105 | /*! no static exports found */ 106 | /***/ (function(module, exports, __webpack_require__) { 107 | 108 | eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./src/products.sass?"); 109 | 110 | /***/ }), 111 | 112 | /***/ "@wordpress/block-editor": 113 | /*!*************************************!*\ 114 | !*** external ["wp","blockEditor"] ***! 115 | \*************************************/ 116 | /*! no static exports found */ 117 | /***/ (function(module, exports) { 118 | 119 | eval("(function() { module.exports = window[\"wp\"][\"blockEditor\"]; }());\n\n//# sourceURL=webpack:///external_%5B%22wp%22,%22blockEditor%22%5D?"); 120 | 121 | /***/ }), 122 | 123 | /***/ "@wordpress/element": 124 | /*!*********************************!*\ 125 | !*** external ["wp","element"] ***! 126 | \*********************************/ 127 | /*! no static exports found */ 128 | /***/ (function(module, exports) { 129 | 130 | eval("(function() { module.exports = window[\"wp\"][\"element\"]; }());\n\n//# sourceURL=webpack:///external_%5B%22wp%22,%22element%22%5D?"); 131 | 132 | /***/ }), 133 | 134 | /***/ "@wordpress/hooks": 135 | /*!*******************************!*\ 136 | !*** external ["wp","hooks"] ***! 137 | \*******************************/ 138 | /*! no static exports found */ 139 | /***/ (function(module, exports) { 140 | 141 | eval("(function() { module.exports = window[\"wp\"][\"hooks\"]; }());\n\n//# sourceURL=webpack:///external_%5B%22wp%22,%22hooks%22%5D?"); 142 | 143 | /***/ }), 144 | 145 | /***/ "lodash": 146 | /*!*************************!*\ 147 | !*** external "lodash" ***! 148 | \*************************/ 149 | /*! no static exports found */ 150 | /***/ (function(module, exports) { 151 | 152 | eval("(function() { module.exports = window[\"lodash\"]; }());\n\n//# sourceURL=webpack:///external_%22lodash%22?"); 153 | 154 | /***/ }) 155 | 156 | /******/ }); -------------------------------------------------------------------------------- /src/sass/hwc-myaccount.sass: -------------------------------------------------------------------------------- 1 | @import "settings" 2 | 3 | $wc-panel: $gray-light 4 | $wc-panel-dark: darken($wc-panel, 5%) 5 | $wc-panel-border: 1px solid darken($wc-panel, 10%) 6 | 7 | ///// LAYOUT 8 | 9 | .woocommerce-account 10 | 11 | .woocommerce 12 | +h( d-grid relative ) 13 | grid-column-gap: 2.5rem 14 | grid-row-gap: 1.5rem 15 | grid-template-columns: 2fr 8fr 16 | 17 | > * 18 | grid-column: span 1 19 | 20 | @media ($below-s) 21 | grid-template-columns: 1fr 22 | 23 | // MyAccount Sidebar 24 | .woocommerce-MyAccount-navigation 25 | background-color: $wc-panel 26 | 27 | ul 28 | +h( d-flex fd-column fw-wrap h100p list-none p0 m0 ) 29 | 30 | @media ($below-s) 31 | +h( w100p ov-hidden brad ) 32 | border: $wc-panel-border 33 | 34 | li 35 | width: 33.3333% 36 | 37 | @media ($below-xs) 38 | li 39 | +h( w50p ) 40 | 41 | 42 | .woocommerce-MyAccount-navigation-link 43 | +h( w100p mb0 ) 44 | 45 | + .woocommerce-MyAccount-navigation-link 46 | border-top: $wc-panel-border 47 | 48 | @media ($below-s) 49 | +h( b0 ) 50 | 51 | &.is-active 52 | a 53 | +h( bc-main c-main ) 54 | background-color: $wc-panel-dark 55 | a::after 56 | +h( c-main ) 57 | 58 | a 59 | +h( d-flex ai-center pv0_75 ph1 w100p c-body transition ) 60 | border-left: 4px solid transparent 61 | border-bottom: none 62 | 63 | &:hover 64 | background-color: $wc-panel-dark 65 | &::after 66 | +h( ml-auto o70 fs-m ) 67 | font-family: "dashicons" 68 | // 69 | @media ($below-s) 70 | +h( ph0_5 ) 71 | border-left: none 72 | border-bottom: 4px solid transparent 73 | 74 | 75 | .woocommerce-MyAccount-navigation-link--orders 76 | a::after 77 | content: "\f174" 78 | 79 | .woocommerce-MyAccount-navigation-link--edit-address 80 | a::after 81 | content: "\f102" 82 | 83 | .woocommerce-MyAccount-navigation-link--edit-account 84 | +h( mb3 ) 85 | 86 | a::after 87 | content: "\f110" 88 | 89 | @media ($below-s) 90 | +h( mb0 ) 91 | 92 | .woocommerce-MyAccount-navigation-link--customer-logout 93 | +h( mt-auto ) 94 | 95 | a::after 96 | content: "\f153" 97 | 98 | 99 | // MyAccount Content 100 | .woocommerce-MyAccount-content 101 | +h( flex1 ) 102 | 103 | body.woocommerce-orders & 104 | +h( maxw100p ovx-auto ) 105 | 106 | .woocommerce-pagination 107 | +h( d-flex mt2 ta-center ) 108 | 109 | a 110 | +h( bg-inherit c-main ) 111 | 112 | a:hover 113 | +h( c-main ) 114 | 115 | .woocommerce-button--previous::before 116 | content: "\00AB" 117 | +h( d-inline-block mr0_25 ) 118 | 119 | .woocommerce-button--next 120 | +h( ml-auto ) 121 | 122 | &::after 123 | content: "\00BB" 124 | +h( d-inline-block ml0_25 ) 125 | 126 | 127 | 128 | ///// FORM General 129 | 130 | %form 131 | +h( d-grid ) 132 | grid-column-gap: 1rem 133 | grid-row-gap: 1rem 134 | grid-template-columns: repeat(12, 1fr) 135 | 136 | > * 137 | grid-column: span 4 138 | 139 | .clear 140 | +h( d-none ) 141 | 142 | 143 | .form-row 144 | +h( d-flex fd-column mb0 w100p ) 145 | 146 | label 147 | +h( cursor-pointer mb2px c-passive fs-s ) 148 | 149 | // hide the label of Address 2 150 | &[id*="_address_2_field"] 151 | label 152 | +h( v-hidden ) 153 | letter-spacing: -1em 154 | 155 | &[id*="separator_field"] 156 | +h( w100p mv1_5 bt1-solid bc-gray ) 157 | 158 | input 159 | +h( d-none ) 160 | 161 | 162 | .woocommerce-input-wrapper 163 | +h( d-flex flex1 ) 164 | 165 | .select2-container 166 | +h( d-flex fd-column relative ) 167 | 168 | 169 | .select2-container 170 | +h( w100p h100p ) 171 | 172 | .selection 173 | +h( d-block h100p ) 174 | 175 | .select2-selection 176 | +h( d-flex ai-center h100p ) 177 | 178 | // selected 179 | .select2-selection--single 180 | +h( pv0_5 bg-black_05 ) 181 | border-bottom-width: 2px 182 | 183 | .select2-selection--single .select2-selection__arrow 184 | +h( top50p right10px w20px ) 185 | transform: translateY(-50%) 186 | 187 | b 188 | +h( m0 ) 189 | 190 | 191 | ///// LOGIN WRAPPER 192 | 193 | .h-login-wrapper 194 | +clearfix 195 | +h( w100p pt1 pb2 ph2 mt2 mb3 bg-gray-light ) 196 | +h( b1-solid bc-black_10 brad ) 197 | grid-column: span 2 198 | 199 | h2 200 | +h( fs-h3 mb1 ta-center ) 201 | 202 | .u-column1, 203 | .u-column2 204 | +h( d-flex fd-column ai-center w50p mh-auto ) 205 | 206 | // Login column 207 | .u-column1 208 | @media ($below-s) 209 | +h( w100p ) 210 | 211 | // Register column 212 | .u-column2 213 | +h( d-none ) 214 | 215 | // show register if URL has #register 216 | &:target 217 | +h( d-flex ) 218 | &:target ~ .u-column1 219 | +h( d-none ) 220 | 221 | // show login if URL has no #register 222 | &:not(:target) ~ .u-column1 223 | +h( d-flex ) 224 | 225 | .button.--passive 226 | +h( mt1 ) 227 | 228 | 229 | ////// User Account Form 230 | 231 | .woocommerce-form-login, 232 | .woocommerce-form-register, 233 | .woocommerce-ResetPassword 234 | @extend %form 235 | +h( m0 mt1 p1_25 bg-white shadow0 brad ) 236 | 237 | em 238 | +h( d-iblock fs-s ) 239 | 240 | // 241 | @media ($below-m) 242 | +h( p1 ) 243 | 244 | 245 | .woocommerce-form-login, 246 | .woocommerce-ResetPassword 247 | > * 248 | grid-column: span 12 249 | 250 | +h( mh-auto w320px ) 251 | 252 | .form-row 253 | +h( d-flex fw-wrap p0 w100p ) 254 | 255 | p:last-of-type 256 | +h( mb0 ) 257 | 258 | 259 | // LOGIN 260 | .woocommerce-form-login 261 | .woocommerce-LostPassword 262 | +h( fs-s ) 263 | 264 | [name="login"] + label // Remember me 265 | +h( ml-auto ) 266 | 267 | // RESET 268 | .woocommerce-ResetPassword 269 | p:first-of-type 270 | +h( fs-s ) 271 | 272 | 273 | // REGISTER 274 | .woocommerce-form-register 275 | p:last-child 276 | +h( mb0 ) 277 | 278 | [id*="_phone_field"] 279 | +h( d-none ) 280 | 281 | [id*="separator"] 282 | grid-column: span 12 283 | 284 | @media ($above-s) 285 | [id*="_address_1_field"] 286 | grid-column: span 7 287 | 288 | [id*="_address_2_field"] 289 | grid-column: span 5 290 | 291 | [id*="_country_field"], 292 | [id*="_city_field"], 293 | [id*="_postcode_field"], 294 | [id*="_state_field"] 295 | grid-column: span 4 296 | 297 | .woocommerce-privacy-policy-text 298 | +h( fs-s ) 299 | grid-column: span 112 300 | 301 | .button 302 | +h( w100p ) 303 | 304 | 305 | .woocommerce-password-strength 306 | +h( mt0_5 mb1 fs-s ) 307 | 308 | &.short, 309 | &.bad 310 | +h( c-red ) 311 | 312 | &.good, 313 | &.strong 314 | +h( fw-header tt-uppercase ) 315 | 316 | &.good 317 | +h( c-yellow ) 318 | 319 | &.strong 320 | +h( c-green ) 321 | 322 | 323 | 324 | 325 | 326 | 327 | ///// ADDRESS FORM and CUSTOMER DETAIL 328 | 329 | // wrapper 330 | .woocommerce-Addresses, 331 | .woocommerce-customer-details 332 | +h( mt1 ) 333 | 334 | .woocommerce-Addresses, 335 | .woocommerce-columns--addresses 336 | +h( d-flex ) 337 | 338 | @media ($below-s) 339 | +h( fd-column ) 340 | 341 | // form 342 | .woocommerce-address-fields__field-wrapper 343 | @extend %form 344 | +h( mb1 ) 345 | 346 | > * 347 | grid-column: span 4 348 | 349 | @media ($below-s) 350 | grid-column: span 6 351 | 352 | [id*="_address_1_field"] 353 | grid-column: span 8 354 | 355 | // 356 | @media ($below-s) 357 | > * 358 | grid-column: span 6 359 | 360 | [id*="_email_field"] 361 | grid-column: span 12 362 | 363 | [id*="_address_1_field"] 364 | grid-column: span 7 365 | 366 | [id*="_address_2_field"] 367 | grid-column: span 5 368 | 369 | 370 | // column 371 | .woocommerce-Address, 372 | .woocommerce-column--billing-address, 373 | .woocommerce-column--shipping-address 374 | +h( flex1 ) 375 | 376 | .title 377 | +h( d-flex ai-center ) 378 | 379 | @media ($below-s) 380 | +h( mb1 ) 381 | 382 | 383 | // title 384 | .woocommerce-Address h3, 385 | .woocommerce-column__title 386 | +h( fs-h3 fw-body mb0_5 ) 387 | 388 | 389 | // edit button 390 | .woocommerce-Address 391 | .edit 392 | +h( d-inline-block ml1 b1-solid bc-main pv0_25 ph0_5 ) 393 | +h( fs-s tt-uppercase lh1 brad ) 394 | 395 | .edit:hover 396 | +h( bg-main c-white ) 397 | 398 | 399 | ///// MY ACCOUNT - ORDER 400 | .account-orders-table 401 | +h( fs-s ) 402 | 403 | .woocommerce-order-details 404 | +h( mv2 ) 405 | 406 | h2 407 | +h( mb1 fw-body ) 408 | 409 | table, thead, tbody, tfoot, tr, td, th 410 | +h( d-block p0 bg-inherit b0 ) 411 | 412 | thead 413 | +h( d-none ) 414 | 415 | .order-again 416 | +h( mt2 ) 417 | 418 | .woocommerce-order-details table 419 | +h( ov-hidden brad shadow0 ) 420 | max-width: 600px 421 | border: 1px solid $wc-panel-dark 422 | 423 | .woocommerce-order-details tbody 424 | +h( d-flex fw-wrap p1 ) 425 | 426 | tr 427 | +h( d-flex ai-center w100p p0_5 ) 428 | border: 1px solid $wc-panel-dark 429 | 430 | tr + tr 431 | +h( mt0_5 ) 432 | 433 | img 434 | +h( mr1 ) 435 | 436 | td:first-child 437 | +h( flex1 ) 438 | 439 | .product-quantity 440 | +h( d-inline-block ph0_25 ml0_5 b1-solid bc-main ) 441 | +h( c-main lh1 fw-body brad ) 442 | padding-top: 2px 443 | padding-bottom: 2px 444 | 445 | 446 | .woocommerce-order-details tfoot 447 | +h( d-flex fw-wrap w100p ) 448 | background-color: $wc-panel 449 | 450 | td, tr, th 451 | +h( d-block ) 452 | 453 | th 454 | +h( tt-uppercase ls25 fs-s ) 455 | 456 | th, td 457 | +h( p0 bg-transparent b0 ) 458 | 459 | tr 460 | +h( w50p b0 ph1 pv0_5 ) 461 | tr:nth-child(even) 462 | +h( bg-transparent ) 463 | 464 | // total 465 | tr:last-child 466 | +h( w100p mt1 p0_5 bg-black_05 ) 467 | 468 | th 469 | +h( lh1 ) 470 | 471 | th, td 472 | +h( ta-center ) 473 | 474 | td 475 | +h( fs-h3 fw-header ) 476 | 477 | .shipped_via 478 | +h( d-block ) 479 | 480 | 481 | .h-customer-note 482 | +h( mt2 ) 483 | 484 | h3 485 | +h( mb1 fw-body ) 486 | 487 | ///// MY ACCOUNT - EDIT ACCOUNT 488 | 489 | .woocommerce-EditAccountForm 490 | @extend %form 491 | 492 | > * 493 | grid-column: span 4 494 | 495 | @media ($below-s) 496 | grid-column: span 6 497 | 498 | @media ($below-xs) 499 | grid-column: span 12 500 | 501 | em 502 | +h( d-block fs-xs c-passive ) 503 | line-height: 1.5 504 | 505 | legend 506 | +h( fs-h5 fw-header pl0_5 ) 507 | 508 | 509 | .woocommerce-EditAccountForm fieldset 510 | +clearfix 511 | grid-column: span 12 512 | 513 | legend 514 | +h( d-block pl0 ) 515 | 516 | p 517 | +h( d-iblock ) 518 | width: calc(33.333% - 5px) 519 | 520 | p + p 521 | +h( pl1 ) 522 | 523 | // 524 | @media ($below-s) 525 | p 526 | +h( mb1 ) 527 | width: calc(50% - 5px) 528 | 529 | p:nth-child(4) 530 | +h( pl0 ) 531 | 532 | @media ($below-xs) 533 | p 534 | width: 100% 535 | 536 | p + p 537 | +h( mt1 pl0 ) 538 | -------------------------------------------------------------------------------- /src/sass/edje/_functional-vars.scss: -------------------------------------------------------------------------------- 1 | $_h-all: (); // store all the Functional variables 2 | 3 | 4 | // Z-Index 5 | $h-z-index: ( 6 | names: ( z: z-index ), 7 | values: ( 8 | '-1': -1, 9 | 0: 0, 10 | 1: 1, 11 | 2: 2, 12 | 5: 5, 13 | 10: 10, 14 | 50: 50, 15 | 100: 100, 16 | ) 17 | ); 18 | 19 | 20 | // Border width 21 | $h-border: ( 22 | names: ( 23 | b: border, 24 | bt: border-top, 25 | bl: border-left, 26 | br: border-right, 27 | bb: border-bottom, 28 | ), 29 | values: ( 30 | '-none': none, // deprecated 31 | '0': 0, 32 | '1-solid': 1px solid, 33 | '1-dashed': 1px dashed, 34 | '2-solid': 2px solid, 35 | '2-dashed': 2px dashed, 36 | ) 37 | ); 38 | 39 | 40 | // Border Radius 41 | $h-border-radius: ( 42 | br: ( border-radius: $g-radius ), // deprecated 43 | br-circle: ( border-radius: 50% ), // deprecated 44 | br-pill: ( border-radius: 999px ), // deprecated 45 | 46 | brad0: ( border-radius: 0 ), 47 | brad: ( border-radius: $g-radius ), 48 | brad-circle: ( border-radius: 50% ), 49 | brad-pill: ( border-radius: 999px ), 50 | ); 51 | 52 | 53 | 54 | // Background Image - name can't be duplicate with BG Color 55 | $h-background-image: ( 56 | names: ( bg-: background-image ), 57 | values: () 58 | ); 59 | 60 | 61 | // Opacity 62 | $h-opacity: ( 63 | names: ( o: opacity ), 64 | values: ( 65 | 100: 1, 66 | 90: .9, 67 | 80: .8, 68 | 70: .7, 69 | 60: .6, 70 | 50: .5, 71 | 40: .4, 72 | 30: .3, 73 | 20: .2, 74 | 10: .1, 75 | 0: 0, 76 | ) 77 | ); 78 | 79 | 80 | // Box Shadow 81 | $h-shadow: ( 82 | names: ( shadow: box-shadow ), 83 | values: ( 84 | 0: $shadow-z0, 85 | 1: $shadow-z1, 86 | 2: $shadow-z2, 87 | 3: $shadow-z3, 88 | '-none': none, 89 | ) 90 | ); 91 | 92 | 93 | // Hover Effect 94 | $h-hover: ( 95 | hover-dim: ( 96 | ':hover': ( opacity: .6 ), 97 | ':active': ( opacity: .8 ), 98 | ), 99 | hover-grow: ( 100 | ':hover': ( '-webkit-transform': scale(1.05), transform: scale(1.05) ), 101 | ':active': ( '-webkit-transform': scale(1), transform: scale(1) ), 102 | ), 103 | hover-u: ( ':hover': ( text-decoration: underline ) ), 104 | ); 105 | 106 | 107 | // Transition 108 | $h-transition: ( 109 | transition: ( transition: $g-transition ), 110 | transition-none: ( transition: none ), 111 | ); 112 | 113 | 114 | // Font Size 115 | $h-font-size: ( 116 | names: ( fs-: font-size ), 117 | values: ( 118 | h1: '%h1', 119 | h2: '%h2', 120 | h3: '%h3', 121 | h4: '%h4', 122 | h5: '%h5', 123 | h6: '%h6', 124 | body: 1rem, 125 | m: 1.125em, 126 | s: 0.875em, 127 | xs: 0.75em, 128 | ), 129 | ); 130 | 131 | 132 | // Letter Spacing 133 | $h-letter-spacing: ( 134 | names: ( ls: letter-spacing ), 135 | values: ( 136 | '-100': -0.1em, 137 | '-50': -0.05em, 138 | '-25': -0.025em, 139 | 0: 0, 140 | 25: 0.025em, 141 | 50: 0.05em, 142 | 75: 0.075em, 143 | 100: 0.1em, 144 | 150: 0.15em 145 | ) 146 | ); 147 | 148 | 149 | // Font Family 150 | $h-font-family: ( 151 | names: ( ff-: font-family ), 152 | values: ( 153 | body: $font-family, 154 | header: $font-family-header, 155 | monospace: $font-family-monospace, 156 | ) 157 | ); 158 | 159 | 160 | // Line Height 161 | $h-line-height: ( 162 | names: ( lh: line-height ), 163 | values: ( 164 | 0: 0, 165 | 1: 1, 166 | '-normal': normal, 167 | '-body': $font-line, 168 | '-header': $header-line, 169 | ) 170 | ); 171 | 172 | 173 | 174 | ///// PRIVATE VARS ////// 175 | // Don't change anything below here 176 | 177 | 178 | // -------- 179 | // DISPLAY 180 | // -------- 181 | 182 | $_h-display: ( 183 | d-inline-block: ( display: inline-block ), 184 | d-iblock: ( display: inline-block ), 185 | d-block: ( display: block ), 186 | d-none: ( display: none ), 187 | d-flex: ( '_display': '-webkit-flex', display: flex ), 188 | d-grid: ( '_display': '-ms-grid', display: grid ), 189 | ); 190 | 191 | // Flexbox 192 | $_h-flex: ( 193 | fd-row: ( flex-direction: row ), 194 | fd-column: ( flex-direction: column ), 195 | fd-column-reverse: ( flex-direction: column-reverse ), 196 | fd-row-reverse: ( flex-direction: row-reverse ), 197 | fw-wrap: ( flex-wrap: wrap ), 198 | ); 199 | 200 | 201 | // Flex Wrapper - Align Items 202 | $_h-align-items: ( 203 | names: ( 204 | ai-: align-items, 205 | ), 206 | values: ( 207 | start: flex-start, 208 | end: flex-end, 209 | center: center, 210 | baseline: baseline, 211 | stretch: stretch, 212 | ) 213 | ); 214 | 215 | 216 | // Flex wrapper - Justify content 217 | $_h-justify-content: ( 218 | names: ( 219 | jc-: justify-content, 220 | ), 221 | values: ( 222 | start: flex-start, 223 | end: flex-end, 224 | center: center, 225 | around: space-around, 226 | between: space-between 227 | ) 228 | ); 229 | 230 | 231 | // Flex portion 232 | $_h-flex-portion: ( 233 | names: ( 234 | flex: flex, 235 | ), 236 | values: ( 237 | 0: 0, 238 | 1: 1, 239 | 2: 2, 240 | 3: 3, 241 | 4: 4, 242 | 5: 5 243 | ) 244 | ); 245 | 246 | 247 | // Flex order 248 | $_h-flex-order: ( 249 | names: ( 250 | order: order, 251 | ), 252 | values: ( 253 | 1: 1, 254 | 2: 2, 255 | 3: 3, 256 | 4: 4, 257 | 5: 5, 258 | '-last': 999 259 | ), 260 | ); 261 | 262 | 263 | // Flex Align Self 264 | $_h-align-self: ( 265 | names: ( 266 | as-: align-self, 267 | ), 268 | values: ( 269 | start: flex-start, 270 | end: flex-end, 271 | center: center, 272 | baseline: baseline, 273 | stretch: stretch, 274 | ) 275 | ); 276 | 277 | 278 | // Overflow 279 | $_h-overflow: ( 280 | names: ( 281 | ov-: overflow, 282 | ovx-: overflow-x, 283 | ovy-: overflow-y, 284 | ), 285 | values: ( 286 | auto: auto, 287 | hidden: hidden, 288 | scroll: scroll, 289 | visible: visible, 290 | ) 291 | ); 292 | 293 | 294 | // Cursor 295 | $_h-cursor: ( 296 | names: ( 297 | cursor-: cursor, 298 | ), 299 | values: ( 300 | default: default, 301 | pointer: pointer, 302 | text: text, 303 | move: move, 304 | grab: grab, 305 | progress: progress, 306 | not-allowed: not-allowed, 307 | zoom-in: zoom-in, 308 | zoom-out: zoom-out, 309 | ) 310 | ); 311 | 312 | // Other Display 313 | $_h-display-misc: ( 314 | v-visible: ( visibility: visible ), 315 | v-hidden: ( visibility: hidden ), 316 | 317 | select-none: ( 318 | '-webkit-touch-callout': none, 319 | '-webkit-user-select': none, 320 | '-moz-user-select': none, 321 | 'user-select': none 322 | ), 323 | 324 | events-none: ( 325 | pointer-events: none, 326 | ), 327 | events-all: ( 328 | pointer-events: all, 329 | ), 330 | 331 | appearance-none: ( 332 | '-moz-appearance': none, 333 | '-webkit-appearance': none, 334 | 'appearance': none 335 | ), 336 | backface-hidden: ( 337 | '-webkit-backface-visibility': hidden, 338 | 'backface-visibility': hidden 339 | ), 340 | 341 | no-select: ( // deprecated 342 | '-webkit-touch-callout': none, 343 | '-webkit-user-select': none, 344 | '-moz-user-select': none, 345 | 'user-select': none 346 | ), 347 | no-appearance: ( // deprecated 348 | '-moz-appearance': none, 349 | '-webkit-appearance': none, 350 | 'appearance': none 351 | ), 352 | no-events: ( // deprecated 353 | pointer-events: none, 354 | ), 355 | ); 356 | 357 | 358 | // ------- 359 | // LAYOUT 360 | // ------- 361 | 362 | 363 | // Position 364 | $_h-position: ( 365 | static: ( position: static ), 366 | relative: ( position: relative ), 367 | absolute: ( position: absolute ), 368 | fixed: ( position: fixed ), 369 | sticky: ( '_position': '-webkit-sticky', position: sticky ), 370 | 371 | absolute-fill: ( position: absolute, top: 0, right: 0, left: 0, bottom: 0 ), 372 | ); 373 | 374 | 375 | // Float 376 | $_h-float: ( 377 | float-left: ( float: left ), 378 | float-right: ( float: right ), 379 | float-none: ( float: none ), 380 | clear-both: ( clear: both ), 381 | clear-none: ( clear: none ), 382 | // clearfix: ( 383 | // '::before': ( content: " ", display: table ), 384 | // '::after': ( content: " ", display: table, clear: both ) 385 | // ) 386 | ); 387 | 388 | 389 | // ------ 390 | // THEME 391 | // ------ 392 | 393 | $_h-background-position: ( 394 | names: ( bgp-: background-position ), 395 | values: ( 396 | cc: center center, 397 | cr: center right, 398 | cl: center left, 399 | tc: top center, 400 | tr: top right, 401 | tl: top left, 402 | bc: bottom center, 403 | br: bottom right, 404 | bl: bottom left, 405 | ) 406 | ); 407 | 408 | 409 | // Background Misc 410 | $_h-background-misc: ( 411 | bgs-cover: ( background-size: cover ), 412 | bgs-contain: ( background-size: contain ), 413 | 414 | bgr: ( background-repeat: repeat ), 415 | bgr-no: ( background-repeat: no-repeat ), 416 | bgr-x: ( background-repeat: repeat-x ), 417 | bgr-y: ( background-repeat: repeat-y ), 418 | 419 | // alias 420 | bgr-repeat: ( background-repeat: repeat ), 421 | bgr-no-repeat: ( background-repeat: no-repeat ), 422 | bgr-repeat-x: ( background-repeat: repeat-x ), 423 | bgr-repeat-y: ( background-repeat: repeat-y ), 424 | ); 425 | 426 | 427 | // Theme Misc 428 | $_h-theme-misc: ( 429 | ); 430 | 431 | 432 | // ----------- 433 | // TYPOGRAPHY 434 | // ----------- 435 | 436 | // List style 437 | $_h-list-style: ( 438 | names: ( list-: list-style-type ), 439 | values: ( 440 | none: none, 441 | disc: disc, 442 | circle: circle, 443 | square: square, 444 | 445 | decimal: decimal, 446 | decimal0: decimal-leading-zero, 447 | alpha: lower-alpha, 448 | roman: lower-roman, 449 | upper-alpha: upper-alpha, 450 | upper-roman: upper-roman, 451 | ) 452 | ); 453 | 454 | 455 | // Font Misc 456 | $_h-font-misc: ( 457 | nowrap: ( white-space: nowrap ), 458 | 459 | tt-uppercase: ( text-transform: uppercase ), 460 | tt-lowercase: ( text-transform: lowercase ), 461 | tt-capitalize: ( text-transform: capitalize ), 462 | tt-none: ( text-transform: none ), 463 | 464 | ta-center: ( text-align: center ), 465 | ta-right: ( text-align: right ), 466 | ta-left: ( text-align: left ), 467 | ta-justify: ( text-align: justify ), 468 | ); 469 | 470 | 471 | // Font Weight 472 | $_h-font-weight: ( 473 | names: ( fw: font-weight ), 474 | values: ( 475 | 300: 300, 476 | 400: 400, 477 | 600: 600, 478 | 700: 700, 479 | 900: 900, 480 | '-body': $font-weight, 481 | '-header': $header-weight, 482 | ) 483 | ); 484 | 485 | 486 | // Font Styles 487 | $_h-font-style: ( 488 | b: ( font-weight: 700 ), 489 | i: ( font-style: italic ), 490 | u: ( text-decoration: underline ), 491 | td-u: ( text-decoration: underline ), 492 | strike: ( text-decoration: line-through ), 493 | td-strike: ( text-decoration: line-through ), 494 | td-none: ( text-decoration: none ), 495 | ); 496 | 497 | 498 | // Vertical Align 499 | $_h-vertical-align: ( 500 | names: ( va-: vertical-align ), 501 | values: ( 502 | baseline: baseline, 503 | top: top, 504 | middle: middle, 505 | bottom: bottom, 506 | sub: sub, 507 | super: super, 508 | text-top: text-top 509 | ) 510 | ); 511 | 512 | 513 | ///// 514 | 515 | $_h-all: map-merge( $_h-all, _merge( 516 | $_h-display, 517 | $_h-flex, 518 | $_h-align-items, 519 | $_h-justify-content, 520 | $_h-flex-order, 521 | $_h-flex-portion, 522 | $_h-align-self, 523 | $_h-overflow, 524 | $_h-cursor, 525 | $_h-display-misc, 526 | 527 | $_h-position, 528 | $h-z-index, 529 | $_h-float, 530 | 531 | $h-border, 532 | $h-border-radius, 533 | 534 | $h-background-image, 535 | $_h-background-position, 536 | $_h-background-misc, 537 | $h-shadow, 538 | $h-opacity, 539 | $_h-theme-misc, 540 | $h-transition, 541 | 542 | $h-font-size, 543 | $h-letter-spacing, 544 | $h-font-family, 545 | $h-line-height, 546 | $_h-list-style, 547 | $_h-font-misc, 548 | $_h-font-weight, 549 | $_h-font-style, 550 | $_h-vertical-align, 551 | 552 | $h-custom, 553 | ) ); -------------------------------------------------------------------------------- /module-gutenberg/dist/h-featured-category.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | /******/ 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | /******/ 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) { 10 | /******/ return installedModules[moduleId].exports; 11 | /******/ } 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ i: moduleId, 15 | /******/ l: false, 16 | /******/ exports: {} 17 | /******/ }; 18 | /******/ 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | /******/ 22 | /******/ // Flag the module as loaded 23 | /******/ module.l = true; 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | /******/ 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | /******/ 36 | /******/ // define getter function for harmony exports 37 | /******/ __webpack_require__.d = function(exports, name, getter) { 38 | /******/ if(!__webpack_require__.o(exports, name)) { 39 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); 40 | /******/ } 41 | /******/ }; 42 | /******/ 43 | /******/ // define __esModule on exports 44 | /******/ __webpack_require__.r = function(exports) { 45 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { 46 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); 47 | /******/ } 48 | /******/ Object.defineProperty(exports, '__esModule', { value: true }); 49 | /******/ }; 50 | /******/ 51 | /******/ // create a fake namespace object 52 | /******/ // mode & 1: value is a module id, require it 53 | /******/ // mode & 2: merge all properties of value into the ns 54 | /******/ // mode & 4: return value when already ns object 55 | /******/ // mode & 8|1: behave like require 56 | /******/ __webpack_require__.t = function(value, mode) { 57 | /******/ if(mode & 1) value = __webpack_require__(value); 58 | /******/ if(mode & 8) return value; 59 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; 60 | /******/ var ns = Object.create(null); 61 | /******/ __webpack_require__.r(ns); 62 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); 63 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); 64 | /******/ return ns; 65 | /******/ }; 66 | /******/ 67 | /******/ // getDefaultExport function for compatibility with non-harmony modules 68 | /******/ __webpack_require__.n = function(module) { 69 | /******/ var getter = module && module.__esModule ? 70 | /******/ function getDefault() { return module['default']; } : 71 | /******/ function getModuleExports() { return module; }; 72 | /******/ __webpack_require__.d(getter, 'a', getter); 73 | /******/ return getter; 74 | /******/ }; 75 | /******/ 76 | /******/ // Object.prototype.hasOwnProperty.call 77 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 78 | /******/ 79 | /******/ // __webpack_public_path__ 80 | /******/ __webpack_require__.p = ""; 81 | /******/ 82 | /******/ 83 | /******/ // Load entry module and return exports 84 | /******/ return __webpack_require__(__webpack_require__.s = "./src/featured-category.jsx"); 85 | /******/ }) 86 | /************************************************************************/ 87 | /******/ ({ 88 | 89 | /***/ "./src/featured-category.jsx": 90 | /*!***********************************!*\ 91 | !*** ./src/featured-category.jsx ***! 92 | \***********************************/ 93 | /*! no exports provided */ 94 | /***/ (function(module, __webpack_exports__, __webpack_require__) { 95 | 96 | "use strict"; 97 | eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/element */ \"@wordpress/element\");\n/* harmony import */ var _wordpress_element__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _featured_category_sass__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./featured-category.sass */ \"./src/featured-category.sass\");\n/* harmony import */ var _featured_category_sass__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_featured_category_sass__WEBPACK_IMPORTED_MODULE_1__);\n/* harmony import */ var lodash__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! lodash */ \"lodash\");\n/* harmony import */ var lodash__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(lodash__WEBPACK_IMPORTED_MODULE_2__);\n/* harmony import */ var _wordpress_hooks__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @wordpress/hooks */ \"@wordpress/hooks\");\n/* harmony import */ var _wordpress_hooks__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(_wordpress_hooks__WEBPACK_IMPORTED_MODULE_3__);\n/* harmony import */ var _wordpress_data__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @wordpress/data */ \"@wordpress/data\");\n/* harmony import */ var _wordpress_data__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_wordpress_data__WEBPACK_IMPORTED_MODULE_4__);\n/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @wordpress/block-editor */ \"@wordpress/block-editor\");\n/* harmony import */ var _wordpress_block_editor__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_5__);\n\n// Add Vertical Alignment to woocommerce/featured-category block\n\n\n\n\n\n\nObject(_wordpress_hooks__WEBPACK_IMPORTED_MODULE_3__[\"addFilter\"])('blocks.registerBlockType', 'wc-featured-category/attributes', addAttribute);\nObject(_wordpress_hooks__WEBPACK_IMPORTED_MODULE_3__[\"addFilter\"])('editor.BlockEdit', 'wc-featured-category/edit', addControl);\n/**\r\n * Add the Vertical Align attribute\r\n */\n\nfunction addAttribute(settings, name) {\n // abort if not our targetted block\n var targetBlocks = ['woocommerce/featured-category', 'woocommerce/featured-product'];\n\n if (!targetBlocks.includes(name)) {\n return settings;\n }\n\n settings.attributes = Object(lodash__WEBPACK_IMPORTED_MODULE_2__[\"assign\"])(settings.attributes, {\n verticalAlignment: {\n type: 'string',\n default: 'center'\n },\n textColor: {\n type: 'string',\n default: 'white'\n }\n });\n return settings;\n}\n/**\r\n * Add the Vertical Align option to the toolbar\r\n */\n\n\nfunction addControl(BlockEdit) {\n return function (props) {\n // abort if not our targetted block\n var targetBlocks = ['woocommerce/featured-category', 'woocommerce/featured-product'];\n\n if (!targetBlocks.includes(props.name)) {\n return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__[\"createElement\"])(BlockEdit, props);\n }\n\n var atts = props.attributes;\n return Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__[\"createElement\"])(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__[\"Fragment\"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__[\"createElement\"])(BlockEdit, props), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__[\"createElement\"])(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_5__[\"BlockControls\"], {\n key: \"controls\"\n }, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__[\"createElement\"])(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_5__[\"BlockVerticalAlignmentToolbar\"], {\n onChange: updateAlignment,\n value: atts.verticalAlignment\n })), Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__[\"createElement\"])(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_5__[\"InspectorControls\"], null, Object(_wordpress_element__WEBPACK_IMPORTED_MODULE_0__[\"createElement\"])(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_5__[\"PanelColorSettings\"], {\n title: \"Text Color\",\n initialOpen: \"true\",\n colorSettings: [{\n label: 'Text Color',\n value: atts.textColor,\n disableCustomColors: false,\n onChange: updateTextColor\n }]\n }))); //\n\n function updateAlignment(newValue) {\n newValue = newValue || '';\n props.setAttributes({\n verticalAlignment: newValue\n }); // remove existing VAlign class\n\n if (atts.className) {\n atts.className = atts.className.replace(/is-vertically-aligned-\\w+/, '');\n } else {\n atts.className = ''; // initialize\n } // add VAlign class\n\n\n if (newValue) {\n props.setAttributes({\n className: \"\".concat(atts.className, \" is-vertically-aligned-\").concat(newValue)\n });\n }\n }\n /**\r\n * \r\n */\n\n\n function updateTextColor(newColor) {\n newColor = newColor || 'white';\n props.setAttributes({\n textColor: newColor\n }); // remove existing color class\n\n if (atts.className) {\n atts.className = atts.className.replace(/has-text-color has-[\\w-]+-color/, '').trim();\n } else {\n atts.className = ''; // initialize\n } // if none selected\n\n\n if (newColor === 'white') {\n props.setAttributes({\n className: atts.className.trim()\n });\n } else {\n var settings = Object(_wordpress_data__WEBPACK_IMPORTED_MODULE_4__[\"select\"])('core/editor').getEditorSettings();\n var colorObject = Object(_wordpress_block_editor__WEBPACK_IMPORTED_MODULE_5__[\"getColorObjectByColorValue\"])(settings.colors, newColor);\n props.setAttributes({\n className: \"\".concat(atts.className, \" has-text-color has-\").concat(colorObject.slug, \"-color\")\n });\n }\n }\n };\n}\n\n//# sourceURL=webpack:///./src/featured-category.jsx?"); 98 | 99 | /***/ }), 100 | 101 | /***/ "./src/featured-category.sass": 102 | /*!************************************!*\ 103 | !*** ./src/featured-category.sass ***! 104 | \************************************/ 105 | /*! no static exports found */ 106 | /***/ (function(module, exports, __webpack_require__) { 107 | 108 | eval("// extracted by mini-css-extract-plugin\n\n//# sourceURL=webpack:///./src/featured-category.sass?"); 109 | 110 | /***/ }), 111 | 112 | /***/ "@wordpress/block-editor": 113 | /*!*************************************!*\ 114 | !*** external ["wp","blockEditor"] ***! 115 | \*************************************/ 116 | /*! no static exports found */ 117 | /***/ (function(module, exports) { 118 | 119 | eval("(function() { module.exports = window[\"wp\"][\"blockEditor\"]; }());\n\n//# sourceURL=webpack:///external_%5B%22wp%22,%22blockEditor%22%5D?"); 120 | 121 | /***/ }), 122 | 123 | /***/ "@wordpress/data": 124 | /*!******************************!*\ 125 | !*** external ["wp","data"] ***! 126 | \******************************/ 127 | /*! no static exports found */ 128 | /***/ (function(module, exports) { 129 | 130 | eval("(function() { module.exports = window[\"wp\"][\"data\"]; }());\n\n//# sourceURL=webpack:///external_%5B%22wp%22,%22data%22%5D?"); 131 | 132 | /***/ }), 133 | 134 | /***/ "@wordpress/element": 135 | /*!*********************************!*\ 136 | !*** external ["wp","element"] ***! 137 | \*********************************/ 138 | /*! no static exports found */ 139 | /***/ (function(module, exports) { 140 | 141 | eval("(function() { module.exports = window[\"wp\"][\"element\"]; }());\n\n//# sourceURL=webpack:///external_%5B%22wp%22,%22element%22%5D?"); 142 | 143 | /***/ }), 144 | 145 | /***/ "@wordpress/hooks": 146 | /*!*******************************!*\ 147 | !*** external ["wp","hooks"] ***! 148 | \*******************************/ 149 | /*! no static exports found */ 150 | /***/ (function(module, exports) { 151 | 152 | eval("(function() { module.exports = window[\"wp\"][\"hooks\"]; }());\n\n//# sourceURL=webpack:///external_%5B%22wp%22,%22hooks%22%5D?"); 153 | 154 | /***/ }), 155 | 156 | /***/ "lodash": 157 | /*!*************************!*\ 158 | !*** external "lodash" ***! 159 | \*************************/ 160 | /*! no static exports found */ 161 | /***/ (function(module, exports) { 162 | 163 | eval("(function() { module.exports = window[\"lodash\"]; }());\n\n//# sourceURL=webpack:///external_%22lodash%22?"); 164 | 165 | /***/ }) 166 | 167 | /******/ }); -------------------------------------------------------------------------------- /src/sass/edje/_output.scss: -------------------------------------------------------------------------------- 1 | $include-normalize: false !default; 2 | $include-grid: false !default; 3 | $include-tile: false !default; 4 | $include-typography: false !default; 5 | $include-visibility: false !default; 6 | $include-colors: false !default; 7 | $output-framework: false !default; 8 | 9 | 10 | @if $output-framework { 11 | /* EDJE Framework 3.0 - hrsetyono.github.io/edje */ 12 | } 13 | 14 | // ------------ 15 | // NORMALIZER 16 | // ------------ 17 | // Based on git.io/normalize v3.0.3 18 | 19 | @if $output-framework and $include-normalize { 20 | *, 21 | *:before, 22 | *:after { 23 | -webkit-box-sizing: border-box; 24 | -moz-box-sizing: border-box; 25 | box-sizing: border-box; 26 | } 27 | 28 | html { 29 | font-family: sans-serif; 30 | -webkit-text-size-adjust: 100%; 31 | -ms-text-size-adjust: 100%; 32 | } 33 | 34 | // Basic reset margin and padding 35 | *, body { 36 | margin: 0; 37 | padding: 0; 38 | } 39 | 40 | // Correct `block` display 41 | article, 42 | aside, 43 | details, 44 | figcaption, 45 | figure, 46 | footer, 47 | header, 48 | hgroup, 49 | main, 50 | nav, 51 | section, 52 | picture, 53 | summary { 54 | display: block; 55 | } 56 | 57 | 58 | // Correct `inline-block` display 59 | audio, 60 | canvas, 61 | progress, 62 | video { 63 | display: inline-block; 64 | } 65 | audio:not([controls]) { 66 | display: none; 67 | height: 0; 68 | } 69 | 70 | // Webkit sibling selector fix 71 | body { -webkit-animation: bugfix infinite 1s; } 72 | @-webkit-keyframes bugfix { 73 | from { padding: 0; } 74 | to { padding: 0; } 75 | } 76 | 77 | // Reset anchor styling 78 | a { 79 | cursor: pointer; 80 | text-decoration: none; 81 | background-color: transparent; 82 | 83 | // &:focus { outline: none; } 84 | &:active, &:hover { outline: 0; } 85 | } 86 | 87 | // Basic typography 88 | b, strong { font-weight: bold; } 89 | em { font-style: italic; } 90 | h1, h2, h3, h4, h5, h6 { margin: 0; } 91 | 92 | // Media 93 | img { 94 | border: 0; 95 | display: inline-block; 96 | vertical-align: middle; 97 | -ms-interpolation-mode: bicubic; 98 | } 99 | svg:not(:root) { overflow: hidden; } 100 | figure { margin: 0; } 101 | 102 | // A better looking default horizontal rule 103 | hr { 104 | -moz-box-sizing: content-box; 105 | box-sizing: content-box; 106 | display: block; 107 | height: 1px; 108 | margin: 1em 0; 109 | padding: 0; 110 | border: 0; 111 | border-top: 1px solid #ccc; 112 | } 113 | 114 | blockquote cite { 115 | display: block; 116 | font-style: italic; 117 | } 118 | 119 | // Code block 120 | pre { overflow: auto; } 121 | code, kbd, pre, samp { 122 | font-family: monospace, monospace; 123 | font-size: 1em; 124 | } 125 | 126 | // Embedded content 127 | img, 128 | object, 129 | embed { 130 | max-width: 100%; 131 | height: auto; 132 | 133 | #map_canvas &, 134 | .map_canvas & { 135 | max-width: none !important; 136 | } 137 | } 138 | object, embed { height: 100%; } 139 | 140 | // Address styling 141 | [hidden], template { display: none; } 142 | address, cite { font-style: normal; } 143 | abbr[title] { border-bottom: 1px dotted; } 144 | dfn { font-style: italic; } 145 | mark { background: #ff0; color: #000; } 146 | 147 | // Misc inline elements 148 | q { quotes: "\201C" "\201D" "\2018" "\2019"; } 149 | small { font-size: 80%; } 150 | sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } 151 | sup { top: -0.5em; } 152 | sub { bottom: -0.25em; } 153 | 154 | // Form styling ----------- 155 | button, 156 | input, 157 | optgroup, 158 | select, 159 | textarea { 160 | outline: none; 161 | margin: 0; 162 | color: inherit; 163 | font: inherit; 164 | } 165 | 166 | button, input[type="submit"] { 167 | overflow: visible; 168 | cursor: pointer; 169 | outline: none; 170 | -webkit-backface-visibility: hidden; 171 | 172 | &:focus { outline: none; } 173 | } 174 | 175 | button, select { text-transform: none; } 176 | optgroup { font-weight: bold; } 177 | button, input, label { line-height: normal; } 178 | label { display: block; } 179 | button, input, select, textarea { 180 | font-family: inherit; 181 | font-size: 100%; 182 | margin: 0; 183 | } 184 | 185 | button, 186 | html input[type="button"], 187 | input[type="reset"], 188 | input[type="submit"] { 189 | -webkit-appearance: button; 190 | cursor: pointer; 191 | } 192 | 193 | button[disabled], 194 | html input[disabled] { cursor: default; } 195 | 196 | button::-moz-focus-inner, 197 | input::-moz-focus-inner { border: 0; padding: 0; } 198 | 199 | input { line-height: normal; } 200 | 201 | input[type="checkbox"], 202 | input[type="radio"] { box-sizing: border-box; padding: 0; } 203 | 204 | input[type="number"]::-webkit-inner-spin-button, 205 | input[type="number"]::-webkit-outer-spin-button { 206 | height: auto; 207 | } 208 | 209 | input[type="search"] { 210 | -webkit-appearance: textfield; 211 | 212 | &::-webkit-search-cancel-button, 213 | &::-webkit-search-decoration { 214 | -webkit-appearance: none; 215 | } 216 | } 217 | 218 | // Disable Chrome's datepicker 219 | input::-webkit-calendar-picker-indicator{ display: none; } 220 | input[type="date"]::-webkit-input-placeholder{ visibility: hidden !important; } 221 | 222 | textarea { 223 | overflow: auto; 224 | vertical-align: top; 225 | resize: vertical; // only vertical resizing 226 | height: auto; 227 | min-height: 50px; 228 | } 229 | 230 | legend { border: 0; padding: 0; } 231 | fieldset { 232 | border: 0; 233 | margin: 0; 234 | padding: 0; 235 | } 236 | 237 | // Table 238 | table { 239 | border-collapse: collapse; 240 | border-spacing: 0; 241 | } 242 | td, th { padding: 0; } 243 | 244 | .hide { display: none !important; visibility: hidden !important; } 245 | 246 | .flex-iframe { 247 | overflow: hidden; position: relative; 248 | height: 0; padding-bottom: 67.5%; padding-top: 1.38889rem; 249 | 250 | iframe, 251 | object, 252 | embed, 253 | video { 254 | position: absolute; top: 0; left: 0; 255 | height: 100%; width: 100%; } 256 | } 257 | 258 | } // include-normalize 259 | 260 | 261 | // ------------ 262 | // GRID SYSTEM 263 | // ------------ 264 | 265 | @mixin grid( 266 | $columns: false, 267 | $gap: false, 268 | $rim: false, 269 | $width: false, 270 | $collapse: false ) { 271 | 272 | @if $columns { 273 | grid-template-columns: repeat( $columns, 1fr ); 274 | } 275 | 276 | @if $gap { 277 | grid-column-gap: $gap; 278 | } 279 | 280 | @if $width and $rim { 281 | max-width: $width + ($rim * 2); 282 | padding: 0 $rim; 283 | } 284 | @else if $width { 285 | max-width: $width + ($grid-rim * 2); 286 | } 287 | @else if $rim { 288 | padding-right: $rim; 289 | padding-left: $rim; 290 | } 291 | 292 | @if $collapse { 293 | grid-column-gap: 0; 294 | } 295 | } 296 | 297 | @mixin column( 298 | $span: false, 299 | $span-s: false, 300 | $span-xs: false, 301 | ) { 302 | @if $span { 303 | grid-column: span #{ $span }; 304 | } 305 | 306 | @if $span-s { 307 | @media ($below-s) { 308 | grid-column: span #{ $span_s }; 309 | } 310 | } 311 | 312 | @if $span-xs { 313 | @media ($below-xs) { 314 | grid-column: span #{ $span_xs }; 315 | } 316 | } 317 | } 318 | 319 | 320 | ///// 321 | 322 | @if $output-framework and $include-grid { 323 | 324 | // Grid wrapper 325 | h-grid { 326 | @include h( d-grid ); 327 | @include grid( $grid-columns ); 328 | @include grid( $gap: $grid-gap ); 329 | @include grid( $width: $grid-max-width ); 330 | @include grid( $rim: $grid-rim ); 331 | margin: 0 auto; 332 | width: 100%; 333 | 334 | &.collapse { 335 | @include grid( $collapse: true ); 336 | } 337 | 338 | h-grid { 339 | margin: 0; 340 | padding: 0; 341 | } 342 | } 343 | 344 | // Column 345 | @for $i from 1 through $grid-columns { 346 | .large-#{$i} { 347 | @include column( $i ); 348 | } 349 | } 350 | 351 | // Small column 352 | @media ($below-s) { 353 | // reset 354 | [class*="large-"] { 355 | @include column( $grid-columns ); 356 | } 357 | 358 | @for $i from 1 through $grid-columns { 359 | .small-#{$i} { 360 | @include column( $i ); 361 | } 362 | } 363 | } 364 | 365 | 366 | } // include-grid 367 | 368 | 369 | 370 | // ------------- 371 | // TILE SYSTEM 372 | // ------------- 373 | 374 | @mixin tile( 375 | $per_row: false, 376 | $per_row_s: false, 377 | $per_row_xs: false, 378 | $gap: false, 379 | $collapse: false ) { 380 | 381 | @if $per_row { 382 | grid-template-columns: repeat( $per_row, 1fr ); 383 | 384 | @if $per_row_s { 385 | @media ($below-s) { 386 | grid-template-columns: repeat( $per_row_s, 1fr ); 387 | } 388 | } 389 | 390 | @if $per_row_xs { 391 | @media ($below-xs) { 392 | grid-template-columns: repeat( $per_row_xs, 1fr ); 393 | } 394 | } 395 | } 396 | 397 | @if $gap { 398 | grid-column-gap: $gap; 399 | grid-row-gap: $gap; 400 | } 401 | 402 | @if $collapse { 403 | grid-column-gap: 0; 404 | } 405 | 406 | } 407 | 408 | 409 | @if $output-framework and $include-tile { 410 | 411 | h-tile { 412 | @include h( d-grid ); 413 | @include tile( $gap: $tile-gap ); 414 | 415 | &.collapse { 416 | @include tile( $collapse: true ); 417 | } 418 | 419 | > * { 420 | grid-column: span 1; 421 | } 422 | } 423 | 424 | @for $i from 1 through $tile-max { 425 | .tile-#{$i} { 426 | @include tile( $i ); 427 | } 428 | } 429 | 430 | @media ($below-s) { 431 | // reset 432 | [class*="tile-"] { @include tile(1); } 433 | 434 | @for $i from 1 through $tile-max { 435 | .small-tile-#{$i} { 436 | @include tile( $i ); 437 | } 438 | } 439 | } 440 | 441 | } // include-tile 442 | 443 | 444 | // ------------ 445 | // TYPOGRAPHY 446 | // ------------ 447 | 448 | %h1 { @include font-sizes( $h1 ); } 449 | %h2 { @include font-sizes( $h2 ); } 450 | %h3 { @include font-sizes( $h3 ); } 451 | %h4 { @include font-sizes( $h4 ); } 452 | %h5 { @include font-sizes( $h5 ); } 453 | %h6 { @include font-sizes( $h6 ); } 454 | 455 | 456 | @if $output-framework and $include-typography { 457 | 458 | body { 459 | position: relative; 460 | background: $body-background; 461 | 462 | font-size: $font-size; 463 | font-family: $font-family; 464 | font-weight: $font-weight; 465 | line-height: $font-line; 466 | color: $font-color; 467 | } 468 | 469 | p { 470 | margin-top: 0; 471 | margin-bottom: 0; 472 | } 473 | 474 | a { 475 | color: $color-link; 476 | transition: $g-transition; 477 | 478 | &:hover { color: $color-link-hover; } 479 | } 480 | 481 | h1, h2, h3, h4, h5, h6 { 482 | font-family: $font-family-header; 483 | font-weight: $header-weight; 484 | line-height: $header-line; 485 | color: $header-color; 486 | 487 | letter-spacing: $header-spacing; 488 | text-transform: $header-transform; 489 | } 490 | 491 | 492 | h1 { @extend %h1; } 493 | h2 { @extend %h2; } 494 | h3 { @extend %h3; } 495 | h4 { @extend %h4; } 496 | h5 { @extend %h5; } 497 | h6 { @extend %h6; } 498 | 499 | // ----- LIST ----- 500 | 501 | ul { 502 | list-style-type: $ul-parent; 503 | 504 | ul { list-style-type: $ul-child; } 505 | } 506 | 507 | ol { 508 | list-style-type: $ol-parent; 509 | 510 | ol { list-style-type: $ol-child; } 511 | } 512 | 513 | 514 | // Create font-face declaration 515 | @each $name, $files in $font-faces { 516 | @each $file, $weight, $style in $files { 517 | @font-face { 518 | src: font-url($file); 519 | font-family: $name; 520 | font-weight: $weight; 521 | font-style: $style; 522 | } 523 | } 524 | } 525 | 526 | 527 | } // include-typography 528 | 529 | 530 | 531 | // ----------- 532 | // VISIBILITY 533 | // ----------- 534 | 535 | @if $output-framework and $include-visibility { 536 | 537 | @media ($above-s) { 538 | .hide-for-l, 539 | .show-for-s { 540 | display: none !important; 541 | } 542 | } 543 | 544 | @media ($below-s) { 545 | .hide-for-s, 546 | .show-for-l { 547 | display: none !important; 548 | } 549 | } 550 | 551 | @media ($above-xs) { 552 | .show-for-xs { 553 | display: none !important; 554 | } 555 | } 556 | 557 | @media ($below-xs) { 558 | .hide-for-xs { 559 | display: none !important; 560 | } 561 | } 562 | 563 | } // include-visibility 564 | 565 | 566 | // ------------ 567 | // ROOT COLORS 568 | // ------------ 569 | 570 | @if $output-framework and $include-colors { 571 | :root { 572 | @each $name, $value in $h-colors { 573 | --#{ $name }: #{ $value }; 574 | 575 | @if type_of( $value ) == 'color' { 576 | --#{ $name }RGB: #{ round(red($value)) }, #{ round(green($value)) }, #{ round(blue($value)) } 577 | } 578 | } 579 | } 580 | } 581 | 582 | // Separator 583 | 584 | @if $output-framework { 585 | /* ----- */ 586 | } -------------------------------------------------------------------------------- /module-variations-ui/src/hwc-variations.js: -------------------------------------------------------------------------------- 1 | import './hwc-variations.sass'; 2 | 3 | const $ = jQuery; 4 | 5 | /** 6 | * PRODUCT TYPE SELECTION 7 | */ 8 | const hProductType = { 9 | init() { 10 | // on change product type 11 | const $select = document.querySelector('#product-type'); 12 | if (!$select) { return; } 13 | 14 | this.addTypeClass($select); 15 | 16 | $select.addEventListener('change', (e) => { 17 | this.addTypeClass(e.currentTarget); 18 | }); 19 | }, 20 | 21 | /** 22 | * Add extra class to so it's easier to target and style 23 | */ 24 | addTypeClass($select) { 25 | const typeName = $select.value; 26 | const $wrapper = document.querySelector('body'); 27 | 28 | if (!$wrapper) { return; } 29 | 30 | const re = new RegExp(/is-product-type-\w+/, 'g'); 31 | 32 | if ($wrapper.className.match(re)) { 33 | $wrapper.className = $wrapper.className.replace(re, `is-product-type-${typeName}`); 34 | } else { 35 | $wrapper.classList.add(`is-product-type-${typeName}`); 36 | } 37 | }, 38 | }; 39 | 40 | /** 41 | * ATTRIBUTE Tab 42 | */ 43 | const hAttributes = { 44 | init() { 45 | this.onAdded(); 46 | this.onSaved(); 47 | this.moveFields(); 48 | }, 49 | 50 | /** 51 | * Tick the "Use as Variations" checkbox whenever new attribute is added 52 | */ 53 | onAdded() { 54 | $('body').on('woocommerce_added_attribute', () => { 55 | // @note - currently no need for check because we hide the Attribute tab when it's not variable 56 | // if (!document.body.classList.contains('is-product-type-variable')) { 57 | // return; 58 | // } 59 | 60 | const $variationToggles = document.querySelectorAll('#product_attributes [name*="attribute_variation["]'); 61 | 62 | [...$variationToggles].forEach(($t) => { 63 | $t.checked = true; 64 | $t.dispatchEvent(new Event('change')); 65 | 66 | this.moveField($t.closest('.wc-metabox')); 67 | }); 68 | }); 69 | }, 70 | 71 | /** 72 | * Move all fields after saving 73 | */ 74 | onSaved() { 75 | $('#variable_product_options').on('reload', () => { 76 | this.moveFields(); 77 | }); 78 | }, 79 | 80 | /** 81 | * Move all input field to Heading 82 | */ 83 | moveFields() { 84 | const $atts = document.querySelectorAll('#product_attributes .wc-metabox'); 85 | 86 | [...$atts].forEach(($a) => { 87 | this.moveField($a); 88 | }); 89 | }, 90 | 91 | /** 92 | * Move an input field to Heading 93 | */ 94 | moveField($att) { 95 | const $heading = $att.querySelector('h3'); 96 | 97 | // if doesn't contain "taxonomy", move the attribute name field too 98 | if (!$att.classList.contains('taxonomy')) { 99 | const $nameWrapper = $att.querySelector('td.attribute_name'); 100 | if ($nameWrapper) { 101 | $heading.append(...$nameWrapper.childNodes); 102 | } 103 | } 104 | 105 | const $termsWrapper = $att.querySelector('td[rowspan="3"]'); 106 | if ($termsWrapper) { 107 | $heading.append(...$termsWrapper.childNodes); 108 | } 109 | }, 110 | }; 111 | 112 | /** 113 | * VARIATIONS 114 | */ 115 | const hVariationButtons = { 116 | init() { 117 | // this.moveActionSelect(); 118 | // this.renderToolbarButtons(); 119 | 120 | this.changeNoticeButton(); 121 | 122 | this.initSetPrice(); 123 | this.initSetSalePrice(); 124 | this.initSetStock(); 125 | 126 | this.initCreateVariations(); 127 | 128 | $('#woocommerce-product-data').on('woocommerce_variations_loaded', () => { 129 | this.moveActionSelect(); 130 | this.renderToolbarButtons(); 131 | }); 132 | }, 133 | 134 | /** 135 | * Move the Action Dropdown to the Default Toolbar 136 | */ 137 | moveActionSelect() { 138 | const $movedSelect = document.querySelector('.toolbar-variations-defaults .variation_actions'); 139 | 140 | // abort if already moved 141 | if ($movedSelect) { return; } 142 | 143 | const $select = document.querySelector('.variation_actions'); 144 | const $selectButton = document.querySelector('.do_variation_action'); 145 | const $wrapper = document.querySelector('.toolbar-variations-defaults'); 146 | 147 | if (!$select || !$wrapper) { return; } 148 | 149 | $wrapper.appendChild($select); 150 | $wrapper.appendChild($selectButton); 151 | }, 152 | 153 | /** 154 | * Create buttons in toolbar that mimic the action from the dropdown 155 | */ 156 | renderToolbarButtons() { 157 | const $wrapper = document.querySelector('#variable_product_options .toolbar-top'); 158 | 159 | // Abort if no toolbar 160 | if (!$wrapper) { return; } 161 | 162 | const $buttons = $wrapper.querySelector('.h-variation-buttons'); 163 | 164 | // abort if already has buttons 165 | if ($buttons) { return; } 166 | 167 | const $template = document.querySelector('#h-variation-buttons'); 168 | 169 | if ($template) { 170 | $wrapper.innerHTML += $template.innerHTML; 171 | } 172 | }, 173 | 174 | /** 175 | * Change the "Learn More" button when variation is empty to open Attributes tab instead of opening documentation. 176 | */ 177 | changeNoticeButton() { 178 | $('#variable_product_options').on('click', '#variable_product_options_inner > .woocommerce-message a', _onClick); 179 | 180 | function _onClick(e) { 181 | e.preventDefault(); 182 | 183 | const $targetTab = document.querySelector('.wc-tabs .attribute_tab a'); 184 | $targetTab.dispatchEvent(new MouseEvent('click', { 185 | view: window, 186 | bubbles: true, 187 | cancelable: true, 188 | })); 189 | } 190 | }, 191 | 192 | /** 193 | * Prompt user for global price 194 | */ 195 | initSetPrice() { 196 | $('#variable_product_options').on('click', '.button[data-action="set-price"]', _onClick.bind(this)); 197 | 198 | function _onClick() { 199 | this.doAction('variable_regular_price'); 200 | } 201 | }, 202 | 203 | /** 204 | * Prompt user for global sale price 205 | */ 206 | initSetSalePrice() { 207 | $('#variable_product_options').on('click', '.button[data-action="set-sale-price"]', _onClick.bind(this)); 208 | 209 | function _onClick() { 210 | const price = prompt('Enter the discounted price (leave empty to remove sale)'); 211 | 212 | // Abort if cancelled 213 | if (price === null) { return; } 214 | 215 | this.fillFields('input[name*="variable_sale_price"]', price); 216 | 217 | // _setSchedule(price); 218 | } 219 | 220 | function _setSchedule(price) { 221 | // Sale schedule 222 | let startDate = ''; 223 | let endDate = ''; 224 | 225 | // Ask whether to set schedule or not (only when sale is not empty) 226 | if (price !== '' && window.confirm('Set Sale Schedule?')) { 227 | startDate = prompt('Enter start date (YYYY-MM-DD or leave blank)'); 228 | endDate = prompt('Enter end date (YYYY-MM-DD or leave blank)'); 229 | 230 | // if format is wrong, empty it 231 | if (!startDate.match(/\d{4}-\d{2}-\d{2}$/)) { 232 | startDate = ''; 233 | } 234 | 235 | if (!endDate.match(/\d{4}-\d{2}-\d{2}$/)) { 236 | endDate = ''; 237 | } 238 | 239 | // show the hidden schedule fields 240 | if (startDate) { 241 | const $hiddenFields = document.querySelectorAll('.form-field.sale_price_dates_fields'); 242 | [...$hiddenFields].forEach(($f) => { 243 | $f.classList.remove('hidden'); 244 | $f.style.display = 'block'; 245 | }); 246 | } 247 | } 248 | 249 | this.fillFields('input[name*="variable_sale_price_dates_from"]', startDate); 250 | this.fillFields('input[name*="variable_sale_price_dates_to"]', endDate); 251 | } 252 | }, 253 | 254 | /** 255 | * Prompt user for stock number 256 | */ 257 | initSetStock() { 258 | $('#variable_product_options').on('click', '.button[data-action="set-stock"]', _onClick.bind(this)); 259 | 260 | function _onClick() { 261 | const amount = prompt('Enter stock amount (leave empty if not managing stock)'); 262 | 263 | // Abort if cancelled 264 | if (amount === null) { return; } 265 | 266 | const isManagingStock = amount !== ''; 267 | this.tickCheckboxes('[name*="variable_manage_stock"]', isManagingStock); 268 | 269 | if (amount === '') { return; } 270 | 271 | this.fillFields('[name*="variable_stock"]', amount); 272 | } 273 | }, 274 | 275 | /** 276 | * Init create variations button (only appear when there's no variation) 277 | */ 278 | initCreateVariations() { 279 | $('#variable_product_options').on('click', '.button[data-action="create-variations"]', _onClick.bind(this)); 280 | 281 | function _onClick() { 282 | this.doAction('link_all_variations'); 283 | } 284 | }, 285 | 286 | /** 287 | * Change the Action Select value and trigger it 288 | */ 289 | doAction(value) { 290 | const $select = document.querySelector('#variable_product_options #field_to_edit'); 291 | const $button = document.querySelector('#variable_product_options .do_variation_action'); 292 | 293 | // @todo - add a check whether value exist or not 294 | $select.value = value; 295 | $button.dispatchEvent(new MouseEvent('click', { 296 | view: window, 297 | bubbles: true, 298 | cancelable: true, 299 | })); 300 | }, 301 | 302 | /** 303 | * Fill all variation fields 304 | */ 305 | fillFields(query, value) { 306 | const $fields = document.querySelectorAll(query); 307 | 308 | [...$fields].forEach(($f) => { 309 | $f.value = value; 310 | $($f).trigger('change'); // has to be jQuery trigger to activate other behavior 311 | }); 312 | }, 313 | 314 | /** 315 | * Tick or Untick all checkboxes 316 | */ 317 | tickCheckboxes(query, value) { 318 | const $checkboxes = document.querySelectorAll(query); 319 | [...$checkboxes].forEach(($cb) => { 320 | $cb.checked = value; 321 | $($cb).trigger('change'); // has to be jQuery trigger to toggle the hidden fields 322 | }); 323 | }, 324 | }; 325 | 326 | /** 327 | * Add a quick info for Price, Sale Price, and Stock 328 | */ 329 | const hVariationOverview = { 330 | init() { 331 | $('#woocommerce-product-data').on('woocommerce_variations_loaded', this.render); 332 | $('#woocommerce-product-data').on('woocommerce_variations_added', this.render); 333 | 334 | const $fieldTargets = [ 335 | { 336 | field: '[name*="regular_price["]', 337 | overview: '[data-info="price"]', 338 | }, 339 | { 340 | field: '[name*="sale_price["]', 341 | overview: '[data-info="sale-price"]', 342 | }, 343 | { 344 | field: '[name*="variable_stock["]', 345 | overview: '[data-info="stock"]', 346 | }, 347 | ]; 348 | 349 | $fieldTargets.forEach((target) => { 350 | // add listener to change the overview 351 | $('#variable_product_options').on('change', target.field, (e) => { 352 | this._updateOverview(e.currentTarget, target.overview); 353 | }); 354 | 355 | // initially populate the overiew 356 | $('#woocommerce-product-data').on('woocommerce_variations_loaded', () => { 357 | const $fields = document.querySelectorAll(target.field); 358 | [...$fields].forEach(($f) => { 359 | this._updateOverview($f, target.overview); 360 | }); 361 | }); 362 | }); 363 | 364 | // If untick "Manage Stock" 365 | $('#variable_product_options').on('change', '[name*="variable_manage_stock["]', (e) => { 366 | // abort if checked 367 | if (e.currentTarget.checked) { return; } 368 | 369 | this._updateOverview(e.currentTarget, '[data-info="stock"]'); 370 | }); 371 | }, 372 | 373 | /** 374 | * Render the overview into each variation heading 375 | */ 376 | render() { 377 | const $headings = document.querySelectorAll('#variable_product_options .wc-metabox h3'); 378 | const template = document.querySelector('#h-variation-overview').innerHTML; 379 | 380 | [...$headings].forEach(($h) => { 381 | // Abort if already have overview 382 | if ($h.innerHTML.match(/h-variation-overview/)) { return; } 383 | 384 | $h.innerHTML += template; 385 | }); 386 | }, 387 | 388 | /** 389 | * Update the overview label 390 | */ 391 | _updateOverview(target, query) { 392 | const $wrapper = target.closest('.wc-metabox').querySelector('.h-variation-overview'); 393 | 394 | if (!$wrapper) { return; } 395 | 396 | const $label = $wrapper.querySelector(query); 397 | 398 | if (target.value > 0) { 399 | $label.classList.remove('hidden'); 400 | } else { 401 | $label.classList.add('hidden'); 402 | } 403 | 404 | $label.querySelector('span').textContent = target.value; 405 | }, 406 | }; 407 | 408 | function onReady() { 409 | hProductType.init(); 410 | hAttributes.init(); 411 | hVariationButtons.init(); 412 | hVariationOverview.init(); 413 | } 414 | 415 | function onLoad() { 416 | // script that runs when everything is loaded 417 | } 418 | 419 | document.addEventListener('DOMContentLoaded', onReady); 420 | window.addEventListener('load', onLoad); 421 | --------------------------------------------------------------------------------