@mccustomapps/helaui 0.1.13 → 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
@@ -17,6 +17,7 @@
17
17
  - [Calendar](#calendar)
18
18
  - [SunMandala](#sunmandala)
19
19
  - [DestinationCard](#destinationcard)
20
+ - [Button](#button)
20
21
  - [RainBackground](#rainbackground)
21
22
  - [Theming](#theming)
22
23
  - [i18n / Localisation](#i18n--localisation)
@@ -42,12 +43,13 @@ import '@mccustomapps/helaui/textfield.css';
42
43
  import '@mccustomapps/helaui/calendar.css';
43
44
  import '@mccustomapps/helaui/sun-mandala.css';
44
45
  import '@mccustomapps/helaui/destination-card.css';
46
+ import '@mccustomapps/helaui/button.css';
45
47
  import '@mccustomapps/helaui/rain-background.css';
46
48
  import '@mccustomapps/helaui/sinhala.css'; // Sinhala font face
47
49
  import '@mccustomapps/helaui/theme.css'; // CSS custom-property tokens
48
50
 
49
51
  // Import components
50
- import { TextField, Calendar, SunMandala, DestinationCard, RainBackground } from '@mccustomapps/helaui';
52
+ import { TextField, Calendar, SunMandala, DestinationCard, Button, RainBackground } from '@mccustomapps/helaui';
51
53
 
52
54
  // Mount components
53
55
  const field = new TextField({ variant: 'name' });
@@ -243,6 +245,53 @@ card.destroy()
243
245
 
244
246
  ---
245
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
+
246
295
  ### RainBackground
247
296
 
248
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/`).
@@ -378,6 +427,7 @@ import '@mccustomapps/helaui/textfield.css'; // TextField styles
378
427
  import '@mccustomapps/helaui/calendar.css'; // Calendar styles
379
428
  import '@mccustomapps/helaui/sun-mandala.css'; // SunMandala styles
380
429
  import '@mccustomapps/helaui/destination-card.css'; // DestinationCard styles
430
+ import '@mccustomapps/helaui/button.css'; // Button styles
381
431
  import '@mccustomapps/helaui/rain-background.css'; // RainBackground styles
382
432
  ```
383
433
 
@@ -393,6 +443,7 @@ import type {
393
443
  CalendarOptions,
394
444
  SunMandalaOptions,
395
445
  DestinationCardOptions,
446
+ ButtonOptions,
396
447
  RainBackgroundOptions,
397
448
  HelaTheme,
398
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
+ }
@@ -1,134 +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
- flex: 1;
90
- min-height: 280px;
91
- }
92
-
93
- .helaui-destination-card__footer {
94
- position: relative;
95
- height: 92px;
96
- margin: 4px -16px 0;
97
- background: linear-gradient(90deg, #c86837 0%, #b8432f 55%, #c86837 100%);
98
- overflow: hidden;
99
- }
100
-
101
- .helaui-destination-card__footer::before {
102
- content: '';
103
- position: absolute;
104
- inset: 0;
105
- opacity: 0.22;
106
- background-image:
107
- radial-gradient(circle at 20% 40%, #f9f3e6 0 10%, transparent 11%),
108
- radial-gradient(circle at 70% 70%, #f9f3e6 0 8%, transparent 9%),
109
- radial-gradient(circle at 50% 20%, transparent 40%, rgba(249, 243, 230, 0.5) 41%, transparent 44%);
110
- }
111
-
112
- .helaui-destination-card__peacocks,
113
- .helaui-destination-card__lotus {
114
- position: absolute;
115
- bottom: -4px;
116
- z-index: 1;
117
- }
118
-
119
- .helaui-destination-card__peacocks {
120
- left: 6px;
121
- width: 58%;
122
- }
123
-
124
- .helaui-destination-card__peacocks svg,
125
- .helaui-destination-card__lotus svg {
126
- display: block;
127
- width: 100%;
128
- height: auto;
129
- }
130
-
131
- .helaui-destination-card__lotus {
132
- right: 4px;
133
- width: 34%;
134
- }
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,6 +22,7 @@ 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,
27
28
  DestinationCard: () => DestinationCard,
@@ -39,6 +40,7 @@ __export(index_exports, {
39
40
  defaultTheme: () => defaultTheme,
40
41
  defaultTranslations: () => defaultTranslations,
41
42
  formatSinhalaNumeral: () => formatSinhalaNumeral,
43
+ getButtonTranslation: () => getButtonTranslation,
42
44
  getCalendarTranslation: () => getCalendarTranslation,
43
45
  getDefaultRainImageUrls: () => getDefaultRainImageUrls,
44
46
  getDestinationCardTranslation: () => getDestinationCardTranslation,
@@ -123,12 +125,16 @@ var defaultTranslations = {
123
125
  poyaDay: "Poya Day"
124
126
  },
125
127
  destinationCard: {
126
- eyebrow: "Explore Sri Lanka",
128
+ eyebrow: "PlaceHolder",
127
129
  reviewsLabel: "Reviews",
128
- bookTrip: "Book Your Trip",
129
- exploreNow: "Explore Now",
130
+ bookTrip: "PlaceHolder",
131
+ exploreNow: "PlaceHolder",
130
132
  startFrom: "Start from",
131
133
  perPerson: "/ person"
134
+ },
135
+ button: {
136
+ primary: "PlaceHolder",
137
+ secondary: "PlaceHolder"
132
138
  }
133
139
  },
134
140
  si: {
@@ -194,6 +200,10 @@ var defaultTranslations = {
194
200
  exploreNow: "\u0DAF\u0DD0\u0DB1\u0DCA \u0D9C\u0DC0\u0DDA\u0DC2\u0DAB\u0DBA \u0D9A\u0DBB\u0DB1\u0DCA\u0DB1",
195
201
  startFrom: "\u0D86\u0DBB\u0DB8\u0DCA\u0DB7\u0DBA",
196
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"
197
207
  }
198
208
  }
199
209
  };
@@ -286,6 +296,9 @@ function getCalendarTranslation(locale = currentLocale) {
286
296
  function getDestinationCardTranslation(locale = currentLocale) {
287
297
  return getMergedTranslations(locale).destinationCard ?? defaultTranslations[locale].destinationCard;
288
298
  }
299
+ function getButtonTranslation(locale = currentLocale) {
300
+ return getMergedTranslations(locale).button ?? defaultTranslations[locale].button;
301
+ }
289
302
  function subscribeLocaleChange(listener) {
290
303
  localeListeners.add(listener);
291
304
  return () => localeListeners.delete(listener);
@@ -1085,6 +1098,66 @@ var DestinationCard = class {
1085
1098
  }
1086
1099
  };
1087
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
+
1088
1161
  // src/theme/defaultTheme.ts
1089
1162
  var defaultTheme = {
1090
1163
  primary: "#8D153A",
@@ -1158,6 +1231,7 @@ function createThemeStyle(theme = {}) {
1158
1231
  0 && (module.exports = {
1159
1232
  BUILTIN_RAIN_IMAGES,
1160
1233
  BUILTIN_SUN_MANDALA_IMAGE,
1234
+ Button,
1161
1235
  Calendar,
1162
1236
  DEFAULT_RAIN_IMAGES,
1163
1237
  DestinationCard,
@@ -1175,6 +1249,7 @@ function createThemeStyle(theme = {}) {
1175
1249
  defaultTheme,
1176
1250
  defaultTranslations,
1177
1251
  formatSinhalaNumeral,
1252
+ getButtonTranslation,
1178
1253
  getCalendarTranslation,
1179
1254
  getDefaultRainImageUrls,
1180
1255
  getDestinationCardTranslation,
package/dist/index.d.cts CHANGED
@@ -25,6 +25,10 @@ interface HelaTextFieldTranslations {
25
25
  email: TextFieldStrings;
26
26
  disabled: TextFieldStrings;
27
27
  }
28
+ interface ButtonStrings {
29
+ primary: string;
30
+ secondary: string;
31
+ }
28
32
  interface DestinationCardStrings {
29
33
  eyebrow: string;
30
34
  reviewsLabel: string;
@@ -49,6 +53,7 @@ interface HelaTranslations {
49
53
  textField: HelaTextFieldTranslations;
50
54
  calendar: CalendarStrings;
51
55
  destinationCard: DestinationCardStrings;
56
+ button: ButtonStrings;
52
57
  }
53
58
  type TextFieldVariant = keyof HelaTextFieldTranslations;
54
59
  type DeepPartial<T> = {
@@ -95,6 +100,8 @@ declare function getTextFieldTranslation(variant: TextFieldVariant, locale?: Hel
95
100
  declare function getCalendarTranslation(locale?: HelaLocale): CalendarStrings;
96
101
  /** Built-in DestinationCard strings for the active (or given) locale. */
97
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;
98
105
  /** Subscribe to locale or override changes. Returns an unsubscribe function. */
99
106
  declare function subscribeLocaleChange(listener: () => void): () => void;
100
107
 
@@ -341,6 +348,42 @@ declare class DestinationCard {
341
348
  destroy(): void;
342
349
  }
343
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
+
344
387
  /** HelaUI brand palette — all values are customizable. */
345
388
  interface HelaTheme {
346
389
  primary: string;
@@ -373,4 +416,4 @@ declare const defaultTheme: HelaTheme;
373
416
  /** Maps theme keys to CSS custom property names. */
374
417
  declare const THEME_VAR_MAP: Record<HelaThemeKey, string>;
375
418
 
376
- export { type ApplyTranslationsOptions, BUILTIN_RAIN_IMAGES, BUILTIN_SUN_MANDALA_IMAGE, 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, getCalendarTranslation, getDefaultRainImageUrls, getDestinationCardTranslation, 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,10 @@ interface HelaTextFieldTranslations {
25
25
  email: TextFieldStrings;
26
26
  disabled: TextFieldStrings;
27
27
  }
28
+ interface ButtonStrings {
29
+ primary: string;
30
+ secondary: string;
31
+ }
28
32
  interface DestinationCardStrings {
29
33
  eyebrow: string;
30
34
  reviewsLabel: string;
@@ -49,6 +53,7 @@ interface HelaTranslations {
49
53
  textField: HelaTextFieldTranslations;
50
54
  calendar: CalendarStrings;
51
55
  destinationCard: DestinationCardStrings;
56
+ button: ButtonStrings;
52
57
  }
53
58
  type TextFieldVariant = keyof HelaTextFieldTranslations;
54
59
  type DeepPartial<T> = {
@@ -95,6 +100,8 @@ declare function getTextFieldTranslation(variant: TextFieldVariant, locale?: Hel
95
100
  declare function getCalendarTranslation(locale?: HelaLocale): CalendarStrings;
96
101
  /** Built-in DestinationCard strings for the active (or given) locale. */
97
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;
98
105
  /** Subscribe to locale or override changes. Returns an unsubscribe function. */
99
106
  declare function subscribeLocaleChange(listener: () => void): () => void;
100
107
 
@@ -341,6 +348,42 @@ declare class DestinationCard {
341
348
  destroy(): void;
342
349
  }
343
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
+
344
387
  /** HelaUI brand palette — all values are customizable. */
345
388
  interface HelaTheme {
346
389
  primary: string;
@@ -373,4 +416,4 @@ declare const defaultTheme: HelaTheme;
373
416
  /** Maps theme keys to CSS custom property names. */
374
417
  declare const THEME_VAR_MAP: Record<HelaThemeKey, string>;
375
418
 
376
- export { type ApplyTranslationsOptions, BUILTIN_RAIN_IMAGES, BUILTIN_SUN_MANDALA_IMAGE, 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, getCalendarTranslation, getDefaultRainImageUrls, getDestinationCardTranslation, 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
@@ -68,12 +68,16 @@ var defaultTranslations = {
68
68
  poyaDay: "Poya Day"
69
69
  },
70
70
  destinationCard: {
71
- eyebrow: "Explore Sri Lanka",
71
+ eyebrow: "PlaceHolder",
72
72
  reviewsLabel: "Reviews",
73
- bookTrip: "Book Your Trip",
74
- exploreNow: "Explore Now",
73
+ bookTrip: "PlaceHolder",
74
+ exploreNow: "PlaceHolder",
75
75
  startFrom: "Start from",
76
76
  perPerson: "/ person"
77
+ },
78
+ button: {
79
+ primary: "PlaceHolder",
80
+ secondary: "PlaceHolder"
77
81
  }
78
82
  },
79
83
  si: {
@@ -139,6 +143,10 @@ var defaultTranslations = {
139
143
  exploreNow: "\u0DAF\u0DD0\u0DB1\u0DCA \u0D9C\u0DC0\u0DDA\u0DC2\u0DAB\u0DBA \u0D9A\u0DBB\u0DB1\u0DCA\u0DB1",
140
144
  startFrom: "\u0D86\u0DBB\u0DB8\u0DCA\u0DB7\u0DBA",
141
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"
142
150
  }
143
151
  }
144
152
  };
@@ -231,6 +239,9 @@ function getCalendarTranslation(locale = currentLocale) {
231
239
  function getDestinationCardTranslation(locale = currentLocale) {
232
240
  return getMergedTranslations(locale).destinationCard ?? defaultTranslations[locale].destinationCard;
233
241
  }
242
+ function getButtonTranslation(locale = currentLocale) {
243
+ return getMergedTranslations(locale).button ?? defaultTranslations[locale].button;
244
+ }
234
245
  function subscribeLocaleChange(listener) {
235
246
  localeListeners.add(listener);
236
247
  return () => localeListeners.delete(listener);
@@ -1030,6 +1041,66 @@ var DestinationCard = class {
1030
1041
  }
1031
1042
  };
1032
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
+
1033
1104
  // src/theme/defaultTheme.ts
1034
1105
  var defaultTheme = {
1035
1106
  primary: "#8D153A",
@@ -1102,6 +1173,7 @@ function createThemeStyle(theme = {}) {
1102
1173
  export {
1103
1174
  BUILTIN_RAIN_IMAGES,
1104
1175
  BUILTIN_SUN_MANDALA_IMAGE,
1176
+ Button,
1105
1177
  Calendar,
1106
1178
  DEFAULT_RAIN_IMAGES,
1107
1179
  DestinationCard,
@@ -1119,6 +1191,7 @@ export {
1119
1191
  defaultTheme,
1120
1192
  defaultTranslations,
1121
1193
  formatSinhalaNumeral,
1194
+ getButtonTranslation,
1122
1195
  getCalendarTranslation,
1123
1196
  getDefaultRainImageUrls,
1124
1197
  getDestinationCardTranslation,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mccustomapps/helaui",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "HelaUI components with Sinhala font support",
5
5
  "author": "mccustomapps",
6
6
  "license": "MIT",
@@ -27,6 +27,7 @@
27
27
  "./rain-background.css": "./dist/rain-background.css",
28
28
  "./sun-mandala.css": "./dist/sun-mandala.css",
29
29
  "./destination-card.css": "./dist/destination-card.css",
30
+ "./button.css": "./dist/button.css",
30
31
  "./theme.css": "./dist/theme.css",
31
32
  "./assets/rain/*": "./dist/assets/rain/*",
32
33
  "./assets/sun-mandala/*": "./dist/assets/sun-mandala/*"