@ticketlayer/elements 0.2.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 (195) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +55 -0
  3. package/dist/cjs/index-DfzcrE9-.js +3598 -0
  4. package/dist/cjs/index.cjs.js +16 -0
  5. package/dist/cjs/loader.cjs.js +12 -0
  6. package/dist/cjs/order-summary-ZMkJ5bez.js +116 -0
  7. package/dist/cjs/sdk-connector-ClDF3013.js +108 -0
  8. package/dist/cjs/ticketlayer-elements.cjs.js +24 -0
  9. package/dist/cjs/tl-buy-modal.cjs.entry.js +127 -0
  10. package/dist/cjs/tl-buy-tickets-button.cjs.entry.js +131 -0
  11. package/dist/cjs/tl-buy-tickets-wrapper.cjs.entry.js +58 -0
  12. package/dist/cjs/tl-cart-badge.cjs.entry.js +109 -0
  13. package/dist/cjs/tl-cart-drawer.cjs.entry.js +67 -0
  14. package/dist/cjs/tl-cart.cjs.entry.js +148 -0
  15. package/dist/cjs/tl-checkout-wrapper.cjs.entry.js +57 -0
  16. package/dist/cjs/tl-event-card.cjs.entry.js +140 -0
  17. package/dist/cjs/tl-event-list.cjs.entry.js +80 -0
  18. package/dist/cjs/tl-login.cjs.entry.js +184 -0
  19. package/dist/cjs/tl-my-orders.cjs.entry.js +123 -0
  20. package/dist/cjs/tl-occurrence-selector_2.cjs.entry.js +754 -0
  21. package/dist/cjs/tl-order-confirmation.cjs.entry.js +146 -0
  22. package/dist/cjs/tl-order-tickets_2.cjs.entry.js +3198 -0
  23. package/dist/cjs/tl-promo-code.cjs.entry.js +75 -0
  24. package/dist/cjs/tl-seat-map.cjs.entry.js +147 -0
  25. package/dist/collection/collection-manifest.json +29 -0
  26. package/dist/collection/components/tl-buy-modal/tl-buy-modal.css +264 -0
  27. package/dist/collection/components/tl-buy-modal/tl-buy-modal.js +249 -0
  28. package/dist/collection/components/tl-buy-tickets-button/tl-buy-tickets-button.css +120 -0
  29. package/dist/collection/components/tl-buy-tickets-button/tl-buy-tickets-button.js +412 -0
  30. package/dist/collection/components/tl-buy-tickets-wrapper/tl-buy-tickets-wrapper.css +23 -0
  31. package/dist/collection/components/tl-buy-tickets-wrapper/tl-buy-tickets-wrapper.js +192 -0
  32. package/dist/collection/components/tl-cart/tl-cart.css +251 -0
  33. package/dist/collection/components/tl-cart/tl-cart.js +314 -0
  34. package/dist/collection/components/tl-cart-badge/tl-cart-badge.css +138 -0
  35. package/dist/collection/components/tl-cart-badge/tl-cart-badge.js +217 -0
  36. package/dist/collection/components/tl-cart-drawer/tl-cart-drawer.css +98 -0
  37. package/dist/collection/components/tl-cart-drawer/tl-cart-drawer.js +185 -0
  38. package/dist/collection/components/tl-checkout-wrapper/tl-checkout-wrapper.css +23 -0
  39. package/dist/collection/components/tl-checkout-wrapper/tl-checkout-wrapper.js +148 -0
  40. package/dist/collection/components/tl-event-card/event-card-adapter.js +23 -0
  41. package/dist/collection/components/tl-event-card/tl-event-card.css +175 -0
  42. package/dist/collection/components/tl-event-card/tl-event-card.js +205 -0
  43. package/dist/collection/components/tl-event-list/tl-event-list.css +134 -0
  44. package/dist/collection/components/tl-event-list/tl-event-list.js +171 -0
  45. package/dist/collection/components/tl-login/tl-login.css +133 -0
  46. package/dist/collection/components/tl-login/tl-login.js +309 -0
  47. package/dist/collection/components/tl-my-orders/tl-my-orders.css +204 -0
  48. package/dist/collection/components/tl-my-orders/tl-my-orders.js +221 -0
  49. package/dist/collection/components/tl-occurrence-selector/tl-occurrence-selector.css +658 -0
  50. package/dist/collection/components/tl-occurrence-selector/tl-occurrence-selector.js +707 -0
  51. package/dist/collection/components/tl-order-confirmation/tl-order-confirmation.css +176 -0
  52. package/dist/collection/components/tl-order-confirmation/tl-order-confirmation.js +298 -0
  53. package/dist/collection/components/tl-order-tickets/tl-order-tickets.css +30 -0
  54. package/dist/collection/components/tl-order-tickets/tl-order-tickets.js +122 -0
  55. package/dist/collection/components/tl-promo-code/tl-promo-code.css +106 -0
  56. package/dist/collection/components/tl-promo-code/tl-promo-code.js +181 -0
  57. package/dist/collection/components/tl-seat-map/tl-seat-map.css +85 -0
  58. package/dist/collection/components/tl-seat-map/tl-seat-map.js +366 -0
  59. package/dist/collection/components/tl-ticket/tl-ticket.css +90 -0
  60. package/dist/collection/components/tl-ticket/tl-ticket.js +129 -0
  61. package/dist/collection/components/tl-ticket-selector/tl-ticket-selector.css +205 -0
  62. package/dist/collection/components/tl-ticket-selector/tl-ticket-selector.js +332 -0
  63. package/dist/collection/index.js +10 -0
  64. package/dist/collection/utils/order-summary.js +101 -0
  65. package/dist/collection/utils/sdk-connector.js +100 -0
  66. package/dist/collection/utils/testing/mock-sdk.js +95 -0
  67. package/dist/components/index.d.ts +35 -0
  68. package/dist/components/index.js +1 -0
  69. package/dist/components/order-summary.js +1 -0
  70. package/dist/components/sdk-connector.js +1 -0
  71. package/dist/components/tl-buy-modal.d.ts +11 -0
  72. package/dist/components/tl-buy-modal.js +1 -0
  73. package/dist/components/tl-buy-tickets-button.d.ts +11 -0
  74. package/dist/components/tl-buy-tickets-button.js +1 -0
  75. package/dist/components/tl-buy-tickets-wrapper.d.ts +11 -0
  76. package/dist/components/tl-buy-tickets-wrapper.js +1 -0
  77. package/dist/components/tl-buy-tickets-wrapper2.js +1 -0
  78. package/dist/components/tl-cart-badge.d.ts +11 -0
  79. package/dist/components/tl-cart-badge.js +1 -0
  80. package/dist/components/tl-cart-drawer.d.ts +11 -0
  81. package/dist/components/tl-cart-drawer.js +1 -0
  82. package/dist/components/tl-cart.d.ts +11 -0
  83. package/dist/components/tl-cart.js +1 -0
  84. package/dist/components/tl-cart2.js +1 -0
  85. package/dist/components/tl-checkout-wrapper.d.ts +11 -0
  86. package/dist/components/tl-checkout-wrapper.js +1 -0
  87. package/dist/components/tl-checkout-wrapper2.js +1 -0
  88. package/dist/components/tl-event-card.d.ts +11 -0
  89. package/dist/components/tl-event-card.js +1 -0
  90. package/dist/components/tl-event-card2.js +1 -0
  91. package/dist/components/tl-event-list.d.ts +11 -0
  92. package/dist/components/tl-event-list.js +1 -0
  93. package/dist/components/tl-login.d.ts +11 -0
  94. package/dist/components/tl-login.js +1 -0
  95. package/dist/components/tl-login2.js +1 -0
  96. package/dist/components/tl-my-orders.d.ts +11 -0
  97. package/dist/components/tl-my-orders.js +1 -0
  98. package/dist/components/tl-occurrence-selector.d.ts +11 -0
  99. package/dist/components/tl-occurrence-selector.js +1 -0
  100. package/dist/components/tl-occurrence-selector2.js +1 -0
  101. package/dist/components/tl-order-confirmation.d.ts +11 -0
  102. package/dist/components/tl-order-confirmation.js +1 -0
  103. package/dist/components/tl-order-tickets.d.ts +11 -0
  104. package/dist/components/tl-order-tickets.js +1 -0
  105. package/dist/components/tl-order-tickets2.js +1 -0
  106. package/dist/components/tl-promo-code.d.ts +11 -0
  107. package/dist/components/tl-promo-code.js +1 -0
  108. package/dist/components/tl-seat-map.d.ts +11 -0
  109. package/dist/components/tl-seat-map.js +1 -0
  110. package/dist/components/tl-ticket-selector.d.ts +11 -0
  111. package/dist/components/tl-ticket-selector.js +1 -0
  112. package/dist/components/tl-ticket-selector2.js +1 -0
  113. package/dist/components/tl-ticket.d.ts +11 -0
  114. package/dist/components/tl-ticket.js +1 -0
  115. package/dist/components/tl-ticket2.js +1 -0
  116. package/dist/elements.docs.d.ts +454 -0
  117. package/dist/elements.docs.json +3008 -0
  118. package/dist/esm/index-Ba-RZTFI.js +3588 -0
  119. package/dist/esm/index.js +4 -0
  120. package/dist/esm/loader.js +10 -0
  121. package/dist/esm/order-summary-BGekdjN9.js +103 -0
  122. package/dist/esm/sdk-connector-CqhvfyKV.js +102 -0
  123. package/dist/esm/ticketlayer-elements.js +20 -0
  124. package/dist/esm/tl-buy-modal.entry.js +125 -0
  125. package/dist/esm/tl-buy-tickets-button.entry.js +129 -0
  126. package/dist/esm/tl-buy-tickets-wrapper.entry.js +56 -0
  127. package/dist/esm/tl-cart-badge.entry.js +107 -0
  128. package/dist/esm/tl-cart-drawer.entry.js +65 -0
  129. package/dist/esm/tl-cart.entry.js +146 -0
  130. package/dist/esm/tl-checkout-wrapper.entry.js +55 -0
  131. package/dist/esm/tl-event-card.entry.js +138 -0
  132. package/dist/esm/tl-event-list.entry.js +78 -0
  133. package/dist/esm/tl-login.entry.js +182 -0
  134. package/dist/esm/tl-my-orders.entry.js +121 -0
  135. package/dist/esm/tl-occurrence-selector_2.entry.js +751 -0
  136. package/dist/esm/tl-order-confirmation.entry.js +144 -0
  137. package/dist/esm/tl-order-tickets_2.entry.js +3195 -0
  138. package/dist/esm/tl-promo-code.entry.js +73 -0
  139. package/dist/esm/tl-seat-map.entry.js +145 -0
  140. package/dist/index.cjs.js +1 -0
  141. package/dist/index.js +1 -0
  142. package/dist/ticketlayer-elements/index.esm.js +1 -0
  143. package/dist/ticketlayer-elements/p-0291df4c.entry.js +1 -0
  144. package/dist/ticketlayer-elements/p-10f01a1f.entry.js +1 -0
  145. package/dist/ticketlayer-elements/p-11273f8f.entry.js +1 -0
  146. package/dist/ticketlayer-elements/p-340ab4f5.entry.js +1 -0
  147. package/dist/ticketlayer-elements/p-41d22d7c.entry.js +1 -0
  148. package/dist/ticketlayer-elements/p-82752e3b.entry.js +1 -0
  149. package/dist/ticketlayer-elements/p-976770f3.entry.js +1 -0
  150. package/dist/ticketlayer-elements/p-9a903ff6.entry.js +1 -0
  151. package/dist/ticketlayer-elements/p-9c9072c8.entry.js +1 -0
  152. package/dist/ticketlayer-elements/p-9d8163d6.entry.js +1 -0
  153. package/dist/ticketlayer-elements/p-BGekdjN9.js +1 -0
  154. package/dist/ticketlayer-elements/p-Ba-RZTFI.js +2 -0
  155. package/dist/ticketlayer-elements/p-CqhvfyKV.js +1 -0
  156. package/dist/ticketlayer-elements/p-a5c90b68.entry.js +1 -0
  157. package/dist/ticketlayer-elements/p-b6d479ad.entry.js +1 -0
  158. package/dist/ticketlayer-elements/p-dd43f015.entry.js +1 -0
  159. package/dist/ticketlayer-elements/p-eb640760.entry.js +1 -0
  160. package/dist/ticketlayer-elements/p-ee3aa227.entry.js +1 -0
  161. package/dist/ticketlayer-elements/p-fb9444c4.entry.js +1 -0
  162. package/dist/ticketlayer-elements/ticketlayer-elements.css +1 -0
  163. package/dist/ticketlayer-elements/ticketlayer-elements.esm.js +1 -0
  164. package/dist/types/components/tl-buy-modal/tl-buy-modal.d.ts +54 -0
  165. package/dist/types/components/tl-buy-tickets-button/tl-buy-tickets-button.d.ts +61 -0
  166. package/dist/types/components/tl-buy-tickets-wrapper/tl-buy-tickets-wrapper.d.ts +52 -0
  167. package/dist/types/components/tl-cart/tl-cart.d.ts +80 -0
  168. package/dist/types/components/tl-cart-badge/tl-cart-badge.d.ts +36 -0
  169. package/dist/types/components/tl-cart-drawer/tl-cart-drawer.d.ts +35 -0
  170. package/dist/types/components/tl-checkout-wrapper/tl-checkout-wrapper.d.ts +39 -0
  171. package/dist/types/components/tl-event-card/event-card-adapter.d.ts +23 -0
  172. package/dist/types/components/tl-event-card/tl-event-card.d.ts +55 -0
  173. package/dist/types/components/tl-event-list/tl-event-list.d.ts +30 -0
  174. package/dist/types/components/tl-login/tl-login.d.ts +59 -0
  175. package/dist/types/components/tl-my-orders/tl-my-orders.d.ts +39 -0
  176. package/dist/types/components/tl-occurrence-selector/tl-occurrence-selector.d.ts +208 -0
  177. package/dist/types/components/tl-order-confirmation/tl-order-confirmation.d.ts +54 -0
  178. package/dist/types/components/tl-order-tickets/tl-order-tickets.d.ts +21 -0
  179. package/dist/types/components/tl-promo-code/tl-promo-code.d.ts +39 -0
  180. package/dist/types/components/tl-seat-map/tl-seat-map.d.ts +68 -0
  181. package/dist/types/components/tl-ticket/tl-ticket.d.ts +28 -0
  182. package/dist/types/components/tl-ticket-selector/tl-ticket-selector.d.ts +78 -0
  183. package/dist/types/components.d.ts +1629 -0
  184. package/dist/types/index.d.ts +14 -0
  185. package/dist/types/stencil-public-runtime.d.ts +1839 -0
  186. package/dist/types/utils/order-summary.d.ts +67 -0
  187. package/dist/types/utils/sdk-connector.d.ts +113 -0
  188. package/dist/types/utils/testing/mock-sdk.d.ts +36 -0
  189. package/elements.catalogue.json +968 -0
  190. package/loader/cdn.js +1 -0
  191. package/loader/index.cjs.js +1 -0
  192. package/loader/index.d.ts +24 -0
  193. package/loader/index.es2017.js +1 -0
  194. package/loader/index.js +2 -0
  195. package/package.json +101 -0
