@excom/fetchable-element 0.1.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.
Files changed (29) hide show
  1. package/.rush/temp/chunked-rush-logs/fetchable-element.apply-exports.chunks.jsonl +1 -0
  2. package/.rush/temp/chunked-rush-logs/fetchable-element.build_docs.chunks.jsonl +1 -0
  3. package/.rush/temp/chunked-rush-logs/fetchable-element.build_package-metas.chunks.jsonl +1 -0
  4. package/.rush/temp/operation/apply-exports/all.log +1 -0
  5. package/.rush/temp/operation/apply-exports/log-chunks.jsonl +1 -0
  6. package/.rush/temp/operation/apply-exports/state.json +3 -0
  7. package/.rush/temp/operation/build_docs/all.log +1 -0
  8. package/.rush/temp/operation/build_docs/log-chunks.jsonl +1 -0
  9. package/.rush/temp/operation/build_docs/state.json +3 -0
  10. package/.rush/temp/operation/build_package-metas/all.log +1 -0
  11. package/.rush/temp/operation/build_package-metas/log-chunks.jsonl +1 -0
  12. package/.rush/temp/operation/build_package-metas/state.json +3 -0
  13. package/.rush/temp/shrinkwrap-deps.json +3 -0
  14. package/config/rig.json +6 -0
  15. package/index.ts +399 -0
  16. package/package.json +48 -0
  17. package/rush-logs/fetchable-element.apply-exports.cache.log +1 -0
  18. package/rush-logs/fetchable-element.apply-exports.log +1 -0
  19. package/rush-logs/fetchable-element.build_docs.cache.log +1 -0
  20. package/rush-logs/fetchable-element.build_docs.log +1 -0
  21. package/rush-logs/fetchable-element.build_package-metas.cache.log +1 -0
  22. package/rush-logs/fetchable-element.build_package-metas.log +1 -0
  23. package/support/custom-elements.json +368 -0
  24. package/support/dist-docs/fetchable-element.md +120 -0
  25. package/support/docs/README.md +67 -0
  26. package/support/package-meta.json +218 -0
  27. package/support/tests/fetch-lifecycle.test.ts +401 -0
  28. package/support/tests/fetchable-element.test.ts +184 -0
  29. package/tsconfig.json +5 -0
