@economist/web-apple-pay 1.2.0 → 1.4.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/README.md +42 -0
- package/dist/index.js +24 -0
- package/dist/src/apple-pay-button.d.ts +17 -0
- package/dist/src/apple-pay-button.js +24 -0
- package/dist/src/apple-pay-button.stories.js +1300 -0
- package/dist/src/apple-pay-modal.stories.js +1142 -0
- package/dist/src/index.js +24 -0
- package/dist/src/stories/fixtures/offer.d.ts +2 -0
- package/dist/src/stories/fixtures/offer.js +28 -0
- package/dist/src/stories/utils/story-env.d.ts +11 -0
- package/dist/src/stories/utils/story-env.js +141 -0
- package/package.json +8 -1
package/README.md
CHANGED
|
@@ -78,6 +78,26 @@ If `merchantId` is not configured, Apple Pay availability checks return `false`
|
|
|
78
78
|
- Skips rendering for excluded variants (`bundle`, `insider_print`).
|
|
79
79
|
- Forwards `data-logged-in` from button to modal (`modal.dataset.loggedIn`).
|
|
80
80
|
|
|
81
|
+
#### Awaiting render completion — `whenReady()`
|
|
82
|
+
|
|
83
|
+
Use `whenReady()` to await the component's render lifecycle after appending it
|
|
84
|
+
to the DOM. This is the supported, stable way to know whether Apple Pay is
|
|
85
|
+
available without touching lifecycle internals.
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
container.appendChild(btn); // spec-compliant — browser fires connectedCallback naturally
|
|
89
|
+
await btn.whenReady(); // resolves when rendering is complete
|
|
90
|
+
if (btn.style.display !== 'none') {
|
|
91
|
+
// Apple Pay rendered successfully
|
|
92
|
+
} else {
|
|
93
|
+
btn.remove(); // unavailable or suppressed
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
> **Important:** calling `whenReady()` _before_ `appendChild` resolves
|
|
98
|
+
> immediately to `undefined` — it does not wait for a future connection.
|
|
99
|
+
> Always call it after appending the element.
|
|
100
|
+
|
|
81
101
|
### `ApplePayModal`
|
|
82
102
|
|
|
83
103
|
- Opened by `ApplePayButton` click.
|
|
@@ -100,6 +120,7 @@ Consumers should listen for this event and continue payment orchestration.
|
|
|
100
120
|
- `defineApplePayElements()`: registers both custom elements.
|
|
101
121
|
- `configureApplePay(config)`: sets required runtime config (merchant ID and wallet API base URL, with optional debug bypass).
|
|
102
122
|
- `ApplePayButton`: button component class.
|
|
123
|
+
- `whenReady(): Promise<void>` — resolves when the current render lifecycle completes (available or hidden). Resolves immediately if called before the element is connected.
|
|
103
124
|
- `ApplePayModal`: modal component class.
|
|
104
125
|
- `ensureApplePayLogoSymbol()`: logo symbol injection helper.
|
|
105
126
|
- `Offer`: offer contract type used by component props.
|
|
@@ -142,3 +163,24 @@ Then in a consuming app:
|
|
|
142
163
|
```sh
|
|
143
164
|
yalc add @economist/web-apple-pay
|
|
144
165
|
```
|
|
166
|
+
|
|
167
|
+
## Storybook
|
|
168
|
+
|
|
169
|
+
Run Storybook locally:
|
|
170
|
+
|
|
171
|
+
```sh
|
|
172
|
+
npm run storybook --workspace @economist/web-apple-pay
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Build static Storybook output:
|
|
176
|
+
|
|
177
|
+
```sh
|
|
178
|
+
npm run build-storybook --workspace @economist/web-apple-pay
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Story coverage matrix:
|
|
182
|
+
|
|
183
|
+
- `ApplePayButton` docs page shows the stable default example.
|
|
184
|
+
- `ApplePayButton` behavior and state variants are available as individual canvas stories in Storybook.
|
|
185
|
+
- `ApplePayModal` docs page shows the stable default example.
|
|
186
|
+
- `ApplePayModal` behavior and state variants are available as individual canvas stories in Storybook.
|
package/dist/index.js
CHANGED
|
@@ -881,6 +881,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
881
881
|
#offer = null;
|
|
882
882
|
#country = "";
|
|
883
883
|
#rendering = false;
|
|
884
|
+
#readyPromise = null;
|
|
884
885
|
get offer() {
|
|
885
886
|
return this.#offer;
|
|
886
887
|
}
|
|
@@ -894,11 +895,34 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
894
895
|
set country(value) {
|
|
895
896
|
this.#country = value;
|
|
896
897
|
}
|
|
898
|
+
/**
|
|
899
|
+
* Awaitable contract for the component's current render lifecycle.
|
|
900
|
+
*
|
|
901
|
+
* - If called **after** the element has been appended to the DOM, resolves
|
|
902
|
+
* once `connectedCallback` finishes — whether Apple Pay rendered
|
|
903
|
+
* successfully or was hidden (unavailable / suppressed by session).
|
|
904
|
+
* - If called **before** the element is appended (or if it has never been
|
|
905
|
+
* connected), resolves immediately to `undefined`. It does **not** wait
|
|
906
|
+
* for a future connection, so always `await whenReady()` after `appendChild`:
|
|
907
|
+
*
|
|
908
|
+
* ```ts
|
|
909
|
+
* container.appendChild(btn); // browser fires connectedCallback
|
|
910
|
+
* await btn.whenReady(); // waits for render to finish
|
|
911
|
+
* if (btn.style.display !== 'none') { /* available *\/ }
|
|
912
|
+
* ```
|
|
913
|
+
*/
|
|
914
|
+
whenReady() {
|
|
915
|
+
return this.#readyPromise ?? Promise.resolve();
|
|
916
|
+
}
|
|
897
917
|
async connectedCallback() {
|
|
898
918
|
if (this.#rendering || this.querySelector(".apple-pay-container")) {
|
|
899
919
|
return;
|
|
900
920
|
}
|
|
901
921
|
this.#rendering = true;
|
|
922
|
+
this.#readyPromise = this.#run();
|
|
923
|
+
await this.#readyPromise;
|
|
924
|
+
}
|
|
925
|
+
async #run() {
|
|
902
926
|
try {
|
|
903
927
|
const available = await isApplePayAvailable();
|
|
904
928
|
if (!available) {
|
|
@@ -11,5 +11,22 @@ export declare class ApplePayButton extends HTMLElement {
|
|
|
11
11
|
set offer(value: Offer | null);
|
|
12
12
|
get country(): string;
|
|
13
13
|
set country(value: string);
|
|
14
|
+
/**
|
|
15
|
+
* Awaitable contract for the component's current render lifecycle.
|
|
16
|
+
*
|
|
17
|
+
* - If called **after** the element has been appended to the DOM, resolves
|
|
18
|
+
* once `connectedCallback` finishes — whether Apple Pay rendered
|
|
19
|
+
* successfully or was hidden (unavailable / suppressed by session).
|
|
20
|
+
* - If called **before** the element is appended (or if it has never been
|
|
21
|
+
* connected), resolves immediately to `undefined`. It does **not** wait
|
|
22
|
+
* for a future connection, so always `await whenReady()` after `appendChild`:
|
|
23
|
+
*
|
|
24
|
+
* ```ts
|
|
25
|
+
* container.appendChild(btn); // browser fires connectedCallback
|
|
26
|
+
* await btn.whenReady(); // waits for render to finish
|
|
27
|
+
* if (btn.style.display !== 'none') { /* available *\/ }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
whenReady(): Promise<void>;
|
|
14
31
|
connectedCallback(): Promise<void>;
|
|
15
32
|
}
|
|
@@ -876,6 +876,7 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
876
876
|
#offer = null;
|
|
877
877
|
#country = "";
|
|
878
878
|
#rendering = false;
|
|
879
|
+
#readyPromise = null;
|
|
879
880
|
get offer() {
|
|
880
881
|
return this.#offer;
|
|
881
882
|
}
|
|
@@ -889,11 +890,34 @@ var ApplePayButton = class _ApplePayButton extends HTMLElement {
|
|
|
889
890
|
set country(value) {
|
|
890
891
|
this.#country = value;
|
|
891
892
|
}
|
|
893
|
+
/**
|
|
894
|
+
* Awaitable contract for the component's current render lifecycle.
|
|
895
|
+
*
|
|
896
|
+
* - If called **after** the element has been appended to the DOM, resolves
|
|
897
|
+
* once `connectedCallback` finishes — whether Apple Pay rendered
|
|
898
|
+
* successfully or was hidden (unavailable / suppressed by session).
|
|
899
|
+
* - If called **before** the element is appended (or if it has never been
|
|
900
|
+
* connected), resolves immediately to `undefined`. It does **not** wait
|
|
901
|
+
* for a future connection, so always `await whenReady()` after `appendChild`:
|
|
902
|
+
*
|
|
903
|
+
* ```ts
|
|
904
|
+
* container.appendChild(btn); // browser fires connectedCallback
|
|
905
|
+
* await btn.whenReady(); // waits for render to finish
|
|
906
|
+
* if (btn.style.display !== 'none') { /* available *\/ }
|
|
907
|
+
* ```
|
|
908
|
+
*/
|
|
909
|
+
whenReady() {
|
|
910
|
+
return this.#readyPromise ?? Promise.resolve();
|
|
911
|
+
}
|
|
892
912
|
async connectedCallback() {
|
|
893
913
|
if (this.#rendering || this.querySelector(".apple-pay-container")) {
|
|
894
914
|
return;
|
|
895
915
|
}
|
|
896
916
|
this.#rendering = true;
|
|
917
|
+
this.#readyPromise = this.#run();
|
|
918
|
+
await this.#readyPromise;
|
|
919
|
+
}
|
|
920
|
+
async #run() {
|
|
897
921
|
try {
|
|
898
922
|
const available = await isApplePayAvailable();
|
|
899
923
|
if (!available) {
|