@@ -0,0 +1,175 @@
1
+ :host {
2
+ display: block;
3
+ font-family: var(--tl-font-family, system-ui, sans-serif);
4
+ }
5
+
6
+ .event-card {
7
+ background: var(--tl-secondary, #f3f4f6);
8
+ border-radius: var(--tl-radius-lg, 0.75rem);
9
+ overflow: hidden;
10
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
11
+ cursor: pointer;
12
+ transition: box-shadow 0.2s ease, transform 0.2s ease;
13
+ }
14
+
15
+ .event-card:hover {
16
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
17
+ transform: translateY(-2px);
18
+ }
19
+
20
+ .image-container {
21
+ position: relative;
22
+ aspect-ratio: 16 / 9;
23
+ overflow: hidden;
24
+ background: var(--tl-muted, #f9fafb);
25
+ }
26
+
27
+ .event-image {
28
+ width: 100%;
29
+ height: 100%;
30
+ object-fit: cover;
31
+ transition: transform 0.3s ease;
32
+ }
33
+
34
+ .event-card:hover .event-image {
35
+ transform: scale(1.05);
36
+ }
37
+
38
+ .image-placeholder {
39
+ width: 100%;
40
+ height: 100%;
41
+ display: flex;
42
+ align-items: center;
43
+ justify-content: center;
44
+ color: var(--tl-muted-foreground, #6b7280);
45
+ }
46
+
47
+ .status-container {
48
+ position: absolute;
49
+ top: 0.5rem;
50
+ right: 0.5rem;
51
+ }
52
+
53
+ .status-badge {
54
+ display: inline-block;
55
+ padding: 0.25rem 0.5rem;
56
+ font-size: 0.75rem;
57
+ font-weight: 500;
58
+ border-radius: var(--tl-radius-sm, 0.25rem);
59
+ }
60
+
61
+ .status-available {
62
+ background: var(--tl-success, #10b981);
63
+ color: var(--tl-success-foreground, #ffffff);
64
+ }
65
+
66
+ .status-limited {
67
+ background: var(--tl-warning, #f59e0b);
68
+ color: var(--tl-warning-foreground, #ffffff);
69
+ }
70
+
71
+ .status-sold-out {
72
+ background: var(--tl-error, #ef4444);
73
+ color: var(--tl-error-foreground, #ffffff);
74
+ }
75
+
76
+ .content {
77
+ padding: var(--tl-spacing-4, 1rem);
78
+ }
79
+
80
+ .category {
81
+ display: inline-block;
82
+ font-size: 0.75rem;
83
+ font-weight: 500;
84
+ text-transform: uppercase;
85
+ letter-spacing: 0.05em;
86
+ color: var(--tl-primary, #6366f1);
87
+ }
88
+
89
+ .title {
90
+ margin: 0.25rem 0 0;
91
+ font-size: 1.125rem;
92
+ font-weight: 600;
93
+ color: var(--tl-foreground, #111827);
94
+ line-height: 1.3;
95
+ }
96
+
97
+ .event-card:hover .title {
98
+ color: var(--tl-primary, #6366f1);
99
+ }
100
+
101
+ .meta {
102
+ display: flex;
103
+ align-items: center;
104
+ gap: 0.5rem;
105
+ margin: 0.5rem 0 0;
106
+ font-size: 0.875rem;
107
+ color: var(--tl-muted-foreground, #6b7280);
108
+ }
109
+
110
+ .meta:first-of-type {
111
+ margin-top: 0.75rem;
112
+ }
113
+
114
+ .icon {
115
+ width: 1rem;
116
+ height: 1rem;
117
+ flex-shrink: 0;
118
+ }
119
+
120
+ .description {
121
+ margin: 0.75rem 0 0;
122
+ font-size: 0.875rem;
123
+ color: var(--tl-muted-foreground, #6b7280);
124
+ line-height: 1.5;
125
+ display: -webkit-box;
126
+ -webkit-line-clamp: 2;
127
+ -webkit-box-orient: vertical;
128
+ overflow: hidden;
129
+ }
130
+ /* Standalone (event-id) loading and error states */
131
+ .card-skeleton {
132
+ cursor: default;
133
+ pointer-events: none;
134
+ }
135
+
136
+ .card-skeleton .image-container {
137
+ animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
138
+ }
139
+
140
+ .skeleton-line {
141
+ height: 0.875rem;
142
+ margin-top: 0.5rem;
143
+ background: var(--tl-muted, #f9fafb);
144
+ border-radius: var(--tl-radius-sm, 0.25rem);
145
+ animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
146
+ }
147
+
148
+ .skeleton-line.short {
149
+ width: 40%;
150
+ }
151
+
152
+ .skeleton-line.long {
153
+ width: 80%;
154
+ }
155
+
156
+ .card-error {
157
+ padding: var(--tl-spacing-4, 1rem);
158
+ font-size: 0.875rem;
159
+ color: var(--tl-error, #ef4444);
160
+ cursor: default;
161
+ }
162
+
163
+ .card-error:hover {
164
+ transform: none;
165
+ }
166
+
167
+ @keyframes pulse {
168
+ 0%,
169
+ 100% {
170
+ opacity: 1;
171
+ }
172
+ 50% {
173
+ opacity: 0.5;
174
+ }
175
+ }
@@ -0,0 +1,205 @@
1
+ import { h } from "@stencil/core";
2
+ import { whenSDK } from "../../utils/sdk-connector";
3
+ import { errorMessage } from "../../utils/order-summary";
4
+ import { toEventCardEvent } from "./event-card-adapter";
5
+ export class TlEventCard {
6
+ constructor() {
7
+ this.loadedEvent = null;
8
+ this.loading = false;
9
+ this.error = null;
10
+ this.handleClick = () => {
11
+ const event = this.current;
12
+ if (!event)
13
+ return;
14
+ console.log('[tl-event-card] Clicked:', event.id);
15
+ this.tlClick.emit({ eventId: event.id });
16
+ };
17
+ }
18
+ watchEventId() {
19
+ this.loadEvent();
20
+ }
21
+ async componentWillLoad() {
22
+ if (!this.event && this.eventId) {
23
+ await this.loadEvent();
24
+ }
25
+ }
26
+ async loadEvent() {
27
+ if (this.event || !this.eventId)
28
+ return;
29
+ try {
30
+ this.loading = true;
31
+ this.error = null;
32
+ const sdk = await whenSDK();
33
+ const detail = (await sdk.getEventsManager().get(this.eventId));
34
+ if (!detail)
35
+ throw new Error('Event not found');
36
+ this.loadedEvent = toEventCardEvent(detail);
37
+ }
38
+ catch (err) {
39
+ console.error('[tl-event-card] Failed to load event:', err);
40
+ this.error = errorMessage(err, 'Failed to load event');
41
+ this.tlError.emit({ message: this.error });
42
+ }
43
+ finally {
44
+ this.loading = false;
45
+ }
46
+ }
47
+ get current() {
48
+ return this.event ?? this.loadedEvent;
49
+ }
50
+ formatDate(dateString) {
51
+ const date = new Date(dateString);
52
+ return date.toLocaleDateString('en-GB', {
53
+ weekday: 'short',
54
+ day: 'numeric',
55
+ month: 'short',
56
+ hour: '2-digit',
57
+ minute: '2-digit',
58
+ });
59
+ }
60
+ getStatusBadgeClass() {
61
+ const baseClass = 'status-badge';
62
+ switch (this.current?.availabilityStatus) {
63
+ case 'available':
64
+ return `${baseClass} status-available`;
65
+ case 'limited':
66
+ return `${baseClass} status-limited`;
67
+ case 'sold_out':
68
+ return `${baseClass} status-sold-out`;
69
+ default:
70
+ return baseClass;
71
+ }
72
+ }
73
+ getStatusLabel() {
74
+ switch (this.current?.availabilityStatus) {
75
+ case 'available':
76
+ return 'Available';
77
+ case 'limited':
78
+ return 'Limited';
79
+ case 'sold_out':
80
+ return 'Sold Out';
81
+ default:
82
+ return '';
83
+ }
84
+ }
85
+ render() {
86
+ if (this.loading) {
87
+ return (h("div", { class: "event-card card-skeleton", "aria-busy": "true" }, h("div", { class: "image-container" }), h("div", { class: "content" }, h("div", { class: "skeleton-line short" }), h("div", { class: "skeleton-line long" }))));
88
+ }
89
+ if (this.error) {
90
+ return h("div", { class: "event-card card-error" }, this.error);
91
+ }
92
+ const event = this.current;
93
+ if (!event) {
94
+ return null;
95
+ }
96
+ // The sales surface exposes a single `imageUrl` (card/listing thumbnail);
97
+ // `thumbnailUrl` is an accepted alias if a host ever supplies a distinct one.
98
+ const image = event.thumbnailUrl || event.imageUrl;
99
+ return (h("div", { class: "event-card", onClick: this.handleClick }, h("div", { class: "image-container" }, image ? (h("img", { src: image, alt: event.name, class: "event-image" })) : (h("div", { class: "image-placeholder" }, h("svg", { width: "48", height: "48", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor" }, h("path", { "stroke-linecap": "round", "stroke-linejoin": "round", "stroke-width": "1.5", d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" })))), h("div", { class: "status-container" }, h("span", { class: this.getStatusBadgeClass() }, this.getStatusLabel()))), h("div", { class: "content" }, event.category && h("span", { class: "category" }, event.category), h("h3", { class: "title" }, event.name), event.nextOccurrence && (h("p", { class: "meta" }, h("svg", { class: "icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor" }, h("path", { "stroke-linecap": "round", "stroke-linejoin": "round", "stroke-width": "2", d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" })), this.formatDate(event.nextOccurrence.startsAt))), event.venue && (h("p", { class: "meta" }, h("svg", { class: "icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor" }, h("path", { "stroke-linecap": "round", "stroke-linejoin": "round", "stroke-width": "2", d: "M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" }), h("path", { "stroke-linecap": "round", "stroke-linejoin": "round", "stroke-width": "2", d: "M15 11a3 3 0 11-6 0 3 3 0 016 0z" })), event.venue.name, ", ", event.venue.city)), event.shortDescription && (h("p", { class: "description" }, event.shortDescription)))));
100
+ }
101
+ static get is() { return "tl-event-card"; }
102
+ static get encapsulation() { return "shadow"; }
103
+ static get originalStyleUrls() {
104
+ return {
105
+ "$": ["tl-event-card.css"]
106
+ };
107
+ }
108
+ static get styleUrls() {
109
+ return {
110
+ "$": ["tl-event-card.css"]
111
+ };
112
+ }
113
+ static get properties() {
114
+ return {
115
+ "event": {
116
+ "type": "unknown",
117
+ "mutable": false,
118
+ "complexType": {
119
+ "original": "TlEventCardEvent",
120
+ "resolved": "TlEventCardEvent | undefined",
121
+ "references": {
122
+ "TlEventCardEvent": {
123
+ "location": "local",
124
+ "path": "/home/runner/work/live-elements/live-elements/src/components/tl-event-card/tl-event-card.tsx",
125
+ "id": "src/components/tl-event-card/tl-event-card.tsx::TlEventCardEvent"
126
+ }
127
+ }
128
+ },
129
+ "required": false,
130
+ "optional": true,
131
+ "docs": {
132
+ "tags": [],
133
+ "text": "Event data to display (tl-event-list passes this)"
134
+ },
135
+ "getter": false,
136
+ "setter": false
137
+ },
138
+ "eventId": {
139
+ "type": "string",
140
+ "mutable": false,
141
+ "complexType": {
142
+ "original": "string",
143
+ "resolved": "string | undefined",
144
+ "references": {}
145
+ },
146
+ "required": false,
147
+ "optional": true,
148
+ "docs": {
149
+ "tags": [],
150
+ "text": "Load the event from the SDK by id when no `event` is given, so a single\ncard works standalone (e.g. on a Webflow page)."
151
+ },
152
+ "getter": false,
153
+ "setter": false,
154
+ "reflect": false,
155
+ "attribute": "event-id"
156
+ }
157
+ };
158
+ }
159
+ static get states() {
160
+ return {
161
+ "loadedEvent": {},
162
+ "loading": {},
163
+ "error": {}
164
+ };
165
+ }
166
+ static get events() {
167
+ return [{
168
+ "method": "tlClick",
169
+ "name": "tlClick",
170
+ "bubbles": true,
171
+ "cancelable": true,
172
+ "composed": true,
173
+ "docs": {
174
+ "tags": [],
175
+ "text": "Emitted when the card is clicked"
176
+ },
177
+ "complexType": {
178
+ "original": "{ eventId: string }",
179
+ "resolved": "{ eventId: string; }",
180
+ "references": {}
181
+ }
182
+ }, {
183
+ "method": "tlError",
184
+ "name": "tlError",
185
+ "bubbles": true,
186
+ "cancelable": true,
187
+ "composed": true,
188
+ "docs": {
189
+ "tags": [],
190
+ "text": "Emitted when the event could not be loaded by id"
191
+ },
192
+ "complexType": {
193
+ "original": "{ message: string }",
194
+ "resolved": "{ message: string; }",
195
+ "references": {}
196
+ }
197
+ }];
198
+ }
199
+ static get watchers() {
200
+ return [{
201
+ "propName": "eventId",
202
+ "methodName": "watchEventId"
203
+ }];
204
+ }
205
+ }
@@ -0,0 +1,134 @@
1
+ :host {
2
+ display: block;
3
+ font-family: var(--tl-font-family, system-ui, sans-serif);
4
+ }
5
+
6
+ .event-grid {
7
+ display: grid;
8
+ gap: var(--tl-spacing-6, 1.5rem);
9
+ }
10
+
11
+ .cols-1 {
12
+ grid-template-columns: 1fr;
13
+ }
14
+
15
+ .cols-2 {
16
+ grid-template-columns: repeat(2, 1fr);
17
+ }
18
+
19
+ .cols-3 {
20
+ grid-template-columns: repeat(3, 1fr);
21
+ }
22
+
23
+ .cols-4 {
24
+ grid-template-columns: repeat(4, 1fr);
25
+ }
26
+
27
+ @media (max-width: 1024px) {
28
+ .cols-4,
29
+ .cols-3 {
30
+ grid-template-columns: repeat(2, 1fr);
31
+ }
32
+ }
33
+
34
+ @media (max-width: 640px) {
35
+ .cols-4,
36
+ .cols-3,
37
+ .cols-2 {
38
+ grid-template-columns: 1fr;
39
+ }
40
+ }
41
+
42
+ /* Skeleton Loading */
43
+ .skeleton-card {
44
+ background: var(--tl-secondary, #f3f4f6);
45
+ border-radius: var(--tl-radius-lg, 0.75rem);
46
+ overflow: hidden;
47
+ }
48
+
49
+ .skeleton-image {
50
+ aspect-ratio: 16 / 9;
51
+ background: var(--tl-muted, #f9fafb);
52
+ animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
53
+ }
54
+
55
+ .skeleton-content {
56
+ padding: var(--tl-spacing-4, 1rem);
57
+ display: flex;
58
+ flex-direction: column;
59
+ gap: 0.5rem;
60
+ }
61
+
62
+ .skeleton-line {
63
+ height: 1rem;
64
+ background: var(--tl-muted, #f9fafb);
65
+ border-radius: var(--tl-radius-sm, 0.25rem);
66
+ animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
67
+ }
68
+
69
+ .skeleton-line.short {
70
+ width: 4rem;
71
+ height: 0.75rem;
72
+ }
73
+
74
+ .skeleton-line.medium {
75
+ width: 75%;
76
+ }
77
+
78
+ .skeleton-line.long {
79
+ width: 50%;
80
+ }
81
+
82
+ @keyframes pulse {
83
+ 0%, 100% {
84
+ opacity: 1;
85
+ }
86
+ 50% {
87
+ opacity: 0.5;
88
+ }
89
+ }
90
+
91
+ /* Error State */
92
+ .error-state {
93
+ background: rgba(239, 68, 68, 0.1);
94
+ border: 1px solid var(--tl-error, #ef4444);
95
+ border-radius: var(--tl-radius-lg, 0.75rem);
96
+ padding: var(--tl-spacing-4, 1rem);
97
+ }
98
+
99
+ .error-title {
100
+ margin: 0;
101
+ font-weight: 500;
102
+ color: var(--tl-error, #ef4444);
103
+ }
104
+
105
+ .error-message {
106
+ margin: 0.25rem 0 0;
107
+ font-size: 0.875rem;
108
+ color: var(--tl-error, #ef4444);
109
+ }
110
+
111
+ /* Empty State */
112
+ .empty-state {
113
+ text-align: center;
114
+ padding: var(--tl-spacing-8, 2rem) var(--tl-spacing-4, 1rem);
115
+ }
116
+
117
+ .empty-icon {
118
+ width: 4rem;
119
+ height: 4rem;
120
+ margin: 0 auto 1rem;
121
+ color: var(--tl-muted-foreground, #6b7280);
122
+ }
123
+
124
+ .empty-title {
125
+ margin: 0;
126
+ font-size: 1.25rem;
127
+ font-weight: 600;
128
+ color: var(--tl-foreground, #111827);
129
+ }
130
+
131
+ .empty-message {
132
+ margin: 0.5rem 0 0;
133
+ color: var(--tl-muted-foreground, #6b7280);
134
+ }
@@ -0,0 +1,171 @@
1
+ import { h } from "@stencil/core";
2
+ import { whenSDK } from "../../utils/sdk-connector";
3
+ export class TlEventList {
4
+ constructor() {
5
+ /**
6
+ * Maximum number of events to display
7
+ */
8
+ this.limit = 12;
9
+ /**
10
+ * Columns for grid layout (1, 2, 3, or 4)
11
+ */
12
+ this.columns = 3;
13
+ this.events = [];
14
+ this.loading = true;
15
+ this.error = null;
16
+ this.handleEventClick = (event) => {
17
+ console.log('[tl-event-list] Event clicked:', event.detail.eventId);
18
+ this.tlEventClick.emit(event.detail);
19
+ };
20
+ }
21
+ watchFiltersChange() {
22
+ this.loadEvents();
23
+ }
24
+ async componentWillLoad() {
25
+ await this.loadEvents();
26
+ }
27
+ async loadEvents() {
28
+ try {
29
+ console.log('[tl-event-list] Loading events via SDK...', { limit: this.limit, category: this.category });
30
+ this.loading = true;
31
+ this.error = null;
32
+ const sdk = await whenSDK();
33
+ const eventsManager = sdk.getEventsManager();
34
+ const response = await eventsManager.list({
35
+ limit: this.limit,
36
+ category: this.category,
37
+ });
38
+ console.log('[tl-event-list] Events loaded:', response.items.length);
39
+ this.events = response.items;
40
+ }
41
+ catch (err) {
42
+ console.error('[tl-event-list] Failed to load events:', err);
43
+ this.error = err instanceof Error ? err.message : 'Failed to load events';
44
+ }
45
+ finally {
46
+ this.loading = false;
47
+ }
48
+ }
49
+ render() {
50
+ const gridClass = `event-grid cols-${Math.min(Math.max(this.columns, 1), 4)}`;
51
+ if (this.loading) {
52
+ return (h("div", { class: gridClass }, Array.from({ length: 6 }).map((_, i) => (h("div", { class: "skeleton-card", key: i }, h("div", { class: "skeleton-image" }), h("div", { class: "skeleton-content" }, h("div", { class: "skeleton-line short" }), h("div", { class: "skeleton-line medium" }), h("div", { class: "skeleton-line long" })))))));
53
+ }
54
+ if (this.error) {
55
+ return (h("div", { class: "error-state" }, h("p", { class: "error-title" }, "Error loading events"), h("p", { class: "error-message" }, this.error)));
56
+ }
57
+ if (this.events.length === 0) {
58
+ return (h("div", { class: "empty-state" }, h("svg", { class: "empty-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor" }, h("path", { "stroke-linecap": "round", "stroke-linejoin": "round", "stroke-width": "1.5", d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" })), h("p", { class: "empty-title" }, "No events available"), h("p", { class: "empty-message" }, "Check back later for upcoming events.")));
59
+ }
60
+ return (h("div", { class: gridClass }, this.events.map((event) => (h("tl-event-card", { key: event.id, event: event, onTlClick: this.handleEventClick })))));
61
+ }
62
+ static get is() { return "tl-event-list"; }
63
+ static get encapsulation() { return "shadow"; }
64
+ static get originalStyleUrls() {
65
+ return {
66
+ "$": ["tl-event-list.css"]
67
+ };
68
+ }
69
+ static get styleUrls() {
70
+ return {
71
+ "$": ["tl-event-list.css"]
72
+ };
73
+ }
74
+ static get properties() {
75
+ return {
76
+ "limit": {
77
+ "type": "number",
78
+ "mutable": false,
79
+ "complexType": {
80
+ "original": "number",
81
+ "resolved": "number",
82
+ "references": {}
83
+ },
84
+ "required": false,
85
+ "optional": false,
86
+ "docs": {
87
+ "tags": [],
88
+ "text": "Maximum number of events to display"
89
+ },
90
+ "getter": false,
91
+ "setter": false,
92
+ "reflect": false,
93
+ "attribute": "limit",
94
+ "defaultValue": "12"
95
+ },
96
+ "category": {
97
+ "type": "string",
98
+ "mutable": false,
99
+ "complexType": {
100
+ "original": "string",
101
+ "resolved": "string | undefined",
102
+ "references": {}
103
+ },
104
+ "required": false,
105
+ "optional": true,
106
+ "docs": {
107
+ "tags": [],
108
+ "text": "Category filter"
109
+ },
110
+ "getter": false,
111
+ "setter": false,
112
+ "reflect": false,
113
+ "attribute": "category"
114
+ },
115
+ "columns": {
116
+ "type": "number",
117
+ "mutable": false,
118
+ "complexType": {
119
+ "original": "number",
120
+ "resolved": "number",
121
+ "references": {}
122
+ },
123
+ "required": false,
124
+ "optional": false,
125
+ "docs": {
126
+ "tags": [],
127
+ "text": "Columns for grid layout (1, 2, 3, or 4)"
128
+ },
129
+ "getter": false,
130
+ "setter": false,
131
+ "reflect": false,
132
+ "attribute": "columns",
133
+ "defaultValue": "3"
134
+ }
135
+ };
136
+ }
137
+ static get states() {
138
+ return {
139
+ "events": {},
140
+ "loading": {},
141
+ "error": {}
142
+ };
143
+ }
144
+ static get events() {
145
+ return [{
146
+ "method": "tlEventClick",
147
+ "name": "tlEventClick",
148
+ "bubbles": true,
149
+ "cancelable": true,
150
+ "composed": true,
151
+ "docs": {
152
+ "tags": [],
153
+ "text": "Emitted when an event card is clicked"
154
+ },
155
+ "complexType": {
156
+ "original": "{ eventId: string }",
157
+ "resolved": "{ eventId: string; }",
158
+ "references": {}
159
+ }
160
+ }];
161
+ }
162
+ static get watchers() {
163
+ return [{
164
+ "propName": "limit",
165
+ "methodName": "watchFiltersChange"
166
+ }, {
167
+ "propName": "category",
168
+ "methodName": "watchFiltersChange"
169
+ }];
170
+ }
171
+ }