@ticketlayer/elements 0.4.0 → 1.0.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/dist/cjs/{index-I9CoYv3k.js → index-DanPUX0s.js} +1 -1
- package/dist/cjs/index.cjs.js +2 -1
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/ticket-selector-BYVL13k_.js +3623 -0
- package/dist/cjs/ticketlayer-elements.cjs.js +2 -2
- package/dist/cjs/tl-buy-modal.cjs.entry.js +3 -3
- package/dist/cjs/tl-buy-tickets-button.cjs.entry.js +89 -74
- package/dist/cjs/tl-buy-tickets-wrapper.cjs.entry.js +61 -30
- package/dist/cjs/tl-cart-badge.cjs.entry.js +74 -61
- package/dist/cjs/tl-cart-drawer.cjs.entry.js +51 -23
- package/dist/cjs/tl-cart.cjs.entry.js +71 -103
- package/dist/cjs/tl-checkout-wrapper.cjs.entry.js +51 -29
- package/dist/cjs/tl-event-card.cjs.entry.js +43 -105
- package/dist/cjs/tl-event-list.cjs.entry.js +72 -35
- package/dist/cjs/tl-login.cjs.entry.js +74 -141
- package/dist/cjs/tl-my-orders.cjs.entry.js +52 -92
- package/dist/cjs/tl-occurrence-selector_2.cjs.entry.js +153 -921
- package/dist/cjs/tl-order-confirmation.cjs.entry.js +71 -107
- package/dist/cjs/tl-order-tickets_2.cjs.entry.js +48 -74
- package/dist/cjs/tl-promo-code.cjs.entry.js +50 -47
- package/dist/cjs/tl-seat-map.cjs.entry.js +3 -3
- package/dist/cjs/web-query-Ce73jB4k.js +16 -0
- package/dist/collection/components/tl-buy-modal/tl-buy-modal.js +2 -2
- package/dist/collection/components/tl-buy-tickets-button/tl-buy-tickets-button.css +37 -0
- package/dist/collection/components/tl-buy-tickets-button/tl-buy-tickets-button.js +105 -79
- package/dist/collection/components/tl-buy-tickets-wrapper/tl-buy-tickets-wrapper.js +73 -30
- package/dist/collection/components/tl-cart/tl-cart.js +82 -107
- package/dist/collection/components/tl-cart-badge/tl-cart-badge.js +62 -62
- package/dist/collection/components/tl-cart-drawer/tl-cart-drawer.js +56 -24
- package/dist/collection/components/tl-checkout-wrapper/tl-checkout-wrapper.js +61 -29
- package/dist/collection/components/tl-event-card/event-card-adapter.js +11 -23
- package/dist/collection/components/tl-event-card/tl-event-card.js +51 -84
- package/dist/collection/components/tl-event-list/tl-event-list.js +82 -38
- package/dist/collection/components/tl-login/tl-login.js +83 -147
- package/dist/collection/components/tl-my-orders/tl-my-orders.js +58 -96
- package/dist/collection/components/tl-occurrence-selector/tl-occurrence-selector.js +137 -516
- package/dist/collection/components/tl-order-confirmation/tl-order-confirmation.js +81 -115
- package/dist/collection/components/tl-order-tickets/tl-order-tickets.js +57 -92
- package/dist/collection/components/tl-promo-code/tl-promo-code.js +55 -50
- package/dist/collection/components/tl-seat-map/tl-seat-map.js +2 -2
- package/dist/collection/components/tl-ticket-selector/tl-ticket-selector.js +34 -20
- package/dist/collection/utils/order-summary.js +15 -135
- package/dist/collection/utils/testing/deep-text.js +29 -0
- package/dist/collection/utils/testing/fixtures.js +290 -0
- package/dist/collection/utils/testing/mock-sdk.js +13 -2
- package/dist/collection/utils/web-query.js +12 -0
- package/dist/collection/utils/web-storage.js +22 -0
- package/dist/components/ticket-selector.js +1 -0
- package/dist/components/tl-buy-modal.js +1 -1
- package/dist/components/tl-buy-tickets-button.js +1 -1
- package/dist/components/tl-buy-tickets-wrapper2.js +1 -1
- package/dist/components/tl-cart-badge.js +1 -1
- package/dist/components/tl-cart-drawer.js +1 -1
- package/dist/components/tl-cart2.js +1 -1
- package/dist/components/tl-checkout-wrapper2.js +1 -1
- package/dist/components/tl-event-card2.js +1 -1
- package/dist/components/tl-event-list.js +1 -1
- package/dist/components/tl-login2.js +1 -1
- package/dist/components/tl-my-orders.js +1 -1
- package/dist/components/tl-occurrence-selector2.js +1 -1
- package/dist/components/tl-order-confirmation.js +1 -1
- package/dist/components/tl-order-tickets2.js +1 -1
- package/dist/components/tl-promo-code.js +1 -1
- package/dist/components/tl-seat-map.js +1 -1
- package/dist/components/tl-ticket-selector2.js +1 -1
- package/dist/components/web-query.js +1 -0
- package/dist/elements.docs.json +34 -34
- package/dist/esm/{index-OoYV1faY.js → index-imfxp765.js} +1 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/loader.js +3 -3
- package/dist/esm/ticket-selector-BwChnHVC.js +3606 -0
- package/dist/esm/ticketlayer-elements.js +3 -3
- package/dist/esm/tl-buy-modal.entry.js +3 -3
- package/dist/esm/tl-buy-tickets-button.entry.js +90 -75
- package/dist/esm/tl-buy-tickets-wrapper.entry.js +62 -31
- package/dist/esm/tl-cart-badge.entry.js +75 -62
- package/dist/esm/tl-cart-drawer.entry.js +52 -24
- package/dist/esm/tl-cart.entry.js +72 -104
- package/dist/esm/tl-checkout-wrapper.entry.js +52 -30
- package/dist/esm/tl-event-card.entry.js +44 -106
- package/dist/esm/tl-event-list.entry.js +73 -36
- package/dist/esm/tl-login.entry.js +75 -142
- package/dist/esm/tl-my-orders.entry.js +53 -93
- package/dist/esm/tl-occurrence-selector_2.entry.js +152 -920
- package/dist/esm/tl-order-confirmation.entry.js +72 -108
- package/dist/esm/tl-order-tickets_2.entry.js +49 -75
- package/dist/esm/tl-promo-code.entry.js +51 -48
- package/dist/esm/tl-seat-map.entry.js +3 -3
- package/dist/esm/web-query-Bdbb2lk5.js +14 -0
- package/dist/ticketlayer-elements/index.esm.js +1 -1
- package/dist/ticketlayer-elements/p-45923d2c.entry.js +1 -0
- package/dist/ticketlayer-elements/p-492adc77.entry.js +1 -0
- package/dist/ticketlayer-elements/p-4cfc9e53.entry.js +1 -0
- package/dist/ticketlayer-elements/{p-ac264adc.entry.js → p-5135630e.entry.js} +1 -1
- package/dist/ticketlayer-elements/p-5bbce3b5.entry.js +1 -0
- package/dist/ticketlayer-elements/p-7d547721.entry.js +1 -0
- package/dist/ticketlayer-elements/p-7fe7b6ba.entry.js +1 -0
- package/dist/ticketlayer-elements/p-8122f0c1.entry.js +1 -0
- package/dist/ticketlayer-elements/p-98d40869.entry.js +1 -0
- package/dist/ticketlayer-elements/p-Bdbb2lk5.js +1 -0
- package/dist/ticketlayer-elements/p-BwChnHVC.js +1 -0
- package/dist/ticketlayer-elements/p-abec290a.entry.js +1 -0
- package/dist/ticketlayer-elements/p-ac79a3f6.entry.js +1 -0
- package/dist/ticketlayer-elements/p-d01f4429.entry.js +1 -0
- package/dist/ticketlayer-elements/p-d7ffaf46.entry.js +1 -0
- package/dist/ticketlayer-elements/p-e7170f3c.entry.js +1 -0
- package/dist/ticketlayer-elements/p-e787e862.entry.js +1 -0
- package/dist/ticketlayer-elements/p-f1ff931f.entry.js +1 -0
- package/dist/ticketlayer-elements/p-imfxp765.js +3 -0
- package/dist/ticketlayer-elements/ticketlayer-elements.css +1 -1
- package/dist/ticketlayer-elements/ticketlayer-elements.esm.js +1 -1
- package/dist/types/components/tl-buy-tickets-button/tl-buy-tickets-button.d.ts +40 -8
- package/dist/types/components/tl-buy-tickets-wrapper/tl-buy-tickets-wrapper.d.ts +20 -1
- package/dist/types/components/tl-cart/tl-cart.d.ts +40 -42
- package/dist/types/components/tl-cart-badge/tl-cart-badge.d.ts +22 -7
- package/dist/types/components/tl-cart-drawer/tl-cart-drawer.d.ts +28 -5
- package/dist/types/components/tl-checkout-wrapper/tl-checkout-wrapper.d.ts +18 -1
- package/dist/types/components/tl-event-card/event-card-adapter.d.ts +9 -20
- package/dist/types/components/tl-event-card/tl-event-card.d.ts +25 -28
- package/dist/types/components/tl-event-list/tl-event-list.d.ts +46 -6
- package/dist/types/components/tl-login/tl-login.d.ts +68 -22
- package/dist/types/components/tl-my-orders/tl-my-orders.d.ts +30 -12
- package/dist/types/components/tl-occurrence-selector/tl-occurrence-selector.d.ts +73 -161
- package/dist/types/components/tl-order-confirmation/tl-order-confirmation.d.ts +48 -15
- package/dist/types/components/tl-order-tickets/tl-order-tickets.d.ts +29 -31
- package/dist/types/components/tl-promo-code/tl-promo-code.d.ts +28 -10
- package/dist/types/components/tl-ticket/tl-ticket.d.ts +2 -11
- package/dist/types/components/tl-ticket-selector/tl-ticket-selector.d.ts +22 -4
- package/dist/types/components.d.ts +270 -62
- package/dist/types/utils/order-summary.d.ts +14 -97
- package/dist/types/utils/testing/deep-text.d.ts +13 -0
- package/dist/types/utils/testing/fixtures.d.ts +225 -0
- package/dist/types/utils/testing/mock-sdk.d.ts +14 -1
- package/dist/types/utils/web-query.d.ts +18 -0
- package/dist/types/utils/web-storage.d.ts +16 -0
- package/elements.catalogue.json +602 -50
- package/package.json +8 -6
- package/dist/cjs/money-BtmM2gt-.js +0 -118
- package/dist/cjs/order-summary-X3TlZxc2.js +0 -150
- package/dist/components/money.js +0 -1
- package/dist/components/order-summary.js +0 -1
- package/dist/esm/money-4ig0-WB6.js +0 -112
- package/dist/esm/order-summary-DiDtvfZM.js +0 -136
- package/dist/ticketlayer-elements/p-0814420f.entry.js +0 -1
- package/dist/ticketlayer-elements/p-0acabc26.entry.js +0 -1
- package/dist/ticketlayer-elements/p-109a3feb.entry.js +0 -1
- package/dist/ticketlayer-elements/p-1a4ba71c.entry.js +0 -1
- package/dist/ticketlayer-elements/p-318965c1.entry.js +0 -1
- package/dist/ticketlayer-elements/p-347c7fd1.entry.js +0 -1
- package/dist/ticketlayer-elements/p-3649c26d.entry.js +0 -1
- package/dist/ticketlayer-elements/p-40260cc9.entry.js +0 -1
- package/dist/ticketlayer-elements/p-4ig0-WB6.js +0 -1
- package/dist/ticketlayer-elements/p-55fd2f9f.entry.js +0 -1
- package/dist/ticketlayer-elements/p-62ee659b.entry.js +0 -1
- package/dist/ticketlayer-elements/p-7d4ecc2b.entry.js +0 -1
- package/dist/ticketlayer-elements/p-7f0abf95.entry.js +0 -1
- package/dist/ticketlayer-elements/p-BXpVGW51.js +0 -1
- package/dist/ticketlayer-elements/p-OoYV1faY.js +0 -3
- package/dist/ticketlayer-elements/p-a3c1b26c.entry.js +0 -1
- package/dist/ticketlayer-elements/p-aeb4c6fb.entry.js +0 -1
- package/dist/ticketlayer-elements/p-ba62541f.entry.js +0 -1
|
@@ -16,6 +16,43 @@
|
|
|
16
16
|
width: 100%;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
+
/* Sale states
|
|
20
|
+
*
|
|
21
|
+
* One state, one @ticketlayer/theme token family, and the hover derived from
|
|
22
|
+
* the same token rather than written down a second time, so a themed palette
|
|
23
|
+
* carries every state with it (TKT-203). These used to be literal hex in the
|
|
24
|
+
* component: red for sold out, blue for the waitlist, amber for coming soon,
|
|
25
|
+
* and a themed channel painted the available state and none of the others.
|
|
26
|
+
*
|
|
27
|
+
* The class comes from the core (`derived.stateClass`), which names the state
|
|
28
|
+
* and nothing more: a core may hold no value and has no shape for saying WHICH
|
|
29
|
+
* family a status paints with, so that decision is made here, exactly as
|
|
30
|
+
* tl-event-card's status badge makes it.
|
|
31
|
+
*/
|
|
32
|
+
.state-available {
|
|
33
|
+
--button-color: var(--tl-primary);
|
|
34
|
+
--button-hover-color: color-mix(in srgb, var(--tl-primary) 90%, black);
|
|
35
|
+
--button-foreground: var(--tl-primary-foreground);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.state-sold-out {
|
|
39
|
+
--button-color: var(--tl-error);
|
|
40
|
+
--button-hover-color: color-mix(in srgb, var(--tl-error) 90%, black);
|
|
41
|
+
--button-foreground: var(--tl-error-foreground);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.state-waitlist {
|
|
45
|
+
--button-color: var(--tl-info);
|
|
46
|
+
--button-hover-color: color-mix(in srgb, var(--tl-info) 90%, black);
|
|
47
|
+
--button-foreground: var(--tl-info-foreground);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.state-coming-soon {
|
|
51
|
+
--button-color: var(--tl-warning);
|
|
52
|
+
--button-hover-color: color-mix(in srgb, var(--tl-warning) 90%, black);
|
|
53
|
+
--button-foreground: var(--tl-warning-foreground);
|
|
54
|
+
}
|
|
55
|
+
|
|
19
56
|
.buy-button {
|
|
20
57
|
display: inline-flex;
|
|
21
58
|
align-items: center;
|
|
@@ -5,11 +5,20 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @element tl-buy-tickets-button
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* -
|
|
11
|
-
*
|
|
12
|
-
*
|
|
8
|
+
* The web harness for `buyTicketsButtonCore`. What a press does, which states
|
|
9
|
+
* are not pressable, the label each state defaults to and how the price reads
|
|
10
|
+
* are all in `@ticketlayer/elements-core` (AGENTS.md, TKT-11); what is left
|
|
11
|
+
* here is the Stencil surface, the icons, the hover, and which key counts as a
|
|
12
|
+
* press.
|
|
13
|
+
*
|
|
14
|
+
* Each state is painted from a @ticketlayer/theme token family rather than
|
|
15
|
+
* from a literal, so a channel theme reaches every one of them. The core says
|
|
16
|
+
* which state the button is in and the stylesheet says which family that
|
|
17
|
+
* state paints with, because a core cannot map a status onto one:
|
|
18
|
+
* - available: "Buy Tickets", the primary family
|
|
19
|
+
* - soldOut: "Sold Out", the error family
|
|
20
|
+
* - waitlist: "Join Waitlist", the info family
|
|
21
|
+
* - comingSoon: "On Sale Soon", the warning family
|
|
13
22
|
*
|
|
14
23
|
* @example
|
|
15
24
|
* <tl-buy-tickets-button event-id="evt_xxx"></tl-buy-tickets-button>
|
|
@@ -17,37 +26,8 @@
|
|
|
17
26
|
* <tl-buy-tickets-button event-id="evt_xxx" price="2500" currency="GBP"></tl-buy-tickets-button>
|
|
18
27
|
*/
|
|
19
28
|
import { h, Host } from "@stencil/core";
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
const STATE_CONFIGS = {
|
|
23
|
-
available: {
|
|
24
|
-
defaultLabel: 'Buy Tickets',
|
|
25
|
-
color: 'var(--tl-primary)',
|
|
26
|
-
// The hover shade used to be a second colour smuggled into the token's
|
|
27
|
-
// fallback slot, which meant it stopped following the channel's brand the
|
|
28
|
-
// moment a theme was applied. Derive it instead.
|
|
29
|
-
hoverColor: 'color-mix(in srgb, var(--tl-primary) 90%, black)',
|
|
30
|
-
foreground: 'var(--tl-primary-foreground)',
|
|
31
|
-
},
|
|
32
|
-
soldOut: {
|
|
33
|
-
defaultLabel: 'Sold Out',
|
|
34
|
-
color: '#dc2626',
|
|
35
|
-
hoverColor: '#b91c1c',
|
|
36
|
-
foreground: '#ffffff',
|
|
37
|
-
},
|
|
38
|
-
waitlist: {
|
|
39
|
-
defaultLabel: 'Join Waitlist',
|
|
40
|
-
color: '#2563eb',
|
|
41
|
-
hoverColor: '#1d4ed8',
|
|
42
|
-
foreground: '#ffffff',
|
|
43
|
-
},
|
|
44
|
-
comingSoon: {
|
|
45
|
-
defaultLabel: 'On Sale Soon',
|
|
46
|
-
color: '#d97706',
|
|
47
|
-
hoverColor: '#b45309',
|
|
48
|
-
foreground: '#ffffff',
|
|
49
|
-
},
|
|
50
|
-
};
|
|
29
|
+
import { buyTicketsButtonCore, createElement, } from "@ticketlayer/elements-core";
|
|
30
|
+
import { getSDK, whenSDK } from "../../utils/sdk-connector";
|
|
51
31
|
export class TlBuyTicketsButton {
|
|
52
32
|
constructor() {
|
|
53
33
|
/** Button state - determines colour, label, and icon */
|
|
@@ -67,65 +47,74 @@ export class TlBuyTicketsButton {
|
|
|
67
47
|
// -------------------------------------------------------------------------
|
|
68
48
|
// State
|
|
69
49
|
// -------------------------------------------------------------------------
|
|
50
|
+
/**
|
|
51
|
+
* Whether the pointer is over the button. A pointer is not a fact every
|
|
52
|
+
* runtime has, so this stays here for the same reason the key handling
|
|
53
|
+
* does: the core knows nothing of mice.
|
|
54
|
+
*/
|
|
70
55
|
this.isHovered = false;
|
|
71
56
|
// -------------------------------------------------------------------------
|
|
72
|
-
//
|
|
57
|
+
// The core
|
|
73
58
|
// -------------------------------------------------------------------------
|
|
59
|
+
this.element = createElement(buyTicketsButtonCore, {
|
|
60
|
+
client: () => getSDK(),
|
|
61
|
+
clientReady: () => whenSDK(),
|
|
62
|
+
emit: (event, detail) => this.forward(event, detail),
|
|
63
|
+
});
|
|
64
|
+
/** The core's whole view. Assigning it is what makes Stencil re-render. */
|
|
65
|
+
this.view = this.element.view;
|
|
74
66
|
this.handleClick = () => {
|
|
75
|
-
|
|
76
|
-
if (this.disabled || this.state === 'soldOut' || this.state === 'comingSoon') {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
// Emit click event
|
|
80
|
-
this.tlClick.emit({ eventId: this.eventId, occurrenceId: this.occurrenceId });
|
|
81
|
-
// Open modal via SDK if available
|
|
82
|
-
if (hasSDK()) {
|
|
83
|
-
try {
|
|
84
|
-
const sdk = getSDK();
|
|
85
|
-
sdk.event(this.eventId).openModal({
|
|
86
|
-
occurrenceId: this.occurrenceId,
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
catch (err) {
|
|
90
|
-
console.error('[tl-buy-tickets-button] Failed to open modal:', err);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
67
|
+
this.element.actions.activate();
|
|
93
68
|
};
|
|
94
69
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
70
|
+
syncProps() {
|
|
71
|
+
this.element.setProps({
|
|
72
|
+
eventId: this.eventId,
|
|
73
|
+
occurrenceId: this.occurrenceId,
|
|
74
|
+
state: this.state,
|
|
75
|
+
label: this.label,
|
|
76
|
+
variant: this.variant,
|
|
77
|
+
size: this.size,
|
|
78
|
+
fullWidth: this.fullWidth,
|
|
79
|
+
price: this.price,
|
|
100
80
|
currency: this.currency,
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
})
|
|
81
|
+
pricePrefix: this.pricePrefix,
|
|
82
|
+
disabled: this.disabled,
|
|
83
|
+
});
|
|
104
84
|
}
|
|
105
|
-
|
|
106
|
-
|
|
85
|
+
connectedCallback() {
|
|
86
|
+
this.syncProps();
|
|
87
|
+
this.unsubscribe ?? (this.unsubscribe = this.element.subscribe((view) => {
|
|
88
|
+
this.view = view;
|
|
89
|
+
}));
|
|
90
|
+
this.view = this.element.view;
|
|
91
|
+
// This core has nothing to do on mount, and is mounted anyway: a harness
|
|
92
|
+
// calls mount() unconditionally and pairs it with its teardown (TKT-197).
|
|
93
|
+
this.teardown = this.element.mount();
|
|
107
94
|
}
|
|
108
|
-
|
|
109
|
-
|
|
95
|
+
disconnectedCallback() {
|
|
96
|
+
this.teardown?.();
|
|
97
|
+
this.teardown = undefined;
|
|
98
|
+
this.unsubscribe?.();
|
|
99
|
+
this.unsubscribe = undefined;
|
|
100
|
+
}
|
|
101
|
+
forward(event, detail) {
|
|
102
|
+
if (event === 'tlClick')
|
|
103
|
+
this.tlClick.emit(detail);
|
|
110
104
|
}
|
|
111
105
|
// -------------------------------------------------------------------------
|
|
112
106
|
// Render
|
|
113
107
|
// -------------------------------------------------------------------------
|
|
114
108
|
render() {
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
const isInteractive = this.isInteractive();
|
|
118
|
-
return (h(Host, { key: '86ee9a81d82c10398dab4e22b3bbae15abb8f449', class: { 'full-width': this.fullWidth } }, h("button", { key: 'b581e199ced7ffd14669ebe0cc727edc2f8c8914', type: "button", class: {
|
|
109
|
+
const { interactive, buttonLabel, stateClass, priceLabel } = this.view.derived;
|
|
110
|
+
return (h(Host, { key: '6d5dddb3fc486c5a877a3718fecbee80a648b274', class: { 'full-width': this.fullWidth } }, h("button", { key: '88f7f0688fb42e97eb2ce352f316b2a085c3bab5', type: "button", class: {
|
|
119
111
|
'buy-button': true,
|
|
112
|
+
[stateClass]: true,
|
|
120
113
|
[`variant-${this.variant}`]: true,
|
|
121
114
|
[`size-${this.size}`]: true,
|
|
122
|
-
'disabled': !
|
|
123
|
-
'hovered': this.isHovered &&
|
|
124
|
-
},
|
|
125
|
-
'--button-color': config.color,
|
|
126
|
-
'--button-hover-color': config.hoverColor,
|
|
127
|
-
'--button-foreground': config.foreground,
|
|
128
|
-
}, disabled: !isInteractive, onClick: this.handleClick, onMouseEnter: () => (this.isHovered = true), onMouseLeave: () => (this.isHovered = false) }, h("span", { key: 'f776bab4a999ed36b25400424d639b4c9261c02a', class: "icon" }, this.state === 'soldOut' && this.renderSoldOutIcon(), this.state === 'waitlist' && this.renderWaitlistIcon(), this.state === 'comingSoon' && this.renderComingSoonIcon(), this.state === 'available' && this.renderTicketIcon()), h("span", { key: 'e98ecbe6debc5c2c18ce1d304b60bf1074b003b3', class: "label" }, buttonLabel), this.price !== undefined && (h("span", { key: 'e7e261d09a541b126b02b88d00992f3a6483a9b8', class: "price" }, h("span", { key: '5eab43a47c2dd4c1339fe84b583902b1e38a0b2a', class: "price-prefix" }, this.pricePrefix), h("span", { key: 'f03b514ff2bc3c9a1b2e922d93a92accdedd0fad', class: "price-value" }, this.formatPrice(this.price)))))));
|
|
115
|
+
'disabled': !interactive,
|
|
116
|
+
'hovered': this.isHovered && interactive,
|
|
117
|
+
}, disabled: !interactive, onClick: this.handleClick, onMouseEnter: () => (this.isHovered = true), onMouseLeave: () => (this.isHovered = false) }, h("span", { key: 'e88c2f05c7bc782d08d78fc8ab53b213ab3c833f', class: "icon" }, this.state === 'soldOut' && this.renderSoldOutIcon(), this.state === 'waitlist' && this.renderWaitlistIcon(), this.state === 'comingSoon' && this.renderComingSoonIcon(), this.state === 'available' && this.renderTicketIcon()), h("span", { key: '7290a58779e884886f26e64c405fd319811613a1', class: "label" }, buttonLabel), priceLabel !== null && (h("span", { key: 'bdf3bcdbfa29d4799f7a64bc0072a4c06c09c393', class: "price" }, h("span", { key: '32b075fc6793ef21e9a2cd188058992f95c10680', class: "price-prefix" }, this.pricePrefix), h("span", { key: 'ff3805b660b2af72a94fabc315507ce063ff02d2', class: "price-value" }, priceLabel))))));
|
|
129
118
|
}
|
|
130
119
|
renderTicketIcon() {
|
|
131
120
|
return (h("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("path", { d: "M2 9a3 3 0 0 1 0 6v2a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-2a3 3 0 0 1 0-6V7a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2Z" }), h("path", { d: "M13 5v2" }), h("path", { d: "M13 17v2" }), h("path", { d: "M13 11v2" })));
|
|
@@ -391,7 +380,8 @@ export class TlBuyTicketsButton {
|
|
|
391
380
|
}
|
|
392
381
|
static get states() {
|
|
393
382
|
return {
|
|
394
|
-
"isHovered": {}
|
|
383
|
+
"isHovered": {},
|
|
384
|
+
"view": {}
|
|
395
385
|
};
|
|
396
386
|
}
|
|
397
387
|
static get events() {
|
|
@@ -412,4 +402,40 @@ export class TlBuyTicketsButton {
|
|
|
412
402
|
}
|
|
413
403
|
}];
|
|
414
404
|
}
|
|
405
|
+
static get watchers() {
|
|
406
|
+
return [{
|
|
407
|
+
"propName": "eventId",
|
|
408
|
+
"methodName": "syncProps"
|
|
409
|
+
}, {
|
|
410
|
+
"propName": "occurrenceId",
|
|
411
|
+
"methodName": "syncProps"
|
|
412
|
+
}, {
|
|
413
|
+
"propName": "state",
|
|
414
|
+
"methodName": "syncProps"
|
|
415
|
+
}, {
|
|
416
|
+
"propName": "label",
|
|
417
|
+
"methodName": "syncProps"
|
|
418
|
+
}, {
|
|
419
|
+
"propName": "variant",
|
|
420
|
+
"methodName": "syncProps"
|
|
421
|
+
}, {
|
|
422
|
+
"propName": "size",
|
|
423
|
+
"methodName": "syncProps"
|
|
424
|
+
}, {
|
|
425
|
+
"propName": "fullWidth",
|
|
426
|
+
"methodName": "syncProps"
|
|
427
|
+
}, {
|
|
428
|
+
"propName": "price",
|
|
429
|
+
"methodName": "syncProps"
|
|
430
|
+
}, {
|
|
431
|
+
"propName": "currency",
|
|
432
|
+
"methodName": "syncProps"
|
|
433
|
+
}, {
|
|
434
|
+
"propName": "pricePrefix",
|
|
435
|
+
"methodName": "syncProps"
|
|
436
|
+
}, {
|
|
437
|
+
"propName": "disabled",
|
|
438
|
+
"methodName": "syncProps"
|
|
439
|
+
}];
|
|
440
|
+
}
|
|
415
441
|
}
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { h, Host } from "@stencil/core";
|
|
2
|
-
import {
|
|
2
|
+
import { buyTicketsWrapperCore, createElement, } from "@ticketlayer/elements-core";
|
|
3
|
+
import { getSDK, whenSDK } from "../../utils/sdk-connector";
|
|
3
4
|
/**
|
|
4
5
|
* @component tl-buy-tickets-wrapper
|
|
5
6
|
*
|
|
6
7
|
* Wraps any content and opens the Ticketlayer modal when clicked.
|
|
7
8
|
* Uses the SDK's modal manager which handles the iframe overlay.
|
|
8
9
|
*
|
|
10
|
+
* The web harness for `buyTicketsWrapperCore`. What a press does, what it
|
|
11
|
+
* announces and what happens when no client has been published are all in
|
|
12
|
+
* `@ticketlayer/elements-core` (AGENTS.md, TKT-11); what is left here is the
|
|
13
|
+
* Stencil surface, the accessibility attributes and the one genuinely web
|
|
14
|
+
* question the core refuses to answer - which key counts as a press.
|
|
15
|
+
*
|
|
9
16
|
* @slot - Content to display (typically a button)
|
|
10
17
|
*
|
|
11
18
|
* @example
|
|
@@ -24,41 +31,61 @@ export class TlBuyTicketsWrapper {
|
|
|
24
31
|
* Whether the wrapper is disabled
|
|
25
32
|
*/
|
|
26
33
|
this.disabled = false;
|
|
34
|
+
this.element = createElement(buyTicketsWrapperCore, {
|
|
35
|
+
client: () => getSDK(),
|
|
36
|
+
clientReady: () => whenSDK(),
|
|
37
|
+
emit: (event, detail) => this.forward(event, detail),
|
|
38
|
+
});
|
|
39
|
+
/** The core's whole view. Assigning it is what makes Stencil re-render. */
|
|
40
|
+
this.view = this.element.view;
|
|
27
41
|
this.handleClick = () => {
|
|
28
|
-
|
|
29
|
-
return;
|
|
30
|
-
if (!hasSDK()) {
|
|
31
|
-
console.error('[tl-buy-tickets-wrapper] SDK not initialized. Call setSDK(ticketlayer) first.');
|
|
32
|
-
this.tlError.emit({ message: 'SDK not initialized' });
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
const sdk = getSDK();
|
|
36
|
-
// Open the modal via SDK
|
|
37
|
-
sdk.event(this.eventId).openModal({
|
|
38
|
-
occurrenceId: this.occurrenceId,
|
|
39
|
-
onComplete: (order) => {
|
|
40
|
-
this.tlComplete.emit(order);
|
|
41
|
-
},
|
|
42
|
-
onError: (err) => {
|
|
43
|
-
this.tlError.emit({ message: err.message });
|
|
44
|
-
},
|
|
45
|
-
onClose: () => {
|
|
46
|
-
this.tlClose.emit();
|
|
47
|
-
},
|
|
48
|
-
});
|
|
42
|
+
this.element.actions.activate();
|
|
49
43
|
};
|
|
44
|
+
/** Enter and Space are a press on the web. The core knows nothing of keys. */
|
|
50
45
|
this.handleKeyDown = (e) => {
|
|
51
46
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
52
47
|
e.preventDefault();
|
|
53
|
-
this.
|
|
48
|
+
this.element.actions.activate();
|
|
54
49
|
}
|
|
55
50
|
};
|
|
56
51
|
}
|
|
52
|
+
syncProps() {
|
|
53
|
+
this.element.setProps({
|
|
54
|
+
eventId: this.eventId,
|
|
55
|
+
occurrenceId: this.occurrenceId,
|
|
56
|
+
disabled: this.disabled,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
connectedCallback() {
|
|
60
|
+
this.syncProps();
|
|
61
|
+
this.unsubscribe ?? (this.unsubscribe = this.element.subscribe((view) => {
|
|
62
|
+
this.view = view;
|
|
63
|
+
}));
|
|
64
|
+
this.view = this.element.view;
|
|
65
|
+
// This core has nothing to do on mount, and is mounted anyway: a harness
|
|
66
|
+
// calls mount() unconditionally and pairs it with its teardown (TKT-197).
|
|
67
|
+
this.teardown = this.element.mount();
|
|
68
|
+
}
|
|
69
|
+
disconnectedCallback() {
|
|
70
|
+
this.teardown?.();
|
|
71
|
+
this.teardown = undefined;
|
|
72
|
+
this.unsubscribe?.();
|
|
73
|
+
this.unsubscribe = undefined;
|
|
74
|
+
}
|
|
75
|
+
forward(event, detail) {
|
|
76
|
+
if (event === 'tlComplete')
|
|
77
|
+
this.tlComplete.emit(detail);
|
|
78
|
+
else if (event === 'tlError')
|
|
79
|
+
this.tlError.emit(detail);
|
|
80
|
+
else if (event === 'tlClose')
|
|
81
|
+
this.tlClose.emit();
|
|
82
|
+
}
|
|
57
83
|
render() {
|
|
58
|
-
|
|
84
|
+
const { interactive } = this.view.derived;
|
|
85
|
+
return (h(Host, { key: '14e91259c1401322f969d43bb16b6d3f20327c65', class: {
|
|
59
86
|
'tl-buy-tickets-wrapper': true,
|
|
60
|
-
'tl-buy-tickets-wrapper--disabled':
|
|
61
|
-
}, onClick: this.handleClick, onKeyDown: this.handleKeyDown, role: "button", tabindex:
|
|
87
|
+
'tl-buy-tickets-wrapper--disabled': !interactive,
|
|
88
|
+
}, onClick: this.handleClick, onKeyDown: this.handleKeyDown, role: "button", tabindex: interactive ? 0 : -1, "aria-disabled": interactive ? null : 'true' }, h("slot", { key: '3fb33786e09f5ecdf20ff0ea8e7336ccfc43b216' })));
|
|
62
89
|
}
|
|
63
90
|
static get is() { return "tl-buy-tickets-wrapper"; }
|
|
64
91
|
static get originalStyleUrls() {
|
|
@@ -133,10 +160,15 @@ export class TlBuyTicketsWrapper {
|
|
|
133
160
|
}
|
|
134
161
|
};
|
|
135
162
|
}
|
|
163
|
+
static get states() {
|
|
164
|
+
return {
|
|
165
|
+
"view": {}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
136
168
|
static get events() {
|
|
137
169
|
return [{
|
|
138
170
|
"method": "tlComplete",
|
|
139
|
-
"name": "
|
|
171
|
+
"name": "tlComplete",
|
|
140
172
|
"bubbles": true,
|
|
141
173
|
"cancelable": true,
|
|
142
174
|
"composed": true,
|
|
@@ -158,7 +190,7 @@ export class TlBuyTicketsWrapper {
|
|
|
158
190
|
}
|
|
159
191
|
}, {
|
|
160
192
|
"method": "tlError",
|
|
161
|
-
"name": "
|
|
193
|
+
"name": "tlError",
|
|
162
194
|
"bubbles": true,
|
|
163
195
|
"cancelable": true,
|
|
164
196
|
"composed": true,
|
|
@@ -173,7 +205,7 @@ export class TlBuyTicketsWrapper {
|
|
|
173
205
|
}
|
|
174
206
|
}, {
|
|
175
207
|
"method": "tlClose",
|
|
176
|
-
"name": "
|
|
208
|
+
"name": "tlClose",
|
|
177
209
|
"bubbles": true,
|
|
178
210
|
"cancelable": true,
|
|
179
211
|
"composed": true,
|
|
@@ -188,5 +220,16 @@ export class TlBuyTicketsWrapper {
|
|
|
188
220
|
}
|
|
189
221
|
}];
|
|
190
222
|
}
|
|
191
|
-
static get
|
|
223
|
+
static get watchers() {
|
|
224
|
+
return [{
|
|
225
|
+
"propName": "eventId",
|
|
226
|
+
"methodName": "syncProps"
|
|
227
|
+
}, {
|
|
228
|
+
"propName": "occurrenceId",
|
|
229
|
+
"methodName": "syncProps"
|
|
230
|
+
}, {
|
|
231
|
+
"propName": "disabled",
|
|
232
|
+
"methodName": "syncProps"
|
|
233
|
+
}];
|
|
234
|
+
}
|
|
192
235
|
}
|