@mccustomapps/helaui 0.1.12 → 0.1.15

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 CHANGED
@@ -16,6 +16,8 @@
16
16
  - [TextField](#textfield)
17
17
  - [Calendar](#calendar)
18
18
  - [SunMandala](#sunmandala)
19
+ - [DestinationCard](#destinationcard)
20
+ - [Button](#button)
19
21
  - [RainBackground](#rainbackground)
20
22
  - [Theming](#theming)
21
23
  - [i18n / Localisation](#i18n--localisation)
@@ -40,12 +42,14 @@ npm install @mccustomapps/helaui
40
42
  import '@mccustomapps/helaui/textfield.css';
41
43
  import '@mccustomapps/helaui/calendar.css';
42
44
  import '@mccustomapps/helaui/sun-mandala.css';
45
+ import '@mccustomapps/helaui/destination-card.css';
46
+ import '@mccustomapps/helaui/button.css';
43
47
  import '@mccustomapps/helaui/rain-background.css';
44
48
  import '@mccustomapps/helaui/sinhala.css'; // Sinhala font face
45
49
  import '@mccustomapps/helaui/theme.css'; // CSS custom-property tokens
46
50
 
47
51
  // Import components
48
- import { TextField, Calendar, SunMandala, RainBackground } from '@mccustomapps/helaui';
52
+ import { TextField, Calendar, SunMandala, DestinationCard, Button, RainBackground } from '@mccustomapps/helaui';
49
53
 
50
54
  // Mount components
51
55
  const field = new TextField({ variant: 'name' });
@@ -205,6 +209,89 @@ const mandala = new SunMandala({ src: '/my-mandala.png' });
205
209
 
206
210
  ---
207
211
 
212
+ ### DestinationCard
213
+
214
+ A decorative parchment **card shell** — cream background, teal/gold frame, side Sinhala script, and a peacock/lotus footer. The inner area is empty so you can place your own content.
215
+
216
+ ```js
217
+ import { DestinationCard } from '@mccustomapps/helaui';
218
+ import '@mccustomapps/helaui/destination-card.css';
219
+
220
+ const card = new DestinationCard({
221
+ height: '280px',
222
+ });
223
+
224
+ document.getElementById('container').appendChild(card.element);
225
+
226
+ // Optional: put your own content in the empty inner area
227
+ card.body.appendChild(document.createElement('div'));
228
+ ```
229
+
230
+ **Options — `DestinationCardOptions`**
231
+
232
+ | Option | Type | Default | Description |
233
+ |---|---|---|---|
234
+ | `content` | `HTMLElement \| string` | — | Inner content |
235
+ | `height` | `string` | `'280px'` | Minimum height of the inner area |
236
+ | `backdrop` | `boolean` | `false` | Blurred photo stage behind the card |
237
+ | `backdropImage` | `string` | — | Image used for the blurred stage |
238
+
239
+ **Methods**
240
+
241
+ ```js
242
+ card.setContent(node) // replace inner content
243
+ card.destroy()
244
+ ```
245
+
246
+ ---
247
+
248
+ ### Button
249
+
250
+ Two pill buttons from the travel-card design: a filled terracotta **primary** action and a teal **outline** secondary action.
251
+
252
+ ```js
253
+ import { Button } from '@mccustomapps/helaui';
254
+ import '@mccustomapps/helaui/button.css';
255
+
256
+ const book = new Button({
257
+ variant: 'primary', // filled — “Book Your Trip”
258
+ onClick: () => {},
259
+ });
260
+
261
+ const explore = new Button({
262
+ variant: 'secondary', // outline — “Explore Now”
263
+ onClick: () => {},
264
+ });
265
+
266
+ const row = document.createElement('div');
267
+ row.className = 'helaui-button-row';
268
+ row.append(book.element, explore.element);
269
+ document.getElementById('container').appendChild(row);
270
+ ```
271
+
272
+ **Options — `ButtonOptions`**
273
+
274
+ | Option | Type | Default | Description |
275
+ |---|---|---|---|
276
+ | `variant` | `'primary' \| 'secondary'` | `'primary'` | Filled terracotta or teal outline |
277
+ | `label` | `string` | locale | Explicit label |
278
+ | `labelKey` | `string` | — | i18n dot-path for the label |
279
+ | `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | Native button type |
280
+ | `disabled` | `boolean` | `false` | Disabled state |
281
+ | `onClick` | `() => void` | — | Click handler |
282
+ | `sinhala` | `boolean` | auto | Force Sinhala font |
283
+
284
+ **Methods**
285
+
286
+ ```js
287
+ button.setLabel('Reserve')
288
+ button.setDisabled(true)
289
+ button.setSinhala(true)
290
+ button.destroy()
291
+ ```
292
+
293
+ ---
294
+
208
295
  ### RainBackground
209
296
 
210
297
  An animated **tropical rain** background with falling food/leaf sprites. Built-in artwork is inlined in the JS bundle (no extra files to copy into `public/`).
@@ -339,6 +426,8 @@ import '@mccustomapps/helaui/sinhala.css'; // Sinhala font face
339
426
  import '@mccustomapps/helaui/textfield.css'; // TextField styles
340
427
  import '@mccustomapps/helaui/calendar.css'; // Calendar styles
341
428
  import '@mccustomapps/helaui/sun-mandala.css'; // SunMandala styles
429
+ import '@mccustomapps/helaui/destination-card.css'; // DestinationCard styles
430
+ import '@mccustomapps/helaui/button.css'; // Button styles
342
431
  import '@mccustomapps/helaui/rain-background.css'; // RainBackground styles
343
432
  ```
344
433
 
@@ -353,6 +442,8 @@ import type {
353
442
  TextFieldOptions,
354
443
  CalendarOptions,
355
444
  SunMandalaOptions,
445
+ DestinationCardOptions,
446
+ ButtonOptions,
356
447
  RainBackgroundOptions,
357
448
  HelaTheme,
358
449
  HelaThemeKey,
@@ -0,0 +1,82 @@
1
+ /* HelaUI Button — pill actions from the destination card design */
2
+
3
+ .helaui-button {
4
+ --helaui-button-primary: #c66b3d;
5
+ --helaui-button-secondary: #1a4d4e;
6
+
7
+ appearance: none;
8
+ display: inline-flex;
9
+ align-items: center;
10
+ justify-content: center;
11
+ min-height: 44px;
12
+ padding: 10px 22px;
13
+ border-radius: 999px;
14
+ font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
15
+ font-size: 0.88rem;
16
+ font-weight: 700;
17
+ line-height: 1.2;
18
+ letter-spacing: 0.01em;
19
+ cursor: pointer;
20
+ box-sizing: border-box;
21
+ transition:
22
+ transform 0.15s ease,
23
+ box-shadow 0.15s ease,
24
+ background 0.15s ease,
25
+ color 0.15s ease,
26
+ border-color 0.15s ease;
27
+ }
28
+
29
+ .helaui-button:focus-visible {
30
+ outline: none;
31
+ box-shadow: 0 0 0 3px var(--helaui-focus-ring, rgba(141, 21, 58, 0.2));
32
+ }
33
+
34
+ .helaui-button:disabled {
35
+ cursor: not-allowed;
36
+ opacity: 0.55;
37
+ transform: none;
38
+ box-shadow: none;
39
+ }
40
+
41
+ .helaui-button--primary {
42
+ border: none;
43
+ color: var(--helaui-white, #ffffff);
44
+ background: var(--helaui-button-primary);
45
+ box-shadow: 0 6px 14px rgba(198, 107, 61, 0.38);
46
+ }
47
+
48
+ .helaui-button--primary:hover:not(:disabled) {
49
+ transform: translateY(-1px);
50
+ background: color-mix(in srgb, var(--helaui-button-primary) 88%, #000);
51
+ }
52
+
53
+ .helaui-button--primary:active:not(:disabled) {
54
+ transform: translateY(0);
55
+ }
56
+
57
+ .helaui-button--secondary {
58
+ border: 1.5px solid var(--helaui-button-secondary);
59
+ color: var(--helaui-button-secondary);
60
+ background: transparent;
61
+ }
62
+
63
+ .helaui-button--secondary:hover:not(:disabled) {
64
+ background: rgba(26, 77, 78, 0.06);
65
+ }
66
+
67
+ .helaui-button-row {
68
+ display: flex;
69
+ gap: 10px;
70
+ width: 100%;
71
+ align-items: stretch;
72
+ }
73
+
74
+ .helaui-button-row .helaui-button {
75
+ flex: 1;
76
+ }
77
+
78
+ @media (max-width: 420px) {
79
+ .helaui-button-row {
80
+ flex-direction: column;
81
+ }
82
+ }
@@ -0,0 +1,137 @@
1
+ /* HelaUI Destination Card — decorative parchment shell */
2
+
3
+ .helaui-destination-card-stage {
4
+ position: relative;
5
+ display: flex;
6
+ justify-content: center;
7
+ align-items: stretch;
8
+ padding: 28px 20px;
9
+ overflow: hidden;
10
+ border-radius: 32px;
11
+ isolation: isolate;
12
+ }
13
+
14
+ .helaui-destination-card-stage__blur {
15
+ position: absolute;
16
+ inset: -24px;
17
+ background-size: cover;
18
+ background-position: center;
19
+ filter: blur(22px) saturate(1.1);
20
+ transform: scale(1.08);
21
+ z-index: 0;
22
+ }
23
+
24
+ .helaui-destination-card-stage__blur::after {
25
+ content: '';
26
+ position: absolute;
27
+ inset: 0;
28
+ background: rgba(20, 28, 24, 0.28);
29
+ }
30
+
31
+ .helaui-destination-card {
32
+ --helaui-card-cream: #f9f3e6;
33
+ --helaui-card-ink: #2d1e17;
34
+ --helaui-card-teal: #1a4d4e;
35
+ --helaui-card-orange: var(--helaui-accent, #c86837);
36
+
37
+ position: relative;
38
+ z-index: 1;
39
+ display: flex;
40
+ flex-direction: column;
41
+ width: min(100%, 380px);
42
+ margin: 0 auto;
43
+ padding: 14px 16px 0;
44
+ box-sizing: border-box;
45
+ background:
46
+ radial-gradient(circle at 12% 18%, rgba(26, 77, 78, 0.06), transparent 28%),
47
+ radial-gradient(circle at 88% 72%, rgba(200, 104, 55, 0.08), transparent 32%),
48
+ var(--helaui-card-cream);
49
+ color: var(--helaui-card-ink);
50
+ border: 1.5px solid var(--helaui-card-teal);
51
+ border-radius: 30px;
52
+ box-shadow:
53
+ inset 0 0 0 5px var(--helaui-card-cream),
54
+ inset 0 0 0 6.5px #c4a574,
55
+ 0 18px 40px rgba(26, 32, 24, 0.28);
56
+ overflow: hidden;
57
+ font-family: Georgia, 'Times New Roman', serif;
58
+ }
59
+
60
+ .helaui-destination-card__watermark {
61
+ pointer-events: none;
62
+ position: absolute;
63
+ inset: 0;
64
+ opacity: 0.09;
65
+ background-image:
66
+ radial-gradient(circle at 50% 50%, transparent 42%, rgba(26, 77, 78, 0.55) 43%, transparent 46%),
67
+ repeating-radial-gradient(circle at 50% 50%, rgba(26, 77, 78, 0.35) 0 1px, transparent 1px 18px);
68
+ background-size: 220px 220px, 220px 220px;
69
+ background-position: 80% 30%, 10% 80%;
70
+ mix-blend-mode: multiply;
71
+ }
72
+
73
+ .helaui-destination-card__script {
74
+ pointer-events: none;
75
+ position: absolute;
76
+ top: 22%;
77
+ right: 8px;
78
+ writing-mode: vertical-rl;
79
+ font-size: 0.72rem;
80
+ letter-spacing: 0.28em;
81
+ color: #c4a574;
82
+ opacity: 0.55;
83
+ z-index: 2;
84
+ }
85
+
86
+ .helaui-destination-card__body {
87
+ position: relative;
88
+ z-index: 1;
89
+ display: flex;
90
+ flex-direction: column;
91
+ flex: 1;
92
+ min-height: 280px;
93
+ padding: 8px 4px 16px;
94
+ }
95
+
96
+ .helaui-destination-card__footer {
97
+ position: relative;
98
+ height: 92px;
99
+ margin: 4px -16px 0;
100
+ background: linear-gradient(90deg, #c86837 0%, #b8432f 55%, #c86837 100%);
101
+ overflow: hidden;
102
+ }
103
+
104
+ .helaui-destination-card__footer::before {
105
+ content: '';
106
+ position: absolute;
107
+ inset: 0;
108
+ opacity: 0.22;
109
+ background-image:
110
+ radial-gradient(circle at 20% 40%, #f9f3e6 0 10%, transparent 11%),
111
+ radial-gradient(circle at 70% 70%, #f9f3e6 0 8%, transparent 9%),
112
+ radial-gradient(circle at 50% 20%, transparent 40%, rgba(249, 243, 230, 0.5) 41%, transparent 44%);
113
+ }
114
+
115
+ .helaui-destination-card__peacocks,
116
+ .helaui-destination-card__lotus {
117
+ position: absolute;
118
+ bottom: -4px;
119
+ z-index: 1;
120
+ }
121
+
122
+ .helaui-destination-card__peacocks {
123
+ left: 6px;
124
+ width: 58%;
125
+ }
126
+
127
+ .helaui-destination-card__peacocks svg,
128
+ .helaui-destination-card__lotus svg {
129
+ display: block;
130
+ width: 100%;
131
+ height: auto;
132
+ }
133
+
134
+ .helaui-destination-card__lotus {
135
+ right: 4px;
136
+ width: 34%;
137
+ }
package/dist/index.cjs CHANGED
@@ -22,8 +22,10 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  BUILTIN_RAIN_IMAGES: () => BUILTIN_RAIN_IMAGES,
24
24
  BUILTIN_SUN_MANDALA_IMAGE: () => BUILTIN_SUN_MANDALA_IMAGE,
25
+ Button: () => Button,
25
26
  Calendar: () => Calendar,
26
27
  DEFAULT_RAIN_IMAGES: () => DEFAULT_RAIN_IMAGES,
28
+ DestinationCard: () => DestinationCard,
27
29
  RainBackground: () => RainBackground,
28
30
  SINHALA_FONT_CLASS: () => SINHALA_FONT_CLASS,
29
31
  SINHALA_FONT_FAMILY: () => SINHALA_FONT_FAMILY,
@@ -38,8 +40,10 @@ __export(index_exports, {
38
40
  defaultTheme: () => defaultTheme,
39
41
  defaultTranslations: () => defaultTranslations,
40
42
  formatSinhalaNumeral: () => formatSinhalaNumeral,
43
+ getButtonTranslation: () => getButtonTranslation,
41
44
  getCalendarTranslation: () => getCalendarTranslation,
42
45
  getDefaultRainImageUrls: () => getDefaultRainImageUrls,
46
+ getDestinationCardTranslation: () => getDestinationCardTranslation,
43
47
  getLocale: () => getLocale,
44
48
  getTextFieldTranslation: () => getTextFieldTranslation,
45
49
  resetTheme: () => resetTheme,
@@ -119,6 +123,18 @@ var defaultTranslations = {
119
123
  clear: "Clear",
120
124
  selectMonth: "Select Month",
121
125
  poyaDay: "Poya Day"
126
+ },
127
+ destinationCard: {
128
+ eyebrow: "PlaceHolder",
129
+ reviewsLabel: "Reviews",
130
+ bookTrip: "PlaceHolder",
131
+ exploreNow: "PlaceHolder",
132
+ startFrom: "Start from",
133
+ perPerson: "/ person"
134
+ },
135
+ button: {
136
+ primary: "PlaceHolder",
137
+ secondary: "PlaceHolder"
122
138
  }
123
139
  },
124
140
  si: {
@@ -176,6 +192,18 @@ var defaultTranslations = {
176
192
  clear: "\u0DB4\u0DD2\u0DBB\u0DD2\u0DC3\u0DD2\u0DAF\u0DD4 \u0D9A\u0DBB\u0DB1\u0DCA\u0DB1",
177
193
  selectMonth: "\u0DB8\u0DCF\u0DC3\u0DBA \u0DAD\u0DDD\u0DBB\u0DB1\u0DCA\u0DB1",
178
194
  poyaDay: "\u0DB4\u0DDD\u0DBA \u0DAF\u0DD2\u0DB1"
195
+ },
196
+ destinationCard: {
197
+ eyebrow: "\u0DC1\u0DCA\u200D\u0DBB\u0DD3 \u0DBD\u0D82\u0D9A\u0DCF\u0DC0 \u0DC3\u0DDC\u0DBA\u0DCF \u0DB6\u0DBD\u0DB1\u0DCA\u0DB1",
198
+ reviewsLabel: "\u0DC3\u0DB8\u0DCF\u0DBD\u0DDD\u0DA0\u0DB1",
199
+ bookTrip: "\u0D94\u0DB6\u0DDA \u0DC3\u0D82\u0DA0\u0DCF\u0DBB\u0DBA \u0DC0\u0DD9\u0DB1\u0DCA\u0D9A\u0DBB\u0DC0\u0DB1\u0DCA\u0DB1",
200
+ exploreNow: "\u0DAF\u0DD0\u0DB1\u0DCA \u0D9C\u0DC0\u0DDA\u0DC2\u0DAB\u0DBA \u0D9A\u0DBB\u0DB1\u0DCA\u0DB1",
201
+ startFrom: "\u0D86\u0DBB\u0DB8\u0DCA\u0DB7\u0DBA",
202
+ perPerson: "/ \u0DB4\u0DD4\u0DAF\u0DCA\u0D9C\u0DBD\u0DBA\u0D9A\u0DD4\u0DA7"
203
+ },
204
+ button: {
205
+ primary: "\u0D94\u0DB6\u0DDA \u0DC3\u0D82\u0DA0\u0DCF\u0DBB\u0DBA \u0DC0\u0DD9\u0DB1\u0DCA\u0D9A\u0DBB\u0DC0\u0DB1\u0DCA\u0DB1",
206
+ secondary: "\u0DAF\u0DD0\u0DB1\u0DCA \u0D9C\u0DC0\u0DDA\u0DC2\u0DAB\u0DBA \u0D9A\u0DBB\u0DB1\u0DCA\u0DB1"
179
207
  }
180
208
  }
181
209
  };
@@ -265,6 +293,12 @@ function getTextFieldTranslation(variant, locale = currentLocale) {
265
293
  function getCalendarTranslation(locale = currentLocale) {
266
294
  return getMergedTranslations(locale).calendar ?? defaultTranslations[locale].calendar;
267
295
  }
296
+ function getDestinationCardTranslation(locale = currentLocale) {
297
+ return getMergedTranslations(locale).destinationCard ?? defaultTranslations[locale].destinationCard;
298
+ }
299
+ function getButtonTranslation(locale = currentLocale) {
300
+ return getMergedTranslations(locale).button ?? defaultTranslations[locale].button;
301
+ }
268
302
  function subscribeLocaleChange(listener) {
269
303
  localeListeners.add(listener);
270
304
  return () => localeListeners.delete(listener);
@@ -964,6 +998,166 @@ var SunMandala = class {
964
998
  }
965
999
  };
966
1000
 
1001
+ // src/components/DestinationCard.ts
1002
+ var PEACOCK_SVG = `
1003
+ <svg viewBox="0 0 220 110" aria-hidden="true">
1004
+ <g fill="none" stroke-linecap="round">
1005
+ <path d="M18 92c8-28 28-52 58-62" stroke="#1a6b6c" stroke-width="5"/>
1006
+ <path d="M32 96c10-22 30-40 56-46" stroke="#2a8f7a" stroke-width="4"/>
1007
+ <path d="M48 100c10-16 26-28 46-32" stroke="#c86837" stroke-width="3.5"/>
1008
+ <ellipse cx="28" cy="38" rx="7" ry="10" fill="#1a4d4e" transform="rotate(-20 28 38)"/>
1009
+ <circle cx="26" cy="34" r="1.6" fill="#f9f3e6"/>
1010
+ <path d="M22 42c8 6 18 8 28 4" stroke="#1a4d4e" stroke-width="3"/>
1011
+ <circle cx="62" cy="28" r="9" fill="#1a6b6c" opacity=".85"/>
1012
+ <circle cx="62" cy="28" r="4" fill="#d4af37"/>
1013
+ <circle cx="88" cy="42" r="10" fill="#2a8f7a" opacity=".8"/>
1014
+ <circle cx="88" cy="42" r="4" fill="#c86837"/>
1015
+ <circle cx="74" cy="62" r="9" fill="#1a4d4e" opacity=".75"/>
1016
+ <circle cx="74" cy="62" r="3.5" fill="#d4af37"/>
1017
+ <path d="M108 96c8-24 26-44 54-52" stroke="#1a6b6c" stroke-width="5"/>
1018
+ <path d="M118 100c8-18 24-32 48-36" stroke="#c86837" stroke-width="3.5"/>
1019
+ <ellipse cx="116" cy="48" rx="6.5" ry="9" fill="#1a4d4e" transform="rotate(-18 116 48)"/>
1020
+ <circle cx="114" cy="44" r="1.4" fill="#f9f3e6"/>
1021
+ <circle cx="148" cy="36" r="8" fill="#1a6b6c" opacity=".85"/>
1022
+ <circle cx="148" cy="36" r="3.5" fill="#d4af37"/>
1023
+ <circle cx="168" cy="52" r="8" fill="#2a8f7a" opacity=".8"/>
1024
+ <circle cx="168" cy="52" r="3.5" fill="#c86837"/>
1025
+ </g>
1026
+ <ellipse cx="96" cy="98" rx="10" ry="6" fill="#e8c9d4"/>
1027
+ <path d="M90 96c4-10 12-12 18-2" fill="#d46a8a"/>
1028
+ <path d="M94 98c3-7 9-8 13-1" fill="#f4c6d4"/>
1029
+ </svg>
1030
+ `;
1031
+ var LOTUS_SVG = `
1032
+ <svg viewBox="0 0 120 110" aria-hidden="true">
1033
+ <path d="M60 96c-16-18-28-34-28-50 0-10 8-16 16-12 6 3 10 12 12 22 2-14 8-28 18-34 8-5 16 0 16 12 0 16-12 32-34 62z" fill="#e8a0b8"/>
1034
+ <path d="M60 96c-10-16-22-36-18-54 3-12 14-16 18-6 4-16 16-24 24-18 8 6 6 22-2 36-8 14-16 28-22 42z" fill="#d46a8a"/>
1035
+ <path d="M60 98c6-20 8-38 4-52-3-10-12-12-14-4-4-12-2-24 8-28 10-4 18 6 18 18 0 16-6 34-16 66z" fill="#f3c3d2"/>
1036
+ <circle cx="60" cy="42" r="8" fill="#d4af37"/>
1037
+ <circle cx="60" cy="42" r="3.5" fill="#f9f3e6"/>
1038
+ </svg>
1039
+ `;
1040
+ function el(tag, className, text) {
1041
+ const node = document.createElement(tag);
1042
+ node.className = className;
1043
+ if (text !== void 0) node.textContent = text;
1044
+ return node;
1045
+ }
1046
+ var DestinationCard = class {
1047
+ element;
1048
+ card;
1049
+ body;
1050
+ constructor(options = {}) {
1051
+ const { content, height = "280px", backdrop = false, backdropImage } = options;
1052
+ this.card = el("article", "helaui-destination-card");
1053
+ this.card.setAttribute("aria-label", "HelaUI card");
1054
+ const watermark = el("div", "helaui-destination-card__watermark");
1055
+ watermark.setAttribute("aria-hidden", "true");
1056
+ this.card.appendChild(watermark);
1057
+ const script = el("div", `helaui-destination-card__script ${SINHALA_FONT_CLASS}`, "\u0DC1\u0DCA\u200D\u0DBB\u0DD3 \u0DBD\u0D82\u0D9A\u0DCF\u0DC0");
1058
+ script.setAttribute("aria-hidden", "true");
1059
+ this.card.appendChild(script);
1060
+ this.body = el("div", "helaui-destination-card__body");
1061
+ this.body.style.minHeight = height;
1062
+ if (typeof content === "string") {
1063
+ this.body.innerHTML = content;
1064
+ } else if (content) {
1065
+ this.body.appendChild(content);
1066
+ }
1067
+ this.card.appendChild(this.body);
1068
+ const footer = el("div", "helaui-destination-card__footer");
1069
+ footer.setAttribute("aria-hidden", "true");
1070
+ const peacocks = el("div", "helaui-destination-card__peacocks");
1071
+ peacocks.innerHTML = PEACOCK_SVG.trim();
1072
+ const lotus = el("div", "helaui-destination-card__lotus");
1073
+ lotus.innerHTML = LOTUS_SVG.trim();
1074
+ footer.append(peacocks, lotus);
1075
+ this.card.appendChild(footer);
1076
+ if (backdrop) {
1077
+ const stage = el("div", "helaui-destination-card-stage");
1078
+ const blur = el("div", "helaui-destination-card-stage__blur");
1079
+ if (backdropImage) {
1080
+ blur.style.backgroundImage = `url("${backdropImage.replace(/"/g, "")}")`;
1081
+ }
1082
+ stage.append(blur, this.card);
1083
+ this.element = stage;
1084
+ } else {
1085
+ this.element = this.card;
1086
+ }
1087
+ }
1088
+ setContent(content) {
1089
+ this.body.replaceChildren();
1090
+ if (typeof content === "string") {
1091
+ this.body.innerHTML = content;
1092
+ } else {
1093
+ this.body.appendChild(content);
1094
+ }
1095
+ }
1096
+ destroy() {
1097
+ this.element.remove();
1098
+ }
1099
+ };
1100
+
1101
+ // src/components/Button.ts
1102
+ var VARIANT_LABEL_KEY = {
1103
+ primary: "button.primary",
1104
+ secondary: "button.secondary"
1105
+ };
1106
+ var Button = class {
1107
+ element;
1108
+ unsubscribeLocale;
1109
+ variant;
1110
+ fixedLabel;
1111
+ labelKey;
1112
+ sinhalaExplicit;
1113
+ constructor(options = {}) {
1114
+ const {
1115
+ variant = "primary",
1116
+ label,
1117
+ labelKey,
1118
+ type = "button",
1119
+ disabled = false,
1120
+ onClick,
1121
+ sinhala
1122
+ } = options;
1123
+ this.variant = variant;
1124
+ this.fixedLabel = label;
1125
+ this.labelKey = labelKey;
1126
+ this.sinhalaExplicit = sinhala !== void 0;
1127
+ this.element = document.createElement("button");
1128
+ this.element.type = type;
1129
+ this.element.className = `helaui-button helaui-button--${variant}`;
1130
+ this.element.disabled = disabled;
1131
+ if (onClick) this.element.addEventListener("click", onClick);
1132
+ this.applyLabel();
1133
+ this.setSinhala(sinhala ?? getLocale() === "si");
1134
+ this.unsubscribeLocale = subscribeLocaleChange(() => {
1135
+ this.applyLabel();
1136
+ if (!this.sinhalaExplicit) this.setSinhala(getLocale() === "si");
1137
+ });
1138
+ }
1139
+ applyLabel() {
1140
+ if (this.fixedLabel !== void 0) {
1141
+ this.element.textContent = this.fixedLabel;
1142
+ return;
1143
+ }
1144
+ this.element.textContent = t(this.labelKey ?? VARIANT_LABEL_KEY[this.variant]);
1145
+ }
1146
+ setLabel(label) {
1147
+ this.element.textContent = label;
1148
+ }
1149
+ setDisabled(disabled) {
1150
+ this.element.disabled = disabled;
1151
+ }
1152
+ setSinhala(enabled) {
1153
+ this.element.classList.toggle(SINHALA_FONT_CLASS, enabled);
1154
+ }
1155
+ destroy() {
1156
+ this.unsubscribeLocale?.();
1157
+ this.element.remove();
1158
+ }
1159
+ };
1160
+
967
1161
  // src/theme/defaultTheme.ts
968
1162
  var defaultTheme = {
969
1163
  primary: "#8D153A",
@@ -1037,8 +1231,10 @@ function createThemeStyle(theme = {}) {
1037
1231
  0 && (module.exports = {
1038
1232
  BUILTIN_RAIN_IMAGES,
1039
1233
  BUILTIN_SUN_MANDALA_IMAGE,
1234
+ Button,
1040
1235
  Calendar,
1041
1236
  DEFAULT_RAIN_IMAGES,
1237
+ DestinationCard,
1042
1238
  RainBackground,
1043
1239
  SINHALA_FONT_CLASS,
1044
1240
  SINHALA_FONT_FAMILY,
@@ -1053,8 +1249,10 @@ function createThemeStyle(theme = {}) {
1053
1249
  defaultTheme,
1054
1250
  defaultTranslations,
1055
1251
  formatSinhalaNumeral,
1252
+ getButtonTranslation,
1056
1253
  getCalendarTranslation,
1057
1254
  getDefaultRainImageUrls,
1255
+ getDestinationCardTranslation,
1058
1256
  getLocale,
1059
1257
  getTextFieldTranslation,
1060
1258
  resetTheme,
package/dist/index.d.cts CHANGED
@@ -25,6 +25,18 @@ interface HelaTextFieldTranslations {
25
25
  email: TextFieldStrings;
26
26
  disabled: TextFieldStrings;
27
27
  }
28
+ interface ButtonStrings {
29
+ primary: string;
30
+ secondary: string;
31
+ }
32
+ interface DestinationCardStrings {
33
+ eyebrow: string;
34
+ reviewsLabel: string;
35
+ bookTrip: string;
36
+ exploreNow: string;
37
+ startFrom: string;
38
+ perPerson: string;
39
+ }
28
40
  interface CalendarStrings {
29
41
  monthNames: [string, string, string, string, string, string, string, string, string, string, string, string];
30
42
  sinhalaMonthNames: [string, string, string, string, string, string, string, string, string, string, string, string];
@@ -40,6 +52,8 @@ interface CalendarStrings {
40
52
  interface HelaTranslations {
41
53
  textField: HelaTextFieldTranslations;
42
54
  calendar: CalendarStrings;
55
+ destinationCard: DestinationCardStrings;
56
+ button: ButtonStrings;
43
57
  }
44
58
  type TextFieldVariant = keyof HelaTextFieldTranslations;
45
59
  type DeepPartial<T> = {
@@ -84,6 +98,10 @@ declare function t(path: string, locale?: HelaLocale): string;
84
98
  declare function getTextFieldTranslation(variant: TextFieldVariant, locale?: HelaLocale): TextFieldStrings;
85
99
  /** Built-in Calendar strings for the active (or given) locale. */
86
100
  declare function getCalendarTranslation(locale?: HelaLocale): CalendarStrings;
101
+ /** Built-in DestinationCard strings for the active (or given) locale. */
102
+ declare function getDestinationCardTranslation(locale?: HelaLocale): DestinationCardStrings;
103
+ /** Built-in Button strings for the active (or given) locale. */
104
+ declare function getButtonTranslation(locale?: HelaLocale): ButtonStrings;
87
105
  /** Subscribe to locale or override changes. Returns an unsubscribe function. */
88
106
  declare function subscribeLocaleChange(listener: () => void): () => void;
89
107
 
@@ -307,6 +325,65 @@ declare class SunMandala {
307
325
  destroy(): void;
308
326
  }
309
327
 
328
+ interface DestinationCardOptions {
329
+ /** Optional node or HTML placed in the empty inner area. */
330
+ content?: HTMLElement | string;
331
+ /** Minimum height of the inner area. Defaults to `280px`. */
332
+ height?: string;
333
+ /** Blurred photo stage behind the card. Defaults to `false`. */
334
+ backdrop?: boolean;
335
+ /** Image used for the optional blurred stage. */
336
+ backdropImage?: string;
337
+ }
338
+ /**
339
+ * Decorative parchment card shell — frame, watermark, side script, and footer motifs.
340
+ * The inner area is empty so callers can place their own content.
341
+ */
342
+ declare class DestinationCard {
343
+ readonly element: HTMLElement;
344
+ readonly card: HTMLElement;
345
+ readonly body: HTMLDivElement;
346
+ constructor(options?: DestinationCardOptions);
347
+ setContent(content: HTMLElement | string): void;
348
+ destroy(): void;
349
+ }
350
+
351
+ type ButtonVariant = 'primary' | 'secondary';
352
+ interface ButtonOptions {
353
+ /**
354
+ * Visual style.
355
+ * `primary` — filled terracotta pill (“Book Your Trip”).
356
+ * `secondary` — teal outline pill (“Explore Now”).
357
+ */
358
+ variant?: ButtonVariant;
359
+ /** Explicit label — overrides locale default. */
360
+ label?: string;
361
+ /** Translation key (dot path). Overrides variant default when `label` is omitted. */
362
+ labelKey?: string;
363
+ type?: 'button' | 'submit' | 'reset';
364
+ disabled?: boolean;
365
+ onClick?: () => void;
366
+ /** Apply Sinhala font. When omitted, follows the active locale. */
367
+ sinhala?: boolean;
368
+ }
369
+ /**
370
+ * Pill action button matching the HelaUI travel-card design.
371
+ */
372
+ declare class Button {
373
+ readonly element: HTMLButtonElement;
374
+ private readonly unsubscribeLocale?;
375
+ private readonly variant;
376
+ private readonly fixedLabel?;
377
+ private readonly labelKey?;
378
+ private readonly sinhalaExplicit;
379
+ constructor(options?: ButtonOptions);
380
+ private applyLabel;
381
+ setLabel(label: string): void;
382
+ setDisabled(disabled: boolean): void;
383
+ setSinhala(enabled: boolean): void;
384
+ destroy(): void;
385
+ }
386
+
310
387
  /** HelaUI brand palette — all values are customizable. */
311
388
  interface HelaTheme {
312
389
  primary: string;
@@ -339,4 +416,4 @@ declare const defaultTheme: HelaTheme;
339
416
  /** Maps theme keys to CSS custom property names. */
340
417
  declare const THEME_VAR_MAP: Record<HelaThemeKey, string>;
341
418
 
342
- export { type ApplyTranslationsOptions, BUILTIN_RAIN_IMAGES, BUILTIN_SUN_MANDALA_IMAGE, Calendar, type CalendarOptions, type CalendarStrings, DEFAULT_RAIN_IMAGES, type DeepPartial, type HelaLocale, type HelaTextFieldTranslations, type HelaTheme, type HelaThemeKey, type HelaTranslationOverrides, type HelaTranslations, type LocaleTranslationOverrides, RainBackground, type RainBackgroundOptions, SINHALA_FONT_CLASS, SINHALA_FONT_FAMILY, SINHALA_MONTH_NAMES, SunMandala, type SunMandalaOptions, THEME_VAR_MAP, TextField, type TextFieldOptions, type TextFieldStrings, type TextFieldVariant, applySinhalaFont, applyTheme, applyTranslations, createThemeStyle, defaultTheme, defaultTranslations, formatSinhalaNumeral, getCalendarTranslation, getDefaultRainImageUrls, getLocale, getTextFieldTranslation, resetTheme, resetTranslations, setLocale, sinhalaFontStyles, subscribeLocaleChange, t };
419
+ export { type ApplyTranslationsOptions, BUILTIN_RAIN_IMAGES, BUILTIN_SUN_MANDALA_IMAGE, Button, type ButtonOptions, type ButtonStrings, type ButtonVariant, Calendar, type CalendarOptions, type CalendarStrings, DEFAULT_RAIN_IMAGES, type DeepPartial, DestinationCard, type DestinationCardOptions, type DestinationCardStrings, type HelaLocale, type HelaTextFieldTranslations, type HelaTheme, type HelaThemeKey, type HelaTranslationOverrides, type HelaTranslations, type LocaleTranslationOverrides, RainBackground, type RainBackgroundOptions, SINHALA_FONT_CLASS, SINHALA_FONT_FAMILY, SINHALA_MONTH_NAMES, SunMandala, type SunMandalaOptions, THEME_VAR_MAP, TextField, type TextFieldOptions, type TextFieldStrings, type TextFieldVariant, applySinhalaFont, applyTheme, applyTranslations, createThemeStyle, defaultTheme, defaultTranslations, formatSinhalaNumeral, getButtonTranslation, getCalendarTranslation, getDefaultRainImageUrls, getDestinationCardTranslation, getLocale, getTextFieldTranslation, resetTheme, resetTranslations, setLocale, sinhalaFontStyles, subscribeLocaleChange, t };
package/dist/index.d.ts CHANGED
@@ -25,6 +25,18 @@ interface HelaTextFieldTranslations {
25
25
  email: TextFieldStrings;
26
26
  disabled: TextFieldStrings;
27
27
  }
28
+ interface ButtonStrings {
29
+ primary: string;
30
+ secondary: string;
31
+ }
32
+ interface DestinationCardStrings {
33
+ eyebrow: string;
34
+ reviewsLabel: string;
35
+ bookTrip: string;
36
+ exploreNow: string;
37
+ startFrom: string;
38
+ perPerson: string;
39
+ }
28
40
  interface CalendarStrings {
29
41
  monthNames: [string, string, string, string, string, string, string, string, string, string, string, string];
30
42
  sinhalaMonthNames: [string, string, string, string, string, string, string, string, string, string, string, string];
@@ -40,6 +52,8 @@ interface CalendarStrings {
40
52
  interface HelaTranslations {
41
53
  textField: HelaTextFieldTranslations;
42
54
  calendar: CalendarStrings;
55
+ destinationCard: DestinationCardStrings;
56
+ button: ButtonStrings;
43
57
  }
44
58
  type TextFieldVariant = keyof HelaTextFieldTranslations;
45
59
  type DeepPartial<T> = {
@@ -84,6 +98,10 @@ declare function t(path: string, locale?: HelaLocale): string;
84
98
  declare function getTextFieldTranslation(variant: TextFieldVariant, locale?: HelaLocale): TextFieldStrings;
85
99
  /** Built-in Calendar strings for the active (or given) locale. */
86
100
  declare function getCalendarTranslation(locale?: HelaLocale): CalendarStrings;
101
+ /** Built-in DestinationCard strings for the active (or given) locale. */
102
+ declare function getDestinationCardTranslation(locale?: HelaLocale): DestinationCardStrings;
103
+ /** Built-in Button strings for the active (or given) locale. */
104
+ declare function getButtonTranslation(locale?: HelaLocale): ButtonStrings;
87
105
  /** Subscribe to locale or override changes. Returns an unsubscribe function. */
88
106
  declare function subscribeLocaleChange(listener: () => void): () => void;
89
107
 
@@ -307,6 +325,65 @@ declare class SunMandala {
307
325
  destroy(): void;
308
326
  }
309
327
 
328
+ interface DestinationCardOptions {
329
+ /** Optional node or HTML placed in the empty inner area. */
330
+ content?: HTMLElement | string;
331
+ /** Minimum height of the inner area. Defaults to `280px`. */
332
+ height?: string;
333
+ /** Blurred photo stage behind the card. Defaults to `false`. */
334
+ backdrop?: boolean;
335
+ /** Image used for the optional blurred stage. */
336
+ backdropImage?: string;
337
+ }
338
+ /**
339
+ * Decorative parchment card shell — frame, watermark, side script, and footer motifs.
340
+ * The inner area is empty so callers can place their own content.
341
+ */
342
+ declare class DestinationCard {
343
+ readonly element: HTMLElement;
344
+ readonly card: HTMLElement;
345
+ readonly body: HTMLDivElement;
346
+ constructor(options?: DestinationCardOptions);
347
+ setContent(content: HTMLElement | string): void;
348
+ destroy(): void;
349
+ }
350
+
351
+ type ButtonVariant = 'primary' | 'secondary';
352
+ interface ButtonOptions {
353
+ /**
354
+ * Visual style.
355
+ * `primary` — filled terracotta pill (“Book Your Trip”).
356
+ * `secondary` — teal outline pill (“Explore Now”).
357
+ */
358
+ variant?: ButtonVariant;
359
+ /** Explicit label — overrides locale default. */
360
+ label?: string;
361
+ /** Translation key (dot path). Overrides variant default when `label` is omitted. */
362
+ labelKey?: string;
363
+ type?: 'button' | 'submit' | 'reset';
364
+ disabled?: boolean;
365
+ onClick?: () => void;
366
+ /** Apply Sinhala font. When omitted, follows the active locale. */
367
+ sinhala?: boolean;
368
+ }
369
+ /**
370
+ * Pill action button matching the HelaUI travel-card design.
371
+ */
372
+ declare class Button {
373
+ readonly element: HTMLButtonElement;
374
+ private readonly unsubscribeLocale?;
375
+ private readonly variant;
376
+ private readonly fixedLabel?;
377
+ private readonly labelKey?;
378
+ private readonly sinhalaExplicit;
379
+ constructor(options?: ButtonOptions);
380
+ private applyLabel;
381
+ setLabel(label: string): void;
382
+ setDisabled(disabled: boolean): void;
383
+ setSinhala(enabled: boolean): void;
384
+ destroy(): void;
385
+ }
386
+
310
387
  /** HelaUI brand palette — all values are customizable. */
311
388
  interface HelaTheme {
312
389
  primary: string;
@@ -339,4 +416,4 @@ declare const defaultTheme: HelaTheme;
339
416
  /** Maps theme keys to CSS custom property names. */
340
417
  declare const THEME_VAR_MAP: Record<HelaThemeKey, string>;
341
418
 
342
- export { type ApplyTranslationsOptions, BUILTIN_RAIN_IMAGES, BUILTIN_SUN_MANDALA_IMAGE, Calendar, type CalendarOptions, type CalendarStrings, DEFAULT_RAIN_IMAGES, type DeepPartial, type HelaLocale, type HelaTextFieldTranslations, type HelaTheme, type HelaThemeKey, type HelaTranslationOverrides, type HelaTranslations, type LocaleTranslationOverrides, RainBackground, type RainBackgroundOptions, SINHALA_FONT_CLASS, SINHALA_FONT_FAMILY, SINHALA_MONTH_NAMES, SunMandala, type SunMandalaOptions, THEME_VAR_MAP, TextField, type TextFieldOptions, type TextFieldStrings, type TextFieldVariant, applySinhalaFont, applyTheme, applyTranslations, createThemeStyle, defaultTheme, defaultTranslations, formatSinhalaNumeral, getCalendarTranslation, getDefaultRainImageUrls, getLocale, getTextFieldTranslation, resetTheme, resetTranslations, setLocale, sinhalaFontStyles, subscribeLocaleChange, t };
419
+ export { type ApplyTranslationsOptions, BUILTIN_RAIN_IMAGES, BUILTIN_SUN_MANDALA_IMAGE, Button, type ButtonOptions, type ButtonStrings, type ButtonVariant, Calendar, type CalendarOptions, type CalendarStrings, DEFAULT_RAIN_IMAGES, type DeepPartial, DestinationCard, type DestinationCardOptions, type DestinationCardStrings, type HelaLocale, type HelaTextFieldTranslations, type HelaTheme, type HelaThemeKey, type HelaTranslationOverrides, type HelaTranslations, type LocaleTranslationOverrides, RainBackground, type RainBackgroundOptions, SINHALA_FONT_CLASS, SINHALA_FONT_FAMILY, SINHALA_MONTH_NAMES, SunMandala, type SunMandalaOptions, THEME_VAR_MAP, TextField, type TextFieldOptions, type TextFieldStrings, type TextFieldVariant, applySinhalaFont, applyTheme, applyTranslations, createThemeStyle, defaultTheme, defaultTranslations, formatSinhalaNumeral, getButtonTranslation, getCalendarTranslation, getDefaultRainImageUrls, getDestinationCardTranslation, getLocale, getTextFieldTranslation, resetTheme, resetTranslations, setLocale, sinhalaFontStyles, subscribeLocaleChange, t };
package/dist/index.js CHANGED
@@ -66,6 +66,18 @@ var defaultTranslations = {
66
66
  clear: "Clear",
67
67
  selectMonth: "Select Month",
68
68
  poyaDay: "Poya Day"
69
+ },
70
+ destinationCard: {
71
+ eyebrow: "PlaceHolder",
72
+ reviewsLabel: "Reviews",
73
+ bookTrip: "PlaceHolder",
74
+ exploreNow: "PlaceHolder",
75
+ startFrom: "Start from",
76
+ perPerson: "/ person"
77
+ },
78
+ button: {
79
+ primary: "PlaceHolder",
80
+ secondary: "PlaceHolder"
69
81
  }
70
82
  },
71
83
  si: {
@@ -123,6 +135,18 @@ var defaultTranslations = {
123
135
  clear: "\u0DB4\u0DD2\u0DBB\u0DD2\u0DC3\u0DD2\u0DAF\u0DD4 \u0D9A\u0DBB\u0DB1\u0DCA\u0DB1",
124
136
  selectMonth: "\u0DB8\u0DCF\u0DC3\u0DBA \u0DAD\u0DDD\u0DBB\u0DB1\u0DCA\u0DB1",
125
137
  poyaDay: "\u0DB4\u0DDD\u0DBA \u0DAF\u0DD2\u0DB1"
138
+ },
139
+ destinationCard: {
140
+ eyebrow: "\u0DC1\u0DCA\u200D\u0DBB\u0DD3 \u0DBD\u0D82\u0D9A\u0DCF\u0DC0 \u0DC3\u0DDC\u0DBA\u0DCF \u0DB6\u0DBD\u0DB1\u0DCA\u0DB1",
141
+ reviewsLabel: "\u0DC3\u0DB8\u0DCF\u0DBD\u0DDD\u0DA0\u0DB1",
142
+ bookTrip: "\u0D94\u0DB6\u0DDA \u0DC3\u0D82\u0DA0\u0DCF\u0DBB\u0DBA \u0DC0\u0DD9\u0DB1\u0DCA\u0D9A\u0DBB\u0DC0\u0DB1\u0DCA\u0DB1",
143
+ exploreNow: "\u0DAF\u0DD0\u0DB1\u0DCA \u0D9C\u0DC0\u0DDA\u0DC2\u0DAB\u0DBA \u0D9A\u0DBB\u0DB1\u0DCA\u0DB1",
144
+ startFrom: "\u0D86\u0DBB\u0DB8\u0DCA\u0DB7\u0DBA",
145
+ perPerson: "/ \u0DB4\u0DD4\u0DAF\u0DCA\u0D9C\u0DBD\u0DBA\u0D9A\u0DD4\u0DA7"
146
+ },
147
+ button: {
148
+ primary: "\u0D94\u0DB6\u0DDA \u0DC3\u0D82\u0DA0\u0DCF\u0DBB\u0DBA \u0DC0\u0DD9\u0DB1\u0DCA\u0D9A\u0DBB\u0DC0\u0DB1\u0DCA\u0DB1",
149
+ secondary: "\u0DAF\u0DD0\u0DB1\u0DCA \u0D9C\u0DC0\u0DDA\u0DC2\u0DAB\u0DBA \u0D9A\u0DBB\u0DB1\u0DCA\u0DB1"
126
150
  }
127
151
  }
128
152
  };
@@ -212,6 +236,12 @@ function getTextFieldTranslation(variant, locale = currentLocale) {
212
236
  function getCalendarTranslation(locale = currentLocale) {
213
237
  return getMergedTranslations(locale).calendar ?? defaultTranslations[locale].calendar;
214
238
  }
239
+ function getDestinationCardTranslation(locale = currentLocale) {
240
+ return getMergedTranslations(locale).destinationCard ?? defaultTranslations[locale].destinationCard;
241
+ }
242
+ function getButtonTranslation(locale = currentLocale) {
243
+ return getMergedTranslations(locale).button ?? defaultTranslations[locale].button;
244
+ }
215
245
  function subscribeLocaleChange(listener) {
216
246
  localeListeners.add(listener);
217
247
  return () => localeListeners.delete(listener);
@@ -911,6 +941,166 @@ var SunMandala = class {
911
941
  }
912
942
  };
913
943
 
944
+ // src/components/DestinationCard.ts
945
+ var PEACOCK_SVG = `
946
+ <svg viewBox="0 0 220 110" aria-hidden="true">
947
+ <g fill="none" stroke-linecap="round">
948
+ <path d="M18 92c8-28 28-52 58-62" stroke="#1a6b6c" stroke-width="5"/>
949
+ <path d="M32 96c10-22 30-40 56-46" stroke="#2a8f7a" stroke-width="4"/>
950
+ <path d="M48 100c10-16 26-28 46-32" stroke="#c86837" stroke-width="3.5"/>
951
+ <ellipse cx="28" cy="38" rx="7" ry="10" fill="#1a4d4e" transform="rotate(-20 28 38)"/>
952
+ <circle cx="26" cy="34" r="1.6" fill="#f9f3e6"/>
953
+ <path d="M22 42c8 6 18 8 28 4" stroke="#1a4d4e" stroke-width="3"/>
954
+ <circle cx="62" cy="28" r="9" fill="#1a6b6c" opacity=".85"/>
955
+ <circle cx="62" cy="28" r="4" fill="#d4af37"/>
956
+ <circle cx="88" cy="42" r="10" fill="#2a8f7a" opacity=".8"/>
957
+ <circle cx="88" cy="42" r="4" fill="#c86837"/>
958
+ <circle cx="74" cy="62" r="9" fill="#1a4d4e" opacity=".75"/>
959
+ <circle cx="74" cy="62" r="3.5" fill="#d4af37"/>
960
+ <path d="M108 96c8-24 26-44 54-52" stroke="#1a6b6c" stroke-width="5"/>
961
+ <path d="M118 100c8-18 24-32 48-36" stroke="#c86837" stroke-width="3.5"/>
962
+ <ellipse cx="116" cy="48" rx="6.5" ry="9" fill="#1a4d4e" transform="rotate(-18 116 48)"/>
963
+ <circle cx="114" cy="44" r="1.4" fill="#f9f3e6"/>
964
+ <circle cx="148" cy="36" r="8" fill="#1a6b6c" opacity=".85"/>
965
+ <circle cx="148" cy="36" r="3.5" fill="#d4af37"/>
966
+ <circle cx="168" cy="52" r="8" fill="#2a8f7a" opacity=".8"/>
967
+ <circle cx="168" cy="52" r="3.5" fill="#c86837"/>
968
+ </g>
969
+ <ellipse cx="96" cy="98" rx="10" ry="6" fill="#e8c9d4"/>
970
+ <path d="M90 96c4-10 12-12 18-2" fill="#d46a8a"/>
971
+ <path d="M94 98c3-7 9-8 13-1" fill="#f4c6d4"/>
972
+ </svg>
973
+ `;
974
+ var LOTUS_SVG = `
975
+ <svg viewBox="0 0 120 110" aria-hidden="true">
976
+ <path d="M60 96c-16-18-28-34-28-50 0-10 8-16 16-12 6 3 10 12 12 22 2-14 8-28 18-34 8-5 16 0 16 12 0 16-12 32-34 62z" fill="#e8a0b8"/>
977
+ <path d="M60 96c-10-16-22-36-18-54 3-12 14-16 18-6 4-16 16-24 24-18 8 6 6 22-2 36-8 14-16 28-22 42z" fill="#d46a8a"/>
978
+ <path d="M60 98c6-20 8-38 4-52-3-10-12-12-14-4-4-12-2-24 8-28 10-4 18 6 18 18 0 16-6 34-16 66z" fill="#f3c3d2"/>
979
+ <circle cx="60" cy="42" r="8" fill="#d4af37"/>
980
+ <circle cx="60" cy="42" r="3.5" fill="#f9f3e6"/>
981
+ </svg>
982
+ `;
983
+ function el(tag, className, text) {
984
+ const node = document.createElement(tag);
985
+ node.className = className;
986
+ if (text !== void 0) node.textContent = text;
987
+ return node;
988
+ }
989
+ var DestinationCard = class {
990
+ element;
991
+ card;
992
+ body;
993
+ constructor(options = {}) {
994
+ const { content, height = "280px", backdrop = false, backdropImage } = options;
995
+ this.card = el("article", "helaui-destination-card");
996
+ this.card.setAttribute("aria-label", "HelaUI card");
997
+ const watermark = el("div", "helaui-destination-card__watermark");
998
+ watermark.setAttribute("aria-hidden", "true");
999
+ this.card.appendChild(watermark);
1000
+ const script = el("div", `helaui-destination-card__script ${SINHALA_FONT_CLASS}`, "\u0DC1\u0DCA\u200D\u0DBB\u0DD3 \u0DBD\u0D82\u0D9A\u0DCF\u0DC0");
1001
+ script.setAttribute("aria-hidden", "true");
1002
+ this.card.appendChild(script);
1003
+ this.body = el("div", "helaui-destination-card__body");
1004
+ this.body.style.minHeight = height;
1005
+ if (typeof content === "string") {
1006
+ this.body.innerHTML = content;
1007
+ } else if (content) {
1008
+ this.body.appendChild(content);
1009
+ }
1010
+ this.card.appendChild(this.body);
1011
+ const footer = el("div", "helaui-destination-card__footer");
1012
+ footer.setAttribute("aria-hidden", "true");
1013
+ const peacocks = el("div", "helaui-destination-card__peacocks");
1014
+ peacocks.innerHTML = PEACOCK_SVG.trim();
1015
+ const lotus = el("div", "helaui-destination-card__lotus");
1016
+ lotus.innerHTML = LOTUS_SVG.trim();
1017
+ footer.append(peacocks, lotus);
1018
+ this.card.appendChild(footer);
1019
+ if (backdrop) {
1020
+ const stage = el("div", "helaui-destination-card-stage");
1021
+ const blur = el("div", "helaui-destination-card-stage__blur");
1022
+ if (backdropImage) {
1023
+ blur.style.backgroundImage = `url("${backdropImage.replace(/"/g, "")}")`;
1024
+ }
1025
+ stage.append(blur, this.card);
1026
+ this.element = stage;
1027
+ } else {
1028
+ this.element = this.card;
1029
+ }
1030
+ }
1031
+ setContent(content) {
1032
+ this.body.replaceChildren();
1033
+ if (typeof content === "string") {
1034
+ this.body.innerHTML = content;
1035
+ } else {
1036
+ this.body.appendChild(content);
1037
+ }
1038
+ }
1039
+ destroy() {
1040
+ this.element.remove();
1041
+ }
1042
+ };
1043
+
1044
+ // src/components/Button.ts
1045
+ var VARIANT_LABEL_KEY = {
1046
+ primary: "button.primary",
1047
+ secondary: "button.secondary"
1048
+ };
1049
+ var Button = class {
1050
+ element;
1051
+ unsubscribeLocale;
1052
+ variant;
1053
+ fixedLabel;
1054
+ labelKey;
1055
+ sinhalaExplicit;
1056
+ constructor(options = {}) {
1057
+ const {
1058
+ variant = "primary",
1059
+ label,
1060
+ labelKey,
1061
+ type = "button",
1062
+ disabled = false,
1063
+ onClick,
1064
+ sinhala
1065
+ } = options;
1066
+ this.variant = variant;
1067
+ this.fixedLabel = label;
1068
+ this.labelKey = labelKey;
1069
+ this.sinhalaExplicit = sinhala !== void 0;
1070
+ this.element = document.createElement("button");
1071
+ this.element.type = type;
1072
+ this.element.className = `helaui-button helaui-button--${variant}`;
1073
+ this.element.disabled = disabled;
1074
+ if (onClick) this.element.addEventListener("click", onClick);
1075
+ this.applyLabel();
1076
+ this.setSinhala(sinhala ?? getLocale() === "si");
1077
+ this.unsubscribeLocale = subscribeLocaleChange(() => {
1078
+ this.applyLabel();
1079
+ if (!this.sinhalaExplicit) this.setSinhala(getLocale() === "si");
1080
+ });
1081
+ }
1082
+ applyLabel() {
1083
+ if (this.fixedLabel !== void 0) {
1084
+ this.element.textContent = this.fixedLabel;
1085
+ return;
1086
+ }
1087
+ this.element.textContent = t(this.labelKey ?? VARIANT_LABEL_KEY[this.variant]);
1088
+ }
1089
+ setLabel(label) {
1090
+ this.element.textContent = label;
1091
+ }
1092
+ setDisabled(disabled) {
1093
+ this.element.disabled = disabled;
1094
+ }
1095
+ setSinhala(enabled) {
1096
+ this.element.classList.toggle(SINHALA_FONT_CLASS, enabled);
1097
+ }
1098
+ destroy() {
1099
+ this.unsubscribeLocale?.();
1100
+ this.element.remove();
1101
+ }
1102
+ };
1103
+
914
1104
  // src/theme/defaultTheme.ts
915
1105
  var defaultTheme = {
916
1106
  primary: "#8D153A",
@@ -983,8 +1173,10 @@ function createThemeStyle(theme = {}) {
983
1173
  export {
984
1174
  BUILTIN_RAIN_IMAGES,
985
1175
  BUILTIN_SUN_MANDALA_IMAGE,
1176
+ Button,
986
1177
  Calendar,
987
1178
  DEFAULT_RAIN_IMAGES,
1179
+ DestinationCard,
988
1180
  RainBackground,
989
1181
  SINHALA_FONT_CLASS,
990
1182
  SINHALA_FONT_FAMILY,
@@ -999,8 +1191,10 @@ export {
999
1191
  defaultTheme,
1000
1192
  defaultTranslations,
1001
1193
  formatSinhalaNumeral,
1194
+ getButtonTranslation,
1002
1195
  getCalendarTranslation,
1003
1196
  getDefaultRainImageUrls,
1197
+ getDestinationCardTranslation,
1004
1198
  getLocale,
1005
1199
  getTextFieldTranslation,
1006
1200
  resetTheme,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mccustomapps/helaui",
3
- "version": "0.1.12",
3
+ "version": "0.1.15",
4
4
  "description": "HelaUI components with Sinhala font support",
5
5
  "author": "mccustomapps",
6
6
  "license": "MIT",
@@ -26,6 +26,8 @@
26
26
  "./calendar.css": "./dist/calendar.css",
27
27
  "./rain-background.css": "./dist/rain-background.css",
28
28
  "./sun-mandala.css": "./dist/sun-mandala.css",
29
+ "./destination-card.css": "./dist/destination-card.css",
30
+ "./button.css": "./dist/button.css",
29
31
  "./theme.css": "./dist/theme.css",
30
32
  "./assets/rain/*": "./dist/assets/rain/*",
31
33
  "./assets/sun-mandala/*": "./dist/assets/sun-mandala/*"