├── Block ├── Adminhtml │ └── Index │ │ └── Index.php └── Product │ ├── ImageFactory.php │ └── Renderer │ └── Configurable.php ├── Controller └── Adminhtml │ └── Index │ └── Index.php ├── DeferJS.php ├── KnockoutMagento2React.jpg ├── KnockoutMagento2React.png ├── LICENSE.md ├── README.md ├── React └── React │ ├── .babelrc │ ├── .gitignore │ └── composer.json ├── ReactInjectPlugin.php ├── RemoveMagentoInitScripts.php ├── Template.php ├── composer.json ├── etc ├── acl.xml ├── adminhtml │ ├── menu.xml │ ├── routes.xml │ └── system.xml ├── config.xml ├── di.xml ├── frontend │ └── events.xml └── module.xml ├── package.json ├── pub └── static │ ├── category-styles-m.css │ ├── product-critical-m.css │ ├── product-styles-m.css │ ├── styles-l.css │ └── styles-m.css ├── registration.php ├── src ├── components │ ├── AddToCartForm.js │ └── App.js ├── gridjs.js ├── index.js └── styles │ ├── gridjs.css │ └── index.css ├── view ├── adminhtml │ ├── layout │ │ └── default.xml │ └── templates │ │ └── index │ │ └── index.phtml ├── base │ ├── requirejs-config.js │ ├── templates │ │ ├── component.phtml │ │ ├── react-component.phtml │ │ └── vue-component.phtml │ └── web │ │ └── js │ │ ├── htm.module.js │ │ ├── index_bundle.js │ │ ├── preact.module.js │ │ ├── react-dom.development.js │ │ ├── react-dom.js │ │ ├── react-dom.production.min.js │ │ ├── react.development.js │ │ ├── react.js │ │ ├── react.production.min.js │ │ ├── vue.js │ │ └── vue2.production.min.js └── frontend │ ├── etc │ └── view.xml │ ├── layout │ ├── catalog_category_view.xml │ ├── catalog_product_view.xml │ ├── catalog_product_view_type_configurable.xml │ ├── default.xml │ └── default_head_blocks.xml │ ├── templates │ ├── product │ │ ├── breadcrumbs.phtml │ │ ├── image_with_borders.phtml │ │ ├── listing │ │ │ └── renderer.phtml │ │ └── view │ │ │ ├── gallery.phtml │ │ │ └── renderer.phtml │ ├── react-footer-css.phtml │ ├── react-footer.phtml │ ├── react-header-css.phtml │ ├── react-header.phtml │ └── topmenu-account.phtml │ └── web │ └── js │ ├── cash.js │ ├── react-core.js │ └── rum.js └── webpack.config.js /Block/Adminhtml/Index/Index.php: -------------------------------------------------------------------------------- 1 | objectManager = $objectManager; 70 | $this->presentationConfig = $presentationConfig; 71 | $this->viewAssetPlaceholderFactory = $viewAssetPlaceholderFactory; 72 | $this->viewAssetImageFactory = $viewAssetImageFactory; 73 | $this->imageParamsBuilder = $imageParamsBuilder; 74 | } 75 | 76 | /** 77 | * Remove class from custom attributes 78 | * 79 | * @param array $attributes 80 | * @return array 81 | */ 82 | private function filterCustomAttributes(array $attributes): array 83 | { 84 | if (isset($attributes['class'])) { 85 | unset($attributes['class']); 86 | } 87 | return $attributes; 88 | } 89 | 90 | /** 91 | * Retrieve image class for HTML element 92 | * 93 | * @param array $attributes 94 | * @return string 95 | */ 96 | private function getClass(array $attributes): string 97 | { 98 | return $attributes['class'] ?? 'product-image-photo'; 99 | } 100 | 101 | /** 102 | * Calculate image ratio 103 | * 104 | * @param int $width 105 | * @param int $height 106 | * @return float 107 | */ 108 | private function getRatio(int $width, int $height): float 109 | { 110 | if ($width && $height) { 111 | return $height / $width; 112 | } 113 | return 1.0; 114 | } 115 | 116 | /** 117 | * Get image label 118 | * 119 | * @param Product $product 120 | * @param string $imageType 121 | * @return string 122 | */ 123 | private function getLabel(Product $product, string $imageType): string 124 | { 125 | $label = $product->getData($imageType . '_' . 'label'); 126 | if (empty($label)) { 127 | $label = $product->getName(); 128 | } 129 | return (string) $label; 130 | } 131 | 132 | /** 133 | * Create image block from product 134 | * 135 | * @param Product $product 136 | * @param string $imageId 137 | * @param array|null $attributes 138 | * @return ImageBlock 139 | */ 140 | public function create(Product $product, string $imageId, array $attributes = null): ImageBlock 141 | { 142 | $viewImageConfig = $this->presentationConfig->getViewConfig()->getMediaAttributes( 143 | 'Magento_Catalog', 144 | ImageHelper::MEDIA_TYPE_CONFIG_NODE, 145 | $imageId 146 | ); 147 | 148 | $imageMiscParams = $this->imageParamsBuilder->build($viewImageConfig); 149 | $originalFilePath = $product->getData($imageMiscParams['image_type']); 150 | 151 | if ($originalFilePath === null || $originalFilePath === 'no_selection') { 152 | $imageAsset = $this->viewAssetPlaceholderFactory->create( 153 | [ 154 | 'type' => $imageMiscParams['image_type'], 155 | ] 156 | ); 157 | } else { 158 | $imageAsset = $this->viewAssetImageFactory->create( 159 | [ 160 | 'miscParams' => $imageMiscParams, 161 | 'filePath' => $originalFilePath, 162 | ] 163 | ); 164 | } 165 | 166 | $attributes = $attributes === null ? [] : $attributes; 167 | 168 | $data = [ 169 | 'data' => [ 170 | 'template' => self::TEMPLATE, 171 | 'image_url' => $imageAsset->getUrl(), 172 | 'width' => $imageMiscParams['image_width'], 173 | 'height' => $imageMiscParams['image_height'], 174 | 'label' => $this->getLabel($product, $imageMiscParams['image_type'] ?? ''), 175 | 'ratio' => $this->getRatio($imageMiscParams['image_width'] ?? 0, $imageMiscParams['image_height'] ?? 0), 176 | 'custom_attributes' => $this->filterCustomAttributes($attributes), 177 | 'class' => $this->getClass($attributes), 178 | 'product_id' => $product->getId(), 179 | ], 180 | ]; 181 | 182 | return $this->objectManager->create(ImageBlock::class, $data); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /Block/Product/Renderer/Configurable.php: -------------------------------------------------------------------------------- 1 | isProductHasSwatchAttribute() ? 20 | self::SWATCH_RENDERER_TEMPLATE : self::CONFIGURABLE_RENDERER_TEMPLATE; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /Controller/Adminhtml/Index/Index.php: -------------------------------------------------------------------------------- 1 | resultPageFactory = $resultPageFactory; 22 | parent::__construct($context); 23 | } 24 | 25 | /** 26 | * Execute view action 27 | * 28 | * @return \Magento\Framework\Controller\ResultInterface 29 | */ 30 | public function execute() 31 | { 32 | return $this->resultPageFactory->create(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /DeferJS.php: -------------------------------------------------------------------------------- 1 | config->getValue('react_vue_config/junk/remove')); 19 | 20 | if ($removeAdobeJSJunk) { 21 | return; 22 | } 23 | $response = $observer->getEvent()->getData('response'); 24 | if (!$response) { 25 | return; 26 | } 27 | $html = $response->getBody(); 28 | if ($html == '') { 29 | return; 30 | } 31 | $conditionalJsPattern = '@(?: 112 | // Babel to avoid compilation 113 | 114 | 115 | //Add to the page to render React component 116 |
117 | 118 | //Write you scripts using babel 119 | 135 | ``` 136 | 137 | # Magento 2 live reload 138 | 139 | This project aims to solve the case where you want assets served by your Magento app server, but still want reloads triggered from web packs build pipeline. 140 | 141 | Add a script tag to your page pointed at the livereload server 142 | 143 | ``` 144 | 145 | ``` 146 | For development purposes, better disable browser caching (https://www.technipages.com/google-chrome-how-to-completely-disable-cache) 147 | 148 | Disable react bundle caching for development purposes using Nginx (not tested yet): 149 | 150 | ``` 151 | location ~ index_bundle\.js { 152 | add_header Cache-Control no-cache; 153 | expires 0; 154 | } 155 | ``` 156 | -------------------------------------------------------------------------------- /React/React/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"], 3 | "plugins": ["@babel/plugin-proposal-class-properties"] 4 | } 5 | -------------------------------------------------------------------------------- /React/React/.gitignore: -------------------------------------------------------------------------------- 1 | ./node_modules 2 | -------------------------------------------------------------------------------- /React/React/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react/react", 3 | "description": "", 4 | "type": "magento2-module", 5 | "license": "proprietary", 6 | "authors": [ 7 | { 8 | "email": "egorshitikov@gmail.com", 9 | "name": "Yegor Shytikov" 10 | }, 11 | { 12 | "email": "sh.kiruh@gmail.com", 13 | "name": "Kirill Shytikov" 14 | } 15 | ], 16 | "minimum-stability": "stable", 17 | "require": {}, 18 | "autoload": { 19 | "psr-4": { 20 | "React\\React\\": "React/React" 21 | }, 22 | "files": [ 23 | "registration.php" 24 | ] 25 | } 26 | } -------------------------------------------------------------------------------- /ReactInjectPlugin.php: -------------------------------------------------------------------------------- 1 | config->getValue('react_vue_config/react/enable')); 72 | $vueEnabled = boolval($this->config->getValue('react_vue_config/vue/enable')); 73 | /* remove default Magento Junky JS */ 74 | $removeAdobeJSJunk = boolval($this->config->getValue('react_vue_config/junk/remove')); 75 | $removeCSSjunk = boolval($this->config->getValue('react_vue_config/css/remove')); 76 | $criticalCSSHTML = boolval($this->config->getValue('react_vue_config/css/critical')); 77 | 78 | if (isset($_GET['css-react']) && $_GET['css-react'] === "false") { 79 | $removeCSSjunk = false; 80 | } 81 | if (isset($_GET['css-react']) && $_GET['css-react'] === "true") { 82 | $removeCSSjunk = true; 83 | } 84 | 85 | if (isset($_GET['js-junk']) && $_GET['js-junk'] === "false") { 86 | $removeAdobeJSJunk = false; 87 | } 88 | if (isset($_GET['js-junk']) && $_GET['js-junk'] === "true") { 89 | $removeAdobeJSJunk = true; 90 | } 91 | 92 | $area = $this->state->getAreaCode(); 93 | $pageFilter = ['checkout', 'customer']; 94 | 95 | $request = $objectManager->get(\Magento\Framework\App\Request\Http::class); 96 | $actionName = $request->getFullActionName(); 97 | @header("Action-Name: $actionName"); 98 | $requestURL = $_SERVER['REQUEST_URI']; 99 | $removeProtection = boolval(boolval(strpos($requestURL, 'checkout')) || boolval(strpos($requestURL, 'customer')) || $area === 'adminhtml'); 100 | @header("React-Protection: $removeProtection"); 101 | $block = $objectManager->get(\Magento\Framework\View\Element\Template::class); 102 | $assets = $this->processMerge($group->getAll(), $group); 103 | $attributes = $this->getGroupAttributes($group); 104 | $type = $group->getProperties()['content_type']; 105 | $result = ''; 106 | $template = ''; 107 | $assetOptimized = false; 108 | $assetOptimizedLarge = false; 109 | $assetProductOptimized = false; 110 | $assetCategoryOptimized = false; 111 | $assetNotOptimisedMobile = false; 112 | $optimisedProductCSSFileCriticalPath = false; 113 | $optimisedCategoryCSSFileCriticalPath = false; 114 | 115 | $removeController = in_array($actionName, $this->actionFilter); 116 | $isProduct = in_array($actionName, ['catalog_product_view']); 117 | $isCategory = in_array($actionName, ['catalog_category_view', 'catalogsearch_result_index']); 118 | 119 | try { 120 | /** @var $asset \Magento\Framework\View\Asset\AssetInterface */ 121 | // Changes Start 122 | $baseURL = $this->store->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_STATIC); 123 | if ($removeCSSjunk && $type === 'css') { 124 | foreach ($assets as $key => $asset) { 125 | if (in_array($actionName, $this->actionFilter) && strpos($asset->getUrl(), 'styles-m')) { 126 | // http://**/static/version1642788857/frontend/Magento/luma/en_US/css/styles-m.css 127 | $assetNotOptimisedMobile = $asset->getUrl(); 128 | $optimisedCSSFileUrl = $baseURL . 'styles-m.css'; 129 | $optimisedCSSFilePath = BP . '/pub/static/styles-m.css'; 130 | 131 | $optimisedProductCSSFileUrl = $baseURL . 'product-styles-m.css'; 132 | $optimisedProductCSSFileCriticalUrl = $baseURL . 'product-critical-m.css'; 133 | $optimisedProductCSSFileCriticalPath = BP . '/pub/static/product-critical-m.css'; 134 | $optimisedProductCSSFilePath = BP . '/pub/static/product-styles-m.css'; 135 | 136 | $optimisedCategoryCSSFileUrl = $baseURL . 'category-styles-m.css'; 137 | $optimisedCategoryCSSFilePath = BP . '/pub/static/category-styles-m.css'; 138 | $optimisedCategoryCSSFileCriticalUrl = $baseURL . 'category-critical-m.css'; 139 | $optimisedCategoryCSSFileCriticalPath = BP . '/pub/static/category-critical-m.css'; 140 | 141 | if (file_exists($optimisedCSSFilePath)) { 142 | // echo $optimisedCSSFileUrl; 143 | $assetOptimized = $optimisedCSSFileUrl; 144 | unset($assets[$key]); 145 | } 146 | if (file_exists($optimisedProductCSSFilePath) && $isProduct) { 147 | // echo $optimisedCSSFileUrl; 148 | $assetProductOptimized = $optimisedProductCSSFileUrl; 149 | unset($assets[$key]); 150 | } 151 | if (file_exists($optimisedCategoryCSSFilePath) && $isCategory) { 152 | // echo $optimisedCSSFileUrl; 153 | $assetCategoryOptimized = $optimisedCategoryCSSFileUrl; 154 | unset($assets[$key]); 155 | } 156 | 157 | } 158 | if (in_array($actionName, $this->actionFilter) && strpos($asset->getUrl(), 'styles-l')) { 159 | // http://**/static/version1642788857/frontend/Magento/luma/en_US/css/styles-l.css 160 | $optimisedCSSFileUrlLarge = $baseURL . 'styles-l.css'; 161 | $optimisedCSSFilePathLarge = BP . '/pub/static/styles-l.css'; 162 | $assetNotOptimisedLarge = $asset->getUrl(); 163 | if (file_exists($optimisedCSSFilePathLarge)) { 164 | // echo $optimisedCSSFileUrl; 165 | $assetOptimizedLarge = $optimisedCSSFileUrlLarge; 166 | unset($assets[$key]); 167 | } else { 168 | @header('Optimised-CSS: false'); 169 | } 170 | } 171 | if (in_array($actionName, $this->actionFilter) && strpos($asset->getUrl(), 'calendar')) { 172 | unset($assets[$key]); 173 | } 174 | if (in_array($actionName, $this->actionFilter) && strpos($asset->getUrl(), 'gallery')) { 175 | unset($assets[$key]); 176 | } 177 | if (in_array($actionName, $this->actionFilter) && strpos($asset->getUrl(), 'uppy-custom')) { 178 | unset($assets[$key]); 179 | } 180 | } 181 | } 182 | // dump($assets); 183 | foreach ($assets as $key => $asset) { 184 | if ($type === 'js' && $removeAdobeJSJunk) { 185 | if (strpos($asset->getUrl(), 'js/react')) { 186 | unset($assets[$key]); 187 | if ($reactEnabled) { 188 | array_unshift($assets, $asset); 189 | } 190 | } 191 | if (strpos($asset->getUrl(), 'vue')) { 192 | unset($assets[$key]); 193 | if ($vueEnabled) { 194 | array_unshift($assets, $asset); 195 | } 196 | } 197 | if (strpos($asset->getUrl(), 'require')) { 198 | if ($removeAdobeJSJunk) 199 | //dd($removeAdobeJSJunk); 200 | { 201 | unset($assets[$key]); 202 | } 203 | 204 | // junk True ; protection False 205 | // echo "require " . (string) $removeProtection; 206 | if (!$removeAdobeJSJunk || !in_array($actionName, $this->actionFilter)); 207 | array_unshift($assets, $asset); 208 | } 209 | if (strpos($asset->getUrl(), 'require')) { 210 | if ($removeAdobeJSJunk) 211 | //dd($removeAdobeJSJunk); 212 | { 213 | unset($assets[$key]); 214 | } 215 | 216 | // junk True ; protection False 217 | // echo "require " . (string) $removeProtection; 218 | if (!$removeAdobeJSJunk || !in_array($actionName, $this->actionFilter)); 219 | array_unshift($assets, $asset); 220 | } 221 | } 222 | if ($type === 'css') { 223 | if (strpos($asset->getUrl(), 'styles-')) { 224 | unset($assets[$key]); 225 | if (!$removeCSSjunk || !in_array($actionName, $this->actionFilter)) { 226 | array_unshift($assets, $asset); 227 | } 228 | } 229 | } 230 | } 231 | // we need execute it one more time to make scripts the same order 232 | foreach ($assets as $key => $asset) { 233 | if (strpos($asset->getUrl(), 'require') && $removeAdobeJSJunk) { 234 | unset($assets[$key]); 235 | array_unshift($assets, $asset); 236 | // dd($assets); 237 | } 238 | } 239 | 240 | if ($type === 'js' && $removeAdobeJSJunk) { 241 | foreach ($assets as $key => $asset) { 242 | if (strpos($asset->getUrl(), 'js/react') || strpos($asset->getUrl(), 'vue')) { 243 | unset($assets[$key]); 244 | array_unshift($assets, $asset); 245 | } 246 | } 247 | } 248 | 249 | // Changes Ends 250 | 251 | foreach ($assets as $asset) { 252 | $template = $this->getAssetTemplate( 253 | $group->getProperty(GroupedCollection::PROPERTY_CONTENT_TYPE), 254 | $this->addDefaultAttributes($this->getAssetContentType($asset), $attributes) 255 | ); 256 | $result .= sprintf($template, $asset->getUrl()); 257 | } 258 | } catch (LocalizedException $e) { 259 | $this->logger->critical($e); 260 | $result .= sprintf($template, $this->urlBuilder->getUrl('', ['_direct' => 'core/index/notFound'])); 261 | } 262 | 263 | if ($removeCSSjunk) { 264 | // mobile CSS 265 | if ($assetOptimized && !($assetProductOptimized || $assetCategoryOptimized)) { 266 | $result = '' . "\n" . $result; 267 | } 268 | if ($assetOptimizedLarge) { 269 | $result = '' . "\n" . $result; 270 | } 271 | if ($assetProductOptimized && $isProduct) { 272 | if ($optimisedProductCSSFileCriticalPath && file_exists($optimisedProductCSSFileCriticalPath)) { 273 | if (!$criticalCSSHTML) { 274 | // ToDo: check if push works 275 | @header("Link: <" . $optimisedProductCSSFileCriticalUrl . ">; rel=preload; as=style", false); 276 | $result = '' . "\n" . $result; 277 | } 278 | $result = '' . "\n" . $result; 279 | } else { 280 | $result = '' . "\n" . $result; 281 | } 282 | } else if (!$assetProductOptimized && $isProduct) { 283 | if ($optimisedProductCSSFileCriticalPath && file_exists($optimisedProductCSSFileCriticalPath)) { 284 | $result = '' . "\n" . $result; 285 | $result = '' . "\n" . $result; 286 | } 287 | } 288 | if ($assetCategoryOptimized && $isCategory) { 289 | if ($optimisedCategoryCSSFileCriticalPath && file_exists($optimisedCategoryCSSFileCriticalPath)) { 290 | $result = '' . "\n" . $result; 291 | $result = '' . "\n" . $result; 292 | } else { 293 | $result = '' . "\n" . $result; 294 | } 295 | } else if (!$assetCategoryOptimized && $isCategory) { 296 | if ($optimisedCategoryCSSFileCriticalPath && file_exists($optimisedCategoryCSSFileCriticalPath)) { 297 | $result = '' . "\n" . $result; 298 | $result = '' . "\n" . $result; 299 | } 300 | } 301 | } 302 | 303 | if ($removeAdobeJSJunk && $type === 'js' && $removeController) { 304 | // dd($result); 305 | // Remove RequireJS and other scripts if needed 306 | $result = preg_replace('/]*require[^>]*><\/script>/', '', $result); 307 | } 308 | $endTime = microtime(true); 309 | $time = $endTime - $startTime; 310 | //header("Server-Timing: x-mag-react;dur=" . number_format($time * 1000, 2), false); 311 | return $result; 312 | } 313 | 314 | public function checkFile($file) 315 | { 316 | // TODO: add APCu or file cache optimisation 317 | return file_exists($file); 318 | } 319 | 320 | /* 321 | * Alternative 322 | * protected function getIncludes() 323 | * { 324 | * $html = parent::getIncludes(); 325 | * 326 | * // Remove all `@msU'; 72 | preg_match_all($conditionalJsPattern, $html, $_matches); 73 | $jsHtml = implode('', $_matches[0]); 74 | $html = preg_replace($conditionalJsPattern, '', $html); 75 | $html .= $jsHtml; 76 | 77 | $result = $html; 78 | 79 | return $result; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Template.php: -------------------------------------------------------------------------------- 1 | om = $om; 25 | $this->registry = $registry; 26 | $this->config = $config; 27 | parent::__construct($context, $data); 28 | } 29 | 30 | // Function to encode an image as Base64 31 | public function imageToBase64($imagePath) 32 | { 33 | if (file_exists($imagePath)) { 34 | $imageData = file_get_contents($imagePath); 35 | $base64 = base64_encode($imageData); 36 | $mimeType = mime_content_type($imagePath); // Get MIME type 37 | return "data:$mimeType;base64,$base64"; 38 | } 39 | return ""; 40 | } 41 | 42 | public function removeAdobeJSJunk() 43 | { 44 | if (isset($_GET['js-junk']) && $_GET['js-junk'] === "false") { 45 | return $removeAdobeJSJunk = false; 46 | } 47 | if (isset($_GET['js-junk']) && $_GET['js-junk'] === "true") { 48 | return $removeAdobeJSJunk = true; 49 | } 50 | return boolval($this->config->getValue('react_vue_config/junk/remove')); 51 | } 52 | 53 | public function removeAdobeCSSJunk() 54 | { 55 | if (!isset($_GET['css-react'])) { 56 | return $removeCSSjunk = boolval($this->config->getValue('react_vue_config/junk/remove')); 57 | } 58 | 59 | if (isset($_GET['css-react']) && $_GET['css-react'] === "false") { 60 | $removeCSSjunk = false; 61 | } 62 | if (isset($_GET['css-react']) && $_GET['css-react'] === "true") { 63 | $removeCSSjunk = true; 64 | } 65 | return $removeCSSjunk; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "genaker/react-luma", 3 | "description": "", 4 | "type": "magento2-module", 5 | "license": "proprietary", 6 | "authors": [ 7 | { 8 | "email": "egorshitikov@gmail.com", 9 | "name": "Yegor Shytikov" 10 | }, 11 | { 12 | "email": "sh.kiruh@gmail.com", 13 | "name": "Kirill Shytikov" 14 | } 15 | ], 16 | "minimum-stability": "stable", 17 | "require": {}, 18 | "autoload": { 19 | "files": [ 20 | "registration.php" 21 | ], 22 | "psr-4": { 23 | "React\\React\\": "" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /etc/acl.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /etc/adminhtml/menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /etc/adminhtml/routes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /etc/adminhtml/system.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | react_vue 10 | React_React::config_react_react 11 | 12 | 13 | 14 | 15 | Magento\Config\Model\Config\Source\Yesno 16 | enable VueJS 17 | 18 | 19 | 20 | 21 | 22 | 23 | Magento\Config\Model\Config\Source\Yesno 24 | enable ReactJS 25 | 26 | 27 | 28 | 29 | 30 | 31 | Magento\Config\Model\Config\Source\Yesno 32 | enable GridJS (https://gridjs.io/) 33 | 34 | 35 | 36 | 37 | 38 | 39 | Magento\Config\Model\Config\Source\Yesno 40 | Remove Magento's default JS garbage (Require,Knokout,jQuery). You will need implement required functionality or use Magento Open Source ReactJS Luma Theme 41 | 42 | 43 | 44 | 45 | 46 | 47 | Magento\Config\Model\Config\Source\Yesno 48 | Remove Magento's default CSS garbage. You will need add optimized CSS to pub/static/styles-m.css and pub/static/styles-l.css. The files will be automaticaly included if they are exists 49 | 50 | 51 | 52 | Magento\Config\Model\Config\Source\Yesno 53 | Output Critical CSS to HTML 54 | 55 | 56 |
57 |
58 |
59 | -------------------------------------------------------------------------------- /etc/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 0 7 | 8 | 9 | 0 10 | 11 | 12 | 0 13 | 14 | 15 | 1 16 | 17 | 18 | 1 19 | 1 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /etc/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /etc/frontend/events.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reacttable", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "webpack --mode development --watch", 8 | "build": "webpack --mode production" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "@babel/core": "^7.4.4", 14 | "@babel/plugin-proposal-class-properties": "^7.4.4", 15 | "@babel/preset-env": "^7.4.4", 16 | "@babel/preset-react": "^7.0.0", 17 | "babel-loader": "^8.0.5", 18 | "copy-webpack-plugin": "^5.0.3", 19 | "css-loader": "^2.1.1", 20 | "html-webpack-harddisk-plugin": "^1.0.1", 21 | "style-loader": "^0.23.1", 22 | "webpack": "^4.32.0", 23 | "webpack-cli": "^3.3.2", 24 | "webpack-livereload-plugin": "^2.2.0" 25 | }, 26 | "dependencies": { 27 | "html-react-parser": "^0.7.1", 28 | "js-cookie": "^2.2.0", 29 | "react": "^16.8.6", 30 | "react-dom": "^16.8.6" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /pub/static/product-critical-m.css: -------------------------------------------------------------------------------- 1 | body{margin:0;padding:0}header,main,nav{display:block}nav ul{list-style:none none}img{max-width:100%;height:auto;border:0}html{font-size:62.5%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;font-size-adjust:100%}body{color:#333;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;font-size:1.4rem}p{margin-top:0;margin-bottom:1rem}strong{font-weight:700}h1{font-weight:300;line-height:1.1;font-size:2.6rem;margin-top:0;margin-bottom:2rem}a{color:#006bb4;text-decoration:none}a:visited{color:#006bb4;text-decoration:none}ul{margin-top:0;margin-bottom:2.5rem}ul>li{margin-top:0;margin-bottom:1rem}ul ul{margin-bottom:0}button{background-image:none;background:#eee;border:1px solid #ccc;color:#333;display:inline-block;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-weight:600;margin:0;padding:7px 15px;font-size:1.4rem;line-height:1.6rem;box-sizing:border-box;vertical-align:middle}button[disabled]{opacity:.5}button::-moz-focus-inner{border:0;padding:0}input[type=number],input[type=text]{background:#fff;background-clip:padding-box;border:1px solid #c2c2c2;border-radius:1px;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-size:14px;height:32px;line-height:1.42857143;padding:0 9px;vertical-align:baseline;width:100%;box-sizing:border-box}input[type=number]::-moz-placeholder,input[type=text]::-moz-placeholder{color:#575757}input[type=number]::-webkit-input-placeholder,input[type=text]::-webkit-input-placeholder{color:#575757}input[type=number]:-ms-input-placeholder,input[type=text]:-ms-input-placeholder{color:#575757}input[type=number]{-moz-appearance:textfield}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}input::-moz-focus-inner{border:0;padding:0}:focus{box-shadow:none;outline:0}.box-tocart .action.tocart{line-height:2.2rem;padding:14px 17px;font-size:1.8rem}.box-tocart .action.tocart{width:100%}.box-tocart .input-text.qty{text-align:center;width:54px}.block{margin-bottom:40px}.action.skip:not(:focus),.minicart-wrapper .action.showcart .counter-label,.minicart-wrapper .action.showcart .text,.product-item-actions .actions-secondary>.action span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.header.content:after,.header.content:before{content:'';display:table}.header.content:after{clear:both}.columns .column.main,.search-autocomplete{box-sizing:border-box}.product-item .action.towishlist,.product-item-actions .actions-secondary>.action,.product-social-links .action.tocompare,.product-social-links .action.towishlist{color:#666;font-weight:600;letter-spacing:.05em;text-transform:uppercase;display:inline-block;text-decoration:none}.product-item .action.towishlist:before,.product-item-actions .actions-secondary>.action:before,.product-social-links .action.tocompare:before,.product-social-links .action.towishlist:before{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:16px;line-height:16px;color:inherit;font-family:luma-icons;margin:-2px 5px 0 0;vertical-align:middle;display:inline-block;font-weight:400;overflow:hidden;speak:none;text-align:center}.product-item .action.towishlist:before,.product-item-actions .actions-secondary>.action:before,.product-social-links .action.tocompare:before,.product-social-links .action.towishlist:before{width:18px}.box-tocart{margin:0 0 30px}.no-display{display:none}.columns{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-wrap:wrap;flex-wrap:wrap;box-sizing:border-box}.columns:after{clear:both;content:' ';display:block;height:0;overflow:hidden;visibility:hidden}.columns .column.main{padding-bottom:40px;-webkit-flex-basis:auto;flex-basis:auto;-webkit-flex-grow:1;flex-grow:1;-ms-flex-order:1;-webkit-order:1;order:1;width:100%}.panel.header .links{display:none}.nav-sections{background:#f0f0f0}.nav-toggle{display:inline-block;text-decoration:none;display:block;font-size:0;left:15px;position:absolute;top:15px;z-index:14}.nav-toggle:before{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:28px;line-height:inherit;color:#757575;content:'\e609';font-family:luma-icons;vertical-align:middle;display:inline-block;font-weight:400;overflow:hidden;speak:none;text-align:center}.nav-toggle>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}button{border-radius:3px}button:not(.primary){box-shadow:none}.action.primary{background-image:none;background:#1979c3;border:1px solid #1979c3;color:#fff;display:inline-block;font-family:'Open Sans','Helvetica Neue',Helvetica,Arial,sans-serif;font-weight:600;padding:7px 15px;font-size:1.4rem;box-sizing:border-box;vertical-align:middle}.action.primary[disabled]{opacity:.5}.breadcrumbs{margin:0 0 15px;min-height:24px}.breadcrumbs a{color:#006bb4;text-decoration:none}.breadcrumbs a:visited{color:#006bb4;text-decoration:none}.swatch-attribute-label{font-weight:700;position:relative}.swatch-attribute-selected-option{color:#646464;padding-left:17px}.swatch-attribute-options{margin:10px 0}.swatch-attribute.size .swatch-option{background:#f0f0f0;color:#949494}.swatch-option{border:1px solid #dadada;float:left;height:20px;margin:0 10px 5px 0;max-width:100%;min-width:30px;overflow:hidden;padding:1px 2px;position:relative;text-align:center;text-overflow:ellipsis}.swatch-option.text{background:#f0f0f0;color:#686868;font-size:12px;font-weight:700;line-height:20px;margin-right:7px;min-width:22px;padding:4px 8px}.swatch-opt{margin:20px 0}.swatch-input{left:-1000px;position:absolute;visibility:hidden}.clearfix:after{clear:both;content:'';display:block;height:0;visibility:hidden}.price-container.weee:before{display:none}.product-item-actions>*{font-size:1.4rem}.product-item-actions .actions-secondary{display:inline-block;font-size:1.4rem;vertical-align:middle}.product-item-actions .actions-secondary>.action{line-height:35px;text-align:center;width:35px}.product-item-actions .actions-secondary>.action:before{margin:0}.product-item .tocompare:before{content:'\e61e'}.price-container .price{font-size:1.4rem}.product-info-main .product-info-price{color:#575757;border-bottom:1px solid #c1c1c1;display:table;margin-bottom:15px;width:100%}.product-info-main .product-info-price .price-box{display:inline-block;vertical-align:top;width:auto}.product-info-main .product-info-price .price-box .price-container>span{display:block;margin-bottom:5px}.product-info-main .product-info-price .weee{font-size:1.4rem}.product-info-main .product-info-price .weee .price{font-size:1.4rem;font-weight:600;line-height:16px}.product-info-main .product-info-price .price-wrapper .price{font-size:2.2rem;font-weight:600;line-height:22px}.product-info-main .product-info-price .price{white-space:nowrap}.product-info-main .product.attribute.sku{word-break:break-all;word-wrap:break-word}.product-info-main .product.attribute.sku .type{font-weight:400;margin-right:5px}.product-info-main .product.attribute.sku .type:after{content:'#:'}.product-info-main .product.attribute.sku .value{display:inline-block}.product-info-main .product-add-form{clear:both;padding-top:15px}.product-info-main .product-reviews-summary{float:left}.product-info-main .product-options-bottom .box-tocart{margin-top:20px}.product-info-price .price-box{color:#575757;display:table-cell;padding-bottom:10px;vertical-align:top}.product-info-price .price-box .price-container>span{display:block;margin-bottom:5px}.product-info-price .price-box .price-container .price{font-size:22px;font-weight:600;line-height:22px}.box-tocart .action.tocart{vertical-align:top}.box-tocart .action.tocart:not(:last-child){margin-bottom:15px}.product-social-links{margin:0 0 20px;text-align:center}.product-social-links .action.tocompare:before{content:'\e61e'}.block-search{margin-bottom:0}.block-search .block-title{display:none}.block-search .block-content{margin-bottom:0}.block-search .label{text-decoration:none;display:inline-block;float:right}.block-search .label>span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.block-search .label:before{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:22px;line-height:28px;color:#757575;content:'\e615';font-family:luma-icons;margin:0 10px 0 0;vertical-align:middle;display:inline-block;font-weight:400;overflow:hidden;speak:none;text-align:center}.block-search .action.search{display:none}.block-search .control{border-top:1px solid #ccc;clear:both;margin:0 -15px -1px;padding:0 15px}.block-search input{font-size:16px;left:-300%;margin:15px 0;position:absolute}.block-search .nested{display:none}.search-autocomplete{display:none;margin-top:-15px;overflow:hidden;position:absolute;z-index:3}.minicart-wrapper{display:inline-block;position:relative;float:right}.minicart-wrapper:after,.minicart-wrapper:before{content:'';display:table}.minicart-wrapper:after{clear:both}.minicart-wrapper .action.showcart{display:inline-block;text-decoration:none}.minicart-wrapper .action.showcart:before{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:22px;line-height:28px;color:#757575;content:'\e611';font-family:luma-icons;margin:0;vertical-align:top;display:inline-block;font-weight:400;overflow:hidden;speak:none;text-align:center}.minicart-wrapper .block-minicart{margin:0;padding:0;list-style:none none;background:#fff;border:1px solid #bbb;margin-top:4px;min-width:100%;width:320px;z-index:101;box-sizing:border-box;display:none;position:absolute;top:100%;right:-10px;box-shadow:0 3px 3px rgba(0,0,0,.15)}.minicart-wrapper .block-minicart:after,.minicart-wrapper .block-minicart:before{border-bottom-style:solid;content:'';display:block;height:0;position:absolute;width:0}.minicart-wrapper .block-minicart:before{border:6px solid;border-color:transparent transparent #fff transparent;z-index:99}.minicart-wrapper .block-minicart:after{border:7px solid;border-color:transparent transparent #bbb transparent;z-index:98}.minicart-wrapper .block-minicart:before{right:12px;top:-12px}.minicart-wrapper .block-minicart:after{right:11px;top:-14px}.minicart-wrapper .block-minicart{padding:25px 20px}.minicart-wrapper .action.showcart{white-space:nowrap}.minicart-wrapper .action.showcart .counter.qty{background:#ff5501;color:#fff;height:24px;line-height:24px;border-radius:2px;display:inline-block;margin:3px 0 0;min-width:18px;overflow:hidden;padding:0 3px;text-align:center;white-space:normal}.minicart-wrapper .action.showcart .counter.qty.empty{display:none}.minicart-wrapper .action.showcart .counter-number{text-shadow:0 0 7px #000}.block .title{display:block;margin-bottom:10px}.block .title strong{font-weight:700;line-height:1.1;font-size:1.4rem;margin-top:2rem;margin-bottom:2rem}.block.newsletter .title{display:none}.rating-summary{overflow:hidden;white-space:nowrap}.rating-summary .rating-result{width:88px;display:inline-block;position:relative;vertical-align:middle}.rating-summary .rating-result:before{left:0;position:absolute;top:0;width:100%;z-index:1;-webkit-font-smoothing:antialiased;color:#c7c7c7;font-family:luma-icons;font-size:16px;height:16px;letter-spacing:2px;line-height:16px;content:'\e605' '\e605' '\e605' '\e605' '\e605';display:block;font-style:normal;font-weight:400;speak:none}.rating-summary .rating-result>span{display:block;overflow:hidden}.rating-summary .rating-result>span:before{position:relative;z-index:2;-webkit-font-smoothing:antialiased;color:#ff5501;font-family:luma-icons;font-size:16px;height:16px;letter-spacing:2px;line-height:16px;content:'\e605' '\e605' '\e605' '\e605' '\e605';display:block;font-style:normal;font-weight:400;speak:none}.rating-summary .rating-result>span span{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.product-reviews-summary .rating-summary .label{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.review-add .block-title{display:none}.product-reviews-summary{margin-bottom:5px}.product-reviews-summary .rating-summary{display:inline-block;vertical-align:middle}.product-reviews-summary .reviews-actions{display:inline-block;font-size:11px;vertical-align:middle}.product-reviews-summary .reviews-actions a:not(:last-child){margin-right:30px}.product-reviews-summary .reviews-actions .action.add{white-space:nowrap}.product-info-main .rating-summary{margin-right:30px}body{background-color:#fff}.page-wrapper{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;min-height:100vh}.page-main{-webkit-flex-grow:1;flex-grow:1}.page-header{border-bottom:1px solid #ccc;margin-bottom:20px}.page-header .panel.wrapper{background-color:#6e716e;color:#fff}.header.panel>.header.links{margin:0;padding:0;list-style:none none;float:right;font-size:0;margin-left:auto;margin-right:20px}.header.panel>.header.links>li{display:inline-block;vertical-align:top}.header.panel>.header.links>li{font-size:14px;margin:0 0 0 15px}.header.panel>.header.links>li>a{color:#fff;text-decoration:none}.header.panel>.header.links>li>a:visited{color:#fff;text-decoration:none}.header.content{padding-top:10px;position:relative}.logo{float:left;margin:0 0 10px 40px;max-width:50%;position:relative;z-index:5}.logo img{display:block;height:auto}.action-skip-wrapper{height:0;position:relative}.message.global p{margin:0}.message.global.noscript{margin:0 0 10px;padding:12px 20px 12px 25px;display:block;font-size:1.3rem;background:#ffee9c;border-color:#d6ca8e;color:#333;margin:0}.message.global.demo{margin:0 0 10px;padding:12px 20px 12px 25px;display:block;font-size:1.3rem;background:#ff0101;border-color:none;color:#fff;margin-bottom:0;text-align:center}.cookie-status-message{display:none}.product-item .action.towishlist:before,.product-social-links .action.towishlist:before{content:'\e600'}@media only screen and (max-width:768px){.breadcrumbs,.header.content,.navigation,.page-header .header.panel,.page-main{padding-left:15px;padding-right:15px}.navigation{padding:0}.navigation .parent .level-top{display:block;text-decoration:none;position:relative}.navigation .parent .level-top:after{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:42px;line-height:inherit;color:inherit;content:'\e622';font-family:luma-icons;vertical-align:middle;display:inline-block;font-weight:400;overflow:hidden;speak:none;text-align:center}.navigation .parent .level-top:after{position:absolute;right:7px;top:-8px}.nav-sections{-webkit-overflow-scrolling:touch;height:100%;left:calc(-1 * (100% - 54px));overflow:auto;position:fixed;top:0;width:calc(100% - 54px)}.nav-sections .header.links{margin:0;padding:0;list-style:none none;border-bottom:1px solid #d1d1d1}.nav-sections .header.links li{font-size:1.6rem;margin:0}.nav-sections .header.links li>a{border-top:1px solid #d1d1d1}.nav-sections .header.links a{color:#575757;text-decoration:none;display:block;font-weight:700;padding:.8rem 15px}.nav-sections-items{position:relative;z-index:1}.nav-sections-items:after,.nav-sections-items:before{content:'';display:table}.nav-sections-items:after{clear:both}.nav-sections-item-title{background:#e3e3e3;border:solid #d7d7d7;border-width:0 0 1px 1px;box-sizing:border-box;float:left;height:71px;padding-top:24px;text-align:center;width:33.33%}.nav-sections-item-content{box-sizing:border-box;float:right;margin-left:-100%;margin-top:71px;width:100%;padding:25px 0}.nav-sections-item-content:after,.nav-sections-item-content:before{content:'';display:table}.nav-sections-item-content:after{clear:both}.navigation{background:#f0f0f0;box-sizing:border-box}.navigation ul{margin:0;padding:0}.navigation li{margin:0}.navigation a{display:block;padding-top:10px;padding-right:0;padding-bottom:10px;padding-left:15px}.navigation a{color:#575757;text-decoration:none}.navigation .level0{border-top:1px solid #d1d1d1;font-size:1.6rem}.navigation .level0>.level-top{font-weight:700;padding:8px 40px 8px 15px;text-transform:uppercase;word-wrap:break-word}.navigation .level0>.level1{font-weight:600}.navigation li.level0:last-child{border-bottom:1px solid #d1d1d1}.navigation .submenu>li{word-wrap:break-word}.navigation .submenu:not(:first-child){font-weight:400;line-height:1.3;left:auto!important;overflow-x:hidden;padding:0;position:relative;top:auto!important}.navigation .submenu:not(:first-child)>li>a{padding-left:15px}.navigation .submenu:not(:first-child)>li:last-child{margin-bottom:0}.navigation .submenu:not(:first-child) ul{display:block;padding-left:15px}.navigation .submenu:not(:first-child) ul>li{margin:0}.navigation .submenu:not(:first-child) ul>li a{color:#575757;display:block;line-height:normal}.breadcrumbs{display:none}.catalog-product-view .column.main{display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column}.catalog-product-view .product.media{-ms-flex-order:-1;-webkit-order:-1;order:-1}.compare.wrapper{display:none}.block-search{margin-top:10px}.minicart-wrapper{margin-top:10px}.minicart-wrapper:after,.minicart-wrapper:before{content:'';display:table}.minicart-wrapper:after{clear:both}.navigation .parent .level-top:after{font-size:1.6rem;right:10px;top:7px}.logo{margin-bottom:13px;margin-top:4px}}@media only screen and (max-width:639px){.product-info-price{margin:0 -10px 0;width:calc(100% + 2*10px)!important}.product-info-price>:first-child{padding-left:10px}.product-info-price>:last-child{padding-right:10px}}@media only screen and (max-width:479px){.minicart-wrapper .block-minicart{width:290px}} -------------------------------------------------------------------------------- /registration.php: -------------------------------------------------------------------------------- 1 | 21 |
22 | 23 | 24 | 25 |
26 | 27 | ) 28 | } 29 | } 30 | 31 | export default AddToCartForm; 32 | -------------------------------------------------------------------------------- /src/components/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import AddToCartForm from './AddToCartForm'; 4 | //import jQuery from 'jquery'; 5 | 6 | class App extends React.Component { 7 | 8 | constructor(props) { 9 | super(props); 10 | //Add to cart Toggle flag 11 | document.afterAddToCart = false; 12 | document.warrantyPopUpWasOpen = false; 13 | 14 | this.state = { 15 | data: document.global_data_for_react_app, 16 | selected: false, 17 | selectedItem: null, 18 | }; 19 | 20 | this.togglePopup = this.togglePopup.bind(this); 21 | } 22 | 23 | togglePopup() { 24 | 25 | } 26 | 27 | 28 | componentDidMount() { 29 | } 30 | 31 | 32 | 33 | 34 | render() { 35 | return ( 36 |
37 |