@@ -0,0 +1,368 @@
1
+ {
2
+ "schemaVersion": "1.0.0",
3
+ "modules": [
4
+ {
5
+ "kind": "javascript-module",
6
+ "path": "index.ts",
7
+ "declarations": [
8
+ {
9
+ "kind": "mixin",
10
+ "name": "FetchableElement",
11
+ "mixins": [
12
+ {
13
+ "name": "AbortableElement",
14
+ "package": "@excom/abortable-element"
15
+ },
16
+ {
17
+ "name": "LoadableElement",
18
+ "package": "@excom/loadable-element"
19
+ }
20
+ ],
21
+ "description": "Composition base that owns the request lifecycle for `fetch()`-backed elements — building request args (attributes, a referenced `<form>`, or a custom override), tracking loading / success / error state (through `LoadableElement`), and canceling in-flight requests (via `AbortableElement`) when superseded or disconnected. Not a registered element on its own (tag is intentionally `noop-tag`) — compose it via `Neutron.compose([FetchableElement, ...])` and the consumer element inherits every attribute, state, and event declared below. Concrete consumers include `<provider-fetch>` (fetch-on-attribute-change), `<super-form>` (fetch-on-submit), and `<web-authn>` (WebAuthn ceremonies that still round-trip to a server). Subclasses call `doFetch(url, requestInit)` — typically built via `getFetchArgs(customFetchArgs?)`, which deep-merges (lowest → highest priority) the element's own attributes, the `<form>` referenced by `form-ref` (action/method/enctype/fields), and any custom args passed in — to run the request and drive `is-loading` / `is-success` / `is-error` / `provision` automatically. A prior in-flight request is canceled before a new one starts.",
22
+ "attributes": [
23
+ {
24
+ "name": "form-ref",
25
+ "type": {
26
+ "text": "string"
27
+ },
28
+ "description": "CSS selector for a `<form>` to source the request from — its `action` (URL), `method`, `enctype` (Content-Type), and field values (as the JSON payload) all take priority over the matching attributes below. Omit to build the request entirely from attributes / custom `doFetch()` args.",
29
+ "fieldName": "formRef",
30
+ "values": [
31
+ "<CSS Selector>"
32
+ ]
33
+ },
34
+ {
35
+ "name": "has-body",
36
+ "type": {
37
+ "text": "boolean"
38
+ },
39
+ "description": "Force a request body even for methods that don't imply one (`GET` / `HEAD`). Already implied for `POST` / `PUT` / `PATCH`.",
40
+ "fieldName": "hasBody"
41
+ },
42
+ {
43
+ "name": "api-url",
44
+ "type": {
45
+ "text": "string"
46
+ },
47
+ "description": "Endpoint URL. When the request has no body, the JSON payload (from `form-ref` or custom `doFetch()` args) is merged in as query params instead.",
48
+ "fieldName": "apiUrl",
49
+ "default": ""
50
+ },
51
+ {
52
+ "name": "api-method",
53
+ "type": {
54
+ "text": "string"
55
+ },
56
+ "description": "HTTP method. Always uppercased before the request is sent.",
57
+ "fieldName": "apiMethod",
58
+ "default": "GET"
59
+ },
60
+ {
61
+ "name": "header-accept",
62
+ "type": {
63
+ "text": "string"
64
+ },
65
+ "description": "`Accept` request header.",
66
+ "fieldName": "headerAccept",
67
+ "default": "application/json"
68
+ },
69
+ {
70
+ "name": "header-content-type",
71
+ "type": {
72
+ "text": "string"
73
+ },
74
+ "description": "`Content-Type` request header. Dropped entirely when the request has no body.",
75
+ "fieldName": "headerContentType",
76
+ "default": "application/json"
77
+ },
78
+ {
79
+ "name": "header-cache-control",
80
+ "type": {
81
+ "text": "string"
82
+ },
83
+ "description": "`Cache-Control` request header. Unset by default (browser default caching applies).",
84
+ "fieldName": "headerCacheControl"
85
+ },
86
+ {
87
+ "name": "fetch-redirect",
88
+ "type": {
89
+ "text": "string"
90
+ },
91
+ "description": "`RequestInit.redirect` mode. Unset defers to the browser default (`follow`).",
92
+ "fieldName": "fetchRedirect",
93
+ "values": [
94
+ "follow",
95
+ "error",
96
+ "manual"
97
+ ]
98
+ },
99
+ {
100
+ "name": "fetch-credentials",
101
+ "type": {
102
+ "text": "string"
103
+ },
104
+ "description": "`RequestInit.credentials` mode.",
105
+ "fieldName": "fetchCredentials",
106
+ "default": "include",
107
+ "values": [
108
+ "omit",
109
+ "same-origin",
110
+ "include"
111
+ ]
112
+ },
113
+ {
114
+ "name": "is-loading",
115
+ "type": {
116
+ "text": "boolean"
117
+ },
118
+ "description": "A request is currently in flight.",
119
+ "fieldName": "isLoading"
120
+ },
121
+ {
122
+ "name": "is-success",
123
+ "type": {
124
+ "text": "boolean"
125
+ },
126
+ "description": "The most recent request resolved successfully. Mutually exclusive with `is-error`.",
127
+ "fieldName": "isSuccess"
128
+ },
129
+ {
130
+ "name": "is-error",
131
+ "type": {
132
+ "text": "boolean"
133
+ },
134
+ "description": "The most recent request failed (non-2xx status, network error, or a thrown error other than `AbortError`). Fires with the `error` event.",
135
+ "fieldName": "isError"
136
+ }
137
+ ],
138
+ "members": [
139
+ {
140
+ "kind": "field",
141
+ "name": "formRef",
142
+ "type": {
143
+ "text": "string"
144
+ },
145
+ "privacy": "public",
146
+ "readonly": false,
147
+ "description": "CSS selector for a `<form>` to source the request from — its `action` (URL), `method`, `enctype` (Content-Type), and field values (as the JSON payload) all take priority over the matching attributes below. Omit to build the request entirely from attributes / custom `doFetch()` args.",
148
+ "_neutron": {
149
+ "surface": "option"
150
+ }
151
+ },
152
+ {
153
+ "kind": "field",
154
+ "name": "hasBody",
155
+ "type": {
156
+ "text": "boolean"
157
+ },
158
+ "privacy": "public",
159
+ "readonly": false,
160
+ "description": "Force a request body even for methods that don't imply one (`GET` / `HEAD`). Already implied for `POST` / `PUT` / `PATCH`.",
161
+ "_neutron": {
162
+ "surface": "option"
163
+ }
164
+ },
165
+ {
166
+ "kind": "field",
167
+ "name": "apiUrl",
168
+ "type": {
169
+ "text": "string"
170
+ },
171
+ "privacy": "public",
172
+ "readonly": false,
173
+ "description": "Endpoint URL. When the request has no body, the JSON payload (from `form-ref` or custom `doFetch()` args) is merged in as query params instead.",
174
+ "default": "",
175
+ "_neutron": {
176
+ "surface": "option"
177
+ }
178
+ },
179
+ {
180
+ "kind": "field",
181
+ "name": "apiMethod",
182
+ "type": {
183
+ "text": "string"
184
+ },
185
+ "privacy": "public",
186
+ "readonly": false,
187
+ "description": "HTTP method. Always uppercased before the request is sent.",
188
+ "default": "GET",
189
+ "_neutron": {
190
+ "surface": "option"
191
+ }
192
+ },
193
+ {
194
+ "kind": "field",
195
+ "name": "headerAccept",
196
+ "type": {
197
+ "text": "string"
198
+ },
199
+ "privacy": "public",
200
+ "readonly": false,
201
+ "description": "`Accept` request header.",
202
+ "default": "application/json",
203
+ "_neutron": {
204
+ "surface": "option"
205
+ }
206
+ },
207
+ {
208
+ "kind": "field",
209
+ "name": "headerContentType",
210
+ "type": {
211
+ "text": "string"
212
+ },
213
+ "privacy": "public",
214
+ "readonly": false,
215
+ "description": "`Content-Type` request header. Dropped entirely when the request has no body.",
216
+ "default": "application/json",
217
+ "_neutron": {
218
+ "surface": "option"
219
+ }
220
+ },
221
+ {
222
+ "kind": "field",
223
+ "name": "headerCacheControl",
224
+ "type": {
225
+ "text": "string"
226
+ },
227
+ "privacy": "public",
228
+ "readonly": false,
229
+ "description": "`Cache-Control` request header. Unset by default (browser default caching applies).",
230
+ "_neutron": {
231
+ "surface": "option"
232
+ }
233
+ },
234
+ {
235
+ "kind": "field",
236
+ "name": "fetchRedirect",
237
+ "type": {
238
+ "text": "string"
239
+ },
240
+ "privacy": "public",
241
+ "readonly": false,
242
+ "description": "`RequestInit.redirect` mode. Unset defers to the browser default (`follow`).",
243
+ "_neutron": {
244
+ "surface": "option"
245
+ }
246
+ },
247
+ {
248
+ "kind": "field",
249
+ "name": "fetchCredentials",
250
+ "type": {
251
+ "text": "string"
252
+ },
253
+ "privacy": "public",
254
+ "readonly": false,
255
+ "description": "`RequestInit.credentials` mode.",
256
+ "default": "include",
257
+ "_neutron": {
258
+ "surface": "option"
259
+ }
260
+ },
261
+ {
262
+ "kind": "field",
263
+ "name": "isLoading",
264
+ "type": {
265
+ "text": "boolean"
266
+ },
267
+ "privacy": "public",
268
+ "readonly": true,
269
+ "description": "A request is currently in flight.",
270
+ "_neutron": {
271
+ "surface": "state"
272
+ }
273
+ },
274
+ {
275
+ "kind": "field",
276
+ "name": "isSuccess",
277
+ "type": {
278
+ "text": "boolean"
279
+ },
280
+ "privacy": "public",
281
+ "readonly": true,
282
+ "description": "The most recent request resolved successfully. Mutually exclusive with `is-error`.",
283
+ "_neutron": {
284
+ "surface": "state"
285
+ }
286
+ },
287
+ {
288
+ "kind": "field",
289
+ "name": "isError",
290
+ "type": {
291
+ "text": "boolean"
292
+ },
293
+ "privacy": "public",
294
+ "readonly": true,
295
+ "description": "The most recent request failed (non-2xx status, network error, or a thrown error other than `AbortError`). Fires with the `error` event.",
296
+ "_neutron": {
297
+ "surface": "state"
298
+ }
299
+ },
300
+ {
301
+ "kind": "field",
302
+ "name": "provision",
303
+ "type": {
304
+ "text": "FetchResponse",
305
+ "expanded": "{ bodyUsed: boolean; headers: [string, string][]; ok: boolean; redirected: boolean; status: number; statusText: string; type: ResponseType; url: string; body: unknown; }"
306
+ },
307
+ "privacy": "public",
308
+ "readonly": false,
309
+ "description": "Response payload on success, or error payload on failure. Success shape: `{ status, statusText, ok, headers, url, redirected, bodyUsed, type, body }`. Failure shape is either that same response shape (server responded with an error status) or `{ message, stack }` (request never completed). Not reflected as an attribute.",
310
+ "_neutron": {
311
+ "surface": "option"
312
+ }
313
+ }
314
+ ],
315
+ "events": [
316
+ {
317
+ "name": "{tag}-loading",
318
+ "description": "Dispatched immediately before the request is sent.",
319
+ "type": {
320
+ "text": "FetchableLoadingEvent",
321
+ "expanded": "CustomEvent & { type: \"{tag}-loading\"; detail: void; bubbles: true; cancelable: true; composed: true }"
322
+ }
323
+ },
324
+ {
325
+ "name": "{tag}-success",
326
+ "description": "Dispatched when the request resolves successfully. `event.detail` is the parsed response (see `provision`).",
327
+ "type": {
328
+ "text": "FetchableSuccessEvent",
329
+ "expanded": "CustomEvent & { type: \"{tag}-success\"; detail: { bodyUsed: boolean; headers: [string, string][]; ok: boolean; redirected: boolean; status: number; statusText: string; type: ResponseType; url: string; body: unknown; }; bubbles: true; cancelable: true; composed: true }"
330
+ }
331
+ },
332
+ {
333
+ "name": "{tag}-error",
334
+ "description": "Dispatched when the request fails — non-2xx status, network error, or a thrown error. `event.detail` is the error payload (see `provision`). Not dispatched for aborted requests.",
335
+ "type": {
336
+ "text": "FetchableErrorEvent",
337
+ "expanded": "CustomEvent & { type: \"{tag}-error\"; detail: { bodyUsed: boolean; headers: [string, string][]; ok: boolean; redirected: boolean; status: number; statusText: string; type: ResponseType; url: string; body: unknown; } | { message: string; stack?: string }; bubbles: true; cancelable: true; composed: true }"
338
+ }
339
+ }
340
+ ],
341
+ "_neutron": {
342
+ "provisions": [
343
+ {
344
+ "name": "provision",
345
+ "type": {
346
+ "text": "FetchResponse",
347
+ "expanded": "{ bodyUsed: boolean; headers: [string, string][]; ok: boolean; redirected: boolean; status: number; statusText: string; type: ResponseType; url: string; body: unknown; }"
348
+ },
349
+ "description": "Response payload on success, or error payload on failure. Success shape: `{ status, statusText, ok, headers, url, redirected, bodyUsed, type, body }`. Failure shape is either that same response shape (server responded with an error status) or `{ message, stack }` (request never completed). Not reflected as an attribute.",
350
+ "fieldName": "provision"
351
+ }
352
+ ]
353
+ }
354
+ }
355
+ ],
356
+ "exports": [
357
+ {
358
+ "kind": "js",
359
+ "name": "FetchableElement",
360
+ "declaration": {
361
+ "name": "FetchableElement",
362
+ "module": "index.ts"
363
+ }
364
+ }
365
+ ]
366
+ }
367
+ ]
368
+ }
@@ -0,0 +1,120 @@
1
+ # fetchable-element
2
+
3
+ Composition base that owns the `fetch()` lifecycle for Neutron elements —
4
+ build the request from attributes, a `<form>`, or a custom override, then
5
+ track loading / success / error state automatically.
6
+
7
+ ## Features
8
+
9
+ - **Shared lifecycle** States, `provision` and events come from [loadable-element](/nucleus/packages/loadable-element)
10
+
11
+ - **Attribute-driven requests** URL, method, headers, redirect, and
12
+ credentials all configurable declaratively
13
+ - **Form-aware** Point `form-ref` at a `<form>` to source action, method,
14
+ enctype, and field values
15
+ - **Merged payloads** Attributes, form, and custom args deep-merge
16
+ (lowest → highest priority)
17
+ - **Lifecycle state** `is-loading` / `is-success` / `is-error` managed
18
+ for you
19
+ - **Provision** `provision` is the parsed response (or error payload) for
20
+ Quark `prop("provision")` — not a reflected attribute
21
+ - **Cancel-safe** Superseded or disconnected requests are aborted via
22
+ `AbortableElement`
23
+
24
+ ## Installation
25
+
26
+
27
+ `@excom/fetchable-element` v0.1.0
28
+
29
+ ```bash
30
+ pnpm add @excom/fetchable-element
31
+ ```
32
+
33
+ ```bash
34
+ npm install @excom/fetchable-element
35
+ ```
36
+
37
+ ```bash
38
+ yarn add @excom/fetchable-element
39
+ ```
40
+
41
+ ### Import
42
+
43
+ ```ts
44
+ import { /* … */ } from "@excom/fetchable-element";
45
+ ```
46
+
47
+
48
+
49
+ ## Usage
50
+
51
+ Compose `FetchableElement`, then call `doFetch(url, requestInit)` —
52
+ usually built via `getFetchArgs(customFetchArgs?)` — whenever the
53
+ subclass decides a request should run. Concrete consumers include
54
+ `<provider-fetch>` (fetch on attribute change), `<super-form>` (fetch on
55
+ submit), and `<web-authn>` (WebAuthn ceremonies that still round-trip to
56
+ a server).
57
+
58
+ ```ts
59
+ import { Neutron } from "@excom/neutron";
60
+ import { FetchableElement } from "@excom/fetchable-element";
61
+
62
+ export const RefreshOnClick = Neutron.compose([
63
+ FetchableElement,
64
+ Neutron({ tag: "refresh-on-click" }),
65
+ ])
66
+ .onEvent("click", ({ getFetchArgs }) => ({
67
+ doFetch: getFetchArgs(),
68
+ }));
69
+
70
+ RefreshOnClick.define();
71
+ ```
72
+
73
+ ```html
74
+ <refresh-on-click api-url="/api/status"></refresh-on-click>
75
+ ```
76
+
77
+ Every prop, state field, and event documented below is inherited
78
+ verbatim by any element that composes `FetchableElement` — it flattens
79
+ directly into that element's own generated docs, so `<provider-fetch>`
80
+ and friends don't redeclare it.
81
+
82
+ ### API Reference
83
+
84
+
85
+ #### Attributes
86
+
87
+ | Name | Surface | Type | Default | Values | Description |
88
+ | --- | --- | --- | --- | --- | --- |
89
+ | `form-ref` | option | `string` | | `<CSS Selector>` | CSS selector for a `<form>` to source the request from — its `action` (URL), `method`, `enctype` (Content-Type), and field values (as the JSON payload) all take priority over the matching attributes below. Omit to build the request entirely from attributes / custom `doFetch()` args. |
90
+ | `has-body` | option | `boolean` | | | Force a request body even for methods that don't imply one (`GET` / `HEAD`). Already implied for `POST` / `PUT` / `PATCH`. |
91
+ | `api-url` | option | `string` | `""` | | Endpoint URL. When the request has no body, the JSON payload (from `form-ref` or custom `doFetch()` args) is merged in as query params instead. |
92
+ | `api-method` | option | `string` | `"GET"` | | HTTP method. Always uppercased before the request is sent. |
93
+ | `header-accept` | option | `string` | `"application/json"` | | `Accept` request header. |
94
+ | `header-content-type` | option | `string` | `"application/json"` | | `Content-Type` request header. Dropped entirely when the request has no body. |
95
+ | `header-cache-control` | option | `string` | | | `Cache-Control` request header. Unset by default (browser default caching applies). |
96
+ | `fetch-redirect` | option | `string` | | `"follow"` \| `"error"` \| `"manual"` | `RequestInit.redirect` mode. Unset defers to the browser default (`follow`). |
97
+ | `fetch-credentials` | option | `string` | `"include"` | `"omit"` \| `"same-origin"` \| `"include"` | `RequestInit.credentials` mode. |
98
+ | `is-loading` | state | `boolean` | | | A request is currently in flight. |
99
+ | `is-success` | state | `boolean` | | | The most recent request resolved successfully. Mutually exclusive with `is-error`. |
100
+ | `is-error` | state | `boolean` | | | The most recent request failed (non-2xx status, network error, or a thrown error other than `AbortError`). Fires with the `error` event. |
101
+
102
+ #### Provision
103
+
104
+ | Name | Type | Description |
105
+ | --- | --- | --- |
106
+ | `provision` | `FetchResponse` (`{ bodyUsed: boolean; headers: [string, string][]; ok: boolean; redirected: boolean; status: number; statusText: string; type: ResponseType; url: string; body: unknown; }`) | Response payload on success, or error payload on failure. Success shape: `{ status, statusText, ok, headers, url, redirected, bodyUsed, type, body }`. Failure shape is either that same response shape (server responded with an error status) or `{ message, stack }` (request never completed). Not reflected as an attribute. |
107
+
108
+ #### Fires
109
+
110
+ | Name | Type | Description |
111
+ | --- | --- | --- |
112
+ | `{tag}-loading` | `FetchableLoadingEvent` (`CustomEvent & { type: "{tag}-loading"; detail: void; bubbles: true; cancelable: true; composed: true }`) | Dispatched immediately before the request is sent. |
113
+ | `{tag}-success` | `FetchableSuccessEvent` (`CustomEvent & { type: "{tag}-success"; detail: { bodyUsed: boolean; headers: [string, string][]; ok: boolean; redirected: boolean; status: number; statusText: string; type: ResponseType; url: string; body: unknown; }; bubbles: true; cancelable: true; composed: true }`) | Dispatched when the request resolves successfully. `event.detail` is the parsed response (see `provision`). |
114
+ | `{tag}-error` | `FetchableErrorEvent` (`CustomEvent & { type: "{tag}-error"; detail: { bodyUsed: boolean; headers: [string, string][]; ok: boolean; redirected: boolean; status: number; statusText: string; type: ResponseType; url: string; body: unknown; } \| { message: string; stack?: string }; bubbles: true; cancelable: true; composed: true }`) | Dispatched when the request fails — non-2xx status, network error, or a thrown error. `event.detail` is the error payload (see `provision`). Not dispatched for aborted requests. |
115
+
116
+
117
+
118
+ There are no demos for this package — see
119
+ [provider-fetch](/nucleus/packages/provider-fetch) for `FetchableElement` in
120
+ action against a real endpoint.
@@ -0,0 +1,67 @@
1
+ # fetchable-element
2
+
3
+ Composition base that owns the `fetch()` lifecycle for Neutron elements —
4
+ build the request from attributes, a `<form>`, or a custom override, then
5
+ track loading / success / error state automatically.
6
+
7
+ ## Features
8
+
9
+ - **Shared lifecycle** States, `provision` and events come from [loadable-element](/nucleus/packages/loadable-element)
10
+
11
+ - **Attribute-driven requests** URL, method, headers, redirect, and
12
+ credentials all configurable declaratively
13
+ - **Form-aware** Point `form-ref` at a `<form>` to source action, method,
14
+ enctype, and field values
15
+ - **Merged payloads** Attributes, form, and custom args deep-merge
16
+ (lowest → highest priority)
17
+ - **Lifecycle state** `is-loading` / `is-success` / `is-error` managed
18
+ for you
19
+ - **Provision** `provision` is the parsed response (or error payload) for
20
+ Quark `prop("provision")` — not a reflected attribute
21
+ - **Cancel-safe** Superseded or disconnected requests are aborted via
22
+ `AbortableElement`
23
+
24
+ ## Installation
25
+
26
+ <include-content is-active template-ref="/views/install-section/install-section.html"></include-content>
27
+
28
+ ## Usage
29
+
30
+ Compose `FetchableElement`, then call `doFetch(url, requestInit)` —
31
+ usually built via `getFetchArgs(customFetchArgs?)` — whenever the
32
+ subclass decides a request should run. Concrete consumers include
33
+ `<provider-fetch>` (fetch on attribute change), `<super-form>` (fetch on
34
+ submit), and `<web-authn>` (WebAuthn ceremonies that still round-trip to
35
+ a server).
36
+
37
+ ```ts
38
+ import { Neutron } from "@excom/neutron";
39
+ import { FetchableElement } from "@excom/fetchable-element";
40
+
41
+ export const RefreshOnClick = Neutron.compose([
42
+ FetchableElement,
43
+ Neutron({ tag: "refresh-on-click" }),
44
+ ])
45
+ .onEvent("click", ({ getFetchArgs }) => ({
46
+ doFetch: getFetchArgs(),
47
+ }));
48
+
49
+ RefreshOnClick.define();
50
+ ```
51
+
52
+ ```html
53
+ <refresh-on-click api-url="/api/status"></refresh-on-click>
54
+ ```
55
+
56
+ Every prop, state field, and event documented below is inherited
57
+ verbatim by any element that composes `FetchableElement` — it flattens
58
+ directly into that element's own generated docs, so `<provider-fetch>`
59
+ and friends don't redeclare it.
60
+
61
+ ### API Reference
62
+
63
+ <include-content is-active template-ref="/views/api-reference/api-reference.html"></include-content>
64
+
65
+ There are no demos for this package — see
66
+ [provider-fetch](/nucleus/packages/provider-fetch) for `FetchableElement` in
67
+ action against a real endpoint.