@orderlyshop/web-components 0.1.0-build.7051 → 0.1.0-build.7057
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/README.md +62 -26
- package/bin/orderly-generate-server-renderers.mjs +624 -0
- package/bin/orderly-hydrate-static-pages.mjs +3 -2
- package/bin/orderly-init-shop.mjs +16 -72
- package/custom-elements.json +15 -5
- package/dist/browser/orderly-web-components.define.global.js +175 -94
- package/dist/browser/orderly-web-components.define.global.js.map +1 -1
- package/dist/browser/orderly-web-components.global.js +175 -94
- package/dist/browser/orderly-web-components.global.js.map +1 -1
- package/dist/{default-shop-Qipu74bd.d.ts → default-shop-Bi2MQyvq.d.ts} +11 -1
- package/dist/default-shop.d.ts +1 -1
- package/dist/default-shop.js +4 -0
- package/dist/default-shop.js.map +1 -1
- package/dist/define-C_iL2zun.d.ts +9 -0
- package/dist/define.d.ts +1 -1
- package/dist/define.js +818 -128
- package/dist/define.js.map +1 -1
- package/dist/index.d.ts +25 -8
- package/dist/index.js +824 -129
- package/dist/index.js.map +1 -1
- package/dist/navigation.d.ts +6 -0
- package/dist/navigation.js +59 -16
- package/dist/navigation.js.map +1 -1
- package/dist/{shop-Dm2UjjIN.d.ts → shop-DQGBksrp.d.ts} +14 -2
- package/dist/shop.d.ts +2 -2
- package/dist/shop.js +810 -117
- package/dist/shop.js.map +1 -1
- package/dist/stores.js +78 -4
- package/dist/stores.js.map +1 -1
- package/docs/components/README.md +117 -3
- package/examples/shop/README.md +6 -4
- package/examples/shop/package.json +2 -2
- package/examples/shop/src/forretningsbetingelser.html +2 -2
- package/examples/shop/src/includes/head.html +1 -1
- package/examples/shop/src/storefront-router.ts +2 -2
- package/examples/shop/src/templates/page-layouts.html +8 -206
- package/examples/shop/vite.config.mjs +2 -67
- package/html-custom-data.json +15 -4
- package/package.json +7 -3
- package/server/README.md +57 -80
- package/server/ssr.mjs +783 -0
- package/server/vite.mjs +48 -0
- package/dist/define-jKa_4XhP.d.ts +0 -9
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ npx orderly-init-shop --account-id 00000000-0000-0000-0000-000000000000
|
|
|
28
28
|
|
|
29
29
|
Re-running `npx orderly-init-shop` in an existing shop is non-destructive by default. Existing scaffold files are left unchanged with warnings, while missing new scaffold files are added. Use `--force` only when you explicitly want scaffold files overwritten.
|
|
30
30
|
|
|
31
|
-
The scaffold uses Vite for local development and static builds, but Vite is added to the generated shop's `devDependencies`. Consumers should test locally from `http://localhost:61677` or `https://localhost:61677` because those are the expected local development origins for backend CORS. The generated Vite setup defaults to `http://localhost:61677`; if a local reverse proxy or TLS terminator is added, keep the same `localhost:61677` origin over HTTPS. `@orderlyshop/web-components` does not depend on Vite at runtime.
|
|
31
|
+
The scaffold uses Vite for local development and static builds, but Vite is added to the generated shop's `devDependencies`. Dev mode SSR for product/category URLs is enabled by default, so View Source on local category/product URLs shows semantic server-rendered markup. Consumers should test locally from `http://localhost:61677` or `https://localhost:61677` because those are the expected local development origins for backend CORS. The generated Vite setup defaults to `http://localhost:61677`; if a local reverse proxy or TLS terminator is added, keep the same `localhost:61677` origin over HTTPS. `@orderlyshop/web-components` does not depend on Vite at runtime.
|
|
32
32
|
|
|
33
33
|
## Browser Standalone Bundle
|
|
34
34
|
|
|
@@ -377,7 +377,7 @@ Build with generated category pages and then clean the generated source files. S
|
|
|
377
377
|
npx orderly-build-category-pages
|
|
378
378
|
```
|
|
379
379
|
|
|
380
|
-
`orderly-build-category-pages` also hydrates the built `dist/index.html` and generated `dist/categories/**/index.html` pages with SEO-friendly fallback HTML. The hydration step embeds
|
|
380
|
+
`orderly-build-category-pages` also hydrates the built `dist/index.html` and generated `dist/categories/**/index.html` pages with SEO-friendly fallback HTML. The hydration step embeds semantic product cards per category using `SearchService.Search`; it reads `--base-url`, `VITE_ORDERLY_BASE_URL`, or `ORDERLY_BASE_URL`, and otherwise uses the default `https://service.orderly.shop` backend. Live web components read the semantic fallback as initial state, hide it, and then continue as normal client components.
|
|
381
381
|
|
|
382
382
|
Hydrate an already-built site manually, for example in a nightly job:
|
|
383
383
|
|
|
@@ -389,6 +389,26 @@ Use `--skip-products` for metadata-only hydration, `--strict-products` when a ni
|
|
|
389
389
|
|
|
390
390
|
The category generator expects `src/navigation.ts` or `src/navigation.js` to export `navigationDefinitions` and the template page to contain `<orderly-category-page></orderly-category-page>`. TypeScript navigation files use the current shop project's `typescript` dependency for one-off transpilation. Useful options include `--navigation`, `--template`, `--categories-dir`, `--site-title`, `--component-tag`, and `--export`. The older `--taxonomy` flag and `categoryDefinitions` export are still accepted as compatibility aliases.
|
|
391
391
|
|
|
392
|
+
## Local SSR Dev Mode
|
|
393
|
+
|
|
394
|
+
Scaffolded shops use SSR in dev mode by default through the package Vite middleware:
|
|
395
|
+
|
|
396
|
+
```js
|
|
397
|
+
import { orderlySsrDevServer } from "@orderlyshop/web-components/server/vite";
|
|
398
|
+
|
|
399
|
+
export default defineConfig({
|
|
400
|
+
plugins: [htmlIncludes(), orderlySsrDevServer(), rootHtmlOutput()]
|
|
401
|
+
});
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
When you run `npm run dev`, product and category URLs such as `http://localhost:61677/products/example.html/` and `http://localhost:61677/categories/sko/` are served from the normal `src/product.html` and `src/category.html` templates with semantic SSR HTML injected before Vite transforms the page. Use browser View Source to inspect the server-rendered markup.
|
|
405
|
+
|
|
406
|
+
SSR responses include a small inline critical CSS block for the semantic fallback markup. Normal browser requests hide that fallback and route component light DOM, such as utility banners, until the web components hydrate, so users do not see an unstyled intermediate layout. Googlebot user agents receive the visible fallback layout instead. The HTML source is identical in both cases; only fallback visibility changes.
|
|
407
|
+
|
|
408
|
+
After the first SSR entry render, the default storefront router intercepts same-origin category, product, checkout, payment-result, and configured static-page links. Navigation then stays virtual with `pushState` and persistent app-shell state, while the anchors still keep real `href` values for SEO, no-JS clients, copied links, and direct entry URLs. Set `storefrontRouter: { enabled: false }` only if the host app deliberately wants physical navigation after every click.
|
|
409
|
+
|
|
410
|
+
Set `ORDERLY_DEV_SSR=0` or run `npm run dev -- --no-ssr` to debug pure client-side rendering. Dev SSR uses `VITE_ORDERLY_BASE_URL`, `ORDERLY_BASE_URL`, or `https://service.orderly.shop`, defaults to `grpc-web`, and keeps a short per-URL in-memory cache. Override the cache with `ORDERLY_DEV_SSR_CACHE_TTL_MS`.
|
|
411
|
+
|
|
392
412
|
## Publish Static Sites
|
|
393
413
|
|
|
394
414
|
Installing `@orderlyshop/web-components` also installs a publish command for the consuming shop project. Run it from the project directory. The command generates category pages, builds, hydrates the built homepage/category pages, and publishes the resulting `dist` folder as vanilla HTML/JS/CSS.
|
|
@@ -419,33 +439,25 @@ Re-enter saved FTP settings:
|
|
|
419
439
|
npx orderly-publish-site --target ftp --configure
|
|
420
440
|
```
|
|
421
441
|
|
|
422
|
-
## Server Side Product URLs
|
|
423
|
-
|
|
424
|
-
Category pages can be generated and hydrated statically. Product pages usually need real URLs without generating one HTML file per product. The package ships server helper files under `server/` for this pattern:
|
|
442
|
+
## Server Side Product And Category URLs
|
|
425
443
|
|
|
426
|
-
|
|
427
|
-
- `server/php/orderly-product.php` reuses the built `product.html`, injects declarative SSR fallback markup into `<orderly-product-detail-page>`, and preserves built JS/CSS references.
|
|
428
|
-
- `server/nginx/orderly-products.conf` provides the equivalent Nginx rewrite for PHP-FPM.
|
|
429
|
-
- `server/node/product-snapshot-server.mjs` is an optional Node snapshot endpoint that calls `SearchService.Search` through `@orderlyshop/core-client` and returns product title, brand, price, image, and description as JSON.
|
|
430
|
-
|
|
431
|
-
Apache deployment example:
|
|
444
|
+
Production SSR for Apache/PHP is generated into the built site:
|
|
432
445
|
|
|
433
446
|
```sh
|
|
434
447
|
npm run build
|
|
435
|
-
|
|
436
|
-
cp node_modules/@orderlyshop/web-components/server/php/orderly-product.php dist/orderly-product.php
|
|
448
|
+
npx orderly-generate-server-renderers --site-title "My Shop"
|
|
437
449
|
```
|
|
438
450
|
|
|
439
|
-
|
|
451
|
+
Scaffolded shops run that generator from `npm run build` by default. It writes `dist/product.php`, `dist/category.php`, `dist/.htaccess`, and `dist/orderly-ssr-manifest.json`. The PHP renderers call `SearchService.Search` over gRPC-web, inject semantic HTML into the built `product.html` or `category.html`, and preserve the normal web-component scripts and styles.
|
|
440
452
|
|
|
441
|
-
|
|
442
|
-
ORDERLY_BACKEND_URL=https://service.orderly.shop \
|
|
443
|
-
node node_modules/@orderlyshop/web-components/server/node/product-snapshot-server.mjs
|
|
453
|
+
Runtime options:
|
|
444
454
|
|
|
445
|
-
|
|
446
|
-
|
|
455
|
+
- `ORDERLY_BASE_URL` overrides the backend URL used by PHP.
|
|
456
|
+
- `ORDERLY_SSR_TIMEOUT` controls PHP backend timeout in seconds.
|
|
457
|
+
- `ORDERLY_SSR_HEADERS` can add internal server-side request headers. Do not expose API keys or bearer tokens to browser JavaScript.
|
|
458
|
+
- `ORDERLY_SSR_MANIFEST` can point PHP to a manifest outside the web root.
|
|
447
459
|
|
|
448
|
-
The
|
|
460
|
+
The semantic fallback uses real headings, links, images, schema.org Product/Offer metadata, and small `data-orderly-*` attributes only for behavior-critical values. Components hydrate from that HTML, then hide the fallback and continue as normal interactive web components. Generated SSR output keeps the same HTML for users and crawlers, hides fallback visibility for normal browser hydration, and serves a visible fallback layout to Googlebot. See [`server/README.md`](./server/README.md) for details.
|
|
449
461
|
|
|
450
462
|
## Define Elements
|
|
451
463
|
|
|
@@ -547,15 +559,15 @@ collection.query = searchQuery;
|
|
|
547
559
|
|
|
548
560
|
## Components
|
|
549
561
|
|
|
550
|
-
- `orderly-page-layout` provides reusable page regions for header, header actions, left/right sidebars, content, footer, and overlay content. It includes a default logo image using `https://orderly.shop/home/App_Icon.svg`; override it with `logo-src`, `logo-alt`, and `logo-href`.
|
|
551
|
-
- `orderly-home-page` composes page layout,
|
|
562
|
+
- `orderly-page-layout` provides reusable page regions for header, header actions, responsive primary navigation placement, left/right sidebars, content, footer, and overlay content. It includes a default logo image using `https://orderly.shop/home/App_Icon.svg`; override it with `logo-src`, `logo-alt`, and `logo-href`. Use `primary-nav-mobile-placement="header"` for the common mobile header burger pattern without a duplicate mobile layout template.
|
|
563
|
+
- `orderly-home-page` composes page layout, responsive primary navigation, one product rail per top-level category, basket icon, basket drawer, product detail dialog, and footer. Configure it with `configureShop({ defaultShop })` plus attributes such as `title`, `eyebrow`, `rail-cta-label`, and `product-href`. The product dialog expand link follows the configured product URL mode, and compact `https://orderly.shop/...` product URLs are preserved when it builds hash or path routes.
|
|
552
564
|
- `orderly-category-page` composes page layout, navigation, search, product grid, product detail, basket icon, and basket around a navigation category. Without properties it uses the package default shop configuration. Override with `configureShop({ defaultShop })` once per shop, set `base-url` or `product-href` in markup, or assign `category`, `navigationItems`, `sortOptions`, `client`, `defaultQuery`, and `basketController` from JavaScript for advanced cases. The product dialog expand link uses the configured product URL mode and still supports explicit per-page `product-href` overrides when a shop wants a different physical product page URL.
|
|
553
|
-
- `orderly-checkout-page` composes page layout,
|
|
565
|
+
- `orderly-checkout-page` composes page layout, responsive primary navigation, checkout form, basket order summary, footer, shared basket state, delivery loading, and order-created cleanup. Delivery methods render as radio cards after address entry, service points render as radio-card pickup choices when required, and delivery changes verify the draft so totals update. Configure copy through `configureShop({ defaultShop: { checkoutPageTitle, checkoutPageDescription, checkoutOrderTitle, checkoutTermsHref, checkoutLabels, basketLabels } })`, or assign `client`, `basketController`, `navigationItems`, `checkoutLabels`, and `basketLabels` from JavaScript.
|
|
554
566
|
- `orderly-product-detail-page` composes page layout, navigation, product detail, basket drawer, and footer for a product route. Set `share-url`, the `shareUrl` property, or pass `#url=<encoded-share-url>` in the page URL; compact Orderly slugs are restored to `https://orderly.shop/...` before it calls `SearchService.Search` with `SearchQuery.ShareUrl` and renders the resolved `SearchObject`.
|
|
555
567
|
- `orderly-stored-image` accepts `image: StoredImage`, resolves image URLs from the configured prefix, and applies `RotationDeg`, crop, and full-size metadata in the browser.
|
|
556
568
|
- `orderly-credit` accepts `credit: Credit` or declarative `amount` and `currency` attributes, then renders stylable money markup. DKK values are formatted as `kr. <pris>`, for example `kr. 100,00`.
|
|
557
569
|
- `orderly-product-tile` accepts `product: SearchObject` and emits `orderly-product-selected`, `orderly-add-to-basket`, and `orderly-remove-from-basket`. Templates can bind the product share URL with `data-orderly-bind="share-url"`; anchors without an existing `href` keep the raw share URL, while anchors that already point at a product page are rewritten to the configured physical product route using hash or path mode. Default tiles and statically hydrated category tiles include `schema.org/Product` and `schema.org/Offer` microdata for name, image, URL, description, SKU, brand, price, currency, and in-stock availability when those fields are present. When a `BasketController` is assigned through `basketController`, the default action button toggles between add and remove, using an icon-only button next to the price.
|
|
558
|
-
- `orderly-product-page` accepts `product: SearchObject`, renders all product image thumbnails, switches the selected image on thumbnail click, and exposes product details plus add-to-basket behavior.
|
|
570
|
+
- `orderly-product-page` accepts `product: SearchObject`, renders all product image thumbnails, switches the selected image on thumbnail click, and exposes product details plus add-to-basket behavior. Product-page templates bind `title`, `description`, `brand`, `size`, `color`, `condition`, `price`, `image`, `addLabel`, and `closeLabel`; they also support `basket-action-label`, `basket-action-icon`, and `basket-action-state` so product-page add-to-basket markup can share the same binding names as product tiles.
|
|
559
571
|
- `orderly-search-box` binds to a target `orderly-product-grid`. Use `mode="textbox"` for an inline search input or `mode="icon"` for a header icon that opens a full-page search overlay. Icon mode searches automatically with a 500ms debounce and renders matching product tiles below the search field. Default home and category pages use icon mode next to the basket icon.
|
|
560
572
|
- `orderly-product-grid` accepts `query: SearchQuery`, merges the configured shop query scope, calls `SearchService.Search`, renders its own sort control from `sortOptions`, supports opaque `ContinuationToken` paging, manual paging, dynamic/infinite scroll, and default loading placeholders while the first page is pending.
|
|
561
573
|
- `orderly-product-rail` accepts `query: SearchQuery`, title, CTA label, and CTA href, then renders the search as a horizontal scroll list by composing `orderly-product-grid`. It is useful for homepages and editorial rows where several category searches should be stacked vertically.
|
|
@@ -563,15 +575,39 @@ collection.query = searchQuery;
|
|
|
563
575
|
- `orderly-shop-footer` renders configurable logo, about text, address, contact information, opening hours, and information links.
|
|
564
576
|
- `orderly-basket-icon` and `orderly-basket` share a `BasketController` backed by `DraftOrder` persistence. Basket state events such as `orderly-basket-open`, `orderly-basket-change`, and `orderly-basket-verified` use the current `DraftOrder` directly as `event.detail`, so consumers can derive counts and totals from Core contracts instead of an internal basket data shape. `orderly-basket` renders an item overview, verifies non-empty persisted drafts on load plus later basket mutations through `OrderService.VerifyDraft` when a client or `base-url` is configured, includes a configurable checkout link through `checkout-href` and `checkout-label`, and only exposes quantity selection for lines where `MaxQuantity > 1`. Summary rows now render only backend-provided `DraftOrder` values, never local subtotal/total math, and the component renders both `DraftOrder.Errors` and `DraftOrderLine.Errors`. Custom basket templates can project order-level errors through `data-orderly-slot="errors"`.
|
|
565
577
|
- `orderly-checkout` persists checkout contact and address fields directly on `DraftOrder.Transport`, defaults the phone country picker to `+45`, validates email and phone values with built-in component logic, looks up Danish city names from the entered postal code through Dataforsyningen's `https://api.dataforsyningen.dk/postnumre/{postnr}` endpoint, loads delivery methods and service points, verifies the draft, and calls `OrderService.Create`.
|
|
566
|
-
- `orderly-navigation` uses `NavigationController` and can be subclassed with site-specific `NavigationItem[]`. It is sticky by default, including when placed in `left`, `right`, or `primary-nav`; set `sticky="false"` to opt out. Use `layout="vertical"` for disclosure side navigation, `layout="horizontal"` for the tiered desktop bar, or `layout="burgermenu"` for an icon trigger that expands into the same nested disclosure menu inside a floating panel.
|
|
578
|
+
- `orderly-navigation` uses `NavigationController` and can be subclassed with site-specific `NavigationItem[]`. It is sticky by default, including when placed in `left`, `right`, or `primary-nav`; set `sticky="false"` to opt out. Use `layout="vertical"` for disclosure side navigation, `layout="horizontal"` for the tiered desktop bar, or `layout="burgermenu"` for an icon trigger that expands into the same nested disclosure menu inside a floating panel. Use `layout-desktop="horizontal" layout-mobile="burgermenu"` with `orderly-page-layout primary-nav-mobile-placement="header"` for desktop horizontal nav plus inline mobile burger.
|
|
567
579
|
- `orderly-search-box`, `orderly-sort-select`, `orderly-filter-panel`, and `orderly-load-more` bind to `orderly-product-grid`.
|
|
568
580
|
|
|
581
|
+
## Navigation Patterns
|
|
582
|
+
|
|
583
|
+
There are two different mobile navigation patterns:
|
|
584
|
+
|
|
585
|
+
- `layout="horizontal"` means the navigation owns its responsive fallback where it is placed. It renders the desktop horizontal category bar and automatically falls back to drawer-style mobile navigation on narrow viewports, but it does not move the trigger into the page header action row.
|
|
586
|
+
- `layout-desktop="horizontal" layout-mobile="burgermenu"` plus `primary-nav-mobile-placement="header"` means desktop horizontal navigation and an inline mobile burger in the page header next to search, basket, or other icon buttons. This is the recommended setup for the common storefront header pattern.
|
|
587
|
+
- Custom `data-orderly-viewport="mobile"` page-layout templates are only needed when a shop replaces the whole page layout and wants manual control over where `data-orderly-slot="primary-nav"` is rendered.
|
|
588
|
+
|
|
589
|
+
```html
|
|
590
|
+
<orderly-page-layout primary-nav-mobile-placement="header">
|
|
591
|
+
<a slot="header" href="/">Shop name</a>
|
|
592
|
+
<orderly-search-box slot="header-actions" mode="icon"></orderly-search-box>
|
|
593
|
+
<orderly-basket-icon slot="header-actions"></orderly-basket-icon>
|
|
594
|
+
<orderly-navigation
|
|
595
|
+
slot="primary-nav"
|
|
596
|
+
layout-desktop="horizontal"
|
|
597
|
+
layout-mobile="burgermenu"
|
|
598
|
+
></orderly-navigation>
|
|
599
|
+
<main slot="content">...</main>
|
|
600
|
+
</orderly-page-layout>
|
|
601
|
+
```
|
|
602
|
+
|
|
569
603
|
## Rendering And Styling
|
|
570
604
|
|
|
571
605
|
The package ships baseline default CSS and uses light DOM. Default markup uses stable `orderly-*` class names and CSS variables, so host CSS can style or replace the default look directly.
|
|
572
606
|
|
|
573
607
|
For consistent theming across the whole package, start with the semantic design contract in [`DESIGN.md`](./DESIGN.md). In practice that means overriding `--orderly-color-primary`, `--orderly-color-primary-soft`, `--orderly-color-primary-contrast`, the `--orderly-action-primary-*` and `--orderly-action-secondary-*` tokens, plus shared tokens such as `--orderly-link-accent-color`, `--orderly-selection-*`, and `--orderly-badge-*`. `--orderly-color-accent` is kept as a compatibility alias, but new themes should treat `--orderly-color-primary` as the source of truth.
|
|
574
608
|
|
|
609
|
+
The package declares its fallback tokens with `:where(:root)`, which has zero selector specificity. If your shop sets tokens on `:root`, those values win even when `defineOrderlyWebComponents()` injects the package CSS after your stylesheet. You should not need to duplicate token overrides on `body` unless you intentionally want a scoped override.
|
|
610
|
+
|
|
575
611
|
Example:
|
|
576
612
|
|
|
577
613
|
```css
|
|
@@ -640,7 +676,7 @@ Rendering can be replaced with templates:
|
|
|
640
676
|
|
|
641
677
|
For dynamic paging, `orderly-product-grid` keeps the returned `PageResult.Continuation` as an opaque `ContinuationToken` and sends it as `SearchQuery.Continuation` when the sentinel enters the viewport. Dynamic and infinite paging do not render a load-more button. Use `paging="button"` only when a visible load-more button is desired, `paging="manual"` when another control calls `loadNextPage()`, and `paging="dynamic"` or `paging="infinite"` for automatic loading.
|
|
642
678
|
|
|
643
|
-
Every component has a default light-DOM implementation and matching template hooks. Use `data-orderly-bind` for values, `data-orderly-action` for behavior, and `data-orderly-slot` for repeated or projected content. Product tile templates can bind `basket-action-icon`, `basket-action-label`, and `basket-action-state` and use `data-orderly-action="add-to-basket"` for the add/remove toggle. Product page galleries use `data-orderly-slot="thumbnails"` and `data-orderly-action="select-image"` for custom thumbnail markup. Basket templates can add `data-orderly-slot="errors"` to place order-level `DraftOrder.Errors` exactly where a shop wants them. Product rail templates can replace the outer `layout`, inner `grid`, product item, loading state, and empty state. The main template names are `layout`, `grid`, `footer`, `product`, `thumbnail`, `image`, `basket`, `basket-icon`, `line`, `checkout`, `navigation`, `item`, `search-box`, `sort`, `sort-select`, `filter-panel`, `load-more`, `address-line`, `contact-item`, `opening-hour`, and `information-link`.
|
|
679
|
+
Every component has a default light-DOM implementation and matching template hooks. Use `data-orderly-bind` for values, `data-orderly-action` for behavior, and `data-orderly-slot` for repeated or projected content. Product tile templates can bind `basket-action-icon`, `basket-action-label`, and `basket-action-state` and use `data-orderly-action="add-to-basket"` for the add/remove toggle. Product page templates keep the existing `addLabel` binding and also support `basket-action-label`, `basket-action-icon`, and `basket-action-state` for the same add-to-basket concept; use `data-orderly-action="add-to-basket"` for the action. Product page galleries use `data-orderly-slot="thumbnails"` and `data-orderly-action="select-image"` for custom thumbnail markup. Basket templates can add `data-orderly-slot="errors"` to place order-level `DraftOrder.Errors` exactly where a shop wants them. Product rail templates can replace the outer `layout`, inner `grid`, product item, loading state, and empty state. The main template names are `layout`, `grid`, `footer`, `product`, `thumbnail`, `image`, `basket`, `basket-icon`, `line`, `checkout`, `navigation`, `item`, `search-box`, `sort`, `sort-select`, `filter-panel`, `load-more`, `address-line`, `contact-item`, `opening-hour`, and `information-link`.
|
|
644
680
|
|
|
645
681
|
Product sorting belongs to `orderly-product-grid`: assign `grid.sortOptions = [{ label, orderBy }]` or pass sort options through `orderly-collection-page.sortOptions`. The default grid layout renders the sort select above the products. Custom grid layouts should include `data-orderly-slot="sort"` where the control should appear, and custom sort templates can use `data-orderly-template="sort"` with a `<select data-orderly-action="sort">`.
|
|
646
682
|
|