@ticketlayer/elements 0.3.3 → 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/README.md +3 -2
- package/dist/cjs/{index-BpfoKd9Q.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 +4 -4
- package/dist/cjs/tl-buy-tickets-button.cjs.entry.js +89 -71
- package/dist/cjs/tl-buy-tickets-wrapper.cjs.entry.js +62 -31
- package/dist/cjs/tl-cart-badge.cjs.entry.js +75 -62
- package/dist/cjs/tl-cart-drawer.cjs.entry.js +52 -24
- package/dist/cjs/tl-cart.cjs.entry.js +72 -98
- package/dist/cjs/tl-checkout-wrapper.cjs.entry.js +52 -30
- package/dist/cjs/tl-event-card.cjs.entry.js +44 -105
- package/dist/cjs/tl-event-list.cjs.entry.js +73 -36
- package/dist/cjs/tl-login.cjs.entry.js +75 -141
- package/dist/cjs/tl-my-orders.cjs.entry.js +53 -92
- package/dist/cjs/tl-occurrence-selector_2.cjs.entry.js +205 -641
- package/dist/cjs/tl-order-confirmation.cjs.entry.js +72 -105
- package/dist/cjs/tl-order-tickets_2.cjs.entry.js +50 -76
- package/dist/cjs/tl-promo-code.cjs.entry.js +51 -47
- package/dist/cjs/tl-seat-map.cjs.entry.js +4 -4
- package/dist/cjs/web-query-Ce73jB4k.js +16 -0
- package/dist/collection/components/tl-buy-modal/tl-buy-modal.css +12 -19
- 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 +41 -4
- package/dist/collection/components/tl-buy-tickets-button/tl-buy-tickets-button.js +105 -76
- package/dist/collection/components/tl-buy-tickets-wrapper/tl-buy-tickets-wrapper.css +2 -2
- package/dist/collection/components/tl-buy-tickets-wrapper/tl-buy-tickets-wrapper.js +73 -30
- package/dist/collection/components/tl-cart/tl-cart.css +52 -51
- package/dist/collection/components/tl-cart/tl-cart.js +82 -101
- package/dist/collection/components/tl-cart-badge/tl-cart-badge.css +11 -11
- package/dist/collection/components/tl-cart-badge/tl-cart-badge.js +62 -62
- package/dist/collection/components/tl-cart-drawer/tl-cart-drawer.css +6 -6
- package/dist/collection/components/tl-cart-drawer/tl-cart-drawer.js +56 -24
- package/dist/collection/components/tl-checkout-wrapper/tl-checkout-wrapper.css +2 -2
- 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.css +22 -22
- package/dist/collection/components/tl-event-card/tl-event-card.js +51 -84
- package/dist/collection/components/tl-event-list/tl-event-list.css +17 -17
- package/dist/collection/components/tl-event-list/tl-event-list.js +82 -38
- package/dist/collection/components/tl-login/tl-login.css +26 -26
- package/dist/collection/components/tl-login/tl-login.js +83 -147
- package/dist/collection/components/tl-my-orders/tl-my-orders.css +40 -40
- package/dist/collection/components/tl-my-orders/tl-my-orders.js +58 -96
- package/dist/collection/components/tl-occurrence-selector/tl-occurrence-selector.css +54 -65
- package/dist/collection/components/tl-occurrence-selector/tl-occurrence-selector.js +137 -516
- package/dist/collection/components/tl-order-confirmation/tl-order-confirmation.css +38 -38
- package/dist/collection/components/tl-order-confirmation/tl-order-confirmation.js +81 -113
- package/dist/collection/components/tl-order-tickets/tl-order-tickets.css +9 -9
- package/dist/collection/components/tl-order-tickets/tl-order-tickets.js +57 -92
- package/dist/collection/components/tl-promo-code/tl-promo-code.css +25 -25
- package/dist/collection/components/tl-promo-code/tl-promo-code.js +55 -50
- package/dist/collection/components/tl-seat-map/tl-seat-map.css +10 -10
- package/dist/collection/components/tl-seat-map/tl-seat-map.js +2 -2
- package/dist/collection/components/tl-ticket/tl-ticket.css +13 -13
- package/dist/collection/components/tl-ticket-selector/tl-ticket-selector.css +74 -49
- package/dist/collection/components/tl-ticket-selector/tl-ticket-selector.js +95 -135
- package/dist/collection/utils/cart-totals.js +9 -0
- package/dist/collection/utils/order-summary.js +15 -99
- 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/tl-ticket2.js +1 -1
- package/dist/components/web-query.js +1 -0
- package/dist/elements.docs.json +36 -36
- package/dist/esm/{index-CNX8hZa8.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 +4 -4
- package/dist/esm/tl-buy-tickets-button.entry.js +90 -72
- package/dist/esm/tl-buy-tickets-wrapper.entry.js +63 -32
- package/dist/esm/tl-cart-badge.entry.js +76 -63
- package/dist/esm/tl-cart-drawer.entry.js +53 -25
- package/dist/esm/tl-cart.entry.js +73 -99
- package/dist/esm/tl-checkout-wrapper.entry.js +53 -31
- package/dist/esm/tl-event-card.entry.js +45 -106
- package/dist/esm/tl-event-list.entry.js +74 -37
- package/dist/esm/tl-login.entry.js +76 -142
- package/dist/esm/tl-my-orders.entry.js +54 -93
- package/dist/esm/tl-occurrence-selector_2.entry.js +206 -642
- package/dist/esm/tl-order-confirmation.entry.js +73 -106
- package/dist/esm/tl-order-tickets_2.entry.js +51 -77
- package/dist/esm/tl-promo-code.entry.js +52 -48
- package/dist/esm/tl-seat-map.entry.js +4 -4
- 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-5135630e.entry.js +1 -0
- 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 -32
- 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 +61 -32
- package/dist/types/components.d.ts +302 -62
- package/dist/types/utils/cart-totals.d.ts +10 -0
- package/dist/types/utils/order-summary.d.ts +16 -65
- 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 +676 -55
- package/package.json +14 -6
- package/dist/cjs/order-summary-ZMkJ5bez.js +0 -116
- package/dist/components/order-summary.js +0 -1
- package/dist/esm/order-summary-BGekdjN9.js +0 -103
- package/dist/ticketlayer-elements/p-0b1d16f8.entry.js +0 -1
- package/dist/ticketlayer-elements/p-1471f6d8.entry.js +0 -1
- package/dist/ticketlayer-elements/p-1c51cbc1.entry.js +0 -1
- package/dist/ticketlayer-elements/p-5169f68b.entry.js +0 -1
- package/dist/ticketlayer-elements/p-895ba1f3.entry.js +0 -1
- package/dist/ticketlayer-elements/p-8d5722e1.entry.js +0 -1
- package/dist/ticketlayer-elements/p-917d8e09.entry.js +0 -1
- package/dist/ticketlayer-elements/p-9629029a.entry.js +0 -1
- package/dist/ticketlayer-elements/p-BGekdjN9.js +0 -1
- package/dist/ticketlayer-elements/p-CNX8hZa8.js +0 -3
- package/dist/ticketlayer-elements/p-a22714d0.entry.js +0 -1
- package/dist/ticketlayer-elements/p-bf73044b.entry.js +0 -1
- package/dist/ticketlayer-elements/p-e02079fa.entry.js +0 -1
- package/dist/ticketlayer-elements/p-e04ace15.entry.js +0 -1
- package/dist/ticketlayer-elements/p-e6fab1d5.entry.js +0 -1
- package/dist/ticketlayer-elements/p-f826b753.entry.js +0 -1
- package/dist/ticketlayer-elements/p-fa639d88.entry.js +0 -1
- package/dist/ticketlayer-elements/p-fbaca948.entry.js +0 -1
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import { h } from "@stencil/core";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { cartBadgeCore, createElement, } from "@ticketlayer/elements-core";
|
|
3
|
+
import { getSDK, whenSDK } from "../../utils/sdk-connector";
|
|
4
|
+
import { webStorage } from "../../utils/web-storage";
|
|
5
|
+
/**
|
|
6
|
+
* The web harness for `cartBadgeCore`.
|
|
7
|
+
*
|
|
8
|
+
* The count, the "99+" rule, the cart subscription and the remembered value
|
|
9
|
+
* are all in `@ticketlayer/elements-core`. What is here is the Stencil surface,
|
|
10
|
+
* the icon, and the two web things the core is handed: the client the page
|
|
11
|
+
* published and `localStorage`.
|
|
12
|
+
*/
|
|
5
13
|
export class TlCartBadge {
|
|
6
14
|
constructor() {
|
|
7
15
|
/**
|
|
@@ -16,66 +24,44 @@ export class TlCartBadge {
|
|
|
16
24
|
* Badge only mode - only shows the count bubble, no icon or button
|
|
17
25
|
*/
|
|
18
26
|
this.badgeOnly = false;
|
|
19
|
-
this.
|
|
27
|
+
this.element = createElement(cartBadgeCore, {
|
|
28
|
+
client: () => getSDK(),
|
|
29
|
+
clientReady: () => whenSDK(),
|
|
30
|
+
storage: webStorage,
|
|
31
|
+
emit: (event, detail) => this.forward(event, detail),
|
|
32
|
+
});
|
|
33
|
+
/** The core's whole view. Assigning it is what makes Stencil re-render. */
|
|
34
|
+
this.view = this.element.view;
|
|
20
35
|
this.handleClick = () => {
|
|
21
|
-
this.
|
|
36
|
+
this.element.actions.click();
|
|
22
37
|
};
|
|
23
38
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
39
|
+
syncProps() {
|
|
40
|
+
this.element.setProps({
|
|
41
|
+
showEmpty: this.showEmpty,
|
|
42
|
+
icon: this.icon,
|
|
43
|
+
size: this.size,
|
|
44
|
+
badgeOnly: this.badgeOnly,
|
|
45
|
+
});
|
|
27
46
|
}
|
|
28
|
-
|
|
29
|
-
this.
|
|
47
|
+
connectedCallback() {
|
|
48
|
+
this.syncProps();
|
|
49
|
+
this.unsubscribe ?? (this.unsubscribe = this.element.subscribe((view) => {
|
|
50
|
+
this.view = view;
|
|
51
|
+
}));
|
|
52
|
+
this.view = this.element.view;
|
|
53
|
+
this.teardown = this.element.mount();
|
|
30
54
|
}
|
|
55
|
+
/** Off screen: the mount's teardown is what drops the cart subscription. */
|
|
31
56
|
disconnectedCallback() {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
getPersistedCartCount() {
|
|
37
|
-
if (typeof window === 'undefined')
|
|
38
|
-
return 0;
|
|
39
|
-
try {
|
|
40
|
-
const stored = localStorage.getItem(CART_COUNT_KEY);
|
|
41
|
-
return stored ? parseInt(stored, 10) || 0 : 0;
|
|
42
|
-
}
|
|
43
|
-
catch {
|
|
44
|
-
return 0;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
persistCartCount(count) {
|
|
48
|
-
if (typeof window === 'undefined')
|
|
49
|
-
return;
|
|
50
|
-
try {
|
|
51
|
-
localStorage.setItem(CART_COUNT_KEY, count.toString());
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
// localStorage may be unavailable
|
|
55
|
-
}
|
|
57
|
+
this.teardown?.();
|
|
58
|
+
this.teardown = undefined;
|
|
59
|
+
this.unsubscribe?.();
|
|
60
|
+
this.unsubscribe = undefined;
|
|
56
61
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return;
|
|
61
|
-
const cartManager = sdk.getCartManager?.();
|
|
62
|
-
if (!cartManager)
|
|
63
|
-
return;
|
|
64
|
-
// Subscribe to cart updates
|
|
65
|
-
this.unsubscribe = cartManager.on?.('cart:updated', (cart) => {
|
|
66
|
-
const newCount = cart?.itemCount || 0;
|
|
67
|
-
console.log('[tl-cart-badge] Cart updated:', newCount);
|
|
68
|
-
this.itemCount = newCount;
|
|
69
|
-
this.persistCartCount(newCount);
|
|
70
|
-
});
|
|
71
|
-
// Load initial cart
|
|
72
|
-
cartManager.get?.().then((cart) => {
|
|
73
|
-
const newCount = cart?.itemCount || 0;
|
|
74
|
-
this.itemCount = newCount;
|
|
75
|
-
this.persistCartCount(newCount);
|
|
76
|
-
}).catch(() => {
|
|
77
|
-
// Cart may not exist yet - keep persisted value
|
|
78
|
-
});
|
|
62
|
+
forward(event, detail) {
|
|
63
|
+
if (event === 'tlClick')
|
|
64
|
+
this.tlClick.emit(detail);
|
|
79
65
|
}
|
|
80
66
|
renderIcon() {
|
|
81
67
|
if (this.icon) {
|
|
@@ -84,17 +70,16 @@ export class TlCartBadge {
|
|
|
84
70
|
return (h("svg", { class: "icon-svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor" }, h("path", { "stroke-linecap": "round", "stroke-linejoin": "round", "stroke-width": "2", d: "M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z" })));
|
|
85
71
|
}
|
|
86
72
|
render() {
|
|
87
|
-
const
|
|
88
|
-
const displayCount = this.itemCount > 99 ? '99+' : this.itemCount.toString();
|
|
73
|
+
const { derived } = this.view;
|
|
89
74
|
// Badge only mode - just show the count bubble
|
|
90
75
|
if (this.badgeOnly) {
|
|
91
|
-
if (
|
|
76
|
+
if (derived.renderNothing) {
|
|
92
77
|
return null;
|
|
93
78
|
}
|
|
94
|
-
return
|
|
79
|
+
return h("span", { class: `badge-only ${derived.sizeClass}` }, derived.displayCount);
|
|
95
80
|
}
|
|
96
81
|
// Full mode with icon and badge
|
|
97
|
-
return (h("button", { class: `cart-badge
|
|
82
|
+
return (h("button", { class: `cart-badge ${derived.sizeClass}`, onClick: this.handleClick, "aria-label": derived.ariaLabel }, this.renderIcon(), derived.showBadge && h("span", { class: "badge-count" }, derived.displayCount)));
|
|
98
83
|
}
|
|
99
84
|
static get is() { return "tl-cart-badge"; }
|
|
100
85
|
static get encapsulation() { return "shadow"; }
|
|
@@ -193,7 +178,7 @@ export class TlCartBadge {
|
|
|
193
178
|
}
|
|
194
179
|
static get states() {
|
|
195
180
|
return {
|
|
196
|
-
"
|
|
181
|
+
"view": {}
|
|
197
182
|
};
|
|
198
183
|
}
|
|
199
184
|
static get events() {
|
|
@@ -214,4 +199,19 @@ export class TlCartBadge {
|
|
|
214
199
|
}
|
|
215
200
|
}];
|
|
216
201
|
}
|
|
202
|
+
static get watchers() {
|
|
203
|
+
return [{
|
|
204
|
+
"propName": "showEmpty",
|
|
205
|
+
"methodName": "syncProps"
|
|
206
|
+
}, {
|
|
207
|
+
"propName": "icon",
|
|
208
|
+
"methodName": "syncProps"
|
|
209
|
+
}, {
|
|
210
|
+
"propName": "size",
|
|
211
|
+
"methodName": "syncProps"
|
|
212
|
+
}, {
|
|
213
|
+
"propName": "badgeOnly",
|
|
214
|
+
"methodName": "syncProps"
|
|
215
|
+
}];
|
|
216
|
+
}
|
|
217
217
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
:host {
|
|
2
|
-
--_bg: var(--tl-background
|
|
3
|
-
--_fg: var(--tl-foreground
|
|
4
|
-
--_muted-fg: var(--tl-muted-foreground
|
|
5
|
-
--_muted: var(--tl-muted
|
|
6
|
-
--_border: var(--tl-border
|
|
7
|
-
--_font: var(--tl-font-family
|
|
2
|
+
--_bg: var(--tl-background);
|
|
3
|
+
--_fg: var(--tl-foreground);
|
|
4
|
+
--_muted-fg: var(--tl-muted-foreground);
|
|
5
|
+
--_muted: var(--tl-muted);
|
|
6
|
+
--_border: var(--tl-border);
|
|
7
|
+
--_font: var(--tl-font-family);
|
|
8
8
|
font-family: var(--_font);
|
|
9
9
|
}
|
|
10
10
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { h, Host } from "@stencil/core";
|
|
2
|
-
import {
|
|
2
|
+
import { cartDrawerCore, createElement, } from "@ticketlayer/elements-core";
|
|
3
|
+
import { getSDK, whenSDK } from "../../utils/sdk-connector";
|
|
3
4
|
/**
|
|
4
5
|
* @component tl-cart-drawer
|
|
5
6
|
*
|
|
@@ -10,6 +11,10 @@ import { onSDKEvent } from "../../utils/sdk-connector";
|
|
|
10
11
|
* so the actual cart rendering / remove / checkout is shared with the inline
|
|
11
12
|
* cart; the drawer only adds the off-canvas chrome.
|
|
12
13
|
*
|
|
14
|
+
* The web harness for `cartDrawerCore`: the open/closed rule and the two
|
|
15
|
+
* intents are the core's (TKT-11). What stays here is the chrome and the one
|
|
16
|
+
* thing only a browser has, the Escape key.
|
|
17
|
+
*
|
|
13
18
|
* @prop side - which edge the panel slides from (default 'right')
|
|
14
19
|
* @event tlOpen - the drawer opened
|
|
15
20
|
* @event tlClose - the drawer closed
|
|
@@ -22,45 +27,66 @@ export class TlCartDrawer {
|
|
|
22
27
|
this.heading = 'Your cart';
|
|
23
28
|
/** Controlled open state (also driven by the `ui:cart-requested` intent). */
|
|
24
29
|
this.open = false;
|
|
25
|
-
this.
|
|
30
|
+
this.element = createElement(cartDrawerCore, {
|
|
31
|
+
client: () => getSDK(),
|
|
32
|
+
clientReady: () => whenSDK(),
|
|
33
|
+
emit: (event, detail) => this.forward(event, detail),
|
|
34
|
+
});
|
|
35
|
+
/** The core's whole view. Assigning it is what makes Stencil re-render. */
|
|
36
|
+
this.view = this.element.view;
|
|
37
|
+
/** The one thing only a browser has. What Escape means is the core's answer. */
|
|
26
38
|
this.onKey = (e) => {
|
|
27
|
-
if (e.key === 'Escape'
|
|
28
|
-
this.setOpen(false);
|
|
39
|
+
if (e.key === 'Escape')
|
|
40
|
+
this.element.actions.setOpen(false);
|
|
29
41
|
};
|
|
30
|
-
this.close = () => this.setOpen(false);
|
|
42
|
+
this.close = () => this.element.actions.setOpen(false);
|
|
43
|
+
}
|
|
44
|
+
syncProps() {
|
|
45
|
+
this.element.setProps({ side: this.side, heading: this.heading, open: this.open });
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The host moved `open`. The core follows it without announcing it, which is
|
|
49
|
+
* what the component's watcher did: an event here would be the host hearing
|
|
50
|
+
* its own write back.
|
|
51
|
+
*/
|
|
52
|
+
onOpenProp(v) {
|
|
53
|
+
this.element.setProps({ open: v });
|
|
54
|
+
this.element.actions.openChanged(v);
|
|
31
55
|
}
|
|
32
56
|
connectedCallback() {
|
|
33
|
-
this.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
57
|
+
this.syncProps();
|
|
58
|
+
this.unsubscribe ?? (this.unsubscribe = this.element.subscribe((view) => {
|
|
59
|
+
this.view = view;
|
|
60
|
+
// Reflect the core's state back onto the prop a host reads. Writing it
|
|
61
|
+
// re-enters onOpenProp, which is a no-op once the core already agrees.
|
|
62
|
+
if (this.open !== view.state.visible)
|
|
63
|
+
this.open = view.state.visible;
|
|
64
|
+
}));
|
|
65
|
+
this.view = this.element.view;
|
|
66
|
+
this.teardown = this.element.mount();
|
|
37
67
|
if (typeof document !== 'undefined')
|
|
38
68
|
document.addEventListener('keydown', this.onKey);
|
|
39
69
|
}
|
|
40
70
|
disconnectedCallback() {
|
|
41
|
-
this.
|
|
42
|
-
this.
|
|
71
|
+
this.teardown?.();
|
|
72
|
+
this.teardown = undefined;
|
|
73
|
+
this.unsubscribe?.();
|
|
74
|
+
this.unsubscribe = undefined;
|
|
43
75
|
if (typeof document !== 'undefined')
|
|
44
76
|
document.removeEventListener('keydown', this.onKey);
|
|
45
77
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
setOpen(v) {
|
|
50
|
-
if (this.visible === v)
|
|
51
|
-
return;
|
|
52
|
-
this.open = v;
|
|
53
|
-
this.visible = v;
|
|
54
|
-
if (v)
|
|
78
|
+
forward(event, _detail) {
|
|
79
|
+
if (event === 'tlOpen')
|
|
55
80
|
this.tlOpen.emit();
|
|
56
|
-
else
|
|
81
|
+
else if (event === 'tlClose')
|
|
57
82
|
this.tlClose.emit();
|
|
58
83
|
}
|
|
59
84
|
render() {
|
|
60
|
-
|
|
85
|
+
const { strings, derived } = this.view;
|
|
86
|
+
return (h(Host, { key: 'ab41f3557cd8dd2b182bbfc3ed631bca7839d4a9' }, h("div", { key: '70bbe63d1f9a2d449cb9ff970631c0c69a2eb757', class: { overlay: true, 'is-open': derived.visible }, onClick: (e) => {
|
|
61
87
|
if (e.target === e.currentTarget)
|
|
62
88
|
this.close();
|
|
63
|
-
} }, h("aside", { key: '
|
|
89
|
+
} }, h("aside", { key: 'eefe601ef6d2d8fc6bcfe62f1777d139875f875d', class: { panel: true, [derived.sideClass]: true, 'is-open': derived.visible }, role: "dialog", "aria-modal": "true", "aria-label": this.heading, "aria-hidden": derived.ariaHidden }, h("header", { key: '753d616182c3a903111dcaaf9b37f03186e17b48', class: "drawer-header" }, h("h2", { key: '3e839ddbc2a2da1f4c8eb0c1e38c421de13426cd', class: "drawer-title" }, this.heading), h("button", { key: '0d80fff5f425d6150fb391fd930161167b5f7d27', class: "close-btn", onClick: this.close, "aria-label": strings.close }, h("svg", { key: '7ffcbfb86f921d13deb5070140f21e4c7ca668f1', viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, h("path", { key: '53d690ef2ac8d1d73038c53fa3aa0146bde0fb51', d: "M6 6l12 12M18 6L6 18", "stroke-linecap": "round" })))), h("div", { key: 'a782b1527cde89656e5f776311f848c446d92d48', class: "drawer-body" }, h("tl-cart", { key: '3cd2c09f728cf14f0ea5b6ff4493b3e51e0dda62' })), h("footer", { key: '2df57237bbd548ae4af09098676d7e1315e11d71', class: "drawer-footer" }, h("div", { key: 'f02f5970181a2d83b70ac44188f00523a188771d', class: "pb-links" }, h("a", { key: 'd799da3a8c1c33b10a268500b02fda5523cd8bcf', href: strings.privacyHref, target: "_blank", rel: "noopener noreferrer" }, strings.privacy), h("a", { key: 'e928acb4c78cef8762d7ae8d258fa705554fd121', href: strings.reportAbuseHref, target: "_blank", rel: "noopener noreferrer" }, strings.reportAbuse)), h("a", { key: '39278516b8da6dd14fe8bf0d0379c32ccfeb1d29', class: "pb-brand", href: strings.brandHref, target: "_blank", rel: "noopener noreferrer" }, h("span", { key: '96b2cb7ac0a73cd0c60fb7977999a00b4989177e', class: "pb-pre" }, strings.poweredBy), h("svg", { key: 'b3950f83eab4a41e63a7919e6872a9ecdafab38b', width: "13", height: "13", viewBox: "0 0 50 50", fill: "none", "aria-hidden": "true" }, h("g", { key: '4c0c7ec66952f8a1956b3061f6bf2eb45c438989', transform: "matrix(0.0129 0 0 -0.0129 25.4752 25.4752)" }, h("path", { key: 'b1c9a143f0b2ad24da843323a4c1c550e9717d1b', fill: "currentColor", transform: "translate(-1781.5, -1759.4003)", d: "M 41 2973 c 1 -285 5 -734 9 -998 c 7 -444 9 -488 30 -580 c 81 -364 235 -634 512 -900 c 135 -130 263 -220 423 -299 c 156 -77 249 -109 409 -143 c 110 -23 142 -25 354 -24 c 230 1 310 8 427 37 c 241 60 453 162 640 309 c 82 64 252 234 317 315 c 210 264 340 604 355 926 l 6 121 l -69 6 c -86 8 -706 9 -755 1 l -36 -6 l -21 -125 c -34 -191 -98 -317 -236 -462 c -111 -115 -249 -198 -396 -238 c -98 -27 -356 -24 -463 5 c -100 27 -183 69 -273 137 c -226 173 -353 409 -354 660 c 0 44 -5 120 -10 169 c -6 49 -8 91 -6 94 c 3 3 65 -22 138 -55 c 140 -64 251 -103 358 -127 c 71 -17 295 -46 347 -46 l 33 0 l 0 434 l 0 434 l -67 7 c -147 14 -269 56 -393 133 c -222 139 -378 393 -397 648 l -6 71 l -75 7 c -41 3 -239 6 -439 6 l -363 0 l 1 -517 z" }))), h("span", { key: '053ca451a9674161799458e731862a93c954be23', class: "pb-word" }, strings.brand)))))));
|
|
64
90
|
}
|
|
65
91
|
static get is() { return "tl-cart-drawer"; }
|
|
66
92
|
static get encapsulation() { return "shadow"; }
|
|
@@ -140,7 +166,7 @@ export class TlCartDrawer {
|
|
|
140
166
|
}
|
|
141
167
|
static get states() {
|
|
142
168
|
return {
|
|
143
|
-
"
|
|
169
|
+
"view": {}
|
|
144
170
|
};
|
|
145
171
|
}
|
|
146
172
|
static get events() {
|
|
@@ -178,6 +204,12 @@ export class TlCartDrawer {
|
|
|
178
204
|
}
|
|
179
205
|
static get watchers() {
|
|
180
206
|
return [{
|
|
207
|
+
"propName": "side",
|
|
208
|
+
"methodName": "syncProps"
|
|
209
|
+
}, {
|
|
210
|
+
"propName": "heading",
|
|
211
|
+
"methodName": "syncProps"
|
|
212
|
+
}, {
|
|
181
213
|
"propName": "open",
|
|
182
214
|
"methodName": "onOpenProp"
|
|
183
215
|
}];
|
|
@@ -10,9 +10,9 @@ tl-checkout-wrapper,
|
|
|
10
10
|
|
|
11
11
|
tl-checkout-wrapper:focus,
|
|
12
12
|
.tl-checkout-wrapper:focus {
|
|
13
|
-
outline: 2px solid var(--tl-ring
|
|
13
|
+
outline: 2px solid var(--tl-ring);
|
|
14
14
|
outline-offset: 2px;
|
|
15
|
-
border-radius: var(--tl-radius-sm
|
|
15
|
+
border-radius: var(--tl-radius-sm);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
tl-checkout-wrapper[disabled],
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { h, Host } from "@stencil/core";
|
|
2
|
-
import {
|
|
2
|
+
import { checkoutWrapperCore, createElement, } from "@ticketlayer/elements-core";
|
|
3
|
+
import { getSDK, whenSDK } from "../../utils/sdk-connector";
|
|
3
4
|
/**
|
|
4
5
|
* @component tl-checkout-wrapper
|
|
5
6
|
*
|
|
6
7
|
* Wraps any content and opens the Ticketlayer checkout modal when clicked.
|
|
7
8
|
* Uses the SDK's modal manager which handles the iframe overlay.
|
|
8
9
|
*
|
|
10
|
+
* The web harness for `checkoutWrapperCore`: it renders, it forwards, and it
|
|
11
|
+
* decides only which key press counts as activation. Everything else is in
|
|
12
|
+
* `@ticketlayer/elements-core` (AGENTS.md, TKT-11).
|
|
13
|
+
*
|
|
9
14
|
* @slot - Content to display (typically a checkout button)
|
|
10
15
|
*
|
|
11
16
|
* @example
|
|
@@ -19,40 +24,57 @@ export class TlCheckoutWrapper {
|
|
|
19
24
|
* Whether the wrapper is disabled
|
|
20
25
|
*/
|
|
21
26
|
this.disabled = false;
|
|
27
|
+
this.element = createElement(checkoutWrapperCore, {
|
|
28
|
+
client: () => getSDK(),
|
|
29
|
+
clientReady: () => whenSDK(),
|
|
30
|
+
emit: (event, detail) => this.forward(event, detail),
|
|
31
|
+
});
|
|
32
|
+
/** The core's whole view. Assigning it is what makes Stencil re-render. */
|
|
33
|
+
this.view = this.element.view;
|
|
22
34
|
this.handleClick = () => {
|
|
23
|
-
|
|
24
|
-
return;
|
|
25
|
-
if (!hasSDK()) {
|
|
26
|
-
console.error('[tl-checkout-wrapper] SDK not initialized. Call setSDK(ticketlayer) first.');
|
|
27
|
-
this.tlError.emit({ message: 'SDK not initialized' });
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
const sdk = getSDK();
|
|
31
|
-
// Open the checkout modal via SDK
|
|
32
|
-
sdk.checkout.openModal({
|
|
33
|
-
onComplete: (order) => {
|
|
34
|
-
this.tlComplete.emit(order);
|
|
35
|
-
},
|
|
36
|
-
onError: (err) => {
|
|
37
|
-
this.tlError.emit({ message: err.message });
|
|
38
|
-
},
|
|
39
|
-
onClose: () => {
|
|
40
|
-
this.tlClose.emit();
|
|
41
|
-
},
|
|
42
|
-
});
|
|
35
|
+
this.element.actions.activate();
|
|
43
36
|
};
|
|
37
|
+
/** Enter and Space are a press on the web. The core knows nothing of keys. */
|
|
44
38
|
this.handleKeyDown = (e) => {
|
|
45
39
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
46
40
|
e.preventDefault();
|
|
47
|
-
this.
|
|
41
|
+
this.element.actions.activate();
|
|
48
42
|
}
|
|
49
43
|
};
|
|
50
44
|
}
|
|
45
|
+
syncProps() {
|
|
46
|
+
this.element.setProps({ disabled: this.disabled });
|
|
47
|
+
}
|
|
48
|
+
connectedCallback() {
|
|
49
|
+
this.syncProps();
|
|
50
|
+
this.unsubscribe ?? (this.unsubscribe = this.element.subscribe((view) => {
|
|
51
|
+
this.view = view;
|
|
52
|
+
}));
|
|
53
|
+
this.view = this.element.view;
|
|
54
|
+
// Nothing to do on mount, and mounted anyway: a harness calls mount()
|
|
55
|
+
// unconditionally and pairs it with its teardown (TKT-197).
|
|
56
|
+
this.teardown = this.element.mount();
|
|
57
|
+
}
|
|
58
|
+
disconnectedCallback() {
|
|
59
|
+
this.teardown?.();
|
|
60
|
+
this.teardown = undefined;
|
|
61
|
+
this.unsubscribe?.();
|
|
62
|
+
this.unsubscribe = undefined;
|
|
63
|
+
}
|
|
64
|
+
forward(event, detail) {
|
|
65
|
+
if (event === 'tlComplete')
|
|
66
|
+
this.tlComplete.emit(detail);
|
|
67
|
+
else if (event === 'tlError')
|
|
68
|
+
this.tlError.emit(detail);
|
|
69
|
+
else if (event === 'tlClose')
|
|
70
|
+
this.tlClose.emit();
|
|
71
|
+
}
|
|
51
72
|
render() {
|
|
52
|
-
|
|
73
|
+
const { interactive } = this.view.derived;
|
|
74
|
+
return (h(Host, { key: 'b261046c2627825258a5905662a79f436d713683', class: {
|
|
53
75
|
'tl-checkout-wrapper': true,
|
|
54
|
-
'tl-checkout-wrapper--disabled':
|
|
55
|
-
}, onClick: this.handleClick, onKeyDown: this.handleKeyDown, role: "button", tabindex:
|
|
76
|
+
'tl-checkout-wrapper--disabled': !interactive,
|
|
77
|
+
}, onClick: this.handleClick, onKeyDown: this.handleKeyDown, role: "button", tabindex: interactive ? 0 : -1, "aria-disabled": interactive ? null : 'true' }, h("slot", { key: '5be08d5007a755e3d88a06ae89c08e082e4ba052' })));
|
|
56
78
|
}
|
|
57
79
|
static get is() { return "tl-checkout-wrapper"; }
|
|
58
80
|
static get originalStyleUrls() {
|
|
@@ -89,10 +111,15 @@ export class TlCheckoutWrapper {
|
|
|
89
111
|
}
|
|
90
112
|
};
|
|
91
113
|
}
|
|
114
|
+
static get states() {
|
|
115
|
+
return {
|
|
116
|
+
"view": {}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
92
119
|
static get events() {
|
|
93
120
|
return [{
|
|
94
121
|
"method": "tlComplete",
|
|
95
|
-
"name": "
|
|
122
|
+
"name": "tlComplete",
|
|
96
123
|
"bubbles": true,
|
|
97
124
|
"cancelable": true,
|
|
98
125
|
"composed": true,
|
|
@@ -114,7 +141,7 @@ export class TlCheckoutWrapper {
|
|
|
114
141
|
}
|
|
115
142
|
}, {
|
|
116
143
|
"method": "tlError",
|
|
117
|
-
"name": "
|
|
144
|
+
"name": "tlError",
|
|
118
145
|
"bubbles": true,
|
|
119
146
|
"cancelable": true,
|
|
120
147
|
"composed": true,
|
|
@@ -129,7 +156,7 @@ export class TlCheckoutWrapper {
|
|
|
129
156
|
}
|
|
130
157
|
}, {
|
|
131
158
|
"method": "tlClose",
|
|
132
|
-
"name": "
|
|
159
|
+
"name": "tlClose",
|
|
133
160
|
"bubbles": true,
|
|
134
161
|
"cancelable": true,
|
|
135
162
|
"composed": true,
|
|
@@ -144,5 +171,10 @@ export class TlCheckoutWrapper {
|
|
|
144
171
|
}
|
|
145
172
|
}];
|
|
146
173
|
}
|
|
147
|
-
static get
|
|
174
|
+
static get watchers() {
|
|
175
|
+
return [{
|
|
176
|
+
"propName": "disabled",
|
|
177
|
+
"methodName": "syncProps"
|
|
178
|
+
}];
|
|
179
|
+
}
|
|
148
180
|
}
|
|
@@ -1,23 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
id: detail.id,
|
|
14
|
-
name: detail.name,
|
|
15
|
-
...(detail.shortDescription ? { shortDescription: detail.shortDescription } : {}),
|
|
16
|
-
...(detail.imageUrl ? { imageUrl: detail.imageUrl } : {}),
|
|
17
|
-
...(detail.venueName
|
|
18
|
-
? { venue: { id: detail.venueId ?? '', name: detail.venueName, city: detail.venueCity ?? '' } }
|
|
19
|
-
: {}),
|
|
20
|
-
...(next ? { nextOccurrence: { startsAt: next } } : {}),
|
|
21
|
-
availabilityStatus: soldOut ? 'sold_out' : 'available',
|
|
22
|
-
};
|
|
23
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Adapts the sales event detail (events manager get) to the shape
|
|
3
|
+
* tl-event-card renders.
|
|
4
|
+
*
|
|
5
|
+
* The adapter and its type moved to `@ticketlayer/elements-core` with the core
|
|
6
|
+
* split (TKT-69): picking the next occurrence and deciding whether a card reads
|
|
7
|
+
* sold out is behaviour, and behaviour lives in a core so every harness decides
|
|
8
|
+
* it the same way. This file stays as the import path the component and its
|
|
9
|
+
* spec already use.
|
|
10
|
+
*/
|
|
11
|
+
export { toEventCardEvent } from '@ticketlayer/elements-core';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
:host {
|
|
2
2
|
display: block;
|
|
3
|
-
font-family: var(--tl-font-family
|
|
3
|
+
font-family: var(--tl-font-family);
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
.event-card {
|
|
7
|
-
background: var(--tl-secondary
|
|
8
|
-
border-radius: var(--tl-radius-lg
|
|
7
|
+
background: var(--tl-secondary);
|
|
8
|
+
border-radius: var(--tl-radius-lg);
|
|
9
9
|
overflow: hidden;
|
|
10
10
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
11
11
|
cursor: pointer;
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
position: relative;
|
|
22
22
|
aspect-ratio: 16 / 9;
|
|
23
23
|
overflow: hidden;
|
|
24
|
-
background: var(--tl-muted
|
|
24
|
+
background: var(--tl-muted);
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
.event-image {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
display: flex;
|
|
42
42
|
align-items: center;
|
|
43
43
|
justify-content: center;
|
|
44
|
-
color: var(--tl-muted-foreground
|
|
44
|
+
color: var(--tl-muted-foreground);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
.status-container {
|
|
@@ -55,26 +55,26 @@
|
|
|
55
55
|
padding: 0.25rem 0.5rem;
|
|
56
56
|
font-size: 0.75rem;
|
|
57
57
|
font-weight: 500;
|
|
58
|
-
border-radius: var(--tl-radius-sm
|
|
58
|
+
border-radius: var(--tl-radius-sm);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
.status-available {
|
|
62
|
-
background: var(--tl-success
|
|
63
|
-
color: var(--tl-success-foreground
|
|
62
|
+
background: var(--tl-success);
|
|
63
|
+
color: var(--tl-success-foreground);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
.status-limited {
|
|
67
|
-
background: var(--tl-warning
|
|
68
|
-
color: var(--tl-warning-foreground
|
|
67
|
+
background: var(--tl-warning);
|
|
68
|
+
color: var(--tl-warning-foreground);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
.status-sold-out {
|
|
72
|
-
background: var(--tl-error
|
|
73
|
-
color: var(--tl-error-foreground
|
|
72
|
+
background: var(--tl-error);
|
|
73
|
+
color: var(--tl-error-foreground);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
.content {
|
|
77
|
-
padding: var(--tl-spacing-4
|
|
77
|
+
padding: var(--tl-spacing-4);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
.category {
|
|
@@ -83,19 +83,19 @@
|
|
|
83
83
|
font-weight: 500;
|
|
84
84
|
text-transform: uppercase;
|
|
85
85
|
letter-spacing: 0.05em;
|
|
86
|
-
color: var(--tl-primary
|
|
86
|
+
color: var(--tl-primary);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
.title {
|
|
90
90
|
margin: 0.25rem 0 0;
|
|
91
91
|
font-size: 1.125rem;
|
|
92
92
|
font-weight: 600;
|
|
93
|
-
color: var(--tl-foreground
|
|
93
|
+
color: var(--tl-foreground);
|
|
94
94
|
line-height: 1.3;
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
.event-card:hover .title {
|
|
98
|
-
color: var(--tl-primary
|
|
98
|
+
color: var(--tl-primary);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
.meta {
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
gap: 0.5rem;
|
|
105
105
|
margin: 0.5rem 0 0;
|
|
106
106
|
font-size: 0.875rem;
|
|
107
|
-
color: var(--tl-muted-foreground
|
|
107
|
+
color: var(--tl-muted-foreground);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
.meta:first-of-type {
|
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
.description {
|
|
121
121
|
margin: 0.75rem 0 0;
|
|
122
122
|
font-size: 0.875rem;
|
|
123
|
-
color: var(--tl-muted-foreground
|
|
123
|
+
color: var(--tl-muted-foreground);
|
|
124
124
|
line-height: 1.5;
|
|
125
125
|
display: -webkit-box;
|
|
126
126
|
-webkit-line-clamp: 2;
|
|
@@ -140,8 +140,8 @@
|
|
|
140
140
|
.skeleton-line {
|
|
141
141
|
height: 0.875rem;
|
|
142
142
|
margin-top: 0.5rem;
|
|
143
|
-
background: var(--tl-muted
|
|
144
|
-
border-radius: var(--tl-radius-sm
|
|
143
|
+
background: var(--tl-muted);
|
|
144
|
+
border-radius: var(--tl-radius-sm);
|
|
145
145
|
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
146
146
|
}
|
|
147
147
|
|
|
@@ -154,9 +154,9 @@
|
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
.card-error {
|
|
157
|
-
padding: var(--tl-spacing-4
|
|
157
|
+
padding: var(--tl-spacing-4);
|
|
158
158
|
font-size: 0.875rem;
|
|
159
|
-
color: var(--tl-error
|
|
159
|
+
color: var(--tl-error);
|
|
160
160
|
cursor: default;
|
|
161
161
|
}
|
|
162
162
|
|