acinguiux-preact-components 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +56 -0
- package/src/content/themes/theme-acinguiux-amg/theme-acinguiux-amg.css +23 -0
- package/src/content/themes/theme-acinguiux-cafe/theme-acinguiux-cafe.css +47 -0
- package/src/content/themes/theme-acinguiux-energy/theme-acinguiux-energy.css +45 -0
- package/src/content/themes/theme-acinguiux-livewire/theme-acinguiux-livewire.css +22 -0
- package/src/content/themes/theme-acinguiux-livewire-italy/theme-acinguiux-livewire-italy.css +22 -0
- package/src/content/themes/theme-acinguiux-recharge/theme-acinguiux-recharge.css +49 -0
- package/src/content/themes/theme-allon/theme-allon.css +25 -0
- package/src/content/themes/theme-atlas/theme-atlas.css +31 -0
- package/src/content/themes/theme-aurvana/resources/favicon/apple-touch-icon.png +0 -0
- package/src/content/themes/theme-aurvana/resources/favicon/favico.ico +0 -0
- package/src/content/themes/theme-aurvana/resources/favicon/favicon-96x96.png +0 -0
- package/src/content/themes/theme-aurvana/resources/favicon/favicon.ico +0 -0
- package/src/content/themes/theme-aurvana/resources/favicon/favicon.png +0 -0
- package/src/content/themes/theme-aurvana/resources/favicon/favicon.svg +13 -0
- package/src/content/themes/theme-aurvana/resources/favicon/google-touch-icon.png +0 -0
- package/src/content/themes/theme-aurvana/resources/favicon/manifest.json +14 -0
- package/src/content/themes/theme-aurvana/resources/favicon/site.webmanifest +21 -0
- package/src/content/themes/theme-aurvana/resources/favicon/web-app-manifest-192x192.png +0 -0
- package/src/content/themes/theme-aurvana/resources/favicon/web-app-manifest-512x512.png +0 -0
- package/src/content/themes/theme-aurvana/theme-aurvana.css +49 -0
- package/src/content/themes/theme-base/theme-base.css +49 -0
- package/src/content/themes/theme-base2/resources/favicon/android-chrome-192x192.png +0 -0
- package/src/content/themes/theme-base2/resources/favicon/android-chrome-512x512.png +0 -0
- package/src/content/themes/theme-base2/resources/favicon/apple-touch-icon.png +0 -0
- package/src/content/themes/theme-base2/resources/favicon/favico.ico +0 -0
- package/src/content/themes/theme-base2/resources/favicon/favicon-16x16.png +0 -0
- package/src/content/themes/theme-base2/resources/favicon/favicon-32x32.png +0 -0
- package/src/content/themes/theme-base2/resources/favicon/favicon-96x96.png +0 -0
- package/src/content/themes/theme-base2/resources/favicon/favicon.ico +0 -0
- package/src/content/themes/theme-base2/resources/favicon/favicon.png +0 -0
- package/src/content/themes/theme-base2/resources/favicon/favicon.svg +9 -0
- package/src/content/themes/theme-base2/resources/favicon/google-touch-icon.png +0 -0
- package/src/content/themes/theme-base2/resources/favicon/manifest.json +14 -0
- package/src/content/themes/theme-base2/resources/favicon/site.webmanifest +1 -0
- package/src/content/themes/theme-base2/resources/favicon/web-app-manifest-192x192.png +0 -0
- package/src/content/themes/theme-base2/resources/favicon/web-app-manifest-512x512.png +0 -0
- package/src/content/themes/theme-base2/resources/fonts/acinguiux-typeface-la-heavy-221208.woff2 +0 -0
- package/src/content/themes/theme-base2/theme-base2.css +47 -0
- package/src/content/themes/theme-eco-marathon/theme-eco-marathon.css +22 -0
- package/src/content/themes/theme-energy-transition-campus-amsterdam/theme-energy-transition-campus-amsterdam.css +26 -0
- package/src/content/themes/theme-evpass/theme-evpass.css +46 -0
- package/src/content/themes/theme-nam-2025/resources/favicon/apple-touch-icon.png +0 -0
- package/src/content/themes/theme-nam-2025/resources/favicon/favico.ico +0 -0
- package/src/content/themes/theme-nam-2025/resources/favicon/favicon-96x96.png +0 -0
- package/src/content/themes/theme-nam-2025/resources/favicon/favicon.ico +0 -0
- package/src/content/themes/theme-nam-2025/resources/favicon/favicon.png +0 -0
- package/src/content/themes/theme-nam-2025/resources/favicon/favicon.svg +9 -0
- package/src/content/themes/theme-nam-2025/resources/favicon/google-touch-icon.png +0 -0
- package/src/content/themes/theme-nam-2025/resources/favicon/manifest.json +14 -0
- package/src/content/themes/theme-nam-2025/resources/favicon/site.webmanifest +21 -0
- package/src/content/themes/theme-nam-2025/resources/favicon/web-app-manifest-192x192.png +0 -0
- package/src/content/themes/theme-nam-2025/resources/favicon/web-app-manifest-512x512.png +0 -0
- package/src/content/themes/theme-nam-2025/theme-nam-2025.css +47 -0
- package/src/content/themes/theme-pennzoil/theme-pennzoil.css +36 -0
- package/src/content/themes/theme-quaker-state/theme-quaker-state.css +63 -0
- package/src/content/themes/theme-tafawoq/theme-tafawoq.css +26 -0
- package/src/content/themes/theme-vegetable/resources/favicon/apple-touch-icon.png +0 -0
- package/src/content/themes/theme-vegetable/resources/favicon/favico.ico +0 -0
- package/src/content/themes/theme-vegetable/resources/favicon/favicon-96x96.png +0 -0
- package/src/content/themes/theme-vegetable/resources/favicon/favicon.ico +0 -0
- package/src/content/themes/theme-vegetable/resources/favicon/favicon.png +0 -0
- package/src/content/themes/theme-vegetable/resources/favicon/favicon.svg +13 -0
- package/src/content/themes/theme-vegetable/resources/favicon/google-touch-icon.png +0 -0
- package/src/content/themes/theme-vegetable/resources/favicon/manifest.json +14 -0
- package/src/content/themes/theme-vegetable/resources/favicon/site.webmanifest +21 -0
- package/src/content/themes/theme-vegetable/resources/favicon/web-app-manifest-192x192.png +0 -0
- package/src/content/themes/theme-vegetable/resources/favicon/web-app-manifest-512x512.png +0 -0
- package/src/content/themes/theme-vegetable/theme-vegetable.css +49 -0
- package/src/content/themes/theme-zeolyst/resources/fonts/type-ar-medium.woff2 +0 -0
- package/src/content/themes/theme-zeolyst/theme-zeolyst.css +29 -0
- package/src/main/atoms/audio.js +16 -0
- package/src/main/atoms/box.js +5 -0
- package/src/main/atoms/button.js +40 -0
- package/src/main/atoms/card.js +22 -0
- package/src/main/atoms/form.js +30 -0
- package/src/main/atoms/heading.js +17 -0
- package/src/main/atoms/icon.js +24 -0
- package/src/main/atoms/img.js +131 -0
- package/src/main/atoms/input.js +55 -0
- package/src/main/atoms/link-text.js +21 -0
- package/src/main/atoms/link.js +60 -0
- package/src/main/atoms/list.js +12 -0
- package/src/main/atoms/logo.js +9 -0
- package/src/main/atoms/menu.js +10 -0
- package/src/main/atoms/message.js +5 -0
- package/src/main/atoms/nav-link.js +49 -0
- package/src/main/atoms/popup.js +47 -0
- package/src/main/atoms/rich-text.js +128 -0
- package/src/main/atoms/scroller.js +224 -0
- package/src/main/atoms/svg.js +65 -0
- package/src/main/atoms/table.js +32 -0
- package/src/main/atoms/textarea.js +10 -0
- package/src/main/atoms/time.js +12 -0
- package/src/main/atoms/video.js +100 -0
- package/src/main/export-main.js +12 -0
- package/src/main/export-matter.js +86 -0
- package/src/main/export-preact-hooks.js +1 -0
- package/src/main/export-preact.js +1 -0
- package/src/main/index.js +13 -0
- package/src/main/molecules/asset.js +23 -0
- package/src/main/molecules/glossary.js +44 -0
- package/src/main/molecules/links.js +23 -0
- package/src/main/molecules/promo-text.js +27 -0
- package/src/main/molecules/tags.js +15 -0
- package/src/main/molecules/tree.js +51 -0
- package/src/main/organisms/accordion-item.js +106 -0
- package/src/main/organisms/author.js +29 -0
- package/src/main/organisms/breadcrumb.js +69 -0
- package/src/main/organisms/call-to-action.js +24 -0
- package/src/main/organisms/carousel.js +178 -0
- package/src/main/organisms/cart-item.js +156 -0
- package/src/main/organisms/cart.js +162 -0
- package/src/main/organisms/contact-form.js +141 -0
- package/src/main/organisms/container/ab-test.js +47 -0
- package/src/main/organisms/container/default.js +6 -0
- package/src/main/organisms/container/filtered-section.js +293 -0
- package/src/main/organisms/container/footer.js +12 -0
- package/src/main/organisms/container/grid.js +44 -0
- package/src/main/organisms/container/header.js +13 -0
- package/src/main/organisms/container/list.js +7 -0
- package/src/main/organisms/container/main.js +6 -0
- package/src/main/organisms/container/raw.js +7 -0
- package/src/main/organisms/container/section.js +28 -0
- package/src/main/organisms/container.js +29 -0
- package/src/main/organisms/content-owner.js +15 -0
- package/src/main/organisms/date-entry.js +56 -0
- package/src/main/organisms/external-search.js +73 -0
- package/src/main/organisms/filtered-item.js +163 -0
- package/src/main/organisms/footer-item.js +17 -0
- package/src/main/organisms/image-gallery.js +164 -0
- package/src/main/organisms/last-modified.js +20 -0
- package/src/main/organisms/legal-footer.js +16 -0
- package/src/main/organisms/list-item.js +48 -0
- package/src/main/organisms/metadata.js +11 -0
- package/src/main/organisms/navigation.js +232 -0
- package/src/main/organisms/notification.js +87 -0
- package/src/main/organisms/order-tracker.js +203 -0
- package/src/main/organisms/page-header-banner.js +26 -0
- package/src/main/organisms/page-header.js +33 -0
- package/src/main/organisms/page-tags.js +14 -0
- package/src/main/organisms/page.js +260 -0
- package/src/main/organisms/press-release.js +24 -0
- package/src/main/organisms/product-admin.js +204 -0
- package/src/main/organisms/promo-banner.js +28 -0
- package/src/main/organisms/promo-bottom.js +23 -0
- package/src/main/organisms/promo-button.js +8 -0
- package/src/main/organisms/promo-card-cover.js +35 -0
- package/src/main/organisms/promo-card.js +33 -0
- package/src/main/organisms/promo-full.js +20 -0
- package/src/main/organisms/promo-image.js +22 -0
- package/src/main/organisms/promo-lure.js +22 -0
- package/src/main/organisms/promo-product-card.js +187 -0
- package/src/main/organisms/promo-product-full.js +293 -0
- package/src/main/organisms/promo-simple.js +23 -0
- package/src/main/organisms/quote.js +21 -0
- package/src/main/organisms/search-form.js +42 -0
- package/src/main/organisms/search-nav.js +66 -0
- package/src/main/organisms/search-result.js +53 -0
- package/src/main/organisms/slider.js +26 -0
- package/src/main/organisms/standalone-asset.js +22 -0
- package/src/main/organisms/tabs.js +277 -0
- package/src/main/organisms/topbar.js +83 -0
- package/src/main/organisms/web-component.js +53 -0
- package/src/main/routing/annotation.js +9 -0
- package/src/main/routing/component.js +138 -0
- package/src/main/routing/empty.js +5 -0
- package/src/main/routing/error-handler.js +64 -0
- package/src/main/routing/placeholder-image.svg +5 -0
- package/src/main/routing/router.js +219 -0
- package/src/main/shared/analytics.js +677 -0
- package/src/main/shared/bubble-event.js +11 -0
- package/src/main/shared/custom-element.js +21 -0
- package/src/main/shared/deep-selector.js +28 -0
- package/src/main/shared/disable-transparency.js +10 -0
- package/src/main/shared/format-time.js +8 -0
- package/src/main/shared/get-id.js +5 -0
- package/src/main/shared/get-meta.js +3 -0
- package/src/main/shared/get-size-class.js +3 -0
- package/src/main/shared/get-size.js +11 -0
- package/src/main/shared/h.js +88 -0
- package/src/main/shared/hash-jump.js +33 -0
- package/src/main/shared/icons/arrow-back.svg +1 -0
- package/src/main/shared/icons/arrow-down.svg +1 -0
- package/src/main/shared/icons/arrow-next.svg +1 -0
- package/src/main/shared/icons/arrow-tail-right.svg +1 -0
- package/src/main/shared/icons/arrow-tail-up.svg +1 -0
- package/src/main/shared/icons/arrow-up.svg +1 -0
- package/src/main/shared/icons/asset-download.svg +1 -0
- package/src/main/shared/icons/logo.svg +5 -0
- package/src/main/shared/icons/low-carbon-placeholder.svg +9 -0
- package/src/main/shared/icons/media-pause.svg +1 -0
- package/src/main/shared/icons/media-play.svg +1 -0
- package/src/main/shared/icons/navigation-burger.svg +1 -0
- package/src/main/shared/icons/navigation-close.svg +1 -0
- package/src/main/shared/icons/navigation-link.svg +1 -0
- package/src/main/shared/icons/navigation-refresh.svg +1 -0
- package/src/main/shared/icons/navigation-search.svg +1 -0
- package/src/main/shared/icons/navigation-share.svg +1 -0
- package/src/main/shared/icons/toggle-newwindow.svg +1 -0
- package/src/main/shared/icons.js +18 -0
- package/src/main/shared/id-from-string.js +5 -0
- package/src/main/shared/mark-selection.js +19 -0
- package/src/main/shared/register.js +26 -0
- package/src/main/shared/renderer.js +43 -0
- package/src/main/shared/simple-consent-api.js +70 -0
- package/src/main/shared/split-links.js +11 -0
- package/src/main/shared/t.js +60 -0
- package/src/main/shared/twind.js +837 -0
- package/src/main/shared/update-head.js +34 -0
- package/src/main/shared/update-scrollbar-width.js +30 -0
- package/src/main/shared/use-link.js +151 -0
- package/src/main/shared/use-persistent-state.js +42 -0
- package/src/main/shared/wait-for-dom-ready.js +6 -0
- package/src/main/shared/wcm-mode.js +4 -0
- package/src/wcs/components/acinguiux-preact-doc/acinguiux-preact-doc.js +207 -0
- package/src/wcs/components/admin-dashboard/admin-dashboard.js +487 -0
- package/src/wcs/components/admin-login/admin-login.js +91 -0
- package/src/wcs/components/bazaar-voice/bazaar-voice.js +56 -0
- package/src/wcs/components/chatbot-koreai/chatbot-koreai.js +176 -0
- package/src/wcs/components/chatbot-koreai/koreai-transport.js +217 -0
- package/src/wcs/components/chatbot-ms/chatbot-ms.js +210 -0
- package/src/wcs/components/chatbot-test/chatbot-test.js +44 -0
- package/src/wcs/components/comparison-chart/comparison-chart.js +111 -0
- package/src/wcs/components/consent-banner/consent-banner.js +248 -0
- package/src/wcs/components/consent-banner/icons/ccpa.svg +6 -0
- package/src/wcs/components/consent-banner/icons/info.svg +1 -0
- package/src/wcs/components/consent-banner/provider-onetrust.js +131 -0
- package/src/wcs/components/decision-tree/arrow-back.svg +3 -0
- package/src/wcs/components/decision-tree/badges.js +37 -0
- package/src/wcs/components/decision-tree/decision-tree.js +162 -0
- package/src/wcs/components/dynamic-contact-details/dynamic-contact-details.js +111 -0
- package/src/wcs/components/example-accordion/example-accordion.js +10 -0
- package/src/wcs/components/example-asset/example-asset.js +12 -0
- package/src/wcs/components/example-form/example-form.js +59 -0
- package/src/wcs/components/example-nested/example-nested.js +10 -0
- package/src/wcs/components/example-routing/example-routing.js +51 -0
- package/src/wcs/components/example-rtl/example-rtl.js +28 -0
- package/src/wcs/components/example-tabs/example-tabs.js +12 -0
- package/src/wcs/components/example-web-component/example-web-component.js +34 -0
- package/src/wcs/components/floating-button/floating-button.js +17 -0
- package/src/wcs/components/formstack-form/fields/address.js +38 -0
- package/src/wcs/components/formstack-form/fields/checkbox.js +42 -0
- package/src/wcs/components/formstack-form/fields/date.js +22 -0
- package/src/wcs/components/formstack-form/fields/description.js +8 -0
- package/src/wcs/components/formstack-form/fields/input.js +8 -0
- package/src/wcs/components/formstack-form/fields/name.js +39 -0
- package/src/wcs/components/formstack-form/fields/radio.js +24 -0
- package/src/wcs/components/formstack-form/fields/rating.js +53 -0
- package/src/wcs/components/formstack-form/fields/section.js +8 -0
- package/src/wcs/components/formstack-form/fields/select.js +10 -0
- package/src/wcs/components/formstack-form/fields/textarea.js +8 -0
- package/src/wcs/components/formstack-form/fields/wrapper.js +11 -0
- package/src/wcs/components/formstack-form/formstack-form.js +280 -0
- package/src/wcs/components/fuel-prices/fuel-prices.js +45 -0
- package/src/wcs/components/furniture-overview/furniture-overview.js +115 -0
- package/src/wcs/components/gauge-value/gauge-value.js +65 -0
- package/src/wcs/components/help-centre/api.js +150 -0
- package/src/wcs/components/help-centre/help-centre.js +400 -0
- package/src/wcs/components/help-centre/icon-search.svg +1 -0
- package/src/wcs/components/image-gen/admin-panel.js +248 -0
- package/src/wcs/components/image-gen/image-gen.js +385 -0
- package/src/wcs/components/image-gen/labels.js +37 -0
- package/src/wcs/components/image-gen/use-api.js +392 -0
- package/src/wcs/components/inspired-gallery/inspired-gallery.js +118 -0
- package/src/wcs/components/launch-container/launch-container.js +95 -0
- package/src/wcs/components/launch-container/ledger.js +140 -0
- package/src/wcs/components/lng-map/lng-map.js +44 -0
- package/src/wcs/components/mouseflow-analytics/mouseflow-analytics.js +39 -0
- package/src/wcs/components/msds-search/msds-search.js +127 -0
- package/src/wcs/components/msds-search/navigation-search.svg +3 -0
- package/src/wcs/components/product-catalogue/icon-back.svg +3 -0
- package/src/wcs/components/product-catalogue/icon-cart.svg +3 -0
- package/src/wcs/components/product-catalogue/icon-close.svg +3 -0
- package/src/wcs/components/product-catalogue/product-catalogue.js +215 -0
- package/src/wcs/components/product-links/icon-cart.svg +3 -0
- package/src/wcs/components/product-links/product-links.js +43 -0
- package/src/wcs/components/rio-iframe/rio-iframe.js +137 -0
- package/src/wcs/components/salsify-products/filter-tools.js +60 -0
- package/src/wcs/components/salsify-products/icon-cart.svg +3 -0
- package/src/wcs/components/salsify-products/process-products.js +53 -0
- package/src/wcs/components/salsify-products/route-tools.js +54 -0
- package/src/wcs/components/salsify-products/salsify-products.js +281 -0
- package/src/wcs/components/shout-out/shout-out.js +51 -0
- package/src/wcs/components/simple-chart/simple-chart.js +53 -0
- package/src/wcs/components/single-stat/single-stat.js +85 -0
- package/src/wcs/components/site-feedback/site-feedback.js +56 -0
- package/src/wcs/components/skds-search/navigation-search.svg +3 -0
- package/src/wcs/components/skds-search/skds-search.js +103 -0
- package/src/wcs/components/smart-banner/smart-banner.js +104 -0
- package/src/wcs/components/standalone-table/arrow-up-down.svg +3 -0
- package/src/wcs/components/standalone-table/arrow-up.svg +3 -0
- package/src/wcs/components/standalone-table/standalone-table.js +440 -0
- package/src/wcs/components/station-locator/station-locator.js +49 -0
- package/src/wcs/components/store-badges/badges.js +60 -0
- package/src/wcs/components/store-badges/store-badges.js +93 -0
- package/src/wcs/components/topbar-button/person.svg +1 -0
- package/src/wcs/components/topbar-button/topbar-button.js +22 -0
- package/src/wcs/components/universal-gallery/universal-gallery.js +308 -0
- package/src/wcs/components/zendesk-chat/zendesk-chat.js +133 -0
- package/src/wcs/shared/chat-bot/README.md +61 -0
- package/src/wcs/shared/chat-bot/chat-bot.js +216 -0
- package/src/wcs/shared/chat-bot/resources/arrow-next.svg +1 -0
- package/src/wcs/shared/chat-bot/resources/navigation-close.svg +1 -0
- package/src/wcs/shared/chat-bot/resources/person.svg +1 -0
- package/src/wcs/shared/chat-bot/resources/upload.svg +1 -0
- package/src/wcs/shared/filtered-data/README.md +52 -0
- package/src/wcs/shared/filtered-data/fetch-data.js +33 -0
- package/src/wcs/shared/filtered-data/filtered-data.js +337 -0
- package/src/wcs/shared/promo-with-popup/icon-close.svg +3 -0
- package/src/wcs/shared/promo-with-popup/icon-next.svg +3 -0
- package/src/wcs/shared/promo-with-popup/icon-prev.svg +3 -0
- package/src/wcs/shared/promo-with-popup/promo-with-popup.js +93 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import PromoWithPopup from '#acinguiux-preact/wcs/shared/promo-with-popup/promo-with-popup.js'
|
|
2
|
+
|
|
3
|
+
const { h, register, preactHooks, matter } = globalThis.ami
|
|
4
|
+
const { useState, useEffect, useMemo } = preactHooks
|
|
5
|
+
const { Box, Button, Input } = matter
|
|
6
|
+
|
|
7
|
+
const LABELS = {
|
|
8
|
+
SEARCH_TEXT: 'Search',
|
|
9
|
+
ORDER_BY: 'Sort by',
|
|
10
|
+
LOAD_MORE: 'Load more',
|
|
11
|
+
RESET_FILTERS: 'Reset filters',
|
|
12
|
+
ASCENDING: 'ascending',
|
|
13
|
+
DESCENDING: 'descending',
|
|
14
|
+
BACK_TO_OVERVIEW: 'Back to overview',
|
|
15
|
+
PREVIOUS_ITEM: 'Go to the previous item',
|
|
16
|
+
NEXT_ITEM: 'Go to the next item'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const SUBCATEGORIES = {
|
|
20
|
+
Sanitaryware: [
|
|
21
|
+
'Showers',
|
|
22
|
+
'Mixer & Diverters',
|
|
23
|
+
'Flushing System',
|
|
24
|
+
'Faucets',
|
|
25
|
+
'Wash Basin',
|
|
26
|
+
'Sinks',
|
|
27
|
+
'Mirror',
|
|
28
|
+
'Bath Tub',
|
|
29
|
+
'Kamod',
|
|
30
|
+
'Toilet Paper Holder',
|
|
31
|
+
'Towel Stand',
|
|
32
|
+
'Shelf & Corner',
|
|
33
|
+
'Hooks',
|
|
34
|
+
'Soap Dispenser',
|
|
35
|
+
'Water Heaters',
|
|
36
|
+
'Washing Machine'
|
|
37
|
+
],
|
|
38
|
+
Hardware: [
|
|
39
|
+
'Tandom Box',
|
|
40
|
+
'Hinges',
|
|
41
|
+
'Drawer Channel (Normal & Softclose)',
|
|
42
|
+
'Sliding Channel',
|
|
43
|
+
'Handles',
|
|
44
|
+
'Locks (Digital Locks & Normal Locks)',
|
|
45
|
+
'Lockers',
|
|
46
|
+
'Doorclosers',
|
|
47
|
+
'Doorprofiles',
|
|
48
|
+
'Liftup system',
|
|
49
|
+
'Kitchen corners',
|
|
50
|
+
'Pantery Unit',
|
|
51
|
+
'Wardrobe',
|
|
52
|
+
'Door chain',
|
|
53
|
+
'Door Stoper',
|
|
54
|
+
'Door Eyes'
|
|
55
|
+
],
|
|
56
|
+
'Kitchen Appliances': [
|
|
57
|
+
'Hob & Induction Hob',
|
|
58
|
+
'Chimney',
|
|
59
|
+
'Oven Microwave',
|
|
60
|
+
'Refrigerator',
|
|
61
|
+
'Deep Fryer',
|
|
62
|
+
'Barbeque Grill',
|
|
63
|
+
'Toaster',
|
|
64
|
+
'Electric Kettle',
|
|
65
|
+
'Dishwasher',
|
|
66
|
+
'Juicer Mixer Grinder',
|
|
67
|
+
'Coffee Maker',
|
|
68
|
+
'Warmer Drawer',
|
|
69
|
+
'Cooking Range',
|
|
70
|
+
'Cold Pressed Juicer',
|
|
71
|
+
'Food Waste Disposer'
|
|
72
|
+
],
|
|
73
|
+
Plywood: [
|
|
74
|
+
'Commercial',
|
|
75
|
+
'Waterproof',
|
|
76
|
+
'Marine',
|
|
77
|
+
'Fire Retardant',
|
|
78
|
+
'Flexible',
|
|
79
|
+
'MDF',
|
|
80
|
+
'Particle Board',
|
|
81
|
+
'Laminates',
|
|
82
|
+
'Veneers',
|
|
83
|
+
'Adhesives',
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function Items ({ items }) {
|
|
88
|
+
const models = items.map(item => ({
|
|
89
|
+
image: item.image,
|
|
90
|
+
title: item.title,
|
|
91
|
+
text: item.text, // This is usually the price
|
|
92
|
+
links: [
|
|
93
|
+
{ name: 'Brand', value: item.brand || 'Generic' },
|
|
94
|
+
{ name: 'Category', value: item.subcategory },
|
|
95
|
+
{ name: 'Product', value: item.text },
|
|
96
|
+
{ name: 'Description', value: item.description || item.title }
|
|
97
|
+
]
|
|
98
|
+
}))
|
|
99
|
+
|
|
100
|
+
return h('div', { className: 'grid gap-5 grid-cols-4 md:grid-cols-2 sm:grid-cols-1', role: 'list' }, models.map((_m, index) =>
|
|
101
|
+
h(PromoWithPopup, { models, currentModelIndex: index })
|
|
102
|
+
))
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function UniversalGallery ({ items = [], src }) {
|
|
106
|
+
const [allItems, setAllItems] = useState([])
|
|
107
|
+
const [loading, setLoading] = useState(true)
|
|
108
|
+
const [searchTerm, setSearchTerm] = useState('')
|
|
109
|
+
const [mainCategory, setMainCategory] = useState('')
|
|
110
|
+
const [subcategory, setSubcategory] = useState('')
|
|
111
|
+
const [brand, setBrand] = useState('')
|
|
112
|
+
|
|
113
|
+
// Load data on mount
|
|
114
|
+
useEffect(() => {
|
|
115
|
+
(async () => {
|
|
116
|
+
try {
|
|
117
|
+
let data = []
|
|
118
|
+
if (items.length) {
|
|
119
|
+
data = items
|
|
120
|
+
} else if (src) {
|
|
121
|
+
const response = await fetch(src)
|
|
122
|
+
if (!response.ok) { throw new Error('Failed to load data') }
|
|
123
|
+
data = await response.json()
|
|
124
|
+
}
|
|
125
|
+
setAllItems(data)
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error('Failed to load products:', error)
|
|
128
|
+
} finally {
|
|
129
|
+
setLoading(false)
|
|
130
|
+
}
|
|
131
|
+
})()
|
|
132
|
+
}, [])
|
|
133
|
+
|
|
134
|
+
// Parse URL hash on mount and hash change
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
const updateFromHash = () => {
|
|
137
|
+
const hash = globalThis.location.hash.substring(1)
|
|
138
|
+
const params = new URLSearchParams(hash)
|
|
139
|
+
setMainCategory(params.get('mainCategory') || '')
|
|
140
|
+
setSubcategory(params.get('subcategory') || '')
|
|
141
|
+
setBrand(params.get('brand') || '')
|
|
142
|
+
setSearchTerm(params.get('q') || '')
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
updateFromHash()
|
|
146
|
+
globalThis.addEventListener('hashchange', updateFromHash)
|
|
147
|
+
return () => globalThis.removeEventListener('hashchange', updateFromHash)
|
|
148
|
+
}, [])
|
|
149
|
+
|
|
150
|
+
// Get unique values for dropdowns
|
|
151
|
+
const mainCategories = useMemo(() =>
|
|
152
|
+
[...new Set(allItems.map(p => p.mainCategory).filter(Boolean))].sort(),
|
|
153
|
+
[allItems]
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
const availableSubcategories = useMemo(() => {
|
|
157
|
+
if (mainCategory && SUBCATEGORIES[mainCategory]) {
|
|
158
|
+
return SUBCATEGORIES[mainCategory]
|
|
159
|
+
}
|
|
160
|
+
return [...new Set(allItems.map(p => p.subcategory).filter(Boolean))].sort()
|
|
161
|
+
}, [mainCategory, allItems])
|
|
162
|
+
|
|
163
|
+
const brands = useMemo(() =>
|
|
164
|
+
[...new Set(allItems.map(p => p.brand).filter(Boolean))].sort(),
|
|
165
|
+
[allItems]
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
// Filter items
|
|
169
|
+
const filteredItems = useMemo(() => {
|
|
170
|
+
let result = allItems
|
|
171
|
+
|
|
172
|
+
if (searchTerm) {
|
|
173
|
+
const search = searchTerm.toLowerCase()
|
|
174
|
+
result = result.filter(p =>
|
|
175
|
+
p.title?.toLowerCase().includes(search) ||
|
|
176
|
+
p.subcategory?.toLowerCase().includes(search) ||
|
|
177
|
+
p.brand?.toLowerCase().includes(search) ||
|
|
178
|
+
p.description?.toLowerCase().includes(search)
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (mainCategory) {
|
|
183
|
+
result = result.filter(p => p.mainCategory === mainCategory)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (subcategory) {
|
|
187
|
+
result = result.filter(p => p.subcategory === subcategory)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (brand) {
|
|
191
|
+
result = result.filter(p => p.brand === brand)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return result
|
|
195
|
+
}, [allItems, searchTerm, mainCategory, subcategory, brand])
|
|
196
|
+
|
|
197
|
+
// Update URL hash
|
|
198
|
+
const updateHash = newFilters => {
|
|
199
|
+
const params = new URLSearchParams()
|
|
200
|
+
if (newFilters.mainCategory || mainCategory) { params.set('mainCategory', newFilters.mainCategory || mainCategory) }
|
|
201
|
+
if (newFilters.subcategory || subcategory) { params.set('subcategory', newFilters.subcategory || subcategory) }
|
|
202
|
+
if (newFilters.brand || brand) { params.set('brand', newFilters.brand || brand) }
|
|
203
|
+
if (newFilters.search || searchTerm) { params.set('q', newFilters.search || searchTerm) }
|
|
204
|
+
globalThis.location.hash = params.toString()
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const handleMainCategoryChange = e => {
|
|
208
|
+
setMainCategory(e.target.value)
|
|
209
|
+
setSubcategory('')
|
|
210
|
+
updateHash({ mainCategory: e.target.value, subcategory: '' })
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const handleSubcategoryChange = e => {
|
|
214
|
+
setSubcategory(e.target.value)
|
|
215
|
+
updateHash({ subcategory: e.target.value })
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const handleBrandChange = e => {
|
|
219
|
+
setBrand(e.target.value)
|
|
220
|
+
updateHash({ brand: e.target.value })
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const handleSearchChange = e => {
|
|
224
|
+
setSearchTerm(e.target.value)
|
|
225
|
+
updateHash({ search: e.target.value })
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const handleResetFilters = () => {
|
|
229
|
+
setSearchTerm('')
|
|
230
|
+
setMainCategory('')
|
|
231
|
+
setSubcategory('')
|
|
232
|
+
setBrand('')
|
|
233
|
+
globalThis.location.hash = ''
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (loading) {
|
|
237
|
+
return h('div', { className: 'text-center py-8' }, 'Loading...')
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (!allItems.length) {
|
|
241
|
+
return null
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return h('div', { className: 'space-y-6' },
|
|
245
|
+
// Filter Bar
|
|
246
|
+
h(Box, { className: 'text-txa bg-bga rounded-2xl p-6' },
|
|
247
|
+
h('div', { className: 'grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-6' },
|
|
248
|
+
// Search
|
|
249
|
+
h(Input, {
|
|
250
|
+
_size: 'sm',
|
|
251
|
+
type: 'search',
|
|
252
|
+
name: 'search',
|
|
253
|
+
placeholder: LABELS.SEARCH_TEXT,
|
|
254
|
+
value: searchTerm,
|
|
255
|
+
onInput: handleSearchChange
|
|
256
|
+
}),
|
|
257
|
+
// Main Category
|
|
258
|
+
h(Input, {
|
|
259
|
+
_size: 'sm',
|
|
260
|
+
type: 'select',
|
|
261
|
+
name: 'mainCategory',
|
|
262
|
+
value: mainCategory,
|
|
263
|
+
onChange: handleMainCategoryChange,
|
|
264
|
+
children: [
|
|
265
|
+
h('option', { value: '' }, 'All Main Categories'),
|
|
266
|
+
...mainCategories.map(cat => h('option', { value: cat }, cat))
|
|
267
|
+
]
|
|
268
|
+
}),
|
|
269
|
+
// Subcategory
|
|
270
|
+
h(Input, {
|
|
271
|
+
_size: 'sm',
|
|
272
|
+
type: 'select',
|
|
273
|
+
name: 'subcategory',
|
|
274
|
+
value: subcategory,
|
|
275
|
+
onChange: handleSubcategoryChange,
|
|
276
|
+
disabled: !mainCategory,
|
|
277
|
+
children: [
|
|
278
|
+
h('option', { value: '' }, 'All Subcategories'),
|
|
279
|
+
...availableSubcategories.map(subcat => h('option', { value: subcat }, subcat))
|
|
280
|
+
]
|
|
281
|
+
}),
|
|
282
|
+
// Brand
|
|
283
|
+
h(Input, {
|
|
284
|
+
_size: 'sm',
|
|
285
|
+
type: 'select',
|
|
286
|
+
name: 'brand',
|
|
287
|
+
value: brand,
|
|
288
|
+
onChange: handleBrandChange,
|
|
289
|
+
children: [
|
|
290
|
+
h('option', { value: '' }, 'All Brands'),
|
|
291
|
+
...brands.map(b => h('option', { value: b }, b))
|
|
292
|
+
]
|
|
293
|
+
}),
|
|
294
|
+
// Reset
|
|
295
|
+
h(Button, {
|
|
296
|
+
_model: { name: LABELS.RESET_FILTERS },
|
|
297
|
+
onClick: handleResetFilters,
|
|
298
|
+
className: 'px-4 py-2'
|
|
299
|
+
})
|
|
300
|
+
),
|
|
301
|
+
h('p', { className: 'text-sm text-gray-600 mt-4' }, `Showing ${filteredItems.length} products`)
|
|
302
|
+
),
|
|
303
|
+
// Items
|
|
304
|
+
h(Items, { items: filteredItems })
|
|
305
|
+
)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
register(UniversalGallery, 'universal-gallery')
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
const { h, register, preactHooks } = globalThis.ami
|
|
2
|
+
const { useRef, useEffect, useState } = preactHooks
|
|
3
|
+
|
|
4
|
+
function ZendeskChat ({ src, locale, department, 'button-label': buttonLabel }) {
|
|
5
|
+
const ref = useRef()
|
|
6
|
+
const [width, setWidth] = useState(148)
|
|
7
|
+
|
|
8
|
+
useEffect(() => createWidget(ref.current, src, locale, department, buttonLabel, setWidth), [])
|
|
9
|
+
|
|
10
|
+
// Use z-20 for floating elements.
|
|
11
|
+
return h('div', {
|
|
12
|
+
ref,
|
|
13
|
+
className: 'box-content bg-transparent fixed bottom-0 end-24 z-20 print:hidden',
|
|
14
|
+
_style: id => `
|
|
15
|
+
${id} { width: ${width}px; height: 70px }
|
|
16
|
+
${id}[data-mobile=true] { width: 88px }
|
|
17
|
+
${id}[data-open=true] { width: 374px; height: 600px; max-height: 100dvh }
|
|
18
|
+
${id}[data-open=true][data-mobile=true] {
|
|
19
|
+
left: 0;
|
|
20
|
+
right: 0;
|
|
21
|
+
top: 0;
|
|
22
|
+
bottom: 0;
|
|
23
|
+
width: 100%;
|
|
24
|
+
height: 100%;
|
|
25
|
+
}
|
|
26
|
+
`
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Documentation: https://developer.zendesk.com/api-reference/widget/introduction/
|
|
31
|
+
function createWidget (div, src, locale, department, buttonLabel, setWidth) {
|
|
32
|
+
div.style = 'margin: 0; padding: 0;'
|
|
33
|
+
|
|
34
|
+
// Create inner iframe.
|
|
35
|
+
// Outer div constraints the size.
|
|
36
|
+
// Inner iframe is 100dvh to make sure retarded Zendesk 'responsiveness' works.
|
|
37
|
+
const innerIframe = document.createElement('iframe')
|
|
38
|
+
innerIframe.style = `border: none; width: ${window.innerWidth}px; height: 100%; position: absolute; bottom: 0; right: 0`
|
|
39
|
+
div.appendChild(innerIframe)
|
|
40
|
+
|
|
41
|
+
const resizeHandler = () => {
|
|
42
|
+
innerIframe.style.height = `${window.innerHeight}px`
|
|
43
|
+
}
|
|
44
|
+
window.addEventListener('resize', resizeHandler)
|
|
45
|
+
|
|
46
|
+
const innerWindow = innerIframe.contentWindow
|
|
47
|
+
const innerDoc = innerWindow.document
|
|
48
|
+
const innerBody = innerDoc.body
|
|
49
|
+
innerBody.style = 'margin: 0; padding: 0;'
|
|
50
|
+
|
|
51
|
+
const updateWidth = () => {
|
|
52
|
+
const launcher = innerDoc.getElementById('launcher')
|
|
53
|
+
const launcherWidth = launcher.clientWidth
|
|
54
|
+
if (launcherWidth > 0) {
|
|
55
|
+
// Add some padding as button is getting cropped in windows.
|
|
56
|
+
setWidth(launcherWidth + 20)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Watch for changes and detect if chat is open and if the retarded 'responsiveness' is enabled.
|
|
61
|
+
const observer = new MutationObserver(() => {
|
|
62
|
+
const launcher = innerDoc.getElementById('launcher')
|
|
63
|
+
const isOpen = innerDoc.getElementById('webWidget')
|
|
64
|
+
const isMobile = launcher?.style.width === '48px'
|
|
65
|
+
div.dataset.mobile = !!isMobile
|
|
66
|
+
div.dataset.open = !!isOpen
|
|
67
|
+
|
|
68
|
+
if (launcher && !isOpen) {
|
|
69
|
+
updateWidth()
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
// Start observing body.
|
|
74
|
+
observer.observe(innerBody, { attributes: true, childList: true, subtree: true })
|
|
75
|
+
|
|
76
|
+
// Add Zendesk configuration.
|
|
77
|
+
innerWindow.zESettings = {
|
|
78
|
+
webWidget: {
|
|
79
|
+
...(buttonLabel && {
|
|
80
|
+
launcher: {
|
|
81
|
+
label: {
|
|
82
|
+
'*': buttonLabel
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}),
|
|
86
|
+
chat: {
|
|
87
|
+
departments: {
|
|
88
|
+
enabled: department ? [''] : undefined,
|
|
89
|
+
select: department
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Add Zendesk script.
|
|
96
|
+
// For some reason locale can only be set after the script is loaded.
|
|
97
|
+
// There does not seem to be a setting for this in zESettings.
|
|
98
|
+
const safeLocale = locale || document.documentElement.lang || navigator.language
|
|
99
|
+
const script = innerDoc.createElement('script')
|
|
100
|
+
script.src = src
|
|
101
|
+
script.id = 'ze-snippet'
|
|
102
|
+
script.addEventListener('load', () => {
|
|
103
|
+
innerWindow.zE('webWidget', 'setLocale', safeLocale)
|
|
104
|
+
const style = innerDoc.createElement('style')
|
|
105
|
+
style.textContent = `
|
|
106
|
+
#launcher {
|
|
107
|
+
margin: 0;
|
|
108
|
+
}
|
|
109
|
+
`
|
|
110
|
+
innerDoc.head.appendChild(style)
|
|
111
|
+
|
|
112
|
+
// Suppress chat if the department is offline.
|
|
113
|
+
if (!department) {
|
|
114
|
+
return
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
innerWindow.zE('webWidget:on', 'chat:connected', () => {
|
|
118
|
+
const offline = innerWindow.zE('webWidget:get', 'chat:department', department)?.status === 'offline'
|
|
119
|
+
if (offline) {
|
|
120
|
+
innerWindow.zE('webWidget', 'updateSettings', { webWidget: { chat: { suppress: true } } })
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
innerBody.appendChild(script)
|
|
126
|
+
|
|
127
|
+
return () => {
|
|
128
|
+
observer.disconnect()
|
|
129
|
+
window.removeEventListener('resize', resizeHandler)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
register(ZendeskChat, 'zendesk-chat')
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# ChatBot
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
A generic chat button and chat window widget.
|
|
6
|
+
|
|
7
|
+
## Attributes
|
|
8
|
+
|
|
9
|
+
- `buttonText` - Text to show on a button that triggers the chat; default is `Ask us`.
|
|
10
|
+
- `headerText` - Text to show on the top bar of the chat window; default is `Chatbot`.
|
|
11
|
+
- `closeText` - Text to show on the close chat button; default is `Close window`.
|
|
12
|
+
- `sendText` - Label for send button; default is `Send`.
|
|
13
|
+
- `attachText` - Label for attachment button; default is `Attach`.
|
|
14
|
+
- `inputText` - Input placeholder; default is `Type your message`.
|
|
15
|
+
- `icon` - SVG icon to show on top on the button.
|
|
16
|
+
- `messages` - List of messages. Each message is an object with the following properties:
|
|
17
|
+
- `children` - A list of Preact's `h` objects. Any arbitrary structure is supported.
|
|
18
|
+
- `isBot` - Flag to mark if a message comes from a bot.
|
|
19
|
+
- `timestamp` - Optional Date object. If present, it will be rendered at the top of each message with `toLocaleString()` method using the locale of the current site (or the browser if not present).
|
|
20
|
+
- `forceOpen` - When set to true, it will show the chat window. Showing the chat always triggers `onInit()`
|
|
21
|
+
- `isBusy` - When set to `true`, sending messages is blocked.
|
|
22
|
+
- `onInit` - Callback triggered when a user clicks on the button for the first time. When `forceShow` is set to true, it will be called automatically.
|
|
23
|
+
- `onSend` - Callback triggered when a user sends a message.
|
|
24
|
+
- `onAttach` - Callback triggered when attachment button is clicked. The attachment button only appears when the callback is provided.
|
|
25
|
+
- `onClose` - Callback triggered on `beforeunload`. Note that clicking the `x` button does not trigger it as it only minimises the chat window.
|
|
26
|
+
|
|
27
|
+
## Examples
|
|
28
|
+
|
|
29
|
+
```js
|
|
30
|
+
h(ChatBot, {
|
|
31
|
+
buttonText: 'Ask us',
|
|
32
|
+
headerText: 'My chatbot',
|
|
33
|
+
closeText: 'Close window',
|
|
34
|
+
sendText: 'Send',
|
|
35
|
+
attachText: 'Attach',
|
|
36
|
+
inputText: 'Type your message',
|
|
37
|
+
icon: 'path/to/icon.svg'
|
|
38
|
+
forceOpen: false,
|
|
39
|
+
isBusy: false,
|
|
40
|
+
onInit () {
|
|
41
|
+
|
|
42
|
+
},
|
|
43
|
+
onSend (text) {
|
|
44
|
+
|
|
45
|
+
},
|
|
46
|
+
onAttach (file) {
|
|
47
|
+
|
|
48
|
+
},
|
|
49
|
+
onClose () {
|
|
50
|
+
|
|
51
|
+
},
|
|
52
|
+
messages: [{
|
|
53
|
+
children: [], // Preact children
|
|
54
|
+
timestamp: new Date() // Optional
|
|
55
|
+
}, {
|
|
56
|
+
children: [], // Preact children
|
|
57
|
+
timestamp: new Date(), // Optional
|
|
58
|
+
isBot: true // Mark if bot response, otherwise user input
|
|
59
|
+
}]
|
|
60
|
+
})
|
|
61
|
+
```
|