React Component<\h1> 38 | 39 |

40 | ); 41 | } 42 | } 43 | 44 | export default App; 45 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './styles/index.css'; 4 | import App from './components/App'; 5 | 6 | const reactApp = function(){ 7 | return { 8 | init(element,parameter) { 9 | console.log('Rendering React Component Into:' + element); 10 | let live = ''; 11 | /// Magento site live reloading feature 12 | if (window.location.hostname == 'localhost' || window.location.hostname.includes('loc')){ 13 | live =''; 14 | var imported = document.createElement('script'); 15 | imported.src = 'http://localhost:35729/livereload.js'; 16 | document.head.appendChild(imported); 17 | } 18 | 19 | return ReactDOM.render(, document.getElementById(element)); 20 | } 21 | } 22 | } 23 | 24 | define(reactApp); -------------------------------------------------------------------------------- /src/styles/gridjs.css: -------------------------------------------------------------------------------- 1 | .gridjs-footer button,.gridjs-head button{background-color:transparent;background-image:none;border:none;cursor:pointer;margin:0;outline:none;padding:0}.gridjs-temp{position:relative}.gridjs-head{margin-bottom:5px;padding:5px 1px;width:100%}.gridjs-head:after{clear:both;content:"";display:block}.gridjs-head:empty{border:none;padding:0}.gridjs-container{color:#000;display:inline-block;overflow:hidden;padding:2px;position:relative;z-index:0}.gridjs-footer{background-color:#fff;border-bottom-width:1px;border-color:#e5e7eb;border-radius:0 0 8px 8px;border-top:1px solid #e5e7eb;box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.26);display:block;padding:12px 24px;position:relative;width:100%;z-index:5}.gridjs-footer:empty{border:none;padding:0}input.gridjs-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border:1px solid #d2d6dc;border-radius:5px;font-size:14px;line-height:1.45;outline:none;padding:10px 13px}input.gridjs-input:focus{border-color:#9bc2f7;box-shadow:0 0 0 3px rgba(149,189,243,.5)}.gridjs-pagination{color:#3d4044}.gridjs-pagination:after{clear:both;content:"";display:block}.gridjs-pagination .gridjs-summary{float:left;margin-top:5px}.gridjs-pagination .gridjs-pages{float:right}.gridjs-pagination .gridjs-pages button{background-color:#fff;border:1px solid #d2d6dc;border-right:none;outline:none;padding:5px 14px;-webkit-user-select:none;-moz-user-select:none;user-select:none}.gridjs-pagination .gridjs-pages button:focus{border-right:1px solid #d2d6dc;box-shadow:0 0 0 2px rgba(149,189,243,.5);margin-right:-1px;position:relative}.gridjs-pagination .gridjs-pages button:hover{background-color:#f7f7f7;color:#3c4257;outline:none}.gridjs-pagination .gridjs-pages button:disabled,.gridjs-pagination .gridjs-pages button:hover:disabled,.gridjs-pagination .gridjs-pages button[disabled]{background-color:#fff;color:#6b7280;cursor:default}.gridjs-pagination .gridjs-pages button.gridjs-spread{background-color:#fff;box-shadow:none;cursor:default}.gridjs-pagination .gridjs-pages button.gridjs-currentPage{background-color:#f7f7f7;font-weight:700}.gridjs-pagination .gridjs-pages button:last-child{border-bottom-right-radius:6px;border-right:1px solid #d2d6dc;border-top-right-radius:6px}.gridjs-pagination .gridjs-pages button:first-child{border-bottom-left-radius:6px;border-top-left-radius:6px}.gridjs-pagination .gridjs-pages button:last-child:focus{margin-right:0}button.gridjs-sort{background-color:transparent;background-position-x:center;background-repeat:no-repeat;background-size:contain;border:none;cursor:pointer;float:right;height:24px;margin:0;outline:none;padding:0;width:13px}button.gridjs-sort-neutral{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0MDEuOTk4IiBoZWlnaHQ9IjQwMS45OTgiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQwMS45OTggNDAxLjk5OCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBhdGggZD0iTTczLjA5MiAxNjQuNDUyaDI1NS44MTNjNC45NDkgMCA5LjIzMy0xLjgwNyAxMi44NDgtNS40MjQgMy42MTMtMy42MTYgNS40MjctNy44OTggNS40MjctMTIuODQ3cy0xLjgxMy05LjIyOS01LjQyNy0xMi44NUwyMTMuODQ2IDUuNDI0QzIxMC4yMzIgMS44MTIgMjA1Ljk1MSAwIDIwMC45OTkgMHMtOS4yMzMgMS44MTItMTIuODUgNS40MjRMNjAuMjQyIDEzMy4zMzFjLTMuNjE3IDMuNjE3LTUuNDI0IDcuOTAxLTUuNDI0IDEyLjg1IDAgNC45NDggMS44MDcgOS4yMzEgNS40MjQgMTIuODQ3IDMuNjIxIDMuNjE3IDcuOTAyIDUuNDI0IDEyLjg1IDUuNDI0ek0zMjguOTA1IDIzNy41NDlINzMuMDkyYy00Ljk1MiAwLTkuMjMzIDEuODA4LTEyLjg1IDUuNDIxLTMuNjE3IDMuNjE3LTUuNDI0IDcuODk4LTUuNDI0IDEyLjg0N3MxLjgwNyA5LjIzMyA1LjQyNCAxMi44NDhMMTg4LjE0OSAzOTYuNTdjMy42MjEgMy42MTcgNy45MDIgNS40MjggMTIuODUgNS40MjhzOS4yMzMtMS44MTEgMTIuODQ3LTUuNDI4bDEyNy45MDctMTI3LjkwNmMzLjYxMy0zLjYxNCA1LjQyNy03Ljg5OCA1LjQyNy0xMi44NDggMC00Ljk0OC0xLjgxMy05LjIyOS01LjQyNy0xMi44NDctMy42MTQtMy42MTYtNy44OTktNS40Mi0xMi44NDgtNS40MnoiLz48L3N2Zz4=");background-position-y:center;opacity:.3}button.gridjs-sort-asc{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOTIuMzYyIiBoZWlnaHQ9IjI5Mi4zNjEiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDI5Mi4zNjIgMjkyLjM2MSIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBhdGggZD0iTTI4Ni45MzUgMTk3LjI4NyAxNTkuMDI4IDY5LjM4MWMtMy42MTMtMy42MTctNy44OTUtNS40MjQtMTIuODQ3LTUuNDI0cy05LjIzMyAxLjgwNy0xMi44NSA1LjQyNEw1LjQyNCAxOTcuMjg3QzEuODA3IDIwMC45MDQgMCAyMDUuMTg2IDAgMjEwLjEzNHMxLjgwNyA5LjIzMyA1LjQyNCAxMi44NDdjMy42MjEgMy42MTcgNy45MDIgNS40MjUgMTIuODUgNS40MjVoMjU1LjgxM2M0Ljk0OSAwIDkuMjMzLTEuODA4IDEyLjg0OC01LjQyNSAzLjYxMy0zLjYxMyA1LjQyNy03Ljg5OCA1LjQyNy0xMi44NDdzLTEuODE0LTkuMjMtNS40MjctMTIuODQ3eiIvPjwvc3ZnPg==");background-position-y:35%;background-size:10px}button.gridjs-sort-desc{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyOTIuMzYyIiBoZWlnaHQ9IjI5Mi4zNjIiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDI5Mi4zNjIgMjkyLjM2MiIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+PHBhdGggZD0iTTI4Ni45MzUgNjkuMzc3Yy0zLjYxNC0zLjYxNy03Ljg5OC01LjQyNC0xMi44NDgtNS40MjRIMTguMjc0Yy00Ljk1MiAwLTkuMjMzIDEuODA3LTEyLjg1IDUuNDI0QzEuODA3IDcyLjk5OCAwIDc3LjI3OSAwIDgyLjIyOGMwIDQuOTQ4IDEuODA3IDkuMjI5IDUuNDI0IDEyLjg0N2wxMjcuOTA3IDEyNy45MDdjMy42MjEgMy42MTcgNy45MDIgNS40MjggMTIuODUgNS40MjhzOS4yMzMtMS44MTEgMTIuODQ3LTUuNDI4TDI4Ni45MzUgOTUuMDc0YzMuNjEzLTMuNjE3IDUuNDI3LTcuODk4IDUuNDI3LTEyLjg0NyAwLTQuOTQ4LTEuODE0LTkuMjI5LTUuNDI3LTEyLjg1eiIvPjwvc3ZnPg==");background-position-y:65%;background-size:10px}button.gridjs-sort:focus{outline:none}table.gridjs-table{border-collapse:collapse;display:table;margin:0;max-width:100%;overflow:auto;padding:0;table-layout:fixed;text-align:left;width:100%}.gridjs-tbody,td.gridjs-td{background-color:#fff}td.gridjs-td{border:1px solid #e5e7eb;box-sizing:content-box;padding:12px 24px}td.gridjs-td:first-child{border-left:none}td.gridjs-td:last-child{border-right:none}td.gridjs-message{text-align:center}th.gridjs-th{background-color:#f9fafb;border:1px solid #e5e7eb;border-top:none;box-sizing:border-box;color:#6b7280;outline:none;padding:14px 24px;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;white-space:nowrap}th.gridjs-th .gridjs-th-content{float:left;overflow:hidden;text-overflow:ellipsis;width:100%}th.gridjs-th-sort{cursor:pointer}th.gridjs-th-sort .gridjs-th-content{width:calc(100% - 15px)}th.gridjs-th-sort:focus,th.gridjs-th-sort:hover{background-color:#e5e7eb}th.gridjs-th-fixed{box-shadow:0 1px 0 0 #e5e7eb;position:sticky}@supports (-moz-appearance:none){th.gridjs-th-fixed{box-shadow:0 0 0 1px #e5e7eb}}th.gridjs-th:first-child{border-left:none}th.gridjs-th:last-child{border-right:none}.gridjs-tr{border:none}.gridjs-tr-selected td{background-color:#ebf5ff}.gridjs-tr:last-child td{border-bottom:0}.gridjs *,.gridjs :after,.gridjs :before{box-sizing:border-box}.gridjs-wrapper{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;border-color:#e5e7eb;border-radius:8px 8px 0 0;border-top-width:1px;box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.26);display:block;overflow:auto;position:relative;width:100%;z-index:1}.gridjs-wrapper:nth-last-of-type(2){border-bottom-width:1px;border-radius:8px}.gridjs-search{float:left}.gridjs-search-input{width:250px}.gridjs-loading-bar{background-color:#fff;opacity:.5;z-index:10}.gridjs-loading-bar,.gridjs-loading-bar:after{bottom:0;left:0;position:absolute;right:0;top:0}.gridjs-loading-bar:after{animation:shimmer 2s infinite;background-image:linear-gradient(90deg,hsla(0,0%,80%,0),hsla(0,0%,80%,.2) 20%,hsla(0,0%,80%,.5) 60%,hsla(0,0%,80%,0));content:"";transform:translateX(-100%)}@keyframes shimmer{to{transform:translateX(100%)}}.gridjs-td .gridjs-checkbox{cursor:pointer;display:block;margin:auto}.gridjs-resizable{bottom:0;position:absolute;right:0;top:0;width:5px}.gridjs-resizable:hover{background-color:#9bc2f7;cursor:ew-resize} 2 | -------------------------------------------------------------------------------- /src/styles/index.css: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /view/adminhtml/layout/default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /view/adminhtml/templates/index/index.phtml: -------------------------------------------------------------------------------- 1 |
2 | 3 | 15 | 16 | -------------------------------------------------------------------------------- /view/base/requirejs-config.js: -------------------------------------------------------------------------------- 1 | var config = { 2 | /* map: { 3 | '*': { 4 | 'react': 'React_React/js/react', 5 | 'react-dom': 'React_React/js/react-dom', 6 | 'react-app': 'React_React/js/index_bundle', 7 | } 8 | },*/ 9 | }; 10 | -------------------------------------------------------------------------------- /view/base/templates/component.phtml: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |
7 | 8 | 18 | -------------------------------------------------------------------------------- /view/base/templates/react-component.phtml: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |
7 | 8 | 18 | -------------------------------------------------------------------------------- /view/base/templates/vue-component.phtml: -------------------------------------------------------------------------------- 1 |
2 |

{{ message }} -> {{ name }} !

3 |
4 | -------------------------------------------------------------------------------- /view/base/web/js/htm.module.js: -------------------------------------------------------------------------------- 1 | var n = function (t, s, r, e) {var u;s[0] = 0;for (var h = 1; h < s.length; h++) {var p = s[h++],a = s[h] ? (s[0] |= p ? 1 : 2, r[s[h++]]) : s[++h];3 === p ? e[0] = a : 4 === p ? e[1] = Object.assign(e[1] || {}, a) : 5 === p ? (e[1] = e[1] || {})[s[++h]] = a : 6 === p ? e[1][s[++h]] += a + "" : p ? (u = t.apply(a, n(t, a, r, ["", null])), e.push(u), a[0] ? s[0] |= 2 : (s[h - 2] = 0, s[h] = u)) : e.push(a);}return e;},t = new Map();export default function (s) {var r = t.get(this);return r || (r = new Map(), t.set(this, r)), (r = n(this, r.get(s) || (r.set(s, r = function (n) {for (var t, s, r = 1, e = "", u = "", h = [0], p = function (n) {1 === r && (n || (e = e.replace(/^\s*\n\s*|\s*\n\s*$/g, ""))) ? h.push(0, n, e) : 3 === r && (n || e) ? (h.push(3, n, e), r = 2) : 2 === r && "..." === e && n ? h.push(4, n, 0) : 2 === r && e && !n ? h.push(5, 0, !0, e) : r >= 5 && ((e || !n && 5 === r) && (h.push(r, 0, e, s), r = 6), n && (h.push(r, n, 0, s), r = 6)), e = "";}, a = 0; a < n.length; a++) {a && (1 === r && p(), p(a));for (var l = 0; l < n[a].length; l++) t = n[a][l], 1 === r ? "<" === t ? (p(), h = [h], r = 3) : e += t : 4 === r ? "--" === e && ">" === t ? (r = 1, e = "") : e = t + e[0] : u ? t === u ? u = "" : e += t : '"' === t || "'" === t ? u = t : ">" === t ? (p(), r = 1) : r && ("=" === t ? (r = 5, s = e, e = "") : "/" === t && (r < 5 || ">" === n[a][l + 1]) ? (p(), 3 === r && (h = h[0]), r = h, (h = h[0]).push(2, 0, r), r = 0) : " " === t || "\t" === t || "\n" === t || "\r" === t ? (p(), r = 2) : e += t), 3 === r && "!--" === e && (r = 4, h = h[0]);}return p(), h;}(s)), r), arguments, [])).length > 1 ? r : r[0];} -------------------------------------------------------------------------------- /view/base/web/js/index_bundle.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Genaker/reactmagento2/a66d7e36b76183634589c684b09bfb832655135d/view/base/web/js/index_bundle.js -------------------------------------------------------------------------------- /view/base/web/js/preact.module.js: -------------------------------------------------------------------------------- 1 | var n,l,u,i,t,r,o,f,e = {},c = [],s = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function a(n, l) {for (var u in l) n[u] = l[u];return n;}function h(n) {var l = n.parentNode;l && l.removeChild(n);}function v(l, u, i) {var t,r,o,f = {};for (o in u) "key" == o ? t = u[o] : "ref" == o ? r = u[o] : f[o] = u[o];if (arguments.length > 2 && (f.children = arguments.length > 3 ? n.call(arguments, 2) : i), "function" == typeof l && null != l.defaultProps) for (o in l.defaultProps) void 0 === f[o] && (f[o] = l.defaultProps[o]);return y(l, f, t, r, null);}function y(n, i, t, r, o) {var f = { type: n, props: i, key: t, ref: r, __k: null, __: null, __b: 0, __e: null, __d: void 0, __c: null, __h: null, constructor: void 0, __v: null == o ? ++u : o };return null == o && null != l.vnode && l.vnode(f), f;}function p() {return { current: null };}function d(n) {return n.children;}function _(n, l) {this.props = n, this.context = l;}function k(n, l) {if (null == l) return n.__ ? k(n.__, n.__.__k.indexOf(n) + 1) : null;for (var u; l < n.__k.length; l++) if (null != (u = n.__k[l]) && null != u.__e) return u.__e;return "function" == typeof n.type ? k(n) : null;}function b(n) {var l, u;if (null != (n = n.__) && null != n.__c) {for (n.__e = n.__c.base = null, l = 0; l < n.__k.length; l++) if (null != (u = n.__k[l]) && null != u.__e) {n.__e = n.__c.base = u.__e;break;}return b(n);}}function m(n) {(!n.__d && (n.__d = !0) && t.push(n) && !g.__r++ || o !== l.debounceRendering) && ((o = l.debounceRendering) || r)(g);}function g() {for (var n; g.__r = t.length;) n = t.sort(function (n, l) {return n.__v.__b - l.__v.__b;}), t = [], n.some(function (n) {var l, u, i, t, r, o;n.__d && (r = (t = (l = n).__v).__e, (o = l.__P) && (u = [], (i = a({}, t)).__v = t.__v + 1, j(o, t, i, l.__n, void 0 !== o.ownerSVGElement, null != t.__h ? [r] : null, u, null == r ? k(t) : r, t.__h), z(u, t), t.__e != r && b(t)));});}function w(n, l, u, i, t, r, o, f, s, a) {var h,v,p,_,b,m,g,w = i && i.__k || c,A = w.length;for (u.__k = [], h = 0; h < l.length; h++) if (null != (_ = u.__k[h] = null == (_ = l[h]) || "boolean" == typeof _ ? null : "string" == typeof _ || "number" == typeof _ || "bigint" == typeof _ ? y(null, _, null, null, _) : Array.isArray(_) ? y(d, { children: _ }, null, null, null) : _.__b > 0 ? y(_.type, _.props, _.key, null, _.__v) : _)) {if (_.__ = u, _.__b = u.__b + 1, null === (p = w[h]) || p && _.key == p.key && _.type === p.type) w[h] = void 0;else for (v = 0; v < A; v++) {if ((p = w[v]) && _.key == p.key && _.type === p.type) {w[v] = void 0;break;}p = null;}j(n, _, p = p || e, t, r, o, f, s, a), b = _.__e, (v = _.ref) && p.ref != v && (g || (g = []), p.ref && g.push(p.ref, null, _), g.push(v, _.__c || b, _)), null != b ? (null == m && (m = b), "function" == typeof _.type && _.__k === p.__k ? _.__d = s = x(_, s, n) : s = P(n, _, p, w, b, s), "function" == typeof u.type && (u.__d = s)) : s && p.__e == s && s.parentNode != n && (s = k(p));}for (u.__e = m, h = A; h--;) null != w[h] && ("function" == typeof u.type && null != w[h].__e && w[h].__e == u.__d && (u.__d = k(i, h + 1)), N(w[h], w[h]));if (g) for (h = 0; h < g.length; h++) M(g[h], g[++h], g[++h]);}function x(n, l, u) {for (var i, t = n.__k, r = 0; t && r < t.length; r++) (i = t[r]) && (i.__ = n, l = "function" == typeof i.type ? x(i, l, u) : P(u, i, i, t, i.__e, l));return l;}function A(n, l) {return l = l || [], null == n || "boolean" == typeof n || (Array.isArray(n) ? n.some(function (n) {A(n, l);}) : l.push(n)), l;}function P(n, l, u, i, t, r) {var o, f, e;if (void 0 !== l.__d) o = l.__d, l.__d = void 0;else if (null == u || t != r || null == t.parentNode) n: if (null == r || r.parentNode !== n) n.appendChild(t), o = null;else {for (f = r, e = 0; (f = f.nextSibling) && e < i.length; e += 2) if (f == t) break n;n.insertBefore(t, r), o = r;}return void 0 !== o ? o : t.nextSibling;}function C(n, l, u, i, t) {var r;for (r in u) "children" === r || "key" === r || r in l || H(n, r, null, u[r], i);for (r in l) t && "function" != typeof l[r] || "children" === r || "key" === r || "value" === r || "checked" === r || u[r] === l[r] || H(n, r, l[r], u[r], i);}function $(n, l, u) {"-" === l[0] ? n.setProperty(l, u) : n[l] = null == u ? "" : "number" != typeof u || s.test(l) ? u : u + "px";}function H(n, l, u, i, t) {var r;n: if ("style" === l) {if ("string" == typeof u) n.style.cssText = u;else {if ("string" == typeof i && (n.style.cssText = i = ""), i) for (l in i) u && l in u || $(n.style, l, "");if (u) for (l in u) i && u[l] === i[l] || $(n.style, l, u[l]);}} else if ("o" === l[0] && "n" === l[1]) r = l !== (l = l.replace(/Capture$/, "")), l = l.toLowerCase() in n ? l.toLowerCase().slice(2) : l.slice(2), n.l || (n.l = {}), n.l[l + r] = u, u ? i || n.addEventListener(l, r ? T : I, r) : n.removeEventListener(l, r ? T : I, r);else if ("dangerouslySetInnerHTML" !== l) {if (t) l = l.replace(/xlink[H:h]/, "h").replace(/sName$/, "s");else if ("href" !== l && "list" !== l && "form" !== l && "tabIndex" !== l && "download" !== l && l in n) try {n[l] = null == u ? "" : u;break n;} catch (n) {}"function" == typeof u || (null != u && (!1 !== u || "a" === l[0] && "r" === l[1]) ? n.setAttribute(l, u) : n.removeAttribute(l));}}function I(n) {this.l[n.type + !1](l.event ? l.event(n) : n);}function T(n) {this.l[n.type + !0](l.event ? l.event(n) : n);}function j(n, u, i, t, r, o, f, e, c) {var s,h,v,y,p,k,b,m,g,x,A,P = u.type;if (void 0 !== u.constructor) return null;null != i.__h && (c = i.__h, e = u.__e = i.__e, u.__h = null, o = [e]), (s = l.__b) && s(u);try {n: if ("function" == typeof P) {if (m = u.props, g = (s = P.contextType) && t[s.__c], x = s ? g ? g.props.value : s.__ : t, i.__c ? b = (h = u.__c = i.__c).__ = h.__E : ("prototype" in P && P.prototype.render ? u.__c = h = new P(m, x) : (u.__c = h = new _(m, x), h.constructor = P, h.render = O), g && g.sub(h), h.props = m, h.state || (h.state = {}), h.context = x, h.__n = t, v = h.__d = !0, h.__h = []), null == h.__s && (h.__s = h.state), null != P.getDerivedStateFromProps && (h.__s == h.state && (h.__s = a({}, h.__s)), a(h.__s, P.getDerivedStateFromProps(m, h.__s))), y = h.props, p = h.state, v) null == P.getDerivedStateFromProps && null != h.componentWillMount && h.componentWillMount(), null != h.componentDidMount && h.__h.push(h.componentDidMount);else {if (null == P.getDerivedStateFromProps && m !== y && null != h.componentWillReceiveProps && h.componentWillReceiveProps(m, x), !h.__e && null != h.shouldComponentUpdate && !1 === h.shouldComponentUpdate(m, h.__s, x) || u.__v === i.__v) {h.props = m, h.state = h.__s, u.__v !== i.__v && (h.__d = !1), h.__v = u, u.__e = i.__e, u.__k = i.__k, u.__k.forEach(function (n) {n && (n.__ = u);}), h.__h.length && f.push(h);break n;}null != h.componentWillUpdate && h.componentWillUpdate(m, h.__s, x), null != h.componentDidUpdate && h.__h.push(function () {h.componentDidUpdate(y, p, k);});}h.context = x, h.props = m, h.state = h.__s, (s = l.__r) && s(u), h.__d = !1, h.__v = u, h.__P = n, s = h.render(h.props, h.state, h.context), h.state = h.__s, null != h.getChildContext && (t = a(a({}, t), h.getChildContext())), v || null == h.getSnapshotBeforeUpdate || (k = h.getSnapshotBeforeUpdate(y, p)), A = null != s && s.type === d && null == s.key ? s.props.children : s, w(n, Array.isArray(A) ? A : [A], u, i, t, r, o, f, e, c), h.base = u.__e, u.__h = null, h.__h.length && f.push(h), b && (h.__E = h.__ = null), h.__e = !1;} else null == o && u.__v === i.__v ? (u.__k = i.__k, u.__e = i.__e) : u.__e = L(i.__e, u, i, t, r, o, f, c);(s = l.diffed) && s(u);} catch (n) {u.__v = null, (c || null != o) && (u.__e = e, u.__h = !!c, o[o.indexOf(e)] = null), l.__e(n, u, i);}}function z(n, u) {l.__c && l.__c(u, n), n.some(function (u) {try {n = u.__h, u.__h = [], n.some(function (n) {n.call(u);});} catch (n) {l.__e(n, u.__v);}});}function L(l, u, i, t, r, o, f, c) {var s,a,v,y = i.props,p = u.props,d = u.type,_ = 0;if ("svg" === d && (r = !0), null != o) for (; _ < o.length; _++) if ((s = o[_]) && "setAttribute" in s == !!d && (d ? s.localName === d : 3 === s.nodeType)) {l = s, o[_] = null;break;}if (null == l) {if (null === d) return document.createTextNode(p);l = r ? document.createElementNS("http://www.w3.org/2000/svg", d) : document.createElement(d, p.is && p), o = null, c = !1;}if (null === d) y === p || c && l.data === p || (l.data = p);else {if (o = o && n.call(l.childNodes), a = (y = i.props || e).dangerouslySetInnerHTML, v = p.dangerouslySetInnerHTML, !c) {if (null != o) for (y = {}, _ = 0; _ < l.attributes.length; _++) y[l.attributes[_].name] = l.attributes[_].value;(v || a) && (v && (a && v.__html == a.__html || v.__html === l.innerHTML) || (l.innerHTML = v && v.__html || ""));}if (C(l, p, y, r, c), v) u.__k = [];else if (_ = u.props.children, w(l, Array.isArray(_) ? _ : [_], u, i, t, r && "foreignObject" !== d, o, f, o ? o[0] : i.__k && k(i, 0), c), null != o) for (_ = o.length; _--;) null != o[_] && h(o[_]);c || ("value" in p && void 0 !== (_ = p.value) && (_ !== y.value || _ !== l.value || "progress" === d && !_) && H(l, "value", _, y.value, !1), "checked" in p && void 0 !== (_ = p.checked) && _ !== l.checked && H(l, "checked", _, y.checked, !1));}return l;}function M(n, u, i) {try {"function" == typeof n ? n(u) : n.current = u;} catch (n) {l.__e(n, i);}}function N(n, u, i) {var t, r;if (l.unmount && l.unmount(n), (t = n.ref) && (t.current && t.current !== n.__e || M(t, null, u)), null != (t = n.__c)) {if (t.componentWillUnmount) try {t.componentWillUnmount();} catch (n) {l.__e(n, u);}t.base = t.__P = null;}if (t = n.__k) for (r = 0; r < t.length; r++) t[r] && N(t[r], u, "function" != typeof n.type);i || null == n.__e || h(n.__e), n.__e = n.__d = void 0;}function O(n, l, u) {return this.constructor(n, u);}function S(u, i, t) {var r, o, f;l.__ && l.__(u, i), o = (r = "function" == typeof t) ? null : t && t.__k || i.__k, f = [], j(i, u = (!r && t || i).__k = v(d, null, [u]), o || e, e, void 0 !== i.ownerSVGElement, !r && t ? [t] : o ? null : i.firstChild ? n.call(i.childNodes) : null, f, !r && t ? t : o ? o.__e : i.firstChild, r), z(f, u);}function q(n, l) {S(n, l, q);}function B(l, u, i) {var t,r,o,f = a({}, l.props);for (o in u) "key" == o ? t = u[o] : "ref" == o ? r = u[o] : f[o] = u[o];return arguments.length > 2 && (f.children = arguments.length > 3 ? n.call(arguments, 2) : i), y(l.type, f, t || l.key, r || l.ref, null);}function D(n, l) {var u = { __c: l = "__cC" + f++, __: n, Consumer: function (n, l) {return n.children(l);}, Provider: function (n) {var u, i;return this.getChildContext || (u = [], (i = {})[l] = this, this.getChildContext = function () {return i;}, this.shouldComponentUpdate = function (n) {this.props.value !== n.value && u.some(m);}, this.sub = function (n) {u.push(n);var l = n.componentWillUnmount;n.componentWillUnmount = function () {u.splice(u.indexOf(n), 1), l && l.call(n);};}), n.children;} };return u.Provider.__ = u.Consumer.contextType = u;}n = c.slice, l = { __e: function (n, l) {for (var u, i, t; l = l.__;) if ((u = l.__c) && !u.__) try {if ((i = u.constructor) && null != i.getDerivedStateFromError && (u.setState(i.getDerivedStateFromError(n)), t = u.__d), null != u.componentDidCatch && (u.componentDidCatch(n), t = u.__d), t) return u.__E = u;} catch (l) {n = l;}throw n;} }, u = 0, i = function (n) {return null != n && void 0 === n.constructor;}, _.prototype.setState = function (n, l) {var u;u = null != this.__s && this.__s !== this.state ? this.__s : this.__s = a({}, this.state), "function" == typeof n && (n = n(a({}, u), this.props)), n && a(u, n), null != n && this.__v && (l && this.__h.push(l), m(this));}, _.prototype.forceUpdate = function (n) {this.__v && (this.__e = !0, n && this.__h.push(n), m(this));}, _.prototype.render = d, t = [], r = "function" == typeof Promise ? Promise.prototype.then.bind(Promise.resolve()) : setTimeout, g.__r = 0, f = 0;export { S as render, q as hydrate, v as createElement, v as h, d as Fragment, p as createRef, i as isValidElement, _ as Component, B as cloneElement, D as createContext, A as toChildArray, l as options }; -------------------------------------------------------------------------------- /view/base/web/js/react-dom.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ReactDOM v15.3.2 3 | * 4 | * Copyright 2013-present, Facebook, Inc. 5 | * All rights reserved. 6 | * 7 | * This source code is licensed under the BSD-style license found in the 8 | * LICENSE file in the root directory of this source tree. An additional grant 9 | * of patent rights can be found in the PATENTS file in the same directory. 10 | * 11 | */ 12 | // Based off https://github.com/ForbesLindesay/umd/blob/master/template.js 13 | ;(function(f) { 14 | // CommonJS 15 | if (typeof exports === "object" && typeof module !== "undefined") { 16 | module.exports = f(require('react')); 17 | 18 | // RequireJS 19 | } else if (typeof define === "function" && define.amd) { 20 | define(['react'], f); 21 | 22 | // 49 | */ 50 | ?> 51 | 52 | -------------------------------------------------------------------------------- /view/frontend/templates/product/view/gallery.phtml: -------------------------------------------------------------------------------- 1 | 14 | 15 | getProduct(); 17 | $images = $block->getGalleryImages()->getItems(); 18 | $mainImage = current(array_filter($images, function ($img) use ($block) { 19 | return $block->isMainImage($img); 20 | })); 21 | 22 | if (!empty($images) && empty($mainImage)) { 23 | $mainImage = $block->getGalleryImages()->getFirstItem(); 24 | } 25 | 26 | // Function to encode an image as Base64 27 | function imageToBase64($imagePath) 28 | { 29 | if (file_exists($imagePath)) { 30 | $imageData = file_get_contents($imagePath); 31 | $base64 = base64_encode($imageData); 32 | $mimeType = mime_content_type($imagePath); // Get MIME type 33 | return "data:$mimeType;base64,$base64"; 34 | } 35 | return ""; 36 | } 37 | 38 | 39 | $helper = $block->getData('imageHelper'); 40 | $mainImageData = $mainImage ? 41 | $mainImage->getData('medium_image_url') : 42 | $helper->getDefaultPlaceholderUrl('image'); 43 | $imageWidth = $block->getImageAttribute('product_page_image_medium', 'width'); 44 | $imageHeight = $block->getImageAttribute('product_page_image_medium', 'height'); 45 | $mobileImage = $helper->init($product, 'product_page_image_small')->resize(365, 260)->keepAspectRatio(true)->setQuality(85); 46 | $mobileImageUrl = $mobileImage->getUrl(); 47 | 48 | if (true) { 49 | $mobileImagePath = BP . '/pub/' . parse_url($mobileImageUrl, PHP_URL_PATH); 50 | $mobileImageUrl = imageToBase64($mobileImagePath); 51 | } 52 | //dd($mobileImagePath); 53 | $gallaryData = $block->getGalleryImagesJson(); 54 | 55 | $images = json_decode($gallaryData, true); 56 | //dump($images); 57 | ?> 58 | 59 | 60 | 84 | 85 | 86 | 90 | 91 | 162 | 163 | 236 | 264 | 265 | -------------------------------------------------------------------------------- /view/frontend/templates/product/view/renderer.phtml: -------------------------------------------------------------------------------- 1 | 7 | getConfigurableViewModel() 11 | ?> 12 | 13 | json_decode($block->getJsonConfig(), true), 17 | "jsonSwatchConfig" => json_decode($block->getJsonSwatchConfig(), true), 18 | "mediaCallback" => json_decode($block->escapeJs($block->escapeUrl($block->getMediaCallback())), true), 19 | "jsonSwatchImageSizeConfig" => json_decode($block->getJsonSwatchSizeConfig(), true), 20 | "showTooltip" => json_decode($block->escapeJs($configurableViewModel->getShowSwatchTooltip()), true), 21 | ]; 22 | 23 | $configurableImages = $swatchData["jsonConfig"]['images']; 24 | $swatchConfig = $swatchData["jsonConfig"]; 25 | $swatchAttributes = $swatchData["jsonSwatchConfig"]; 26 | 27 | $optionToImage = []; 28 | $imageIndex = $swatchData["jsonConfig"]['index']; 29 | foreach ($imageIndex as $imageId => $options) { 30 | foreach ($options as $option) { 31 | $optionToImage[$option] = $imageId; 32 | } 33 | } 34 | 35 | //dd($optionToImage); 36 | $configurableGallary = []; 37 | 38 | foreach ($configurableImages as $productId => $images) { 39 | $galleryHtml = ''; 67 | 68 | // Store the generated HTML in the array 69 | $configurableGallery[$productId] = $galleryHtml; 70 | } 71 | 72 | ?> 73 | 76 | 77 |
78 | 79 | 80 |
81 |
82 |
83 | 84 | 85 | $swatchData): ?> 86 |
89 | 90 | escapeHtml($swatchData['label'])?> 92 | 93 | 94 |
95 | $optionData): ?> 96 | 100 | 101 |
107 | escapeHtml($optionData['value']) : ''?> 108 |
109 | 110 |
111 | 112 |
113 | 114 | 115 |
116 |
117 |
118 | 119 | 210 | -------------------------------------------------------------------------------- /view/frontend/templates/react-footer-css.phtml: -------------------------------------------------------------------------------- 1 | registry->registry('current_product'); 3 | ?> 4 | 5 | 6 | 7 | 8 | 9 | 288 | -------------------------------------------------------------------------------- /view/frontend/templates/react-footer.phtml: -------------------------------------------------------------------------------- 1 | 7 | 8 | removeAdobeJSJunk()) { 10 | if(!$inlineJs) { 11 | ?> 12 | 13 | getInlineJs('react-core.js'); 16 | } 17 | } 18 | ?> 19 | 20 | -------------------------------------------------------------------------------- /view/frontend/templates/react-header-css.phtml: -------------------------------------------------------------------------------- 1 | 2 | 59 | 156 | -------------------------------------------------------------------------------- /view/frontend/templates/react-header.phtml: -------------------------------------------------------------------------------- 1 | registry->registry('current_product') ? true : false; 3 | $criticalCSSHTML = boolval($this->config->getValue('react_vue_config/css/critical')); 4 | 5 | if ($criticalCSSHTML || isset($_GET['css-html'])) { 6 | $criticalCSSHTML = true; 7 | } 8 | if ($isProductPage && $criticalCSSHTML) { 9 | $css = @file_get_contents(BP . '/pub/static/product-critical-m.css'); 10 | ?> 11 | 14 | 16 | 34 | 35 | 36 | removeAdobeJSJunk()) { 38 | ?> 39 | 49 | 52 | 53 | -------------------------------------------------------------------------------- /view/frontend/templates/topmenu-account.phtml: -------------------------------------------------------------------------------- 1 | 20 | -------------------------------------------------------------------------------- /view/frontend/web/js/cash.js: -------------------------------------------------------------------------------- 1 | //CAsh v1.0.0 2 | "use strict";!function(t,e){"function"==typeof define&&define.amd?define(e):"undefined"!=typeof exports?module.exports=e():t.cash=t.$=e()}(this,function(){function t(e,n){return new t.fn.init(e,n)}function e(t){var e=e||s.createDocumentFragment(),n=n||e.appendChild(s.createElement("div"));return n.innerHTML=t,n}function n(t,e){return parseInt(u.getComputedStyle(t[0],null)[e],10)}function i(){function t(t){var e=(Math.random().toString(16)+"000000000").substr(2,8);return t?"-"+e.substr(0,4)+"-"+e.substr(4,4):e}return t()+t(!0)+t(!0)+t()}function r(e,n,r){var s=t(e).data("cshid")||i();t(e).data("cshid",s),s in p||(p[s]={}),n in p[s]||(p[s][n]=[]),p[s][n].push(r)}var s=document,u=window,c=Array.prototype,a=c.slice,h=c.filter,o=/^#[\w-]*$/,f=/^\.[\w-]*$/,l=/^[\w-]*$/,d=t.fn=t.prototype={cash:!0,length:0};d.init=function(e,n){var i,r,u=[];if(!e)return this;if(this.length=1,"string"!=typeof e)return e.cash?e:(this[0]=e,this);if("<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3)u=t.parseHTML(e);else{if(i=o.test(e),r=e.slice(1),!n&&i)return this[0]=s.getElementById(r),this;n=t(n)[0]||s,u=a.call(l.test(r)?f.test(e)?s.getElementsByClassName(r):s.getElementsByTagName(e):n.querySelectorAll(e))}return this.length=0,t.merge(this,u),this},d.init.prototype=d,t.each=function(t,e){for(var n=t.length,i=0;n>i;i++)e.call(t[i],t[i],i,t)},t.extend=d.extend=function(t,e){var n;e||(e=t,t=this);for(n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t},t.matches=function(t,e){return(t.matches||t.matchesSelector||t.msMatchesSelector||t.mozMatchesSelector||t.webkitMatchesSelector||t.oMatchesSelector).call(t,e)},t.merge=function(t,e){for(var n=+e.length,i=t.length,r=0;n>r;i++,r++)t[i]=e[r];return t.length=i,t},t.parseHTML=function(t){var n=/^<(\w+)\s*\/?>(?:<\/\1>|)$/.exec(t);return n?[s.createElement(n[1])]:(n=e(t),a.call(n.childNodes))},t.unique=function(e){return t.merge(t(),a.call(e).filter(function(t,e,n){return n.indexOf(t)===e}))};var m=/\S+/g;d.extend({addClass:function(t){var e,n,i=t.match(m);return this.each(function(t){if(n=i.length,t.classList)for(;n--;)t.classList.add(i[n]);else for(;n--;)e=" "+t.className+" ",-1===e.indexOf(" "+i[n]+" ")&&(t.className+=" "+i[n])}),this},attr:function(t,e){return e?(this.each(function(n){return n.setAttribute(t,e)}),this):this[0].getAttribute(t)},hasClass:function(t){return this[0].classList?this[0].classList.contains(t):-1!==this[0].className.indexOf(t)},prop:function(t){return this[0][t]},removeAttr:function(t){return this.each(function(e){return e.removeAttribute(t)}),this},removeClass:function(t){var e,n,i=t.match(m);return this.each(function(t){if(e=i.length,t.classList)for(;e--;)t.classList.remove(i[e]);else{for(n=" "+t.className+" ";e--;)n=n.replace(" "+i[e]+" "," ");t.className=n.trim()}}),this}}),d.extend({add:function(){var e,n=a.call(this),i=0;for(e=arguments.length;e>i;i++)n=n.concat(a.call(t(arguments[i])));return t.unique(n)},each:function(e){t.each(this,e)},eq:function(e){return t(this[e])},filter:function(e){return"string"==typeof e?h.call(this,function(n){return t.matches(n,e)}):h.call(this,e)},first:function(){return t(this[0])},get:function(t){return this[t]},index:function(e){return e?a.call(t(e).children()).indexOf(this[0]):a.call(t(this[0]).parent().children()).indexOf(this[0])},last:function(){return t(this[this.length-1])}}),d.extend({css:function(t,e){return"object"!=typeof t?e?(this.each(function(n){return n.style[t]=e}),this):u.getComputedStyle(this[0],null)[t]:void this.each(function(e){for(var n in t)t.hasOwnProperty(n)&&(e.style[n]=t[n])})}}),d.extend({data:function(e,n){return n?(this.each(function(i){i.dataset?i.dataset[e]=n:t(i).attr("data-"+e,n)}),this):this[0].dataset?this[0].dataset[e]:t(this[0]).attr("data-"+e)},removeData:function(e){return this.each(function(n){n.dataset?delete n.dataset[e]:t(n).removeAttr("data-"+e)}),this}}),d.extend({height:function(){return this[0].getBoundingClientRect().height},innerWidth:function(){return this[0].clientWidth},innerHeight:function(){return this[0].clientHeight},outerWidth:function(t){return t===!0?this[0].offsetWidth+(n(this,"margin-left")||n(this,"marginLeft")||0)+(n(this,"margin-right")||n(this,"marginRight")||0):this[0].offsetWidth},outerHeight:function(t){return t===!0?this[0].offsetHeight+(n(this,"margin-top")||n(this,"marginTop")||0)+(n(this,"margin-bottom")||n(this,"marginBottom")||0):this[0].offsetHeight},width:function(){return this[0].getBoundingClientRect().width}});var p={};d.extend({off:function(e,n){return this.each(function(i){if(n)i.removeEventListener(e,n);else for(var r in p[t(i).data("cshid")][e])i.removeEventListener(e,p[t(i).data("cshid")][e][r])}),this},on:function(e,n,i){return"function"==typeof n?(i=n,this.each(function(n){r(t(n),e,i),n.addEventListener(e,i)}),this):(this.each(function(s){function u(e){var r=e.target;if(t.matches(r,n))i.call(r);else{for(;!t.matches(r,n);){if(r===s)return r=!1;r=r.parentNode}r&&i.call(r)}}r(t(s),e,u),s.addEventListener(e,u)}),this)},ready:function(t){this[0].addEventListener("DOMContentLoaded",t)},trigger:function(t){var e=s.createEvent("HTMLEvents");return e.initEvent(t,!0,!1),this.each(function(t){return t.dispatchEvent(e)}),this}});var g=encodeURIComponent;return d.extend({serialize:function(){var t,e,n,i=this[0],r="";for(e=i.elements.length-1;e>=0;e--)if(t=i.elements[e],t.name&&"file"!==t.type&&"reset"!==t.type)if("select-multiple"===t.type)for(n=i.elements[e].options.length-1;n>=0;n--)t.options[n].selected&&(r+="&"+t.name+"="+g(t.options[n].value).replace(/%20/g,"+"));else"submit"!==t.type&&"button"!==t.type&&(r+="&"+t.name+"="+g(t.value).replace(/%20/g,"+"));return r.substr(1)},val:function(t){return void 0===t?this[0].value:(this.each(function(e){return e.value=t}),this)}}),d.extend({append:function(e){return this[0].appendChild(t(e)[0]),this},appendTo:function(e){return t(e)[0].appendChild(this[0]),this},clone:function(){return t(this[0].cloneNode(!0))},empty:function(){return this.each(function(t){return t.innerHTML=""}),this},html:function(e){var n;return"undefined"===e?this[0].innerHTML:(n="object"==typeof e?t(e)[0].outerHTML:e,this.each(function(t){return t.innerHTML=""+n}),this)},insertAfter:function(e){return t(e)[0].insertAdjacentHTML("afterend",this[0].outerHTML),this},insertBefore:function(e){return t(e)[0].insertAdjacentHTML("beforebegin",this[0].outerHTML),this},prepend:function(e){return t(this)[0].insertAdjacentHTML("afterBegin",t(e)[0].outerHTML),this},prependTo:function(e){return t(e)[0].insertAdjacentHTML("afterBegin",this[0].outerHTML),this},remove:function(){this.each(function(t){return t.parentNode.removeChild(t)})},text:function(t){return t?(this.each(function(e){return e.textContent=t}),this):this[0].textContent}}),d.extend({children:function(e){return e?t(this[0].children).filter(function(n){return t.matches(n,e)}):t.fn.extend(this[0].children,t.fn)},closest:function(e){return!e||t.matches(this[0],e)?this:this.parent().closest(e)},is:function(e){return e?e.cash?this[0]===e[0]:"string"==typeof e?t.matches(this[0],e):!1:!1},find:function(e){return t.fn.extend(this[0].querySelectorAll(e),t.fn)},has:function(e){return h.call(this,function(n){return 0!==t(n).find(e).length})},next:function(){return t(this[0].nextElementSibling)},not:function(e){return h.call(this,function(n){return!t.matches(n,e)})},parent:function(){var e=c.map.call(this,function(t){return t.parentElement||s.body.parentNode});return t.unique(e)},parents:function(e){var n,i=[],r=0;return this.each(function(u){for(n=u;n!==s.body.parentNode;)n=n.parentElement,(!e||e&&t.matches(n,e))&&(i[r]=n,r++)}),t.unique(i)},prev:function(){return t(this[0].previousElementSibling)},siblings:function(){var t=this.parent().children(),e=this[0];return h.call(t,function(t){return t!==e})}}),t}); -------------------------------------------------------------------------------- /view/frontend/web/js/react-core.js: -------------------------------------------------------------------------------- 1 | var mage = (() => { 2 | var loaded = false; 3 | var localStorage = window.localStorage; 4 | var doc = document; 5 | window.addEventListener('load', () => { 6 | loaded = true; 7 | }); 8 | 9 | function isLoaded(){ 10 | return loaded; 11 | } 12 | 13 | function getCookie(name) { 14 | let match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)')); 15 | return match ? decodeURIComponent(match[2]) : null; 16 | } 17 | 18 | function setCookie(name, value, days = 7, path = "/") { 19 | let expires = ""; 20 | if (days) { 21 | let date = new Date(); 22 | date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); 23 | expires = "; expires=" + date.toUTCString(); 24 | } 25 | document.cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}${expires}; path=${path}`; 26 | } 27 | 28 | function displayMessages() { 29 | const cookieMessages = getCookie('mage-messages'); // Ensure the cookie name matches Magento's setup 30 | if (!cookieMessages) return; 31 | 32 | try { 33 | let messages = JSON.parse(cookieMessages); 34 | if (!Array.isArray(messages) || messages.length === 0) return; 35 | const messageContainer = document.querySelector('.page.messages'); 36 | 37 | messageContainer.innerHTML = ""; // Clear existing messages 38 | 39 | messages.forEach(message => { 40 | let messageDiv = document.createElement("div"); 41 | messageContainer.style.display = "block"; 42 | messageDiv.className = `message-${message.type} ${message.type} message`; 43 | messageDiv.setAttribute("data-ui-id", `message-${message.type}`); 44 | messageDiv.innerHTML = `
${message.text}
`; 45 | 46 | messageContainer.appendChild(messageDiv); 47 | }); 48 | document.cookie = "mage-messages=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; 49 | // Optionally, clear messages after 5 seconds 50 | setTimeout(() => { 51 | const messageContainer = document.querySelector('.page.messages'); 52 | const messageDiv = document.querySelector("message"); 53 | messageContainer.innerHTML = ""; 54 | messageContainer.style.display = "none"; 55 | }, 10000); 56 | } catch (error) { 57 | console.error("Error parsing messages from cookie:", error); 58 | } 59 | } 60 | 61 | const defaultSectionData = [ 62 | "messages", "customer", 63 | "compare-products", 64 | "last-ordered-items", 65 | "cart", "wishlist", 66 | "loggedAsCustomer" 67 | ]; 68 | 69 | async function loadSectionData(sections=defaultSectionData) { 70 | try { 71 | let valid = false; 72 | let data = null; 73 | const privateContentVersionCokies = getCookie('private_content_version'); 74 | const privateContentVersionLocal = localStorage.getItem('private_content_version'); 75 | const url = BASE_URL+`customer/section/load/?sections=${encodeURIComponent(sections.join(','))}`; 76 | 77 | if(privateContentVersionCokies && privateContentVersionLocal && 78 | privateContentVersionCokies === privateContentVersionLocal) { 79 | const ttl = new Date(localStorage.getItem('mage-cache-timeout')); 80 | if (ttl < new Date()) { 81 | valid = false 82 | localStorage.removeItem('mage-cache-storage'); 83 | localStorage.removeItem('mage-cache-timeout'); 84 | localStorage.removeItem('private_content_version'); 85 | } else { 86 | valid = true 87 | data = JSON.parse(localStorage.getItem('mage-cache-storage')); 88 | } 89 | } 90 | if (!valid){ 91 | const request = new Request(url, 92 | { 93 | method: 'GET', 94 | cache: 'no-store', 95 | headers: { 96 | 'Content-Type': 'application/json', 97 | 'X-Requested-With': 'XMLHttpRequest' 98 | } 99 | } 100 | ); 101 | const response = await fetch(request); 102 | 103 | if (!response.ok) { 104 | throw new Error(`Failed to fetch data: ${response.status} ${response.statusText}`); 105 | } 106 | 107 | data = await response.json(); 108 | localStorage.setItem('mage-cache-storage', JSON.stringify(data)); 109 | localStorage.setItem('mage-cache-timeout', new Date(Date.now() + (3600 * 1000)).toISOString()); 110 | const version = getCookie('private_content_version'); 111 | localStorage.setItem('private_content_version', version); 112 | 113 | setCookie( 114 | 'section_data_ids', 115 | JSON.stringify( 116 | Object.keys(data).reduce((ids, key) => { 117 | ids[key] = data[key]['data_id']; 118 | return ids; 119 | }, {}) 120 | ), 121 | false, 122 | true 123 | ); 124 | } 125 | if(typeof data === null){ 126 | console.log("Private Data issue"); 127 | } 128 | 129 | //console.log("Fetched private content:", data); 130 | updateCartData(data.cart); 131 | updateCustomer(data.customer); 132 | updateFormKeys(); 133 | return data; 134 | } catch (error) { 135 | console.error("Error fetching private content:", error); 136 | return null; 137 | } 138 | } 139 | 140 | function getLocalStorage() { 141 | if (!window.localStorage) { 142 | console.warn('Local Storage is issue'); 143 | return false; 144 | } 145 | return window.localStorage 146 | } 147 | 148 | function updateCustomer(data) { 149 | let isLoggedIn = false; 150 | if (data) { 151 | const name = data.firstname; 152 | 153 | const customerName = document.querySelector('.customer-name'); 154 | if (customerName && name && name !== '') { 155 | isLoggedIn = true; 156 | customerName.innerHTML += 'Welcome, ' + name + ''; 157 | const customerMenu = document.querySelector(".customer-menu"); 158 | document.querySelectorAll('.link.logout').forEach(elem => (elem.style.display="none")); 159 | document.querySelectorAll('.link.login').forEach(elem => (elem.style.display="block")); 160 | 161 | customerName.addEventListener("click", function (event) { 162 | event.preventDefault(); 163 | if (customerMenu) { 164 | customerMenu.style.display = customerMenu.style.display === "block" ? "none" : "block"; 165 | } 166 | }); 167 | } 168 | } 169 | if (!isLoggedIn){ 170 | document.querySelectorAll('.link.logout').forEach(elem => (elem.style.display="block")); 171 | document.querySelectorAll('.link.login').forEach(elem => (elem.style.display="none")); 172 | } 173 | } 174 | 175 | function updateCartData(data) { 176 | if (data) { 177 | const summaryCount = data.summary_count; // Number of items 178 | if (summaryCount !== 0 && summaryCount !== null){ 179 | const subtotalAmount = parseFloat(data.subtotalAmount); // Subtotal amount 180 | // Updatethe cart counter 181 | const subtotalElement = document.querySelector('.counter-number'); 182 | if (subtotalElement) { 183 | const cartElement = document.querySelector('.counter.qty.empty'); 184 | if (cartElement) { 185 | cartElement.classList.remove('empty'); 186 | } 187 | subtotalElement.innerText = subtotalAmount ? `$${subtotalAmount.toFixed(2)}` : ''; 188 | } 189 | } 190 | } 191 | } 192 | 193 | getFormKey = function () { 194 | let formKey = getCookie('form_key'); 195 | if (!formKey) { 196 | formKey = crypto.randomUUID(); // More secure than random strings 197 | setCookie('form_key', formKey, 86400); // Set for 1 day 198 | } 199 | return formKey; 200 | }; 201 | 202 | updateFormKeys = function () { 203 | const formKey = getFormKey().replace(/-/g, '\\u002D'); 204 | document.querySelectorAll('input[name="form_key"]').forEach(input => input.value = formKey); 205 | }; 206 | 207 | onLoad = (callback, ...args) => { 208 | window.addEventListener("load", () => callback(...args)); 209 | }; 210 | 211 | onDOM = (callback, ...args) => { 212 | document.addEventListener("DOMContentLoaded", () => callback(...args)); 213 | } 214 | 215 | const checkInterval = 150; 216 | const loadTimeout = 3000 217 | 218 | // Function to run code only after the page has loaded, with optional arguments 219 | runAfterLoad = (interval = checkInterval, callback, ...args) => { 220 | let counter = 5; 221 | const checkLoad = setInterval(() => { 222 | if (isLoaded()) { 223 | clearInterval(checkLoad); 224 | callback(...args); 225 | } 226 | counter++; 227 | }, interval); 228 | } 229 | 230 | loadScript = (src) => { 231 | return new Promise((resolve, reject) => { 232 | const script = document.createElement("script"); 233 | script.src = src; 234 | script.async = true; 235 | script.onload = () => resolve(src); 236 | script.onerror = () => reject(new Error(`Failed to load script: ${src}`)); 237 | document.head.appendChild(script); 238 | }); 239 | } 240 | 241 | getUenc = () => { 242 | return window.curentUenc; 243 | } 244 | 245 | async function addToCompare(productId) { 246 | try { 247 | const formKey = getFormKey(); 248 | const postUrl = BASE_URL + `catalog/product_compare/add/`; 249 | const bodyData = new URLSearchParams({ 250 | form_key: formKey, 251 | product: productId, 252 | uenc: getUenc() 253 | }); 254 | 255 | const request = new Request(postUrl, 256 | { 257 | method: 'POST', 258 | cache: 'no-store', 259 | headers: { 260 | "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", 261 | }, 262 | body: bodyData, 263 | mode: "cors", 264 | credentials: "include" 265 | } 266 | ); 267 | 268 | const response = await fetch(request); 269 | 270 | if (response.redirected) { 271 | window.location.href = response.url; 272 | } 273 | loadSectionData(); 274 | } catch (error) { 275 | if (typeof window.dispatchMessages !== "undefined") { 276 | alert(`❌ Error: ${error.message || "An unexpected error occurred."}`); 277 | } 278 | } 279 | } 280 | 281 | async function addToWishlist(productId) { 282 | try { 283 | const formKey = getFormKey(); 284 | const postUrl = BASE_URL + `wishlist/index/add/`; 285 | const uenc = getUenc(); 286 | 287 | const response = await fetch(postUrl, { 288 | method: "POST", 289 | headers: { 290 | "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", 291 | }, 292 | body: new URLSearchParams({ 293 | form_key: formKey, 294 | product: productId, 295 | uenc: uenc, 296 | }), 297 | mode: "cors", 298 | credentials: "include", 299 | }); 300 | 301 | if (response.redirected) { 302 | window.location.href = response.url; 303 | return; 304 | } 305 | 306 | if (!response.ok) { 307 | alert("⚠️ Could not add item to wishlist."); 308 | return; 309 | } 310 | 311 | const data = await response.json(); 312 | 313 | alert( 314 | data.success 315 | ? "✅ Product has been added to your Wish List." 316 | : `❌ ${data.error_message || "Something went wrong!"}` 317 | ); 318 | 319 | // Trigger customer section reload 320 | loadSectionData() 321 | } catch (error) { 322 | alert(`❌ Error: ${error.message || "An unexpected error occurred."}`); 323 | } 324 | } 325 | 326 | return { 327 | displayMessages, 328 | loadSectionData, 329 | getLocalStorage, 330 | updateCartData, 331 | updateFormKeys, 332 | addToWishlist, 333 | localStorage, 334 | addToCompare, 335 | getFormKey, 336 | isLoaded, 337 | getUenc, 338 | onLoad, 339 | onDOM, 340 | doc 341 | }; 342 | })(); 343 | 344 | mage.loadSectionData(); 345 | 346 | mage.onDOM( function () { 347 | const navToggle = document.querySelector(".action.nav-toggle"); 348 | const navMenu = document.querySelector(".nav-sections"); 349 | // Toggle menu on click 350 | navToggle.addEventListener("click", function () { 351 | navMenu.classList.toggle("active"); 352 | }); 353 | // Close menu when clicking outside 354 | document.addEventListener("click", function (event) { 355 | if (!navMenu.contains(event.target) && event.target !== navToggle) { 356 | navMenu.classList.remove("active"); 357 | } 358 | }); 359 | }); 360 | 361 | mage.onDOM( function () { 362 | const filterSections = document.querySelectorAll(".filter-options-item"); 363 | filterSections.forEach(section => { 364 | const title = section.querySelector(".filter-options-title"); 365 | title.addEventListener("click", function () { 366 | // Toggle active class 367 | section.classList.toggle("active"); 368 | }); 369 | }); 370 | }); 371 | 372 | mage.onDOM( function () { 373 | mage.displayMessages(); 374 | setInterval(() => { 375 | mage.displayMessages();; 376 | }, 5000); 377 | }); 378 | 379 | mage.onDOM( function () { 380 | document.querySelectorAll(".block.related li.item.product.product-item").forEach(productItem => { 381 | productItem.style.display = ""; 382 | }); 383 | } 384 | ); 385 | 386 | if(window.productType === "simple") { 387 | const button = document.getElementById("product-addtocart-button"); 388 | if (button) { 389 | button.removeAttribute("disabled"); 390 | } 391 | } 392 | 393 | if(window.controller === "category"){ 394 | const buttons = document.querySelectorAll(".action.tocart.primary"); 395 | if (buttons) { 396 | buttons.forEach(btn => { 397 | btn.removeAttribute("disabled"); 398 | }); 399 | }} 400 | 401 | window.onload = () => { 402 | const sorter = document.getElementById("sorter"); 403 | if(sorter){ 404 | sorter.addEventListener("change", function () { 405 | const selectedValue = sorter.value; 406 | const currentUrl = new URL(window.location.href); 407 | currentUrl.searchParams.set("product_list_order", selectedValue); 408 | window.location.href = currentUrl.toString(); 409 | }); 410 | } 411 | }; 412 | 413 | mage.onDOM( function () { 414 | const limiterSelect = document.getElementById("limiter"); 415 | 416 | if (limiterSelect) { 417 | limiterSelect.addEventListener("change", function () { 418 | const selectedValue = this.value; 419 | const currentUrl = new URL(window.location.href); 420 | 421 | // Update the 'limit' query parameter 422 | currentUrl.searchParams.set("product_list_limit", selectedValue); 423 | 424 | // Redirect to the updated URL 425 | window.location.href = currentUrl.toString(); 426 | }); 427 | } 428 | }); 429 | 430 | mage.onDOM( function () { 431 | const sortDirectionLink = document.querySelector("[data-role='direction-switcher']"); 432 | 433 | if (sortDirectionLink) { 434 | sortDirectionLink.addEventListener("click", function (event) { 435 | event.preventDefault(); // Prevent the default link behavior 436 | 437 | const currentUrl = new URL(window.location.href); 438 | const currentDirection = currentUrl.searchParams.get("dir") || "asc"; // Default to ascending 439 | const newDirection = currentDirection === "asc" ? "desc" : "asc"; // Toggle between asc and desc 440 | 441 | // Update the 'dir' query parameter 442 | currentUrl.searchParams.set("product_list_dir", newDirection); 443 | 444 | // Redirect to the updated URL 445 | window.location.href = currentUrl.toString(); 446 | }); 447 | } 448 | }); 449 | 450 | mage.onDOM(function () { 451 | function toggleSection(event) { 452 | event.preventDefault(); 453 | 454 | const targetId = this.getAttribute("href"); 455 | const contentElements = document.querySelectorAll('.section-item-content.nav-sections-item-content'); 456 | contentElements.forEach(content => { 457 | content.style.display = "none"; 458 | }); 459 | 460 | document.querySelectorAll(".section-item-title").forEach(title => { 461 | title.classList.remove("active"); 462 | }); 463 | 464 | document.getElementById(targetId.substring(1)).style.display = 'block'; 465 | 466 | this.parentElement.setAttribute("aria-hidden", "true"); 467 | this.parentElement.classList.add("active"); 468 | 469 | } 470 | 471 | // Attach event listeners to menu and account links 472 | document.querySelectorAll("a.nav-sections-item-switch").forEach(link => { 473 | link.addEventListener("click", toggleSection); 474 | }); 475 | var n = 0; 476 | document.querySelectorAll(".section-item-content.nav-sections-item-content").forEach(menu => { 477 | if(menu.id !== "store.menu"){ 478 | menu.style.display = "none"; 479 | } 480 | }); 481 | 482 | // Select all parent menu items 483 | document.querySelectorAll("level0.category-item.parent > a").forEach(menuItem => { 484 | menuItem.addEventListener("click", function (event) { 485 | event.preventDefault(); // Prevent the default link behavior 486 | 487 | let submenu = this.nextElementSibling; // Get the submenu 488 | if (submenu) { 489 | submenu.style.display = submenu.style.display === "block" ? "none" : "block"; 490 | } 491 | }); 492 | }); 493 | }); 494 | 495 | mage.onDOM(() => { 496 | // Select the search button and the input field 497 | const searchButton = document.querySelector('[data-role="minisearch-label"]'); 498 | const searchBlock = document.querySelector('form.minisearch .control'); 499 | 500 | if (searchButton && searchBlock) { 501 | searchButton.addEventListener('click', function() { 502 | // Toggle the display property 503 | if (searchBlock.style.display === 'block') { 504 | searchBlock.style.display = 'none'; 505 | } else { 506 | searchBlock.style.display = 'block'; 507 | } 508 | }); 509 | } 510 | 511 | const shopByTitle = document.querySelector('strong[data-role="title"]'); 512 | const filterOptions = document.querySelector('.filter-options'); 513 | 514 | if (shopByTitle && filterOptions) { 515 | shopByTitle.addEventListener("click", function () { 516 | filterOptions.style.display = 517 | filterOptions.style.display === "none" || filterOptions.style.display === "" 518 | ? "block" 519 | : "none"; 520 | }); 521 | } 522 | }); -------------------------------------------------------------------------------- /view/frontend/web/js/rum.js: -------------------------------------------------------------------------------- 1 | !function(){var e={343:function(e){"use strict";for(var t=[],n=0;n<256;++n)t[n]=(n+256).toString(16).substr(1);e.exports=function(e,n){var r=n||0,i=t;return[i[e[r++]],i[e[r++]],i[e[r++]],i[e[r++]],"-",i[e[r++]],i[e[r++]],"-",i[e[r++]],i[e[r++]],"-",i[e[r++]],i[e[r++]],"-",i[e[r++]],i[e[r++]],i[e[r++]],i[e[r++]],i[e[r++]],i[e[r++]]].join("")}},944:function(e){"use strict";var t="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof window.msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto);if(t){var n=new Uint8Array(16);e.exports=function(){return t(n),n}}else{var r=new Array(16);e.exports=function(){for(var e,t=0;t<16;t++)0==(3&t)&&(e=4294967296*Math.random()),r[t]=e>>>((3&t)<<3)&255;return r}}},508:function(e,t,n){"use strict";var r=n(944),i=n(343);e.exports=function(e,t,n){var o=t&&n||0;"string"==typeof e&&(t="binary"===e?new Array(16):null,e=null);var a=(e=e||{}).random||(e.rng||r)();if(a[6]=15&a[6]|64,a[8]=63&a[8]|128,t)for(var c=0;c<16;++c)t[o+c]=a[c];return t||i(a)}},168:function(e,t,n){"use strict";var r=this&&this.__assign||function(){return r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&(t+=r)}return t}function t(e,t){for(var n in e){var r=e[n];void 0!==t&&("number"!=typeof r&&"string"!=typeof r||(t[n]=r))}}!function(){var n,u,s=window.performance||window.webkitPerformance||window.msPerformance||window.mozPerformance,f="data-cf-beacon",d=document.currentScript||("function"==typeof document.querySelector?document.querySelector("script[".concat(f,"]")):void 0),l=c(),v=[],p=window.__cfBeacon?window.__cfBeacon:{};if(!p||"single"!==p.load){if(d){var m=d.getAttribute(f);if(m)try{p=r(r({},p),JSON.parse(m))}catch(e){}else{var g=d.getAttribute("src");if(g&&"function"==typeof URLSearchParams){var y=new URLSearchParams(g.replace(/^[^\?]+\??/,"")),h=y.get("token");h&&(p.token=h);var T=y.get("spa");p.spa=null===T||"true"===T}}p&&"multi"!==p.load&&(p.load="single"),window.__cfBeacon=p}if(s&&p&&p.token){var w,S,b=!1;document.addEventListener("visibilitychange",(function(){if("hidden"===document.visibilityState){if(L&&A()){var t=e();(null==w?void 0:w.url)==t&&(null==w?void 0:w.triggered)||P(),_(t)}!b&&w&&(b=!0,B())}else"visible"===document.visibilityState&&(new Date).getTime()}));var E={};"function"==typeof PerformanceObserver&&((0,a.onLCP)(x),(0,a.onFID)(x),(0,a.onFCP)(x),(0,a.onINP)(x),(0,a.onTTFB)(x),PerformanceObserver.supportedEntryTypes&&PerformanceObserver.supportedEntryTypes.includes("layout-shift")&&(0,a.onCLS)(x));var L=p&&(void 0===p.spa||!0===p.spa),C=p.send&&p.send.to?p.send.to:void 0===p.version?"https://cloudflareinsights.com/cdn-cgi/rum":null,P=function(r){var a=function(r){var o,a,c=s.timing,u=s.memory,f=r||e(),d={memory:{},timings:{},resources:[],referrer:(o=document.referrer||"",a=v[v.length-1],L&&w&&a?a.url:o),eventType:i.EventType.Load,firstPaint:0,firstContentfulPaint:0,startTime:F(),versions:{fl:p?p.version:"",js:"2024.6.1",timings:1},pageloadId:l,location:f,nt:S,serverTimings:I()};if(null==n){if("function"==typeof s.getEntriesByType){var m=s.getEntriesByType("navigation");m&&Array.isArray(m)&&m.length>0&&(d.timingsV2={},d.versions.timings=2,d.dt=m[0].deliveryType,delete d.timings,t(m[0],d.timingsV2))}1===d.versions.timings&&t(c,d.timings),t(u,d.memory)}else O(d);return d.firstPaint=k("first-paint"),d.firstContentfulPaint=k("first-contentful-paint"),p&&(p.icTag&&(d.icTag=p.icTag),d.siteToken=p.token),void 0!==n&&(delete d.timings,delete d.memory),d}(r);a&&p&&(a.resources=[],p&&((0,o.sendObjectBeacon)("",a,(function(){}),!1,C),void 0!==p.forward&&void 0!==p.forward.url&&(0,o.sendObjectBeacon)("",a,(function(){}),!1,p.forward.url)))},B=function(){var t=function(){var t=s.getEntriesByType("navigation")[0],n="";try{n="function"==typeof s.getEntriesByType?new URL(null==t?void 0:t.name).pathname:u?new URL(u).pathname:window.location.pathname}catch(e){}var r={referrer:document.referrer||"",eventType:i.EventType.WebVitalsV2,versions:{js:"2024.6.1"},pageloadId:l,location:e(),landingPath:n,startTime:F(),nt:S,serverTimings:I()};return p&&(p.version&&(r.versions.fl=p.version),p.icTag&&(r.icTag=p.icTag),r.siteToken=p.token),E&&["lcp","fid","cls","fcp","ttfb","inp"].forEach((function(e){r[e]={value:-1,path:void 0},E[e]&&void 0!==E[e].value&&(r[e]=E[e])})),O(r),r}();p&&(0,o.sendObjectBeacon)("",t,(function(){}),!0,C)},R=function(){var t=window.__cfRl&&window.__cfRl.done||window.__cfQR&&window.__cfQR.done;t?t.then(P):P(),w={id:l,url:e(),ts:(new Date).getTime(),triggered:!0}};"complete"===window.document.readyState?R():window.addEventListener("load",(function(){window.setTimeout(R)}));var A=function(){return L&&0===v.filter((function(e){return e.id===l})).length},_=function(e){v.push({id:l,url:e,ts:(new Date).getTime()}),v.length>3&&v.shift()};L&&(u=e(),function(t){var r=t.pushState;if(r){var i=function(){l=c()};t.pushState=function(o,a,c){n=e(c);var u=e(),s=!0;return n==u&&(s=!1),s&&(A()&&((null==w?void 0:w.url)==u&&(null==w?void 0:w.triggered)||P(u),_(u)),i()),r.apply(t,[o,a,c])},window.addEventListener("popstate",(function(t){A()&&((null==w?void 0:w.url)==n&&(null==w?void 0:w.triggered)||P(n),_(n)),n=e(),i()}))}}(window.history))}}function x(e){var t,n,r,i,o,a,c,u=window.location.pathname;switch(S||(S=e.navigationType),"INP"!==e.name&&(E[e.name.toLowerCase()]={value:e.value,path:u}),e.name){case"CLS":(c=e.attribution)&&E.cls&&(E.cls.element=c.largestShiftTarget,E.cls.currentRect=null===(t=c.largestShiftSource)||void 0===t?void 0:t.currentRect,E.cls.previousRect=null===(n=c.largestShiftSource)||void 0===n?void 0:n.previousRect);break;case"FID":(c=e.attribution)&&E.fid&&(E.fid.element=c.eventTarget,E.fid.name=c.eventType);break;case"LCP":(c=e.attribution)&&E.lcp&&(E.lcp.element=c.element,E.lcp.size=null===(r=c.lcpEntry)||void 0===r?void 0:r.size,E.lcp.url=c.url,E.lcp.rld=c.resourceLoadDelay,E.lcp.rlt=c.resourceLoadTime,E.lcp.erd=c.elementRenderDelay,E.lcp.it=null===(i=c.lcpResourceEntry)||void 0===i?void 0:i.initiatorType,E.lcp.fp=null===(a=null===(o=c.lcpEntry)||void 0===o?void 0:o.element)||void 0===a?void 0:a.getAttribute("fetchpriority"));break;case"INP":(null==E.inp||Number(E.inp.value)-1&&parseInt(c[1])<81&&(a=!1)}catch(e){}if(navigator&&"function"==typeof navigator.sendBeacon&&a&&r){t.st=1;var u=JSON.stringify(t),s=navigator.sendBeacon&&navigator.sendBeacon.bind(navigator);null==s||s(o,new Blob([u],{type:"application/json"}))}else{t.st=2,u=JSON.stringify(t);var f=new XMLHttpRequest;n&&(f.onreadystatechange=function(){4==this.readyState&&204==this.status&&n()}),f.open("POST",o,!0),f.setRequestHeader("content-type","application/json"),f.send(u)}}},699:function(e,t){"use strict";var n,r;t.__esModule=!0,t.FetchPriority=t.EventType=void 0,(r=t.EventType||(t.EventType={}))[r.Load=1]="Load",r[r.Additional=2]="Additional",r[r.WebVitalsV2=3]="WebVitalsV2",(n=t.FetchPriority||(t.FetchPriority={})).High="high",n.Low="low",n.Auto="auto"},104:function(e,t){!function(e){"use strict";var t,n,r,i,o,a=function(){return window.performance&&performance.getEntriesByType&&performance.getEntriesByType("navigation")[0]},c=function(e){if("loading"===document.readyState)return"loading";var t=a();if(t){if(e(t||100)-1)return n||i;if(n=n?i+">"+n:i,r.id)break;e=r.parentNode}}catch(e){}return n},f=-1,d=function(){return f},l=function(e){addEventListener("pageshow",(function(t){t.persisted&&(f=t.timeStamp,e(t))}),!0)},v=function(){var e=a();return e&&e.activationStart||0},p=function(e,t){var n=a(),r="navigate";return d()>=0?r="back-forward-cache":n&&(document.prerendering||v()>0?r="prerender":document.wasDiscarded?r="restore":n.type&&(r=n.type.replace(/_/g,"-"))),{name:e,value:void 0===t?-1:t,rating:"good",delta:0,entries:[],id:"v3-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:r}},m=function(e,t,n){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){var r=new PerformanceObserver((function(e){Promise.resolve().then((function(){t(e.getEntries())}))}));return r.observe(Object.assign({type:e,buffered:!0},n||{})),r}}catch(e){}},g=function(e,t,n,r){var i,o;return function(a){t.value>=0&&(a||r)&&((o=t.value-(i||0))||void 0===i)&&(i=t.value,t.delta=o,t.rating=function(e,t){return e>t[1]?"poor":e>t[0]?"needs-improvement":"good"}(t.value,n),e(t))}},y=function(e){requestAnimationFrame((function(){return requestAnimationFrame((function(){return e()}))}))},h=function(e){var t=function(t){"pagehide"!==t.type&&"hidden"!==document.visibilityState||e(t)};addEventListener("visibilitychange",t,!0),addEventListener("pagehide",t,!0)},T=function(e){var t=!1;return function(n){t||(e(n),t=!0)}},w=-1,S=function(){return"hidden"!==document.visibilityState||document.prerendering?1/0:0},b=function(e){"hidden"===document.visibilityState&&w>-1&&(w="visibilitychange"===e.type?e.timeStamp:0,L())},E=function(){addEventListener("visibilitychange",b,!0),addEventListener("prerenderingchange",b,!0)},L=function(){removeEventListener("visibilitychange",b,!0),removeEventListener("prerenderingchange",b,!0)},C=function(){return w<0&&(w=S(),E(),l((function(){setTimeout((function(){w=S(),E()}),0)}))),{get firstHiddenTime(){return w}}},P=function(e){document.prerendering?addEventListener("prerenderingchange",(function(){return e()}),!0):e()},B=[1800,3e3],R=function(e,t){t=t||{},P((function(){var n,r=C(),i=p("FCP"),o=m("paint",(function(e){e.forEach((function(e){"first-contentful-paint"===e.name&&(o.disconnect(),e.startTime=0&&n1e12?new Date:performance.now())-e.timeStamp;"pointerdown"==e.type?function(e,t){var n=function(){F(e,t),i()},r=function(){i()},i=function(){removeEventListener("pointerup",n,_),removeEventListener("pointercancel",r,_)};addEventListener("pointerup",n,_),addEventListener("pointercancel",r,_)}(t,e):F(t,e)}},k=function(e){["mousedown","keydown","touchstart","pointerdown"].forEach((function(t){return e(t,O,_)}))},M=[100,300],D=function(e,r){r=r||{},P((function(){var o,a=C(),c=p("FID"),u=function(e){e.startTimet.latency){if(n)n.entries.push(e),n.latency=Math.max(n.latency,e.duration);else{var r={id:e.interactionId,latency:e.duration,entries:[e]};X[r.id]=r,Q.push(r)}Q.sort((function(e,t){return t.latency-e.latency})),Q.splice(10).forEach((function(e){delete X[e.id]}))}},K=[2500,4e3],Y={},Z=[800,1800],$=function e(t){document.prerendering?P((function(){return e(t)})):"complete"!==document.readyState?addEventListener("load",(function(){return e(t)}),!0):setTimeout(t,0)},ee=function(e,t){t=t||{};var n=p("TTFB"),r=g(e,n,Z,t.reportAllChanges);$((function(){var i=a();if(i){var o=i.responseStart;if(o<=0||o>performance.now())return;n.value=Math.max(o-v(),0),n.entries=[i],r(!0),l((function(){n=p("TTFB",0),(r=g(e,n,Z,t.reportAllChanges))(!0)}))}}))};e.CLSThresholds=A,e.FCPThresholds=B,e.FIDThresholds=M,e.INPThresholds=U,e.LCPThresholds=K,e.TTFBThresholds=Z,e.onCLS=function(e,t){!function(e,t){t=t||{},R(T((function(){var n,r=p("CLS",0),i=0,o=[],a=function(e){e.forEach((function(e){if(!e.hadRecentInput){var t=o[0],n=o[o.length-1];i&&e.startTime-n.startTime<1e3&&e.startTime-t.startTime<5e3?(i+=e.value,o.push(e)):(i=e.value,o=[e])}})),i>r.value&&(r.value=i,r.entries=o,n())},c=m("layout-shift",a);c&&(n=g(e,r,A,t.reportAllChanges),h((function(){a(c.takeRecords()),n(!0)})),l((function(){i=0,r=p("CLS",0),n=g(e,r,A,t.reportAllChanges),y((function(){return n()}))})),setTimeout(n,0))})))}((function(t){!function(e){if(e.entries.length){var t=e.entries.reduce((function(e,t){return e&&e.value>t.value?e:t}));if(t&&t.sources&&t.sources.length){var n=(r=t.sources).find((function(e){return e.node&&1===e.node.nodeType}))||r[0];if(n)return void(e.attribution={largestShiftTarget:s(n.node),largestShiftTime:t.startTime,largestShiftValue:t.value,largestShiftSource:n,largestShiftEntry:t,loadState:c(t.startTime)})}}var r;e.attribution={}}(t),e(t)}),t)},e.onFCP=function(e,t){R((function(t){!function(e){if(e.entries.length){var t=a(),n=e.entries[e.entries.length-1];if(t){var r=t.activationStart||0,i=Math.max(0,t.responseStart-r);return void(e.attribution={timeToFirstByte:i,firstByteToFCP:e.value-i,loadState:c(e.entries[0].startTime),navigationEntry:t,fcpEntry:n})}}e.attribution={timeToFirstByte:0,firstByteToFCP:e.value,loadState:c(d())}}(t),e(t)}),t)},e.onFID=function(e,t){D((function(t){!function(e){var t=e.entries[0];e.attribution={eventTarget:s(t.target),eventType:t.name,eventTime:t.startTime,eventEntry:t,loadState:c(t.startTime)}}(t),e(t)}),t)},e.onINP=function(e,t){!function(e,t){t=t||{},P((function(){var n;z();var r,i=p("INP"),o=function(e){e.forEach((function(e){e.interactionId&&G(e),"first-input"===e.entryType&&!Q.some((function(t){return t.entries.some((function(t){return e.duration===t.duration&&e.startTime===t.startTime}))}))&&G(e)}));var t,n=(t=Math.min(Q.length-1,Math.floor(W()/50)),Q[t]);n&&n.latency!==i.value&&(i.value=n.latency,i.entries=n.entries,r())},a=m("event",o,{durationThreshold:null!==(n=t.durationThreshold)&&void 0!==n?n:40});r=g(e,i,U,t.reportAllChanges),a&&("PerformanceEventTiming"in window&&"interactionId"in PerformanceEventTiming.prototype&&a.observe({type:"first-input",buffered:!0}),h((function(){o(a.takeRecords()),i.value<0&&W()>0&&(i.value=0,i.entries=[]),r(!0)})),l((function(){Q=[],J=H(),i=p("INP"),r=g(e,i,U,t.reportAllChanges)})))}))}((function(t){!function(e){if(e.entries.length){var t=e.entries.sort((function(e,t){return t.duration-e.duration||t.processingEnd-t.processingStart-(e.processingEnd-e.processingStart)}))[0],n=e.entries.find((function(e){return e.target}));e.attribution={eventTarget:s(n&&n.target),eventType:t.name,eventTime:t.startTime,eventEntry:t,loadState:c(t.startTime)}}else e.attribution={}}(t),e(t)}),t)},e.onLCP=function(e,t){!function(e,t){t=t||{},P((function(){var n,r=C(),i=p("LCP"),o=function(e){var t=e[e.length-1];t&&t.startTime