@luigisbox/luma 0.4.0 → 0.6.0
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/CHANGELOG.md +152 -0
- package/README.md +76 -9
- package/build/baseline.mjs +2 -2
- package/build/vite.mjs +255 -20
- package/docs/ACCESSIBILITY.md +31 -5
- package/package.json +3 -2
- package/src/analytics/chain.ts +1 -1
- package/src/analytics/pageview.ts +1 -1
- package/src/analytics/start.ts +3 -4
- package/src/analytics/wire.ts +1 -1
- package/src/api/ai.ts +32 -20
- package/src/api/token.ts +7 -7
- package/src/core/a11y.ts +6 -35
- package/src/core/context.ts +2 -0
- package/src/core/contrast-toggle.ts +32 -0
- package/src/core/default-button.ts +66 -0
- package/src/core/early-rules.ts +3 -2
- package/src/core/features.ts +109 -0
- package/src/core/frameworks-check.ts +32 -0
- package/src/core/frameworks.ts +35 -0
- package/src/core/image-load.ts +0 -26
- package/src/core/image-preload.ts +29 -0
- package/src/core/image-tags.ts +7 -1
- package/src/core/images.ts +3 -2
- package/src/core/integration.ts +42 -26
- package/src/core/listings.ts +9 -5
- package/src/core/locales.ts +2 -1
- package/src/core/own.ts +7 -3
- package/src/core/recommenders.ts +2 -2
- package/src/core/reconciler.ts +32 -23
- package/src/core/routes.ts +7 -6
- package/src/core/scheduler.ts +39 -5
- package/src/core/speculation.ts +2 -0
- package/src/core/stash.ts +15 -6
- package/src/core/styles.ts +6 -5
- package/src/core/support.ts +1 -1
- package/src/core/takeover.ts +6 -5
- package/src/core/templates.ts +5 -2
- package/src/core/tiles.ts +33 -10
- package/src/core/url.ts +6 -3
- package/src/core/widget-inits.ts +4 -1
- package/src/lit.ts +2 -1
- package/src/locales/cs.json +1 -1
- package/src/locales/de.json +1 -1
- package/src/locales/en.json +1 -1
- package/src/main.ts +70 -53
- package/src/types.ts +48 -14
- package/src/widgets/autocomplete/index.ts +167 -34
- package/src/widgets/autocomplete/style-autocomplete.css +16 -8
- package/src/widgets/autocomplete/template-autocomplete-empty.ts +1 -1
- package/src/widgets/autocomplete/template-autocomplete-sheet.ts +13 -9
- package/src/widgets/listing/applied.ts +87 -0
- package/src/widgets/listing/element.ts +279 -78
- package/src/widgets/listing/intent.ts +15 -0
- package/src/widgets/listing/query.ts +6 -3
- package/src/widgets/listing/stash.ts +33 -16
- package/src/widgets/listing/state.ts +12 -0
- package/src/widgets/listing/view.ts +2 -1
- package/src/widgets/plp/route.ts +3 -2
- package/src/widgets/recommender/index.ts +3 -2
- package/src/widgets/search/direct.ts +39 -0
- package/src/widgets/search/form-url.ts +38 -34
- package/src/widgets/search/in-place.ts +43 -108
- package/src/widgets/search/index.ts +7 -2
- package/src/widgets/search/speculate.ts +48 -27
- package/src/widgets/search/submit.ts +136 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@luigisbox/luma`. Follows [semver](https://semver.org);
|
|
4
|
+
before 1.0, a minor version may break the integration API.
|
|
5
|
+
|
|
6
|
+
## Unreleased
|
|
7
|
+
|
|
8
|
+
## 0.6.0 — 2026-10-20
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Phone sheet: a swipe through the results puts the keyboard away. The sheet
|
|
13
|
+
stays open and grows to the full screen. A tap on its input brings the
|
|
14
|
+
keyboard back.
|
|
15
|
+
- Phone sheet: no tab bar when only one type has results.
|
|
16
|
+
- Phone sheet: "Show all products" is at the end of the list, no longer a bar
|
|
17
|
+
pinned above the keyboard.
|
|
18
|
+
- Phone sheet: the list (and the no-results column) runs on behind Safari's
|
|
19
|
+
floating bars and the keyboard, down to the bottom of the screen. Its end
|
|
20
|
+
scrolls clear of them.
|
|
21
|
+
- Staged filter drawer (`facetsApply: 'staged'`): the held selection is
|
|
22
|
+
fetched in the background once the changes pause, so the apply button
|
|
23
|
+
shows the results without waiting. The results still change only on
|
|
24
|
+
apply. Off with `_global.prefetchFilters: false`, Save-Data or 2G.
|
|
25
|
+
- Staged filter drawer: apply marks the swap. The old list fades out, the
|
|
26
|
+
new products fade in, and a status at the top of the listing says
|
|
27
|
+
"Filters applied · 9 products" for 2.5 s. Translation key
|
|
28
|
+
`search.applied`; CSS variables `--lbx-applied-bg`, `--lbx-applied-fg`,
|
|
29
|
+
`--lbx-applied-top`, `--lbx-applied-offset`, or
|
|
30
|
+
`[data-lbx-applied-cue]::part(pill)`;
|
|
31
|
+
`data-lbx-applied` on the listing meanwhile.
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- Autocomplete "No results": `emptyState` phrases and browse links keep their
|
|
36
|
+
config text and URL when `computedAttributes` override `title` or `url`.
|
|
37
|
+
Before, a browse link could have no URL, and a tap on it did nothing.
|
|
38
|
+
- Autocomplete, phone sheet, no results: each "browse" link is one row again,
|
|
39
|
+
its chevron at the right, not on a line under the title. The links' wrapper
|
|
40
|
+
is now `.e-links` (was `.browse`, the class each link also has).
|
|
41
|
+
|
|
42
|
+
## 0.5.0 — 2026-10-19
|
|
43
|
+
|
|
44
|
+
Upgrading from 0.4.0: read **Changed** first.
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
|
|
48
|
+
- `search.queryUrl` hook: the search page URL for a phrase. Use it when the
|
|
49
|
+
site's server redirects its search form (e.g. `/search?q=x` → `/search/x/`).
|
|
50
|
+
Enter, suggestions and "show all results" then go straight to that page.
|
|
51
|
+
- `search.pageWhileTyping`: `'prefetch'` (default), `'prerender'` or `false`.
|
|
52
|
+
`prerenderWhileTyping: true` equals `'prerender'`.
|
|
53
|
+
- `clientConfig` option `framework` (name or list): build in support for these
|
|
54
|
+
frameworks only. List every framework that renders part of a page Luma runs
|
|
55
|
+
on. Unknown names fail the build.
|
|
56
|
+
- `clientConfig` option `serverRendering: false`: leave out hydration of
|
|
57
|
+
server-rendered listings.
|
|
58
|
+
- `clientConfig` option `locales`: ship only these dictionaries (plus English).
|
|
59
|
+
Unknown locales or an empty list fail the build.
|
|
60
|
+
|
|
61
|
+
### Changed
|
|
62
|
+
|
|
63
|
+
- The build includes only widgets that have a folder (`autocomplete/`,
|
|
64
|
+
`search/`, `plp/`, `recommender <name>/`). Config for a widget without a
|
|
65
|
+
folder is ignored. A `recommender` folder without a name fails the build.
|
|
66
|
+
`yarn dev` still includes every widget.
|
|
67
|
+
- These are built only if their name appears literally in a `.ts`, `.js` (or
|
|
68
|
+
variant) or `.html` file of the integration's repository, outside
|
|
69
|
+
`node_modules`, `dist` and hidden folders:
|
|
70
|
+
- attributes `data-lbx-cart`, `data-lbx-drawer`, `data-lbx-menu`,
|
|
71
|
+
`data-lbx-dropdown`
|
|
72
|
+
- hooks `onRender`, `readQuery`, `queryUrl`, `facetsFor`, `onOpen`,
|
|
73
|
+
`onClose`, `onSelect`, `onReady`
|
|
74
|
+
- options `emptyValues`, `prerenderWhileTyping` / `pageWhileTyping`,
|
|
75
|
+
`contentVisibility`
|
|
76
|
+
|
|
77
|
+
A name that only appears in a `.vue`, `.svelte` or `.hbs` file or in a
|
|
78
|
+
package does not count.
|
|
79
|
+
- The search page for the typed phrase is prefetched by default. Set
|
|
80
|
+
`search.pageWhileTyping: false` to turn it off.
|
|
81
|
+
- Results fetched while typing are cached per query, not per URL.
|
|
82
|
+
- Enter in the search form follows the browser's implicit submission rules.
|
|
83
|
+
- The `_config.ts` check (no functions) runs in development only.
|
|
84
|
+
|
|
85
|
+
### Fixed
|
|
86
|
+
|
|
87
|
+
- WebKit: when frames stalled, the site's listing could show instead of
|
|
88
|
+
Luma's.
|
|
89
|
+
- Safari: listing images were all fetched on render, twice. Bind `src` last
|
|
90
|
+
in your own `<img>` templates too.
|
|
91
|
+
- WebKit: two chunks were fetched twice per page.
|
|
92
|
+
- Autocomplete: ARIA attributes could stay on the site's input after focus
|
|
93
|
+
left.
|
|
94
|
+
|
|
95
|
+
## 0.4.0 — 2026-10-16
|
|
96
|
+
|
|
97
|
+
### Added
|
|
98
|
+
|
|
99
|
+
- Readers can return `{ reference, attributedToList: true }` for clicks and
|
|
100
|
+
add-to-carts on the site's own lists.
|
|
101
|
+
|
|
102
|
+
### Fixed
|
|
103
|
+
|
|
104
|
+
- Analytics: clicks and add-to-carts from Luma's widgets were never credited
|
|
105
|
+
to the search or recommendation that showed the product. They now carry
|
|
106
|
+
`attributed_to_list: true`, as does GA4 `select_item`.
|
|
107
|
+
- Early hold now covers search routes with the query in the path (`urlMatch`
|
|
108
|
+
with a capture group). The snippet is unchanged.
|
|
109
|
+
|
|
110
|
+
## 0.3.0 — 2026-10-15
|
|
111
|
+
|
|
112
|
+
### Added
|
|
113
|
+
|
|
114
|
+
- `alignTo: { field, column }` for the autocomplete panel. By default the
|
|
115
|
+
panel stays within the page's content column.
|
|
116
|
+
|
|
117
|
+
### Changed
|
|
118
|
+
|
|
119
|
+
- Cancelling the phone autocomplete sheet restores the site's input value.
|
|
120
|
+
- Back closes an open staged filter drawer (`facetsApply`) and discards its
|
|
121
|
+
changes.
|
|
122
|
+
- Reloading a listing within a minute after "show more" restores it as left.
|
|
123
|
+
|
|
124
|
+
### Fixed
|
|
125
|
+
|
|
126
|
+
- Phone autocomplete sheet: sized to the visible viewport, shown in
|
|
127
|
+
landscape, `autocorrect="off"`, keeps letters typed while it opens.
|
|
128
|
+
- Autocomplete: lists scroll to top on new results; top product's prices
|
|
129
|
+
sit under its title.
|
|
130
|
+
- iOS Safari: Back to a listing restores position and "show more" pages.
|
|
131
|
+
- Listing position survives a reload or a redirect back within a minute.
|
|
132
|
+
- Position is restored at the clicked link, not a hidden copy.
|
|
133
|
+
- Staged drawer: Apply scrolls to the listing's top; crossing a breakpoint
|
|
134
|
+
closes the drawer.
|
|
135
|
+
- A filter group opened by a selection stays open when the value is
|
|
136
|
+
unticked.
|
|
137
|
+
- Range slider: touch drag on the track follows the finger; vertical scroll
|
|
138
|
+
starting on the track doesn't move a thumb.
|
|
139
|
+
|
|
140
|
+
## 0.2.0 — 2026-10-13
|
|
141
|
+
|
|
142
|
+
### Added
|
|
143
|
+
|
|
144
|
+
- Analytics, configured in `_global/_analytics.ts`: one `collect.<event>` line
|
|
145
|
+
per event, with triggers (`lumaPages`, `lumaClicks`, `lumaCarts`, `dl`,
|
|
146
|
+
`domClick`, `urlChange`, `mutationOf`, `xhrMatching`, `manual`) and readers
|
|
147
|
+
(`fromLuma`, `fromGa4` or a function). `analytics: false` turns it off.
|
|
148
|
+
- `yarn luma chrome --allow HOST`: keep that host's Luigi's Box scripts.
|
|
149
|
+
|
|
150
|
+
## 0.1.0 — 2026-10-12
|
|
151
|
+
|
|
152
|
+
First published version.
|
package/README.md
CHANGED
|
@@ -10,10 +10,10 @@ This package is what an integration is built with. Each integration lives in
|
|
|
10
10
|
its own repository and depends on `@luigisbox/luma`
|
|
11
11
|
([Integration repository](#integration-repository)).
|
|
12
12
|
|
|
13
|
-
> **Pre-release.** Until 1.0, a minor version (0.
|
|
13
|
+
> **Pre-release.** Until 1.0, a minor version (0.7.0) may change the
|
|
14
14
|
> integration API (config keys, template scope, the build); a patch version
|
|
15
|
-
> (0.
|
|
16
|
-
> changes.
|
|
15
|
+
> (0.6.1) only fixes. Depend on `^0.6.0` to take fixes without breaking
|
|
16
|
+
> changes. [`CHANGELOG.md`](CHANGELOG.md) says what each version changed.
|
|
17
17
|
|
|
18
18
|
## Core principles
|
|
19
19
|
|
|
@@ -245,6 +245,51 @@ import { clientConfig } from '@luigisbox/luma/build/vite.mjs';
|
|
|
245
245
|
export default clientConfig(import.meta.url, { plugins: [mkcert()], server: { host: 'localhost', https: {} } });
|
|
246
246
|
```
|
|
247
247
|
|
|
248
|
+
`framework` names the site's frontend framework, so the build carries Luma's
|
|
249
|
+
support for that framework only. Without it, every integration carries the
|
|
250
|
+
support for all of them (waiting for each one's hydration, writing URLs through
|
|
251
|
+
its router, keeping out of its page snapshots), and Luma tells them apart on
|
|
252
|
+
each page. Declared, a listing page loads about 1.4 to 2.3 kB gzip less, and
|
|
253
|
+
every page about 0.2 kB less unless React hydrates the whole document. It is
|
|
254
|
+
one of the following, or a list of them:
|
|
255
|
+
|
|
256
|
+
| `framework` | the site |
|
|
257
|
+
|---|---|
|
|
258
|
+
| `next` | Next.js (app or pages router) |
|
|
259
|
+
| `remix`, `react-router` | Remix, React Router 7, Hydrogen |
|
|
260
|
+
| `react` | a React app in a root element (Vite, Create React App) |
|
|
261
|
+
| `vue`, `nuxt` | Vue 2 or 3, Nuxt |
|
|
262
|
+
| `angular` | Angular |
|
|
263
|
+
| `svelte`, `sveltekit` | a Svelte app, SvelteKit |
|
|
264
|
+
| `astro` | Astro (add the framework of its islands that hold Luma's anchors) |
|
|
265
|
+
| `turbo` | Turbo Drive or Turbolinks |
|
|
266
|
+
| `none` | server-rendered pages: jQuery, htmx, Alpine |
|
|
267
|
+
|
|
268
|
+
```ts
|
|
269
|
+
export default clientConfig(import.meta.url, { framework: 'vue', plugins: [mkcert()], server: { host: 'localhost', https: {} } });
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
`serverRendering: false` declares that the site has no server-rendered
|
|
273
|
+
listings (the server-side includes above): the build then leaves out adopting
|
|
274
|
+
and hydrating the server's markup, about 0.9 kB gzip on a listing page. Leave
|
|
275
|
+
it out when the site uses them or may; in development Luma reports
|
|
276
|
+
server-rendered markup a build without them meets.
|
|
277
|
+
|
|
278
|
+
`locales` lists the locales the site uses (`['cs', 'sk']`): every page then
|
|
279
|
+
carries the map of those dictionaries and English only (about 20 B gzip per
|
|
280
|
+
locale left out). A widget in a locale not listed reads English. Without it,
|
|
281
|
+
every locale Luma has a dictionary for. A locale Luma has no dictionary for
|
|
282
|
+
fails the build.
|
|
283
|
+
|
|
284
|
+
List every framework that renders a part of the page Luma places into or
|
|
285
|
+
navigates with, on every page Luma runs on (`['astro', 'react']` for an Astro
|
|
286
|
+
site with React islands). Without its framework's support, Luma does not
|
|
287
|
+
wait for that framework's hydration: React or Svelte renders the page anew,
|
|
288
|
+
Vue drops Luma's element, Angular binds the wrong element, a router puts its
|
|
289
|
+
own URL back. In development (`yarn dev`) Luma reports a framework the page
|
|
290
|
+
uses and the build leaves out in `window.__lbx.health.errors`. An unknown name
|
|
291
|
+
fails the build.
|
|
292
|
+
|
|
248
293
|
Its `tsconfig.json` extends `@luigisbox/luma/tsconfig.json`, includes
|
|
249
294
|
`integration/**/*` and `node_modules/@luigisbox/luma/src/**/*`, and maps `@/*`
|
|
250
295
|
to `./node_modules/@luigisbox/luma/src/*`. Its `package.json` depends on
|
|
@@ -265,19 +310,31 @@ integration/
|
|
|
265
310
|
recommender <name>/ _config.ts [_init.ts] _translations.ts
|
|
266
311
|
```
|
|
267
312
|
|
|
268
|
-
- **`_config.ts` is JSON** (checked at boot
|
|
313
|
+
- **`_config.ts` is JSON** (checked at boot in development: `yarn dev`);
|
|
314
|
+
anything that needs code goes in
|
|
269
315
|
`_init.ts`. `_global/_init.ts` runs first and can change any config or return
|
|
270
316
|
`false` to stop; a widget's `_init.ts` gets that widget's config. Every config
|
|
271
317
|
key is typed and documented in `src/types.ts`.
|
|
318
|
+
- **A widget is its folder.** The build carries only the widgets the
|
|
319
|
+
integration has folders for (`autocomplete/`, `search/`, `plp/`,
|
|
320
|
+
`recommender <name>/`) and analytics only where a folder has an
|
|
321
|
+
`_analytics.ts`: an integration with an autocomplete only loads about half
|
|
322
|
+
as much on every page as one with every widget. A config `_global/_init.ts`
|
|
323
|
+
creates for a widget without its folder is ignored. The development server
|
|
324
|
+
(`yarn dev`) carries every widget.
|
|
272
325
|
- **`_init.ts` ships and runs on every page; `_widget.ts` loads with its
|
|
273
326
|
widget.** Keep in `_init.ts` only what decides whether and where a widget
|
|
274
|
-
runs (`disabled`, `active`, `readQuery`, `items`, `intent`, selectors set in
|
|
327
|
+
runs (`disabled`, `active`, `readQuery`, `queryUrl`, `items`, `intent`, selectors set in
|
|
275
328
|
code, switching the site's own widgets off). Hooks only a widget calls
|
|
276
329
|
(`computedAttributes`, `toFilter`, `facetsFor`, `onRender`, `onOpen`, …) go
|
|
277
330
|
in the folder's optional `_widget.ts`, same signature (its return value is
|
|
278
331
|
ignored): it is loaded with the widget's chunk and run once before its
|
|
279
332
|
context is made, `_global/_widget.ts` first. `__integration.ts` hands it
|
|
280
333
|
over as a lazy glob: `widgetInits: import.meta.glob('./*/_widget.ts', { import: 'default' })`.
|
|
334
|
+
The build calls `onRender`, `readQuery`, `queryUrl`, `facetsFor` and the autocomplete's
|
|
335
|
+
`onOpen`, `onClose`, `onSelect`, `onReady` only where a file of the
|
|
336
|
+
integration's repository (a script or `.html` file, not in `node_modules`, `dist` or a hidden folder) names them, as setting
|
|
337
|
+
them does (`config.search.onRender = …`).
|
|
281
338
|
- **`style-host.css`** hides the host's own listing or suggestions, only while
|
|
282
339
|
Luma has the page. Other `style-*.css` load with their widget. Luma's built-in
|
|
283
340
|
CSS sits in `@layer lbx`, so the integration's and the site's CSS win.
|
|
@@ -328,7 +385,10 @@ export default ({ r, i, img, price }: SearchResultScope) => html`
|
|
|
328
385
|
- **Helpers** in every scope: `t(key, params)`, `price(n)`, `plain()`,
|
|
329
386
|
`first()`, `include()`, and `img(r, i)` (a complete `<img>` in its placeholder
|
|
330
387
|
box) / `image(r, i)` (its attributes, for your own markup), configured by
|
|
331
|
-
`_global.images` (srcset, sizes, the eager first row, placeholders).
|
|
388
|
+
`_global.images` (srcset, sizes, the eager first row, placeholders). In
|
|
389
|
+
your own `<img>`, bind `src` last: Safari starts the fetch when `src` is
|
|
390
|
+
set, so a `loading` or `srcset` bound after it loads every image at once,
|
|
391
|
+
and twice.
|
|
332
392
|
- **Pagination** is "show more" only: templates get `results`, `more` and
|
|
333
393
|
`showMore`; there are no numbered pages.
|
|
334
394
|
- **No results under filters**: the scope still holds the selected groups,
|
|
@@ -348,15 +408,21 @@ export default ({ r, i, img, price }: SearchResultScope) => html`
|
|
|
348
408
|
### Behaviour switches
|
|
349
409
|
|
|
350
410
|
On by default unless noted; each falls back to what the page would do anyway.
|
|
411
|
+
`emptyValues`, `prerenderWhileTyping` and `contentVisibility`, off by
|
|
412
|
+
default, are in the build only where a file of the integration's repository
|
|
413
|
+
(a script or `.html` file, not in `node_modules`, `dist` or a hidden folder) names them, as `_config.ts` or `_init.ts` does when
|
|
414
|
+
it sets them; a switch on by default that no file names is built as on.
|
|
351
415
|
|
|
352
416
|
| Config | What it does | Turn it off when |
|
|
353
417
|
|---|---|---|
|
|
354
418
|
| `search.inPlaceQuery` | a new query on the search page renders in place, without a page load | the host's page-view analytics or server-rendered parts of the search page must follow every query |
|
|
355
419
|
| `search.prefetchWhileTyping` | the search result is fetched once the typed phrase settles, so Enter shows it at once | |
|
|
420
|
+
| `search.pageWhileTyping` (`'prefetch'`, `'prerender'`, `false`) | the search page of the typed phrase is fetched ahead (Chrome, Edge; Firefox and Safari as they ship it), so Enter from another page skips the site's server render; `'prerender'` renders it ahead as well (Chrome, Edge) | the site cannot take a document request per typed phrase; `'prerender'` only where its tags wait for `prerenderingchange` |
|
|
421
|
+
| `search.queryUrl` (an `_init.ts` hook, off unless set) | where the site's server redirects its search form to the query's page (`/search?q=x` to `/search/x/`), names that page: Enter, the autocomplete's "show all" and a picked query load it directly, without the redirect, and the result fetched while typing is shown there | the form's other fields decide the page, or the site must handle every search itself |
|
|
356
422
|
| `restoreOnBack` | Back from a product restores the listing (every page shown) and the followed tile's position, as does the page loaded again within a minute of following a link (a reload, a link whose server redirects back to it); Luma turns the browser's own scroll restoration (`history.scrollRestoration`) off for the listing's history entry until it has placed the page, unless the site set it | |
|
|
357
423
|
| `prefetchNextPage` | "show more" is fetched as the shopper nears the end | |
|
|
358
424
|
| `contentVisibility` (opt-in) | tiles out of view skip style, layout and paint, each at its own measured size: a long list's re-render about halves | keep it off where a tile draws outside its box (a hover panel, a badge hanging out) or holds a `position: fixed` element |
|
|
359
|
-
| `_global.prefetchFilters` | a filter, sort or chip is fetched on hover, touch or focus | |
|
|
425
|
+
| `_global.prefetchFilters` | a filter, sort or chip is fetched on hover, touch or focus; in a drawer with `facetsApply: 'staged'`, the selection it holds is fetched once the changes pause, so its apply button shows the results without waiting | |
|
|
360
426
|
| `_global.speculation` | product pages are prerendered on hover (`'prerender'`, `'prefetch'`, `false`) | the site's server or its product-page scripts can't take a render per unfollowed hover |
|
|
361
427
|
|
|
362
428
|
### Analytics
|
|
@@ -416,7 +482,7 @@ collect.purchase.on(dl('purchase')).read(fromGa4.purchase);
|
|
|
416
482
|
|---|---|---|
|
|
417
483
|
| `lumaPages()` | each page: the first, the next page of a single-page app, a page restored from the back/forward cache, a prerendered page once it is shown. Filtering or sorting a Luma listing is not a new page | `{ url, referrer }` |
|
|
418
484
|
| `lumaClicks()` | a click on a product in a Luma widget: any link to it, middle and modifier clicks included, and a pick in the autocomplete | `{ reference, result, index, list }` |
|
|
419
|
-
| `lumaCarts()` | a click on a `[data-lbx-cart]` button in a Luma product tile (its value: the quantity). `_global.addToCart(result, { count, el, event })` adds the product to the site's cart, with or without analytics | `{ reference, result, index, list, count, price? }` |
|
|
485
|
+
| `lumaCarts()` | a click on a `[data-lbx-cart]` button in a Luma product tile (its value: the quantity). `_global.addToCart(result, { count, el, event })` adds the product to the site's cart, with or without analytics. The attribute is written in a template of the integration as `data-lbx-cart`: the build includes add-to-cart only where a file of the integration's repository (a script or `.html` file, not in `node_modules`, `dist` or a hidden folder) has it | `{ reference, result, index, list, count, price? }` |
|
|
420
486
|
| `dl(event)` | a dataLayer push with that event name, object or `gtag()` form, including pushes made before Luma loaded. `_global.dataLayer` in `_config.ts` names another layer | `{ event, eventType, data, ecommerce }` |
|
|
421
487
|
| `domClick(selector)` | a click (or middle click) on an element of the site's that matches `selector` | `{ element, event }` |
|
|
422
488
|
| `urlChange()` | a navigation in a single-page app | `{ url, previousUrl }` |
|
|
@@ -522,7 +588,8 @@ integration repository").
|
|
|
522
588
|
add-to-carts on Luma's products and dataLayer pushes are kept for the next
|
|
523
589
|
page. A/B tests are not supported yet (`listing_ab_test` is always `false`).
|
|
524
590
|
- **Prerendering** costs the site a page render per unfollowed hover
|
|
525
|
-
(`speculation: false` turns it off)
|
|
591
|
+
(`speculation: false` turns it off), and the search page fetched ahead
|
|
592
|
+
while typing a document per settled phrase (`search.pageWhileTyping: false`).
|
|
526
593
|
- **Early hold**: the snippet carries no site's rules, so the first page
|
|
527
594
|
view is not held.
|
|
528
595
|
- **Host routers out of reach**: where Luma cannot find the host's router (Vue
|
package/build/baseline.mjs
CHANGED
|
@@ -53,8 +53,8 @@ export const ALLOW = [
|
|
|
53
53
|
{
|
|
54
54
|
// Limited availability (Chromium only). document.prerendering through `any`, as above.
|
|
55
55
|
feature: 'speculation-rules',
|
|
56
|
-
files: ['src/core/speculation.ts', 'src/core/takeover.ts', 'src/main.ts'],
|
|
57
|
-
why: "The prerender rule
|
|
56
|
+
files: ['src/core/speculation.ts', 'src/core/takeover.ts', 'src/main.ts', 'src/widgets/search/speculate.ts'],
|
|
57
|
+
why: "The product-page prerender rule, and the search page of the phrase typed fetched ahead (prerendered with pageWhileTyping 'prerender'), are added only when HTMLScriptElement.supports('speculationrules'); without it Enter loads the page as usual and its result comes from the stash. document.prerendering is undefined (falsy) elsewhere, so a hold's timer starts at once.",
|
|
58
58
|
},
|
|
59
59
|
];
|
|
60
60
|
|