@superleapai/flow-ui 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/LICENSE +21 -0
  3. package/README.md +451 -0
  4. package/components/alert.js +282 -0
  5. package/components/avatar.js +195 -0
  6. package/components/badge.js +135 -0
  7. package/components/button.js +201 -0
  8. package/components/checkbox.js +254 -0
  9. package/components/currency.js +227 -0
  10. package/components/date-time-picker/date-time-picker-utils.js +253 -0
  11. package/components/date-time-picker/date-time-picker.js +532 -0
  12. package/components/duration/duration-constants.js +46 -0
  13. package/components/duration/duration-utils.js +164 -0
  14. package/components/duration/duration.js +448 -0
  15. package/components/enum-multiselect.js +869 -0
  16. package/components/enum-select.js +831 -0
  17. package/components/enumeration.js +213 -0
  18. package/components/file-input.js +533 -0
  19. package/components/icon.js +200 -0
  20. package/components/input.js +259 -0
  21. package/components/label.js +111 -0
  22. package/components/multiselect.js +351 -0
  23. package/components/phone-input/phone-input.js +392 -0
  24. package/components/phone-input/phone-utils.js +157 -0
  25. package/components/popover.js +240 -0
  26. package/components/radio-group.js +435 -0
  27. package/components/record-multiselect.js +956 -0
  28. package/components/record-select.js +930 -0
  29. package/components/select.js +544 -0
  30. package/components/spinner.js +136 -0
  31. package/components/table.js +335 -0
  32. package/components/textarea.js +114 -0
  33. package/components/time-picker.js +357 -0
  34. package/components/toast.js +343 -0
  35. package/core/flow.js +1729 -0
  36. package/core/superleapClient.js +146 -0
  37. package/dist/output.css +2 -0
  38. package/index.d.ts +458 -0
  39. package/index.js +253 -0
  40. package/package.json +70 -0
