vite-plugin-shopify-theme-islands 1.0.2 → 1.1.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/README.md +68 -25
- package/dist/contract.d.ts +139 -0
- package/dist/discovery.d.ts +12 -0
- package/dist/index.d.ts +11 -71
- package/dist/index.js +173 -92
- package/dist/revive-module.d.ts +25 -0
- package/dist/runtime.d.ts +11 -6
- package/dist/runtime.js +137 -52
- package/package.json +1 -1
- package/skills/custom-directives/SKILL.md +89 -26
- package/skills/directives/SKILL.md +56 -6
- package/skills/lifecycle/SKILL.md +36 -21
- package/skills/setup/SKILL.md +11 -7
- package/skills/writing-islands/SKILL.md +29 -2
package/README.md
CHANGED
|
@@ -190,16 +190,51 @@ Loads the island after a fixed delay. The delay in milliseconds is read from the
|
|
|
190
190
|
|
|
191
191
|
Unlike `client:idle`, which waits for genuine browser idle time, `client:defer` always waits exactly the specified number of milliseconds.
|
|
192
192
|
|
|
193
|
+
### `client:interaction`
|
|
194
|
+
|
|
195
|
+
Loads the island when the user interacts with the element. Listens for `mouseenter`, `touchstart`, and `focusin` by default — the module starts downloading the moment the user moves their cursor toward or focuses the element.
|
|
196
|
+
|
|
197
|
+
```html
|
|
198
|
+
<cart-flyout client:interaction>
|
|
199
|
+
<!-- ... -->
|
|
200
|
+
</cart-flyout>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
The attribute value overrides the events for that element only (space-separated MDN event names):
|
|
204
|
+
|
|
205
|
+
```html
|
|
206
|
+
<!-- only mouseenter — touchstart and focusin are excluded -->
|
|
207
|
+
<cart-flyout client:interaction="mouseenter">
|
|
208
|
+
<!-- ... -->
|
|
209
|
+
</cart-flyout>
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Combine with `client:visible` to avoid attaching listeners to off-screen elements. Because directives resolve sequentially, interaction listeners are only registered once the element has entered the viewport:
|
|
213
|
+
|
|
214
|
+
```html
|
|
215
|
+
<mega-menu client:visible client:interaction>
|
|
216
|
+
<!-- loads when visible, then waits for hover/touch/focus -->
|
|
217
|
+
</mega-menu>
|
|
218
|
+
```
|
|
219
|
+
|
|
193
220
|
### Combining directives
|
|
194
221
|
|
|
195
|
-
Directives can be combined — the element
|
|
222
|
+
Directives can be combined — the element works through each condition in sequence before loading. The resolution order is: `visible` → `media` → `idle` → `defer` → `interaction` → custom directives.
|
|
196
223
|
|
|
197
224
|
```html
|
|
225
|
+
<!-- must scroll into view, then wait for user interaction -->
|
|
226
|
+
<product-recommendations client:visible client:interaction>
|
|
227
|
+
<!-- ... -->
|
|
228
|
+
</product-recommendations>
|
|
229
|
+
|
|
230
|
+
<!-- must scroll into view, then wait for idle time -->
|
|
198
231
|
<heavy-widget client:visible client:idle>
|
|
199
232
|
<!-- ... -->
|
|
200
233
|
</heavy-widget>
|
|
201
234
|
```
|
|
202
235
|
|
|
236
|
+
Because conditions resolve sequentially, each directive is only evaluated after the previous one has passed. Interaction listeners, for example, are never attached to an element that isn't yet visible.
|
|
237
|
+
|
|
203
238
|
### Custom directives
|
|
204
239
|
|
|
205
240
|
Register your own loading conditions via `directives.custom`. A custom directive is a function that receives a `load` callback and decides when to call it.
|
|
@@ -207,24 +242,28 @@ Register your own loading conditions via `directives.custom`. A custom directive
|
|
|
207
242
|
#### 1. Write the directive
|
|
208
243
|
|
|
209
244
|
```ts
|
|
210
|
-
// src/directives/
|
|
245
|
+
// src/directives/hash.ts
|
|
211
246
|
import type { ClientDirective } from "vite-plugin-shopify-theme-islands";
|
|
212
247
|
|
|
213
|
-
const
|
|
214
|
-
|
|
248
|
+
const hashDirective: ClientDirective = (load, opts) => {
|
|
249
|
+
const target = opts.value;
|
|
250
|
+
if (location.hash === target) { load(); return; }
|
|
251
|
+
window.addEventListener("hashchange", () => {
|
|
252
|
+
if (location.hash === target) load();
|
|
253
|
+
});
|
|
215
254
|
};
|
|
216
255
|
|
|
217
|
-
export default
|
|
256
|
+
export default hashDirective;
|
|
218
257
|
```
|
|
219
258
|
|
|
220
|
-
|
|
259
|
+
Useful for anchor-linked sections — `<product-reviews client:hash="#reviews">` loads only when the URL fragment matches, so deep-links like `/products/shirt#reviews` activate the island immediately while other visitors never load it.
|
|
221
260
|
|
|
222
261
|
The function signature is `(load, options, el) => void | Promise<void>`:
|
|
223
262
|
|
|
224
263
|
| Parameter | Type | Description |
|
|
225
264
|
| --------------- | ---------------------- | ----------------------------------------------------- |
|
|
226
265
|
| `load` | `() => Promise<void>` | Call this to trigger the island module load |
|
|
227
|
-
| `options.name` | `string` | The matched attribute name, e.g. `'client:
|
|
266
|
+
| `options.name` | `string` | The matched attribute name, e.g. `'client:hash'` |
|
|
228
267
|
| `options.value` | `string` | The attribute value; empty string if no value was set |
|
|
229
268
|
| `el` | `HTMLElement` | The island element |
|
|
230
269
|
|
|
@@ -238,7 +277,7 @@ export default defineConfig({
|
|
|
238
277
|
plugins: [
|
|
239
278
|
shopifyThemeIslands({
|
|
240
279
|
directives: {
|
|
241
|
-
custom: [{ name: "client:
|
|
280
|
+
custom: [{ name: "client:hash", entrypoint: "./src/directives/hash.ts" }],
|
|
242
281
|
},
|
|
243
282
|
}),
|
|
244
283
|
],
|
|
@@ -250,9 +289,9 @@ The `entrypoint` supports Vite aliases.
|
|
|
250
289
|
#### 3. Use it in Liquid
|
|
251
290
|
|
|
252
291
|
```html
|
|
253
|
-
<
|
|
292
|
+
<product-reviews client:hash="#reviews">
|
|
254
293
|
<!-- ... -->
|
|
255
|
-
</
|
|
294
|
+
</product-reviews>
|
|
256
295
|
```
|
|
257
296
|
|
|
258
297
|
#### Ordering
|
|
@@ -260,21 +299,21 @@ The `entrypoint` supports Vite aliases.
|
|
|
260
299
|
Built-in directives always run first. A custom directive is only invoked after all built-in conditions on the element have been met. This means you can gate a custom directive behind `client:visible` to avoid wiring event listeners for off-screen elements:
|
|
261
300
|
|
|
262
301
|
```html
|
|
263
|
-
<!-- element must enter the viewport before the
|
|
264
|
-
<
|
|
302
|
+
<!-- element must enter the viewport before the hash handler is registered -->
|
|
303
|
+
<product-reviews client:visible client:hash="#reviews">
|
|
265
304
|
<!-- ... -->
|
|
266
|
-
</
|
|
305
|
+
</product-reviews>
|
|
267
306
|
```
|
|
268
307
|
|
|
269
308
|
The custom directive owns the `load()` call — the built-in chain never calls it directly when a custom directive is matched.
|
|
270
309
|
|
|
271
|
-
Multiple custom directives on the same element use AND semantics — the island loads only once all matched directives have called `load()`. For example, given two registered custom directives `client:
|
|
310
|
+
Multiple custom directives on the same element use AND semantics — the island loads only once all matched directives have called `load()`. For example, given two registered custom directives `client:hash` and `client:network`:
|
|
272
311
|
|
|
273
312
|
```html
|
|
274
|
-
<!-- client:visible runs first (built-in); then both client:
|
|
275
|
-
<
|
|
313
|
+
<!-- client:visible runs first (built-in); then both client:hash and client:network must fire -->
|
|
314
|
+
<product-reviews client:visible client:hash="#reviews" client:network="4g">
|
|
276
315
|
<!-- ... -->
|
|
277
|
-
</
|
|
316
|
+
</product-reviews>
|
|
278
317
|
```
|
|
279
318
|
|
|
280
319
|
## Configuration
|
|
@@ -307,6 +346,10 @@ shopifyThemeIslands({
|
|
|
307
346
|
attribute: "client:defer", // HTML attribute name
|
|
308
347
|
delay: 3000, // fallback delay (ms) when the attribute has no value
|
|
309
348
|
},
|
|
349
|
+
interaction: {
|
|
350
|
+
attribute: "client:interaction", // HTML attribute name
|
|
351
|
+
events: ["mouseenter", "touchstart", "focusin"], // DOM events that trigger load
|
|
352
|
+
},
|
|
310
353
|
custom: [], // custom directives — see Custom directives above
|
|
311
354
|
},
|
|
312
355
|
});
|
|
@@ -372,12 +415,12 @@ The `/events` entry point provides typed helpers that unwrap `e.detail` for you
|
|
|
372
415
|
```ts
|
|
373
416
|
import { onIslandLoad, onIslandError } from "vite-plugin-shopify-theme-islands/events";
|
|
374
417
|
|
|
375
|
-
const offLoad = onIslandLoad(({ tag }) => {
|
|
376
|
-
analytics.track("island_loaded", { tag });
|
|
418
|
+
const offLoad = onIslandLoad(({ tag, duration, attempt }) => {
|
|
419
|
+
analytics.track("island_loaded", { tag, duration, attempt });
|
|
377
420
|
});
|
|
378
421
|
|
|
379
|
-
const offError = onIslandError(({ tag, error }) => {
|
|
380
|
-
errorReporter.capture(error, { context: tag });
|
|
422
|
+
const offError = onIslandError(({ tag, error, attempt }) => {
|
|
423
|
+
errorReporter.capture(error, { context: tag, attempt });
|
|
381
424
|
});
|
|
382
425
|
|
|
383
426
|
// Remove listeners when no longer needed (e.g. SPA teardown)
|
|
@@ -395,10 +438,10 @@ document.addEventListener("islands:load", (e) => {
|
|
|
395
438
|
});
|
|
396
439
|
```
|
|
397
440
|
|
|
398
|
-
| Event | Detail properties
|
|
399
|
-
| --------------- |
|
|
400
|
-
| `islands:load` | `tag`
|
|
401
|
-
| `islands:error` | `tag`, `error`
|
|
441
|
+
| Event | Detail properties | When it fires |
|
|
442
|
+
| --------------- | ------------------------------ | ---------------------------------------------------------- |
|
|
443
|
+
| `islands:load` | `tag`, `duration`, `attempt` | Island module resolves successfully |
|
|
444
|
+
| `islands:error` | `tag`, `error`, `attempt` | Load or custom directive fails (alongside `console.error`) |
|
|
402
445
|
|
|
403
446
|
`islands:error` fires on each retry attempt, not just the final failure. Multiple independent listeners are supported — each receives its own event.
|
|
404
447
|
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin ↔ Runtime contract (deep module).
|
|
3
|
+
*
|
|
4
|
+
* Single source of truth for the payload shape, key→tag derivation, and defaults.
|
|
5
|
+
* Plugin and runtime both depend on this module in-process.
|
|
6
|
+
*/
|
|
7
|
+
/** Loader function for one island chunk. */
|
|
8
|
+
export type IslandLoader = () => Promise<unknown>;
|
|
9
|
+
/** Directive config for the runtime (built-in + no plugin-only `custom` entrypoints). */
|
|
10
|
+
export interface RuntimeDirectivesConfig {
|
|
11
|
+
visible?: {
|
|
12
|
+
attribute?: string;
|
|
13
|
+
rootMargin?: string;
|
|
14
|
+
threshold?: number;
|
|
15
|
+
};
|
|
16
|
+
idle?: {
|
|
17
|
+
attribute?: string;
|
|
18
|
+
timeout?: number;
|
|
19
|
+
};
|
|
20
|
+
media?: {
|
|
21
|
+
attribute?: string;
|
|
22
|
+
};
|
|
23
|
+
defer?: {
|
|
24
|
+
attribute?: string;
|
|
25
|
+
delay?: number;
|
|
26
|
+
};
|
|
27
|
+
interaction?: {
|
|
28
|
+
attribute?: string;
|
|
29
|
+
events?: string[];
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/** Retry configuration. */
|
|
33
|
+
export interface RetryConfig {
|
|
34
|
+
retries?: number;
|
|
35
|
+
delay?: number;
|
|
36
|
+
}
|
|
37
|
+
/** Options passed from plugin to runtime (subset of plugin options). */
|
|
38
|
+
export interface ReviveOptions {
|
|
39
|
+
directives?: RuntimeDirectivesConfig;
|
|
40
|
+
debug?: boolean;
|
|
41
|
+
retry?: RetryConfig;
|
|
42
|
+
}
|
|
43
|
+
/** Options passed to a custom client directive function. */
|
|
44
|
+
export interface ClientDirectiveOptions {
|
|
45
|
+
/** The matched attribute name, e.g. `'client:on-click'` */
|
|
46
|
+
name: string;
|
|
47
|
+
/** The attribute value; empty string if no value was set */
|
|
48
|
+
value: string;
|
|
49
|
+
}
|
|
50
|
+
/** Custom directive function at runtime (load, opts, element). */
|
|
51
|
+
export type ClientDirective = (load: () => Promise<void>, options: ClientDirectiveOptions, el: HTMLElement) => void | Promise<void>;
|
|
52
|
+
/** Event detail for the `islands:load` DOM event. */
|
|
53
|
+
export interface IslandLoadDetail {
|
|
54
|
+
/** The custom element tag name, e.g. `'product-form'` */
|
|
55
|
+
tag: string;
|
|
56
|
+
/** Milliseconds from directive resolution to successful module load (chunk fetch time). */
|
|
57
|
+
duration: number;
|
|
58
|
+
/** Which attempt succeeded. 1 = first try, 2 = first retry, etc. */
|
|
59
|
+
attempt: number;
|
|
60
|
+
}
|
|
61
|
+
/** Event detail for the `islands:error` DOM event. */
|
|
62
|
+
export interface IslandErrorDetail {
|
|
63
|
+
/** The custom element tag name, e.g. `'product-form'` */
|
|
64
|
+
tag: string;
|
|
65
|
+
/** The error thrown by the loader or custom directive */
|
|
66
|
+
error: unknown;
|
|
67
|
+
/** Which attempt failed. 1 = initial attempt, 2 = first retry, etc. */
|
|
68
|
+
attempt: number;
|
|
69
|
+
}
|
|
70
|
+
declare global {
|
|
71
|
+
interface DocumentEventMap {
|
|
72
|
+
"islands:load": CustomEvent<IslandLoadDetail>;
|
|
73
|
+
"islands:error": CustomEvent<IslandErrorDetail>;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Payload the plugin emits and the runtime consumes.
|
|
78
|
+
* Islands: glob key → loader (e.g. "/frontend/js/islands/product-form.ts" → loader).
|
|
79
|
+
* Custom directives: attribute name → directive implementation (resolved at build).
|
|
80
|
+
* Options may be partial; runtime uses normalizeReviveOptions() to fill defaults.
|
|
81
|
+
*/
|
|
82
|
+
export interface RevivePayload {
|
|
83
|
+
islands: Record<string, IslandLoader>;
|
|
84
|
+
options?: ReviveOptions;
|
|
85
|
+
customDirectives?: Map<string, ClientDirective>;
|
|
86
|
+
}
|
|
87
|
+
/** Fully resolved options; all directive and retry fields have defaults applied. */
|
|
88
|
+
export interface NormalizedReviveOptions {
|
|
89
|
+
directives: {
|
|
90
|
+
visible: {
|
|
91
|
+
attribute: string;
|
|
92
|
+
rootMargin: string;
|
|
93
|
+
threshold: number;
|
|
94
|
+
};
|
|
95
|
+
idle: {
|
|
96
|
+
attribute: string;
|
|
97
|
+
timeout: number;
|
|
98
|
+
};
|
|
99
|
+
media: {
|
|
100
|
+
attribute: string;
|
|
101
|
+
};
|
|
102
|
+
defer: {
|
|
103
|
+
attribute: string;
|
|
104
|
+
delay: number;
|
|
105
|
+
};
|
|
106
|
+
interaction: {
|
|
107
|
+
attribute: string;
|
|
108
|
+
events: string[];
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
debug: boolean;
|
|
112
|
+
retry: {
|
|
113
|
+
retries: number;
|
|
114
|
+
delay: number;
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/** Default directive config. Single source of truth for plugin merge and runtime normalization. */
|
|
118
|
+
export declare const DEFAULT_DIRECTIVES: NormalizedReviveOptions["directives"];
|
|
119
|
+
/**
|
|
120
|
+
* Applies default values for all runtime options.
|
|
121
|
+
* Single source of truth so plugin and runtime do not duplicate defaults.
|
|
122
|
+
*/
|
|
123
|
+
export declare function normalizeReviveOptions(options?: ReviveOptions): NormalizedReviveOptions;
|
|
124
|
+
export type KeyToTagResult = {
|
|
125
|
+
tag: string;
|
|
126
|
+
skip?: boolean;
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* Maps a glob key (e.g. "/frontend/js/islands/product-form.ts") to a custom element tag.
|
|
130
|
+
* Return { tag, skip: true } to exclude this entry from the island map.
|
|
131
|
+
*/
|
|
132
|
+
export type KeyToTagFn = (key: string) => KeyToTagResult;
|
|
133
|
+
/** Default: last path segment, extension stripped; skip (and warn) when tag has no hyphen. */
|
|
134
|
+
export declare function defaultKeyToTag(key: string): KeyToTagResult;
|
|
135
|
+
/**
|
|
136
|
+
* Builds tag → loader map from payload.
|
|
137
|
+
* Applies the default key→tag derivation and deduplicates by tag (first wins).
|
|
138
|
+
*/
|
|
139
|
+
export declare function buildIslandMap(payload: RevivePayload): Map<string, IslandLoader>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Matches .ts or .js extension. Exported for plugin transform/watch filters. */
|
|
2
|
+
export declare const TS_JS_RE: RegExp;
|
|
3
|
+
/** Matches the island mixin import. Exported for plugin transform/watch detection. */
|
|
4
|
+
export declare const ISLAND_IMPORT_RE: RegExp;
|
|
5
|
+
/** True if file is under any of the given absolute directory paths. */
|
|
6
|
+
export declare function inDirectory(file: string, absDirs: string[]): boolean;
|
|
7
|
+
/** Paths for load() virtual module: "/relative/to/root" form, forward slashes. */
|
|
8
|
+
export declare function getIslandPathsForLoad(islandFiles: Set<string>, root: string): string[];
|
|
9
|
+
/** Scan from root for files containing the island import; returns paths (not in absDirs). */
|
|
10
|
+
export declare function discoverIslandFiles(root: string, absDirs: string[]): Set<string>;
|
|
11
|
+
/** Tag names (filename without extension) for TS/JS files in a directory. Used for debug logging. */
|
|
12
|
+
export declare function collectTagNames(dir: string): string[];
|
package/dist/index.d.ts
CHANGED
|
@@ -1,41 +1,7 @@
|
|
|
1
1
|
import type { Plugin } from "vite";
|
|
2
2
|
/** A function that triggers the load of an island module. */
|
|
3
3
|
export type ClientDirectiveLoader = () => Promise<void>;
|
|
4
|
-
|
|
5
|
-
export interface ClientDirectiveOptions {
|
|
6
|
-
/** The matched attribute name, e.g. `'client:on-click'` */
|
|
7
|
-
name: string;
|
|
8
|
-
/** The attribute value; empty string if no value was set */
|
|
9
|
-
value: string;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* A custom client directive function.
|
|
13
|
-
*
|
|
14
|
-
* Called by the runtime when a matching attribute is found on an island element.
|
|
15
|
-
* The function is responsible for calling `load()` when the desired condition is met.
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```ts
|
|
19
|
-
* // src/directives/hover.ts
|
|
20
|
-
* import type { ClientDirective } from 'vite-plugin-shopify-theme-islands';
|
|
21
|
-
*
|
|
22
|
-
* const hoverDirective: ClientDirective = (load, _opts, el) => {
|
|
23
|
-
* el.addEventListener('mouseenter', load, { once: true });
|
|
24
|
-
* };
|
|
25
|
-
*
|
|
26
|
-
* export default hoverDirective;
|
|
27
|
-
* ```
|
|
28
|
-
*
|
|
29
|
-
* Register it in `vite.config.ts`:
|
|
30
|
-
* ```ts
|
|
31
|
-
* shopifyThemeIslands({
|
|
32
|
-
* directives: {
|
|
33
|
-
* custom: [{ name: 'client:hover', entrypoint: './src/directives/hover.ts' }],
|
|
34
|
-
* },
|
|
35
|
-
* })
|
|
36
|
-
* ```
|
|
37
|
-
*/
|
|
38
|
-
export type ClientDirective = (load: ClientDirectiveLoader, options: ClientDirectiveOptions, el: HTMLElement) => void | Promise<void>;
|
|
4
|
+
export type { ClientDirective, ClientDirectiveOptions } from "./contract.js";
|
|
39
5
|
/** Plugin option entry for registering a custom client directive. */
|
|
40
6
|
export interface ClientDirectiveDefinition {
|
|
41
7
|
/** HTML attribute name, e.g. `'client:on-click'` */
|
|
@@ -73,38 +39,19 @@ export interface DirectivesConfig {
|
|
|
73
39
|
/** Fallback delay (ms) when the attribute has no value. Default: `3000` */
|
|
74
40
|
delay?: number;
|
|
75
41
|
};
|
|
42
|
+
/** Configuration for the `client:interaction` directive (mouseenter/touchstart/focusin). */
|
|
43
|
+
interaction?: {
|
|
44
|
+
/** HTML attribute name. Default: `'client:interaction'` */
|
|
45
|
+
attribute?: string;
|
|
46
|
+
/** DOM event names to listen for. Default: `['mouseenter', 'touchstart', 'focusin']` */
|
|
47
|
+
events?: string[];
|
|
48
|
+
};
|
|
76
49
|
/** Custom client directives to register. Each entry maps an attribute name to a module entrypoint. */
|
|
77
50
|
custom?: ClientDirectiveDefinition[];
|
|
78
51
|
}
|
|
79
|
-
/**
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
export interface RetryConfig {
|
|
83
|
-
/** Number of times to retry after the initial failure. Default: `0` (no auto-retry) */
|
|
84
|
-
retries?: number;
|
|
85
|
-
/** Base delay in ms between retries; doubles each attempt. Default: `1000` */
|
|
86
|
-
delay?: number;
|
|
87
|
-
}
|
|
88
|
-
/** Event detail for the `islands:load` DOM event. */
|
|
89
|
-
export interface IslandLoadDetail {
|
|
90
|
-
/** The custom element tag name, e.g. `'product-form'` */
|
|
91
|
-
tag: string;
|
|
92
|
-
}
|
|
93
|
-
/** Event detail for the `islands:error` DOM event. */
|
|
94
|
-
export interface IslandErrorDetail {
|
|
95
|
-
/** The custom element tag name, e.g. `'product-form'` */
|
|
96
|
-
tag: string;
|
|
97
|
-
/** The error thrown by the loader or custom directive */
|
|
98
|
-
error: unknown;
|
|
99
|
-
}
|
|
100
|
-
declare global {
|
|
101
|
-
interface DocumentEventMap {
|
|
102
|
-
/** Fired after an island module resolves successfully. */
|
|
103
|
-
"islands:load": CustomEvent<IslandLoadDetail>;
|
|
104
|
-
/** Fired when an island load or custom directive fails. Fired on each retry attempt. */
|
|
105
|
-
"islands:error": CustomEvent<IslandErrorDetail>;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
52
|
+
/** Event detail and runtime options (single source of truth in contract). */
|
|
53
|
+
import type { RetryConfig } from "./contract.js";
|
|
54
|
+
export type { IslandLoadDetail, IslandErrorDetail, ReviveOptions, RetryConfig, RuntimeDirectivesConfig, } from "./contract.js";
|
|
108
55
|
export interface ShopifyThemeIslandsOptions {
|
|
109
56
|
/** Directories to scan for island files. Accepts paths or Vite aliases. Default: `['/frontend/js/islands/']` */
|
|
110
57
|
directories?: string | string[];
|
|
@@ -115,11 +62,4 @@ export interface ShopifyThemeIslandsOptions {
|
|
|
115
62
|
/** Automatic retry behaviour for failed island loads. */
|
|
116
63
|
retry?: RetryConfig;
|
|
117
64
|
}
|
|
118
|
-
export interface ReviveOptions {
|
|
119
|
-
directives?: RuntimeDirectivesConfig;
|
|
120
|
-
/** Log island activation and directive events to the console. Default: `false` */
|
|
121
|
-
debug?: boolean;
|
|
122
|
-
/** Automatic retry behaviour for failed island loads. */
|
|
123
|
-
retry?: RetryConfig;
|
|
124
|
-
}
|
|
125
65
|
export default function shopifyThemeIslands(options?: ShopifyThemeIslandsOptions): Plugin;
|