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,30 @@
|
|
|
1
|
+
import h from '../shared/h.js'
|
|
2
|
+
import useLink from '../shared/use-link.js'
|
|
3
|
+
import bubbleEvent from '../shared/bubble-event.js'
|
|
4
|
+
|
|
5
|
+
export function Form ({ action, onSubmit, ...props }) {
|
|
6
|
+
const { href, onClick } = useLink({ href: action })
|
|
7
|
+
|
|
8
|
+
return h('form', {
|
|
9
|
+
...props,
|
|
10
|
+
className: undefined, // Suppress.
|
|
11
|
+
action: href,
|
|
12
|
+
onSubmit: event => {
|
|
13
|
+
if (!event.composed && !onSubmit) {
|
|
14
|
+
// Include data in the action URL.
|
|
15
|
+
const { currentTarget: el } = event
|
|
16
|
+
const data = new FormData(el)
|
|
17
|
+
el.setAttribute('action', href + new URLSearchParams(data).toString())
|
|
18
|
+
|
|
19
|
+
// Navigation handler.
|
|
20
|
+
onClick?.(event)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
bubbleEvent(event)
|
|
24
|
+
|
|
25
|
+
if (!event.composed && onSubmit) {
|
|
26
|
+
onSubmit(event)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import h from '../shared/h.js'
|
|
2
|
+
import idFromString from '../shared/id-from-string.js'
|
|
3
|
+
|
|
4
|
+
const SIZES = ['4xl', '3xl', '2xl', 'xl', 'lg', 'base']
|
|
5
|
+
|
|
6
|
+
export function Heading ({ _level = 1, _size, _align, id, children, ...props }) {
|
|
7
|
+
const index = _size || _level
|
|
8
|
+
const size = SIZES[index - 1]
|
|
9
|
+
const alignClass = _align ? `text-${_align}` : ''
|
|
10
|
+
|
|
11
|
+
return h(`h${_level}`, {
|
|
12
|
+
...props,
|
|
13
|
+
children,
|
|
14
|
+
className: `font-custom font-bold text-txc text-${size} ${alignClass}`,
|
|
15
|
+
id: id || idFromString(children)
|
|
16
|
+
})
|
|
17
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import h from '../shared/h.js'
|
|
2
|
+
import { SVG } from './svg.js'
|
|
3
|
+
|
|
4
|
+
export function Icon ({ _size, _rtlFlip, children, ...props }) {
|
|
5
|
+
const size = { xs: '12', sm: '16' }[_size] ?? 24
|
|
6
|
+
const isRtl = document.documentElement.dir === 'rtl'
|
|
7
|
+
const transform = isRtl && _rtlFlip ? 'transform: scaleX(-1)' : ''
|
|
8
|
+
|
|
9
|
+
// Set size on the container. This prevents content shift.
|
|
10
|
+
return h('div', {
|
|
11
|
+
...props,
|
|
12
|
+
className: undefined, // Suppress.
|
|
13
|
+
'aria-hidden': true,
|
|
14
|
+
style: `width: calc(var(--font-scale) * ${size}px); height: calc(var(--font-scale) * ${size}px);`,
|
|
15
|
+
children: h(SVG, {
|
|
16
|
+
_tall: true,
|
|
17
|
+
_model: { src: children },
|
|
18
|
+
_style: id => `
|
|
19
|
+
${id} path, ${id} polygon { fill: currentColor; }
|
|
20
|
+
${id} { ${transform} }
|
|
21
|
+
`
|
|
22
|
+
})
|
|
23
|
+
})
|
|
24
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { useEffect, useLayoutEffect, useRef } from 'preact/hooks'
|
|
2
|
+
import getSizeClass from '../shared/get-size-class.js'
|
|
3
|
+
import h from '../shared/h.js'
|
|
4
|
+
|
|
5
|
+
const MINIMUM_SUPPORTED_WIDTH = 48
|
|
6
|
+
const MAXIMUM_SUPPORTED_WIDTH = 3840
|
|
7
|
+
const DEBOUNCE = 100
|
|
8
|
+
const MAXIMUM_RESCALE_FACTOR = 1.3
|
|
9
|
+
|
|
10
|
+
function * generateWidths (factor) {
|
|
11
|
+
for (let size = MINIMUM_SUPPORTED_WIDTH; size <= MAXIMUM_SUPPORTED_WIDTH; size *= factor) {
|
|
12
|
+
yield Math.round(size)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Maximum linear upscale is 130%, only generate widths that produce scaling factor of 1.3 or less
|
|
17
|
+
const WIDTHS = [...generateWidths(MAXIMUM_RESCALE_FACTOR)].sort((a, b) => b - a)
|
|
18
|
+
|
|
19
|
+
// Global resize handler
|
|
20
|
+
const registeredImages = new Set()
|
|
21
|
+
|
|
22
|
+
let resizeId = null
|
|
23
|
+
// The resize handler is debounced to avoid excessive processing during window resizing.
|
|
24
|
+
const handleResize = () => {
|
|
25
|
+
clearTimeout(resizeId)
|
|
26
|
+
resizeId = setTimeout(() => {
|
|
27
|
+
for (const img of registeredImages) {
|
|
28
|
+
// Prune any images that may no longer be in the DOM
|
|
29
|
+
if (!img.isConnected) {
|
|
30
|
+
registeredImages.delete(img)
|
|
31
|
+
continue
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Refresh image size parameters
|
|
35
|
+
refreshImage(img)
|
|
36
|
+
}
|
|
37
|
+
}, DEBOUNCE)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Register the resize handler
|
|
41
|
+
globalThis.addEventListener('resize', handleResize)
|
|
42
|
+
|
|
43
|
+
export function Img ({ _model, _fit = 'cover', _tall, role, ...props }) {
|
|
44
|
+
const { src, alt = '', width, height } = _model
|
|
45
|
+
if (!src) {
|
|
46
|
+
return null
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const sizeClass = getSizeClass(_tall)
|
|
50
|
+
const ref = useRef(null)
|
|
51
|
+
|
|
52
|
+
// Set the resize handler once for the current image on mount.
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
const img = ref.current
|
|
55
|
+
if (!img) {
|
|
56
|
+
// For consistency, explicitly return undefined here.
|
|
57
|
+
return undefined
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
registeredImages.add(img)
|
|
61
|
+
return () => {
|
|
62
|
+
registeredImages.delete(img)
|
|
63
|
+
}
|
|
64
|
+
}, [])
|
|
65
|
+
|
|
66
|
+
// Set eager loading when the image is in the viewport on mount.
|
|
67
|
+
useLayoutEffect(() => {
|
|
68
|
+
const img = ref.current
|
|
69
|
+
if (!img) {
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Ensure the image size parameters are correctly set.
|
|
74
|
+
refreshImage(img)
|
|
75
|
+
|
|
76
|
+
// Check if any part of the image is part of the initial viewport (even partially).
|
|
77
|
+
const rect = img.getBoundingClientRect()
|
|
78
|
+
const viewportHeight = window.innerHeight || document.documentElement.clientHeight
|
|
79
|
+
const viewportWidth = window.innerWidth || document.documentElement.clientWidth
|
|
80
|
+
const isVisible = rect.bottom >= 0 && rect.right >= 0 && rect.top <= viewportHeight && rect.left <= viewportWidth
|
|
81
|
+
|
|
82
|
+
// Ensure that the image is loaded eagerly if it is in the initial viewport. All those images are part of the Largest Contentful Paint.
|
|
83
|
+
if (isVisible) {
|
|
84
|
+
img.loading = 'eager'
|
|
85
|
+
img.fetchPriority = 'high'
|
|
86
|
+
}
|
|
87
|
+
}, []) // Run once only on mount
|
|
88
|
+
|
|
89
|
+
return h('img', {
|
|
90
|
+
...props,
|
|
91
|
+
className: `cq-dd-image block object-${_fit} ${sizeClass}`,
|
|
92
|
+
ref,
|
|
93
|
+
src,
|
|
94
|
+
loading: 'lazy',
|
|
95
|
+
alt: role === 'presentation' ? '' : alt,
|
|
96
|
+
role: alt ? role : 'presentation',
|
|
97
|
+
width,
|
|
98
|
+
height
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function refreshImage (img) {
|
|
103
|
+
const src = img.getAttribute('src')
|
|
104
|
+
const baseSrc = URL.parse(src, globalThis.location.href)
|
|
105
|
+
if (!baseSrc) {
|
|
106
|
+
return // Invalid URL
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (baseSrc.protocol === 'data:') {
|
|
110
|
+
return // Do not refresh data URLs
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const params = baseSrc.searchParams
|
|
114
|
+
|
|
115
|
+
// Set the current pixel density of the device
|
|
116
|
+
params.set('imdensity', window.devicePixelRatio || 1)
|
|
117
|
+
|
|
118
|
+
// Set new width if larger than the current.
|
|
119
|
+
const currentWidth = Number.parseInt(params.get('imwidth') || '0', 10)
|
|
120
|
+
const newWidth = WIDTHS.find(w => w <= img.width) || WIDTHS.at(-1)
|
|
121
|
+
if (newWidth > currentWidth) {
|
|
122
|
+
params.set('imwidth', newWidth)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Set image policy.
|
|
126
|
+
const ratio = img.dataset.ratio ? `-${img.dataset.ratio}` : ''
|
|
127
|
+
params.set('impolicy', `acinguiux-preact-image${ratio}`)
|
|
128
|
+
|
|
129
|
+
// Update image source.
|
|
130
|
+
img.src = baseSrc.toString()
|
|
131
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import h from '../shared/h.js'
|
|
2
|
+
import bubbleEvent from '../shared/bubble-event.js'
|
|
3
|
+
|
|
4
|
+
export function Input ({ type, disabled, ...props }) {
|
|
5
|
+
const disabledClass = disabled ? 'bg-txa/10' : 'pal-brand1 bg-bga'
|
|
6
|
+
const commonClass = `block rounded-lg text-txa border-txa/60 border w-full p-3 ${disabledClass}`
|
|
7
|
+
const style = 'box-shadow: inset 1px 1px 2px 2px hsla(var(--color-txa), 0.1)'
|
|
8
|
+
const onInvalid = bubbleEvent
|
|
9
|
+
|
|
10
|
+
switch (type) {
|
|
11
|
+
case 'checkbox':
|
|
12
|
+
case 'radio':
|
|
13
|
+
return h('input', { ...props, onInvalid, type, disabled, className: 'appearance-auto' })
|
|
14
|
+
case 'file':
|
|
15
|
+
return h('input', {
|
|
16
|
+
...props,
|
|
17
|
+
type,
|
|
18
|
+
disabled,
|
|
19
|
+
className: `block cursor-pointer ${disabled ? 'grayscale' : ''}`,
|
|
20
|
+
onInvalid,
|
|
21
|
+
_style: id => `
|
|
22
|
+
${id}::file-selector-button {
|
|
23
|
+
border-radius: 6px;
|
|
24
|
+
padding: 4px 12px;
|
|
25
|
+
border-width: 1px;
|
|
26
|
+
border-style: solid;
|
|
27
|
+
background-color: hsl(var(--color-bgb));
|
|
28
|
+
border-color: hsl(var(--color-bgb));
|
|
29
|
+
color: hsl(var(--color-txb));
|
|
30
|
+
font-weight: bold;
|
|
31
|
+
transition-property: background-color, border-color, color;
|
|
32
|
+
transition-duration: var(--anim-time);
|
|
33
|
+
height: 32px;
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
}
|
|
36
|
+
${id}:not([disabled])::file-selector-button:hover {
|
|
37
|
+
background-color: hsl(var(--color-txb));
|
|
38
|
+
color: hsl(var(--color-bgb));
|
|
39
|
+
}
|
|
40
|
+
`
|
|
41
|
+
})
|
|
42
|
+
case 'textarea':
|
|
43
|
+
return h('textarea', {
|
|
44
|
+
...props,
|
|
45
|
+
disabled,
|
|
46
|
+
onInvalid,
|
|
47
|
+
style: `${style}; resize: vertical`,
|
|
48
|
+
className: `${commonClass} h-36`
|
|
49
|
+
})
|
|
50
|
+
case 'select':
|
|
51
|
+
return h('select', { ...props, onInvalid, disabled, style, className: `${commonClass} h-12` })
|
|
52
|
+
default:
|
|
53
|
+
return h('input', { ...props, type, onInvalid, disabled, style, className: `${commonClass} h-12` })
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import h from '../shared/h.js'
|
|
2
|
+
import { TOGGLE_NEWWINDOW } from '../shared/icons.js'
|
|
3
|
+
import useLink from '../shared/use-link.js'
|
|
4
|
+
import { Icon } from './icon.js'
|
|
5
|
+
|
|
6
|
+
export function LinkText ({ _model, target: forcedTarget, ...props }) {
|
|
7
|
+
const { name, value } = _model
|
|
8
|
+
const { text, target } = useLink({ href: value, text: name, target: forcedTarget })
|
|
9
|
+
const newWindow = target === '_blank'
|
|
10
|
+
|
|
11
|
+
if (!newWindow) {
|
|
12
|
+
return text?.length > 0 ? h('span', text) : null
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return h('span', { ...props, className: 'space-x-1' },
|
|
16
|
+
text?.length > 0 ? h('span', text) : null,
|
|
17
|
+
h('span', { className: 'inline-block align-top' },
|
|
18
|
+
h(Icon, { _size: 'sm' }, TOGGLE_NEWWINDOW)
|
|
19
|
+
)
|
|
20
|
+
)
|
|
21
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { useMemo } from 'preact/hooks'
|
|
2
|
+
import h from '../shared/h.js'
|
|
3
|
+
import useLink from '../shared/use-link.js'
|
|
4
|
+
import { Icon } from './icon.js'
|
|
5
|
+
import { LinkText } from './link-text.js'
|
|
6
|
+
|
|
7
|
+
const VARIANTS_CLICKABLE = {
|
|
8
|
+
default: 'clickable cursor-pointer',
|
|
9
|
+
simple: 'clickable cursor-pointer hover:underline',
|
|
10
|
+
underline: 'clickable cursor-pointer underline',
|
|
11
|
+
bold: 'clickable cursor-pointer hover:underline font-bold',
|
|
12
|
+
full: 'clickable cursor-pointer font-bold underline',
|
|
13
|
+
tag: 'clickable cursor-pointer transition px-2 py-1 text-sm bg-txa/10 hover:text-bga hover:bg-txa/100 rounded-sm',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const VARIANTS_NON_CLICKABLE = {
|
|
17
|
+
bold: 'font-bold',
|
|
18
|
+
full: 'font-bold',
|
|
19
|
+
tag: 'transition px-2 py-1 text-sm bg-txa/10 rounded-sm',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function Link ({ _model, _variant, target: forcedTarget, className = '', children, ...props }) {
|
|
23
|
+
const { name, value, icon } = _model
|
|
24
|
+
const { href, onClick, target } = useLink({ href: value, text: name, target: forcedTarget })
|
|
25
|
+
const isClickable = value || props.onClick
|
|
26
|
+
const variant = _variant || 'default'
|
|
27
|
+
const variantMap = isClickable ? VARIANTS_CLICKABLE : VARIANTS_NON_CLICKABLE
|
|
28
|
+
|
|
29
|
+
const isContainer = useMemo(() => {
|
|
30
|
+
const arr = (Array.isArray(children) ? children : [children]).filter(Boolean) // Normalize to array.
|
|
31
|
+
return arr.some(c => typeof c !== 'string')
|
|
32
|
+
}, [children])
|
|
33
|
+
|
|
34
|
+
const linkProps = {
|
|
35
|
+
onClick,
|
|
36
|
+
...props,
|
|
37
|
+
target,
|
|
38
|
+
rel: target === '_blank' ? 'noopener' : undefined,
|
|
39
|
+
className: [variantMap[variant], className].map(x => x ?? '').join(' ').trim() || undefined,
|
|
40
|
+
href
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Container link.
|
|
44
|
+
if (isContainer) {
|
|
45
|
+
return h('a', linkProps, children)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Add classes for icon alignment.
|
|
49
|
+
if (icon) {
|
|
50
|
+
linkProps.className += ' space-x-2 inline-flex items-center'
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Output regular link.
|
|
54
|
+
return h('a', linkProps,
|
|
55
|
+
icon && h('span', { className: 'grow-0' },
|
|
56
|
+
h(Icon, icon)
|
|
57
|
+
),
|
|
58
|
+
h(LinkText, { _model, target })
|
|
59
|
+
)
|
|
60
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import h from '../shared/h.js'
|
|
2
|
+
|
|
3
|
+
export function List ({ _ordered, ...props }) {
|
|
4
|
+
const tag = _ordered ? 'ol' : 'ul'
|
|
5
|
+
const prefix = _ordered ? 'list-decimal' : 'list-disc'
|
|
6
|
+
return h(tag, {
|
|
7
|
+
...props,
|
|
8
|
+
// Ensure equal space for nested lists.
|
|
9
|
+
_style: id => `li > ${id} { margin-top: 8px }`,
|
|
10
|
+
className: `ps-6 space-y-2 ${prefix}`
|
|
11
|
+
})
|
|
12
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import h from '../shared/h.js'
|
|
2
|
+
|
|
3
|
+
export function Menu (props) {
|
|
4
|
+
return h('div', {
|
|
5
|
+
style: 'top: calc(100% + 10px); inset-inline-start: -5px', // Align text.
|
|
6
|
+
...props,
|
|
7
|
+
// Use z-10 for sticky elements.
|
|
8
|
+
className: 'absolute bg-bga text-txa z-20 overflow-x-hidden overflow-y-auto shadow animate-expand rounded-lg w-72',
|
|
9
|
+
})
|
|
10
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import h from '../shared/h.js'
|
|
2
|
+
import { ARROW_DOWN, ARROW_UP } from '../shared/icons.js'
|
|
3
|
+
import { Icon } from './icon.js'
|
|
4
|
+
import { LinkText } from './link-text.js'
|
|
5
|
+
import { Link } from './link.js'
|
|
6
|
+
|
|
7
|
+
const SIZE_CLASSES = { md: 8, lg: 12 }
|
|
8
|
+
const SELECTION_CLASSES = {
|
|
9
|
+
default: 'p-2',
|
|
10
|
+
top: 'border-t-4 px-1 pb-2 pt-1',
|
|
11
|
+
bottom: 'border-b-4 px-1 pb-1 pt-2',
|
|
12
|
+
right: 'border-e-4 ps-2 pe-1 py-1'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function NavLink ({ _model, _level, _expanded, _textless, _size, _bold, _highlighted, _selection, ...props }) {
|
|
16
|
+
const { name, value, icon, selected } = _model
|
|
17
|
+
|
|
18
|
+
const size = SIZE_CLASSES[_size ?? 'md']
|
|
19
|
+
const sizeClass = _textless ? `min-h-${size} min-w-${size}` : `w-full min-h-${size}`
|
|
20
|
+
const highlightClass = _highlighted ? 'bg-txa/10' : ''
|
|
21
|
+
const indentClass = `ps-${2 + (_level ?? 0) * 4}`
|
|
22
|
+
const boldClass = _bold ? 'font-bold' : ''
|
|
23
|
+
|
|
24
|
+
return h('div', {
|
|
25
|
+
className: `h-full transition ${selected ? 'border-bgb/100' : 'border-bgb/0'} ${SELECTION_CLASSES[_selection ?? 'default']}`,
|
|
26
|
+
children: h(Link, {
|
|
27
|
+
...props,
|
|
28
|
+
title: _textless ? name : undefined,
|
|
29
|
+
className: 'h-full',
|
|
30
|
+
_model: { name, icon, value: value ?? '#' }, // Make sure it's tabbable.
|
|
31
|
+
children: h('div', {
|
|
32
|
+
className: `h-full transition hover:bg-txa/10 pe-2 py-1 flex space-x-2 items-center justify-center rounded overflow-hidden ${sizeClass} ${highlightClass} ${indentClass} ${boldClass}`,
|
|
33
|
+
children: [
|
|
34
|
+
// Custom icon.
|
|
35
|
+
icon && h('div', { className: 'flex items-center' },
|
|
36
|
+
h(Icon, icon)
|
|
37
|
+
),
|
|
38
|
+
_textless || h('div', { className: 'grow' },
|
|
39
|
+
h(LinkText, { _model })
|
|
40
|
+
),
|
|
41
|
+
// Expand and collapse arrow.
|
|
42
|
+
_expanded !== undefined && h('div', { className: 'flex items-center' },
|
|
43
|
+
h(Icon, { _size: 'xs' }, _expanded ? ARROW_UP : ARROW_DOWN)
|
|
44
|
+
)
|
|
45
|
+
]
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useMemo, useRef, useLayoutEffect } from 'preact/hooks'
|
|
2
|
+
import h from '../shared/h.js'
|
|
3
|
+
|
|
4
|
+
const PADDINGS = { full: 3, center: 6, toast: 9 }
|
|
5
|
+
const LAYOUTS = {
|
|
6
|
+
// Follow the page scroll behaviour for full width popups.
|
|
7
|
+
full: 'm-0 w-full h-full overflow-y-scroll',
|
|
8
|
+
toast: 'ml-0 mr-0 mb-0 mt-auto max-h-4/5 w-full overflow-y-scroll',
|
|
9
|
+
center: 'm-auto rounded-xl w-128 h-fit'
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function Popup ({ _show, _layout = 'toast', _modal = true, children, ...props }) {
|
|
13
|
+
const classes = LAYOUTS[_layout]
|
|
14
|
+
const popupRef = useRef(null)
|
|
15
|
+
const scrollbarWidth = useMemo(() => window.innerWidth - document.body.clientWidth, [])
|
|
16
|
+
|
|
17
|
+
useLayoutEffect(() => {
|
|
18
|
+
if (!popupRef?.current) {
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (!_show) {
|
|
23
|
+
popupRef?.current?.close?.()
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
_modal ? popupRef?.current?.showModal?.() : popupRef?.current?.show?.()
|
|
28
|
+
}, [_show, _modal, children])
|
|
29
|
+
|
|
30
|
+
return [
|
|
31
|
+
h('dialog', {
|
|
32
|
+
...props,
|
|
33
|
+
ref: popupRef,
|
|
34
|
+
className: `z-30 overscroll-none scrollbar-stable animate-toast shadow-lg bg-bga text-txa focus-visible:outline-none ${classes}`,
|
|
35
|
+
// Limit max size on center popups to leave some space around when the viewport is too small.
|
|
36
|
+
style: _layout === 'center' ? 'max-width: calc(100dvw - 12px); max-height: calc(100dvh - 12px)' : null,
|
|
37
|
+
// Overlay style.
|
|
38
|
+
_style: id => `${id}::backdrop { background: hsla(0, 0%, 0%, 0.5); backdrop-filter: blur(4px) }`,
|
|
39
|
+
children: h('div', {
|
|
40
|
+
className: `max-w-page m-auto space-y-5 w-full h-full p-${PADDINGS[_layout]}`,
|
|
41
|
+
// Compensate for scrollbar in center layout.
|
|
42
|
+
style: _layout === 'center' ? `padding-inline-end: ${24 - scrollbarWidth}px` : null,
|
|
43
|
+
children
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
]
|
|
47
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/* global DOMParser, Node */
|
|
2
|
+
import h from '../shared/h.js'
|
|
3
|
+
import { Link } from '../atoms/link.js'
|
|
4
|
+
import { Heading } from '../atoms/heading.js'
|
|
5
|
+
import { Table } from '../atoms/table.js'
|
|
6
|
+
import { List } from '../atoms/list.js'
|
|
7
|
+
import { Img } from '../atoms/img.js'
|
|
8
|
+
|
|
9
|
+
// Rich text provides basic typography rules for HTML content.
|
|
10
|
+
export function RichText ({ children: text, ...props }) {
|
|
11
|
+
if (text) {
|
|
12
|
+
const dp = new DOMParser()
|
|
13
|
+
const doc = dp.parseFromString(text, 'text/html')
|
|
14
|
+
const parsedChildren = [...doc.body.childNodes].map(child => getNode(child))
|
|
15
|
+
|
|
16
|
+
return h('div', {
|
|
17
|
+
...props,
|
|
18
|
+
className: 'space-y-4',
|
|
19
|
+
_style: id => `
|
|
20
|
+
${id} :is(h1, h2, h3, h4, h5, h6):not(:first-child) { margin-top: 24px }
|
|
21
|
+
${id} pre { background-color: hsla(var(--color-txa), 0.05) }
|
|
22
|
+
${id} pre code { background: none; margin: 0; padding: 0; }
|
|
23
|
+
${id} code { background-color: hsla(var(--color-txa), 0.05) }
|
|
24
|
+
${id} details[open] > summary::after { rotate: 270deg }
|
|
25
|
+
${id} details[open] > *:not(:last-child) { margin-bottom: 8px }
|
|
26
|
+
${id} details > summary::after {
|
|
27
|
+
position: absolute;
|
|
28
|
+
top: 0;
|
|
29
|
+
right: 0;
|
|
30
|
+
height: 100%;
|
|
31
|
+
display: flex;
|
|
32
|
+
align-items: center;
|
|
33
|
+
justify-content: center;
|
|
34
|
+
content: '❯';
|
|
35
|
+
transition: var(--anim-time);
|
|
36
|
+
rotate: 90deg;
|
|
37
|
+
width: 12px;
|
|
38
|
+
font-weight: normal;
|
|
39
|
+
margin-right: 8px;
|
|
40
|
+
}
|
|
41
|
+
`,
|
|
42
|
+
children: parsedChildren
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return null
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function getNode (parent) {
|
|
50
|
+
if (parent.nodeType === Node.ELEMENT_NODE) {
|
|
51
|
+
const children = [...parent.childNodes].map(child => getNode(child))
|
|
52
|
+
const tag = parent.tagName.toLowerCase()
|
|
53
|
+
|
|
54
|
+
// Pass all attributes except style and class.
|
|
55
|
+
const attrs = parent.getAttributeNames().reduce((obj, name) => {
|
|
56
|
+
if (!['style', 'class'].includes(name)) {
|
|
57
|
+
obj[name] = parent.getAttribute(name)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return obj
|
|
61
|
+
}, { id: parent.id || undefined })
|
|
62
|
+
|
|
63
|
+
const dispatcher = [{
|
|
64
|
+
tags: ['a'],
|
|
65
|
+
handler: () => {
|
|
66
|
+
const _model = { value: parent.getAttribute('href') }
|
|
67
|
+
|
|
68
|
+
// Text links.
|
|
69
|
+
if (children.length === 1 && typeof children[0] === 'string') {
|
|
70
|
+
_model.name = parent.text
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return h(Link, {
|
|
74
|
+
...attrs,
|
|
75
|
+
name: parent.name || undefined,
|
|
76
|
+
target: parent.target || undefined,
|
|
77
|
+
children,
|
|
78
|
+
_model,
|
|
79
|
+
_variant: 'underline'
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
}, {
|
|
83
|
+
tags: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
|
|
84
|
+
handler: () => h(Heading, { _level: tag.substr(1), ...attrs }, children)
|
|
85
|
+
}, {
|
|
86
|
+
tags: ['table'],
|
|
87
|
+
handler: () => h(Table, attrs, h('tbody', {}, children))
|
|
88
|
+
}, {
|
|
89
|
+
tags: ['thead', 'tbody'],
|
|
90
|
+
handler: () => children
|
|
91
|
+
}, {
|
|
92
|
+
tags: ['ol', 'ul'],
|
|
93
|
+
handler: () => h(List, { _ordered: tag === 'ol' }, children)
|
|
94
|
+
}, {
|
|
95
|
+
tags: ['hr'],
|
|
96
|
+
handler: () => h('hr', { className: 'w-6 h-1 bg-bgb' }, children)
|
|
97
|
+
}, {
|
|
98
|
+
tags: ['img'],
|
|
99
|
+
handler: () => h('div', { className: 'rounded-lg overflow-hidden' },
|
|
100
|
+
h(Img, { _model: { src: parent.src, alt: parent.alt } })
|
|
101
|
+
)
|
|
102
|
+
}, {
|
|
103
|
+
tags: ['pre'],
|
|
104
|
+
handler: () => h('pre', { className: 'p-2 rounded-lg' }, children)
|
|
105
|
+
}, {
|
|
106
|
+
tags: ['code'],
|
|
107
|
+
handler: () => h('code', { className: 'inline-block rounded-sm font-mono text-sm px-1 py-px m-px break-all whitespace-pre-wrap' }, children)
|
|
108
|
+
}, {
|
|
109
|
+
tags: ['details'],
|
|
110
|
+
handler: () => h('details', { className: 'rounded-md border border-txa/20 p-2', open: parent.open }, children)
|
|
111
|
+
}, {
|
|
112
|
+
tags: ['summary'],
|
|
113
|
+
handler: () => h('summary', { className: 'clickable rounded-md py-2 ps-2 pe-6 -m-2 relative block pe-7 cursor-pointer font-bold' }, children)
|
|
114
|
+
}]
|
|
115
|
+
|
|
116
|
+
// Use predefined components if available.
|
|
117
|
+
const route = dispatcher.find(item => item.tags.includes(tag))
|
|
118
|
+
if (route) {
|
|
119
|
+
return route.handler()
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Everything else.
|
|
123
|
+
return h(tag, attrs, children)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Text nodes.
|
|
127
|
+
return parent.data
|
|
128
|
+
}
|