@@ -0,0 +1,392 @@
1
+ /**
2
+ * Phone Input Component
3
+ * International phone number input with country selector
4
+ */
5
+
6
+ (function (global) {
7
+ "use strict";
8
+
9
+ if (!global.PhoneInputUtils) {
10
+ console.error("[PhoneInput] PhoneInputUtils is required");
11
+ return;
12
+ }
13
+
14
+ const utils = global.PhoneInputUtils;
15
+
16
+ /** Resolve component by name (works after index.js captures and removes globals). */
17
+ function getComponent(name) {
18
+ if (typeof global.FlowUI !== "undefined" && typeof global.FlowUI._getComponent === "function") {
19
+ const c = global.FlowUI._getComponent(name);
20
+ if (c) return c;
21
+ }
22
+ return global[name];
23
+ }
24
+
25
+ // Selector icon SVG
26
+ const SELECTOR_ICON =
27
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m7 15 5 5 5-5"/><path d="m7 9 5-5 5 5"/></svg>';
28
+
29
+ const SEARCH_ICON =
30
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>';
31
+
32
+ const CHECK_ICON =
33
+ '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>';
34
+
35
+ /**
36
+ * Create a phone input component
37
+ * @param {Object} config
38
+ * @param {string} [config.variant] - 'default' | 'error' | 'warning' | 'borderless' | 'inline'
39
+ * @param {string} [config.inputSize] - 'default' | 'large' | 'small'
40
+ * @param {string} [config.defaultCountryCode] - Default country code (e.g., 'US', 'IN')
41
+ * @param {string} [config.defaultPhoneNumber] - Default phone number in format "callingCode-nationalNumber"
42
+ * @param {boolean} [config.disabled]
43
+ * @param {boolean} [config.disableCountrySelect] - Disable country selector
44
+ * @param {boolean} [config.hideCountrySelect] - Hide country selector completely
45
+ * @param {string} [config.placeholder] - Custom placeholder (overrides auto-generated)
46
+ * @param {string} [config.className] - Extra class for wrapper
47
+ * @param {string} [config.countryCodeClassName] - Extra class for country selector
48
+ * @param {Function} [config.onCountryChange] - Called when country changes (country)
49
+ * @param {Function} [config.onPhoneNumberChange] - Called when phone number changes (fullValue)
50
+ * @param {Function} [config.onChange] - Called when either changes (fullValue, country)
51
+ * @returns {HTMLElement} Phone input wrapper
52
+ */
53
+ function create(config = {}) {
54
+ const variant = config.variant || "default";
55
+ const inputSize = config.inputSize || "default";
56
+ const disabled = !!config.disabled;
57
+ const disableCountrySelect = !!config.disableCountrySelect;
58
+ const hideCountrySelect = !!config.hideCountrySelect;
59
+
60
+ const options = utils.getCountriesOptions();
61
+
62
+ // Determine initial country
63
+ let initialCountry = null;
64
+ if (config.defaultPhoneNumber) {
65
+ const parsed = utils.parsePhoneNumber(config.defaultPhoneNumber);
66
+ if (parsed.callingCode) {
67
+ const countryCode = utils.getCountryCodeFromCallingCode(
68
+ parsed.callingCode
69
+ );
70
+ if (countryCode) {
71
+ initialCountry = options.find((opt) => opt.value === countryCode);
72
+ }
73
+ }
74
+ }
75
+ if (!initialCountry && config.defaultCountryCode) {
76
+ initialCountry = options.find(
77
+ (opt) => opt.value === config.defaultCountryCode
78
+ );
79
+ }
80
+ // Default to India if no country specified
81
+ if (!initialCountry) {
82
+ initialCountry = options.find((opt) => opt.value === "IN") || options[0];
83
+ }
84
+
85
+ let currentCountry = initialCountry;
86
+ let phoneNumber = "";
87
+
88
+ // Parse initial phone number
89
+ if (config.defaultPhoneNumber) {
90
+ const parsed = utils.parsePhoneNumber(config.defaultPhoneNumber);
91
+ phoneNumber = parsed.nationalNumber;
92
+ }
93
+
94
+ // Main wrapper
95
+ const wrapper = document.createElement("div");
96
+ wrapper.className = "flex w-full flex-col gap-4";
97
+
98
+ // Row container
99
+ const row = document.createElement("div");
100
+ row.className = "flex items-center gap-2";
101
+
102
+ // Country selector (combobox-style with popover)
103
+ let countrySelector = null;
104
+ if (!hideCountrySelect) {
105
+ countrySelector = createCountrySelector({
106
+ variant,
107
+ inputSize,
108
+ disabled: disabled || disableCountrySelect,
109
+ options,
110
+ value: currentCountry,
111
+ getValue: () => currentCountry,
112
+ className: config.countryCodeClassName,
113
+ onChange: (country) => {
114
+ currentCountry = country;
115
+ updatePlaceholder();
116
+ if (config.onCountryChange) config.onCountryChange(country);
117
+ const fullValue = utils.formatPhoneNumber(
118
+ country.indicatif,
119
+ phoneNumber
120
+ );
121
+ if (config.onPhoneNumberChange)
122
+ config.onPhoneNumberChange(fullValue);
123
+ if (config.onChange) config.onChange(fullValue, country);
124
+ },
125
+ });
126
+ row.appendChild(countrySelector);
127
+ }
128
+
129
+ // Phone number input
130
+ const InputComponent = getComponent("InputComponent");
131
+ if (!InputComponent || typeof InputComponent.create !== "function") {
132
+ console.error("[PhoneInput] InputComponent is required");
133
+ return wrapper;
134
+ }
135
+ const phoneInputWrapper = InputComponent.create({
136
+ variant,
137
+ inputSize,
138
+ type: "tel",
139
+ placeholder:
140
+ config.placeholder || utils.getExampleFormat(currentCountry.value),
141
+ value: phoneNumber,
142
+ disabled,
143
+ className: config.className || "",
144
+ onInput: (e) => {
145
+ const input = e.target;
146
+ const digitsOnly = (input.value || "").replace(/\D/g, "");
147
+ if (input.value !== digitsOnly) {
148
+ input.value = digitsOnly;
149
+ }
150
+ phoneNumber = digitsOnly;
151
+ const fullValue = utils.formatPhoneNumber(
152
+ currentCountry.indicatif,
153
+ phoneNumber
154
+ );
155
+ if (config.onPhoneNumberChange) config.onPhoneNumberChange(fullValue);
156
+ if (config.onChange) config.onChange(fullValue, currentCountry);
157
+ },
158
+ });
159
+
160
+ row.appendChild(phoneInputWrapper);
161
+ wrapper.appendChild(row);
162
+
163
+ function updatePlaceholder() {
164
+ const input = phoneInputWrapper.getInput();
165
+ if (input) {
166
+ input.placeholder =
167
+ config.placeholder || utils.getExampleFormat(currentCountry.value);
168
+ }
169
+ // Update prefix
170
+ if (!hideCountrySelect) {
171
+ const prefix = phoneInputWrapper.querySelector(
172
+ "span.text-typography-quaternary-text"
173
+ );
174
+ if (prefix) {
175
+ prefix.textContent = `+${currentCountry.indicatif}`;
176
+ }
177
+ }
178
+ }
179
+
180
+ // Public API
181
+ wrapper.getValue = function () {
182
+ return utils.formatPhoneNumber(currentCountry.indicatif, phoneNumber);
183
+ };
184
+
185
+ wrapper.setValue = function (value) {
186
+ const parsed = utils.parsePhoneNumber(value);
187
+ if (parsed.callingCode) {
188
+ const countryCode = utils.getCountryCodeFromCallingCode(
189
+ parsed.callingCode
190
+ );
191
+ if (countryCode) {
192
+ const country = options.find((opt) => opt.value === countryCode);
193
+ if (country) {
194
+ currentCountry = country;
195
+ if (countrySelector) {
196
+ // Update country selector display
197
+ const triggerInput = countrySelector.querySelector("input");
198
+ if (triggerInput) {
199
+ triggerInput.value = utils.isoToEmoji(country.value) + " " + country.indicatif;
200
+ }
201
+ }
202
+ }
203
+ }
204
+ }
205
+ phoneNumber = parsed.nationalNumber;
206
+ phoneInputWrapper.setValue(phoneNumber);
207
+ updatePlaceholder();
208
+ };
209
+
210
+ wrapper.getCountry = function () {
211
+ return currentCountry;
212
+ };
213
+
214
+ wrapper.setCountry = function (countryCode) {
215
+ const country = options.find((opt) => opt.value === countryCode);
216
+ if (country) {
217
+ currentCountry = country;
218
+ if (countrySelector) {
219
+ const triggerInput = countrySelector.querySelector("input");
220
+ if (triggerInput) {
221
+ triggerInput.value = utils.isoToEmoji(country.value) + " " + country.indicatif;
222
+ }
223
+ }
224
+ updatePlaceholder();
225
+ }
226
+ };
227
+
228
+ wrapper.setDisabled = function (d) {
229
+ phoneInputWrapper.setDisabled(d);
230
+ if (countrySelector) {
231
+ const triggerInput = countrySelector.querySelector("input");
232
+ if (triggerInput) {
233
+ triggerInput.disabled = d;
234
+ }
235
+ }
236
+ };
237
+
238
+ return wrapper;
239
+ }
240
+
241
+ /**
242
+ * Create country selector (combobox with popover)
243
+ */
244
+ function createCountrySelector(config) {
245
+ const { variant, inputSize, disabled, options, value, getValue, className, onChange } =
246
+ config;
247
+ const getSelected = getValue && typeof getValue === "function" ? getValue : () => value;
248
+
249
+ const wrapper = document.createElement("div");
250
+ wrapper.className = "relative";
251
+
252
+ // Trigger (input with flag emoji)
253
+ const InputComponent = getComponent("InputComponent");
254
+ if (!InputComponent || typeof InputComponent.create !== "function") return wrapper;
255
+ const trigger = InputComponent.create({
256
+ variant,
257
+ inputSize,
258
+ type: "button",
259
+ value: utils.isoToEmoji(value.value) + " " + value.indicatif,
260
+ disabled,
261
+ readOnly: true,
262
+ showReadOnlyIcon: false,
263
+ className: "w-fit !gap-x-2 cursor-pointer " + (className || ""),
264
+ endIcon: SELECTOR_ICON,
265
+ });
266
+
267
+ const triggerInput = trigger.getInput();
268
+ triggerInput.style.cursor = "pointer";
269
+ triggerInput.style.caretColor = "transparent";
270
+
271
+ wrapper.appendChild(trigger);
272
+
273
+ // Create popover content (using Select component styles)
274
+ const popoverContent = document.createElement("div");
275
+ popoverContent.className = "w-[280px] max-w-full";
276
+
277
+ // Search input
278
+ const searchWrapper = document.createElement("div");
279
+ searchWrapper.className = "py-2 border-b-1/2 border-border-primary";
280
+
281
+ const searchInput = InputComponent.create({
282
+ variant: "borderless",
283
+ inputSize: "small",
284
+ type: "text",
285
+ placeholder: "Find your country...",
286
+ startIcon: SEARCH_ICON,
287
+ });
288
+
289
+ searchWrapper.appendChild(searchInput);
290
+ popoverContent.appendChild(searchWrapper);
291
+
292
+ // Options list (using Select component's option styles)
293
+ const listWrapper = document.createElement("div");
294
+ listWrapper.className =
295
+ "overflow-y-auto max-h-[200px] p-2 w-full rounded-4 bg-fill-quarternary-fill-white";
296
+
297
+ function renderOptions(filter = "") {
298
+ listWrapper.innerHTML = "";
299
+ const filtered = options.filter((opt) =>
300
+ opt.label.toLowerCase().includes(filter.toLowerCase())
301
+ );
302
+
303
+ if (filtered.length === 0) {
304
+ const empty = document.createElement("div");
305
+ empty.className =
306
+ "flex h-full min-h-[100px] w-full items-center justify-center p-4 !text-reg-13 text-typography-quaternary-text";
307
+ empty.textContent = "No country found.";
308
+ listWrapper.appendChild(empty);
309
+ return;
310
+ }
311
+
312
+ filtered.forEach((opt) => {
313
+ const selected = getSelected();
314
+ const isSelected = selected && selected.value === opt.value;
315
+
316
+ // Using Select component's option classes
317
+ const item = document.createElement("div");
318
+ item.setAttribute("role", "option");
319
+ item.setAttribute("data-value", opt.value);
320
+ item.setAttribute("aria-selected", isSelected);
321
+ item.className = [
322
+ "relative flex w-full cursor-pointer select-none items-center gap-8 rounded-2 px-12 py-6 text-reg-13 outline-none first:rounded-t-4 last:rounded-b-4",
323
+ "hover:bg-fill-tertiary-fill-light-gray focus:bg-fill-tertiary-fill-light-gray",
324
+ isSelected ? "bg-primary-surface hover:!bg-primary-surface-hover" : ""
325
+ ].filter(Boolean).join(" ");
326
+
327
+ const label = document.createElement("span");
328
+ label.className = "flex items-center gap-8 flex-1 truncate";
329
+ label.textContent = `${utils.isoToEmoji(opt.value)} ${opt.label}`;
330
+ item.appendChild(label);
331
+
332
+ if (isSelected) {
333
+ const check = document.createElement("span");
334
+ check.className = "ml-auto text-primary-base size-16";
335
+ check.innerHTML = CHECK_ICON;
336
+ item.appendChild(check);
337
+ }
338
+
339
+ item.addEventListener("click", () => {
340
+ triggerInput.value = utils.isoToEmoji(opt.value) + " " + opt.indicatif;
341
+ onChange(opt);
342
+ popover.hide();
343
+ });
344
+
345
+ listWrapper.appendChild(item);
346
+ });
347
+ }
348
+
349
+ renderOptions();
350
+ popoverContent.appendChild(listWrapper);
351
+
352
+ // Search handler
353
+ const searchInputEl = searchInput.getInput();
354
+ searchInputEl.addEventListener("input", (e) => {
355
+ renderOptions(e.target.value);
356
+ });
357
+
358
+ // Create popover
359
+ const Popover = getComponent("Popover");
360
+ if (!Popover || typeof Popover.create !== "function") return wrapper;
361
+ const popover = Popover.create({
362
+ trigger,
363
+ content: popoverContent,
364
+ placement: "bottom",
365
+ align: "start",
366
+ closeOnClickOutside: true,
367
+ bodyClassName: "p-0",
368
+ panelClassName: "w-[280px]",
369
+ onOpen: () => {
370
+ searchInputEl.value = "";
371
+ renderOptions();
372
+ // Focus search input after popover opens
373
+ setTimeout(() => searchInputEl.focus(), 100);
374
+ },
375
+ });
376
+
377
+ if (!disabled) {
378
+ trigger.addEventListener("click", (e) => {
379
+ e.preventDefault();
380
+ e.stopPropagation();
381
+ });
382
+ }
383
+
384
+ return wrapper;
385
+ }
386
+
387
+ global.PhoneInput = {
388
+ create,
389
+ };
390
+
391
+ console.log("[PhoneInput] Component loaded successfully");
392
+ })(typeof window !== "undefined" ? window : this);
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Phone Input Utilities
3
+ * Country data and helper functions for phone number formatting
4
+ */
5
+
6
+ (function (global) {
7
+ "use strict";
8
+
9
+ // Country codes with calling codes and names
10
+ const COUNTRIES_DATA = [
11
+ { code: "US", name: "United States", callingCode: "1" },
12
+ { code: "GB", name: "United Kingdom", callingCode: "44" },
13
+ { code: "CA", name: "Canada", callingCode: "1" },
14
+ { code: "AU", name: "Australia", callingCode: "61" },
15
+ { code: "IN", name: "India", callingCode: "91" },
16
+ { code: "DE", name: "Germany", callingCode: "49" },
17
+ { code: "FR", name: "France", callingCode: "33" },
18
+ { code: "IT", name: "Italy", callingCode: "39" },
19
+ { code: "ES", name: "Spain", callingCode: "34" },
20
+ { code: "BR", name: "Brazil", callingCode: "55" },
21
+ { code: "MX", name: "Mexico", callingCode: "52" },
22
+ { code: "AR", name: "Argentina", callingCode: "54" },
23
+ { code: "CN", name: "China", callingCode: "86" },
24
+ { code: "JP", name: "Japan", callingCode: "81" },
25
+ { code: "KR", name: "South Korea", callingCode: "82" },
26
+ { code: "RU", name: "Russia", callingCode: "7" },
27
+ { code: "ZA", name: "South Africa", callingCode: "27" },
28
+ { code: "NG", name: "Nigeria", callingCode: "234" },
29
+ { code: "EG", name: "Egypt", callingCode: "20" },
30
+ { code: "AE", name: "United Arab Emirates", callingCode: "971" },
31
+ { code: "SA", name: "Saudi Arabia", callingCode: "966" },
32
+ { code: "SG", name: "Singapore", callingCode: "65" },
33
+ { code: "MY", name: "Malaysia", callingCode: "60" },
34
+ { code: "TH", name: "Thailand", callingCode: "66" },
35
+ { code: "ID", name: "Indonesia", callingCode: "62" },
36
+ { code: "PH", name: "Philippines", callingCode: "63" },
37
+ { code: "VN", name: "Vietnam", callingCode: "84" },
38
+ { code: "PK", name: "Pakistan", callingCode: "92" },
39
+ { code: "BD", name: "Bangladesh", callingCode: "880" },
40
+ { code: "NZ", name: "New Zealand", callingCode: "64" },
41
+ { code: "IE", name: "Ireland", callingCode: "353" },
42
+ { code: "NL", name: "Netherlands", callingCode: "31" },
43
+ { code: "BE", name: "Belgium", callingCode: "32" },
44
+ { code: "CH", name: "Switzerland", callingCode: "41" },
45
+ { code: "AT", name: "Austria", callingCode: "43" },
46
+ { code: "SE", name: "Sweden", callingCode: "46" },
47
+ { code: "NO", name: "Norway", callingCode: "47" },
48
+ { code: "DK", name: "Denmark", callingCode: "45" },
49
+ { code: "FI", name: "Finland", callingCode: "358" },
50
+ { code: "PL", name: "Poland", callingCode: "48" },
51
+ { code: "PT", name: "Portugal", callingCode: "351" },
52
+ { code: "GR", name: "Greece", callingCode: "30" },
53
+ { code: "TR", name: "Turkey", callingCode: "90" },
54
+ { code: "IL", name: "Israel", callingCode: "972" },
55
+ { code: "CL", name: "Chile", callingCode: "56" },
56
+ { code: "CO", name: "Colombia", callingCode: "57" },
57
+ { code: "PE", name: "Peru", callingCode: "51" },
58
+ { code: "VE", name: "Venezuela", callingCode: "58" },
59
+ ];
60
+
61
+ // ISO 3166-1 alpha-2 to emoji flag
62
+ function isoToEmoji(code) {
63
+ if (!code || code.length !== 2) return "";
64
+ const codePoints = code
65
+ .toUpperCase()
66
+ .split("")
67
+ .map((char) => 127397 + char.charCodeAt(0));
68
+ return String.fromCodePoint(...codePoints);
69
+ }
70
+
71
+ // Get all countries as options for select/combobox
72
+ function getCountriesOptions() {
73
+ return COUNTRIES_DATA.map((country) => ({
74
+ value: country.code,
75
+ label: country.name,
76
+ indicatif: country.callingCode,
77
+ }));
78
+ }
79
+
80
+ // Find country by code
81
+ function getCountryByCode(code) {
82
+ return COUNTRIES_DATA.find((c) => c.code === code);
83
+ }
84
+
85
+ // Find country by calling code
86
+ function getCountryCodeFromCallingCode(callingCode) {
87
+ const normalized = callingCode.replace(/^\+/, "");
88
+ const country = COUNTRIES_DATA.find((c) => c.callingCode === normalized);
89
+ return country ? country.code : null;
90
+ }
91
+
92
+ // Replace numbers with zeros for placeholder (e.g., "+1 (555) 123-4567" -> "+1 (000) 000-0000")
93
+ function replaceNumbersWithZeros(str) {
94
+ return str.replace(/\d/g, "0");
95
+ }
96
+
97
+ // Get example phone number format for a country
98
+ function getExampleFormat(countryCode) {
99
+ const formats = {
100
+ US: "(000) 000-0000",
101
+ GB: "00000 000000",
102
+ IN: "00000 00000",
103
+ CA: "(000) 000-0000",
104
+ AU: "0000 000 000",
105
+ DE: "0000 0000000",
106
+ FR: "00 00 00 00 00",
107
+ IT: "000 000 0000",
108
+ ES: "000 00 00 00",
109
+ BR: "(00) 00000-0000",
110
+ MX: "00 0000 0000",
111
+ CN: "000 0000 0000",
112
+ JP: "00-0000-0000",
113
+ KR: "00-0000-0000",
114
+ RU: "(000) 000-00-00",
115
+ };
116
+ return formats[countryCode] || "000000000000";
117
+ }
118
+
119
+ // Parse phone number from format "callingCode-nationalNumber"
120
+ function parsePhoneNumber(value) {
121
+ if (!value) return { callingCode: "", nationalNumber: "" };
122
+ const parts = value.split("-");
123
+ if (parts.length === 2) {
124
+ return {
125
+ callingCode: parts[0].replace(/^\+/, ""),
126
+ nationalNumber: parts[1],
127
+ };
128
+ }
129
+ // Try to extract calling code from beginning
130
+ const match = value.match(/^\+?(\d{1,4})/);
131
+ if (match) {
132
+ return {
133
+ callingCode: match[1],
134
+ nationalNumber: value.substring(match[0].length),
135
+ };
136
+ }
137
+ return { callingCode: "", nationalNumber: value };
138
+ }
139
+
140
+ // Format phone number as "callingCode-nationalNumber"
141
+ function formatPhoneNumber(callingCode, nationalNumber) {
142
+ if (!nationalNumber) return callingCode || "";
143
+ return callingCode ? `${callingCode}-${nationalNumber}` : nationalNumber;
144
+ }
145
+
146
+ global.PhoneInputUtils = {
147
+ COUNTRIES_DATA,
148
+ isoToEmoji,
149
+ getCountriesOptions,
150
+ getCountryByCode,
151
+ getCountryCodeFromCallingCode,
152
+ replaceNumbersWithZeros,
153
+ getExampleFormat,
154
+ parsePhoneNumber,
155
+ formatPhoneNumber,
156
+ };
157
+ })(typeof window !== "undefined" ? window : this);