@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,282 @@
1
+ /**
2
+ * Alert Component (vanilla JS, Tailwind)
3
+ * Alert notification component with multiple variants.
4
+ * Displays contextual feedback messages with optional icons and actions.
5
+ */
6
+
7
+ (function (global) {
8
+ "use strict";
9
+
10
+ // SVG Icons
11
+ const ICONS = {
12
+ alertCircle: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>`,
13
+ circleCheck: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>`,
14
+ infoCircle: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>`,
15
+ playstationX: `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6"/><path d="m9 9 6 6"/></svg>`,
16
+ x: `<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>`,
17
+ };
18
+
19
+ // Variant to icon mapping
20
+ const VARIANT_ICONS = {
21
+ default: null,
22
+ destructive: "playstationX",
23
+ warning: "alertCircle",
24
+ error: "playstationX",
25
+ success: "circleCheck",
26
+ info: "infoCircle",
27
+ };
28
+
29
+ /**
30
+ * Get variant-specific Tailwind classes
31
+ */
32
+ function getVariantClasses(variant) {
33
+ const variants = {
34
+ default: {
35
+ container: "bg-fill-quarternary-fill-white border-borderColor-border-primary",
36
+ title: "text-typography-primary-text",
37
+ description: "text-typography-secondary-text",
38
+ },
39
+ destructive: {
40
+ container: "bg-fill-quarternary-fill-white border-error-border",
41
+ title: "text-error-text-base",
42
+ description: "text-error-text-base",
43
+ },
44
+ warning: {
45
+ container: "bg-warning-surface border-warning-border",
46
+ title: "text-warning-text-base",
47
+ description: "text-warning-text-base",
48
+ },
49
+ error: {
50
+ container: "bg-error-surface border-error-border",
51
+ title: "text-error-text-base",
52
+ description: "text-error-text-base",
53
+ },
54
+ success: {
55
+ container: "bg-success-surface border-success-border",
56
+ title: "text-success-text-base",
57
+ description: "text-success-text-base",
58
+ },
59
+ info: {
60
+ container: "bg-info-surface border-info-border",
61
+ title: "text-info-text-base",
62
+ description: "text-info-text-base",
63
+ },
64
+ };
65
+ return variants[variant] || variants.default;
66
+ }
67
+
68
+ /**
69
+ * Create an alert element
70
+ * @param {Object} config - Configuration object
71
+ * @param {string} config.title - Alert title (optional)
72
+ * @param {string} config.description - Alert description/message
73
+ * @param {string} [config.variant='default'] - 'default' | 'destructive' | 'warning' | 'error' | 'success' | 'info'
74
+ * @param {HTMLElement|string} [config.icon] - Custom icon element or HTML string (optional)
75
+ * @param {HTMLElement|string} [config.action] - Action element or HTML string (optional, e.g., close button)
76
+ * @param {string} [config.className] - Additional CSS classes
77
+ * @returns {HTMLElement} Alert element
78
+ */
79
+ function create(config = {}) {
80
+ const {
81
+ title = "",
82
+ description = "",
83
+ variant = "default",
84
+ icon = null,
85
+ action = null,
86
+ className = "",
87
+ } = config;
88
+
89
+ if (!description && !title) {
90
+ console.warn("[Alert] No title or description provided");
91
+ return null;
92
+ }
93
+
94
+ const variantClasses = getVariantClasses(variant);
95
+
96
+ // Create alert root element
97
+ const alert = document.createElement("div");
98
+ alert.setAttribute("data-slot", "alert");
99
+ alert.setAttribute("role", "alert");
100
+
101
+ // Base classes - using flex layout for better control
102
+ const baseClasses = "flex gap-8 rounded-4 border-1/2 p-8 text-left w-full";
103
+
104
+ alert.className = `${baseClasses} ${variantClasses.container} ${className}`.trim();
105
+
106
+ // Add icon if provided or if variant has default icon
107
+ const iconKey = VARIANT_ICONS[variant];
108
+ if (icon !== null || iconKey) {
109
+ const iconWrapper = document.createElement("div");
110
+ iconWrapper.className = "flex-shrink-0 flex items-start pt-2";
111
+ iconWrapper.style.cssText = "width: 16px; height: 16px;";
112
+
113
+ if (icon !== null) {
114
+ if (typeof icon === "string") {
115
+ iconWrapper.innerHTML = icon;
116
+ } else if (icon instanceof HTMLElement) {
117
+ iconWrapper.appendChild(icon);
118
+ }
119
+ } else if (iconKey) {
120
+ iconWrapper.innerHTML = ICONS[iconKey];
121
+ }
122
+
123
+ alert.appendChild(iconWrapper);
124
+ }
125
+
126
+ // Create content wrapper for title and description
127
+ const contentWrapper = document.createElement("div");
128
+ contentWrapper.className = "flex-1 flex flex-col gap-4 min-w-0";
129
+
130
+ // Create title if provided
131
+ if (title) {
132
+ const titleEl = document.createElement("div");
133
+ titleEl.setAttribute("data-slot", "alert-title");
134
+ titleEl.className = `text-med-12 ${variantClasses.title}`;
135
+
136
+ if (typeof title === "string") {
137
+ titleEl.textContent = title;
138
+ } else if (title instanceof HTMLElement) {
139
+ titleEl.appendChild(title);
140
+ }
141
+
142
+ contentWrapper.appendChild(titleEl);
143
+ }
144
+
145
+ // Create description if provided
146
+ if (description) {
147
+ const descEl = document.createElement("div");
148
+ descEl.setAttribute("data-slot", "alert-description");
149
+ descEl.className = `text-reg-12 ${variantClasses.description}`;
150
+
151
+ if (typeof description === "string") {
152
+ descEl.textContent = description;
153
+ } else if (description instanceof HTMLElement) {
154
+ descEl.appendChild(description);
155
+ }
156
+
157
+ contentWrapper.appendChild(descEl);
158
+ }
159
+
160
+ alert.appendChild(contentWrapper);
161
+
162
+ // Add action if provided
163
+ if (action !== null) {
164
+ const actionWrapper = document.createElement("div");
165
+ actionWrapper.setAttribute("data-slot", "alert-action");
166
+ actionWrapper.className = "flex-shrink-0 flex items-start pt-2";
167
+ actionWrapper.style.cssText = "margin-left: auto;";
168
+
169
+ if (typeof action === "string") {
170
+ actionWrapper.innerHTML = action;
171
+ } else if (action instanceof HTMLElement) {
172
+ actionWrapper.appendChild(action);
173
+ }
174
+
175
+ alert.appendChild(actionWrapper);
176
+ }
177
+
178
+ return alert;
179
+ }
180
+
181
+ /**
182
+ * Create a simple alert with default styling
183
+ * @param {string} message - Alert message
184
+ * @param {string} [variant='default'] - Alert variant
185
+ * @param {Object} [options] - Additional options
186
+ * @returns {HTMLElement} Alert element
187
+ */
188
+ function simple(message, variant = "default", options = {}) {
189
+ return create({
190
+ description: message,
191
+ variant: variant,
192
+ ...options,
193
+ });
194
+ }
195
+
196
+ /**
197
+ * Create a success alert
198
+ * @param {string} message - Alert message
199
+ * @param {Object} [options] - Additional options
200
+ * @returns {HTMLElement} Alert element
201
+ */
202
+ function success(message, options = {}) {
203
+ return simple(message, "success", options);
204
+ }
205
+
206
+ /**
207
+ * Create an error alert
208
+ * @param {string} message - Alert message
209
+ * @param {Object} [options] - Additional options
210
+ * @returns {HTMLElement} Alert element
211
+ */
212
+ function error(message, options = {}) {
213
+ return simple(message, "error", options);
214
+ }
215
+
216
+ /**
217
+ * Create a warning alert
218
+ * @param {string} message - Alert message
219
+ * @param {Object} [options] - Additional options
220
+ * @returns {HTMLElement} Alert element
221
+ */
222
+ function warning(message, options = {}) {
223
+ return simple(message, "warning", options);
224
+ }
225
+
226
+ /**
227
+ * Create an info alert
228
+ * @param {string} message - Alert message
229
+ * @param {Object} [options] - Additional options
230
+ * @returns {HTMLElement} Alert element
231
+ */
232
+ function info(message, options = {}) {
233
+ return simple(message, "info", options);
234
+ }
235
+
236
+ /**
237
+ * Create a destructive alert
238
+ * @param {string} message - Alert message
239
+ * @param {Object} [options] - Additional options
240
+ * @returns {HTMLElement} Alert element
241
+ */
242
+ function destructive(message, options = {}) {
243
+ return simple(message, "destructive", options);
244
+ }
245
+
246
+ /**
247
+ * Create a close button for use in alert actions
248
+ * @param {Function} onClick - Click handler
249
+ * @param {string} [variant='default'] - Alert variant to match button color
250
+ * @returns {HTMLElement} Close button element
251
+ */
252
+ function createCloseButton(onClick, variant = 'default') {
253
+ const button = document.createElement("button");
254
+ button.type = "button";
255
+
256
+ // Get the appropriate text color class based on variant
257
+ const variantClasses = getVariantClasses(variant);
258
+ const colorClass = variantClasses.title; // Use title color for consistency
259
+
260
+ button.className = `flex items-center justify-center rounded-4 transition-opacity opacity-70 hover:opacity-100 focus:opacity-100 focus:outline-none ${colorClass}`;
261
+ button.style.cssText = "flex-shrink: 0; width: 20px; height: 20px; border: none; background: transparent; cursor: pointer; padding: 2px;";
262
+ button.innerHTML = ICONS.x;
263
+
264
+ if (onClick) {
265
+ button.addEventListener("click", onClick);
266
+ }
267
+
268
+ return button;
269
+ }
270
+
271
+ // Export to global namespace
272
+ global.Alert = {
273
+ create,
274
+ simple,
275
+ success,
276
+ error,
277
+ warning,
278
+ info,
279
+ destructive,
280
+ createCloseButton,
281
+ };
282
+ })(typeof window !== "undefined" ? window : this);
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Avatar Component (vanilla JS)
3
+ * Avatar, VividAvatar (name-based color), AvatarGroup, VividAvatarGroup.
4
+ * Uses stringToColor for deterministic background/text colors from a string (e.g. user name).
5
+ */
6
+
7
+ (function (global) {
8
+ "use strict";
9
+
10
+ var AVATAR_BASE =
11
+ "flex shrink-0 overflow-hidden items-center justify-center bg-primary-base !text-typography-invert-text object-cover";
12
+
13
+ var AVATAR_SIZE = {
14
+ custom: "size-full",
15
+ large: "size-40 text-reg-14",
16
+ default: "size-32 text-reg-12",
17
+ small: "size-20 text-reg-12",
18
+ };
19
+
20
+ var AVATAR_SHAPE = {
21
+ circle: "rounded-128",
22
+ square: "rounded-4",
23
+ };
24
+
25
+ var GROUP_SPACING = {
26
+ custom: "-space-x-12",
27
+ large: "-space-x-12",
28
+ default: "-space-x-4",
29
+ small: "-space-x-8",
30
+ };
31
+
32
+ var VIVID_COLORS = [
33
+ { backgroundColor: "#f8cfcd", textColor: "#550b15" },
34
+ { backgroundColor: "#fde09b", textColor: "#5f1a05" },
35
+ { backgroundColor: "#a6eb84", textColor: "#004433" },
36
+ { backgroundColor: "#c7dcfc", textColor: "#0c2c5b" },
37
+ { backgroundColor: "#a5dbe2", textColor: "#002a2e" },
38
+ { backgroundColor: "#82ffd3", textColor: "#00916b" },
39
+ { backgroundColor: "#8eeee2", textColor: "#016f66" },
40
+ { backgroundColor: "#f8d5d8", textColor: "#5c0d21" },
41
+ { backgroundColor: "#fef7be", textColor: "#4a4410" },
42
+ { backgroundColor: "#f1d4fc", textColor: "#4c0e5f" },
43
+ { backgroundColor: "#f8d4eb", textColor: "#570e45" },
44
+ { backgroundColor: "#d9d8fc", textColor: "#2b0c7b" },
45
+ { backgroundColor: "#d8dcd2", textColor: "#233400" },
46
+ { backgroundColor: "#dbd6e1", textColor: "#371c51" },
47
+ { backgroundColor: "#bcfb94", textColor: "#213b0d" },
48
+ { backgroundColor: "#d4dcfc", textColor: "#190d8a" },
49
+ { backgroundColor: "#ffd2b1", textColor: "#4a2400" },
50
+ ];
51
+
52
+ function join() {
53
+ return Array.prototype.filter.call(arguments, Boolean).join(" ");
54
+ }
55
+
56
+ /**
57
+ * Map a string to a deterministic background and text color pair.
58
+ * @param {string} str - e.g. user name
59
+ * @returns {{ backgroundColor: string, textColor: string }}
60
+ */
61
+ function stringToColor(str) {
62
+ if (!str || typeof str !== "string") {
63
+ return { backgroundColor: "#f4f6f6", textColor: "#292929" };
64
+ }
65
+ var s = str.toLowerCase();
66
+ var hash = 0;
67
+ for (var i = 0; i < s.length; i += 1) {
68
+ hash = s.charCodeAt(i) + ((hash << 5) - hash);
69
+ }
70
+ var idx = Math.abs(hash % VIVID_COLORS.length);
71
+ return VIVID_COLORS[idx];
72
+ }
73
+
74
+ /**
75
+ * Create a single Avatar element (no vivid colors).
76
+ * @param {Object} config
77
+ * @param {string} [config.name] - Used for fallback initial (first letter)
78
+ * @param {string} [config.image] - Image URL
79
+ * @param {'small'|'default'|'large'|'custom'} [config.size]
80
+ * @param {'circle'|'square'} [config.shape]
81
+ * @param {string} [config.className]
82
+ * @returns {HTMLElement}
83
+ */
84
+ function create(config) {
85
+ var size = (config && config.size) || "default";
86
+ var shape = (config && config.shape) || "circle";
87
+ var name = (config && config.name) || "";
88
+ var image = config && config.image;
89
+ var className = (config && config.className) || "";
90
+
91
+ var root = document.createElement("div");
92
+ root.className = join(AVATAR_BASE, AVATAR_SIZE[size], AVATAR_SHAPE[shape], className);
93
+
94
+ var fallback = document.createElement("span");
95
+ fallback.className = "flex h-full w-full items-center justify-center capitalize";
96
+ fallback.textContent = name ? name.charAt(0).toUpperCase() : "?";
97
+ root.appendChild(fallback);
98
+
99
+ if (image) {
100
+ var img = document.createElement("img");
101
+ img.src = image;
102
+ img.alt = name || "Avatar";
103
+ img.className = "h-full w-full object-cover";
104
+ img.setAttribute("referrerpolicy", "no-referrer");
105
+ img.onerror = function () {
106
+ img.style.display = "none";
107
+ fallback.style.display = "flex";
108
+ };
109
+ img.onload = function () {
110
+ fallback.style.display = "none";
111
+ };
112
+ fallback.style.display = "none";
113
+ root.appendChild(img);
114
+ }
115
+
116
+ return root;
117
+ }
118
+
119
+ /**
120
+ * Create a VividAvatar: same as Avatar but background and text color come from stringToColor(name).
121
+ * @param {Object} config - Same as create(), name is used for color and fallback initial
122
+ * @returns {HTMLElement}
123
+ */
124
+ function createVivid(config) {
125
+ var name = (config && config.name) || "";
126
+ var el = create(config);
127
+ var colors = stringToColor(name);
128
+ el.style.backgroundColor = colors.backgroundColor;
129
+ var fallbackSpan = el.querySelector("span");
130
+ if (fallbackSpan) fallbackSpan.style.color = colors.textColor;
131
+ return el;
132
+ }
133
+
134
+ /**
135
+ * Create an AvatarGroup (overlapping avatars, max 3 shown + remainder count).
136
+ * @param {Object} config
137
+ * @param {{ id: number, name: string, image?: string }[]} config.users
138
+ * @param {'small'|'default'|'large'|'custom'} [config.size]
139
+ * @param {string} [config.className]
140
+ * @returns {HTMLElement}
141
+ */
142
+ function createGroup(config) {
143
+ var users = (config && config.users) || [];
144
+ var size = (config && config.size) || "default";
145
+ var className = (config && config.className) || "";
146
+ var vivid = !!(config && config.vivid);
147
+
148
+ var wrap = document.createElement("div");
149
+ wrap.className = join("flex", GROUP_SPACING[size], className);
150
+
151
+ var displayUsers = users.slice(0, 3);
152
+ var remaining = users.length - 3;
153
+
154
+ displayUsers.forEach(function (user) {
155
+ var avatar = vivid
156
+ ? createVivid({ name: user.name, image: user.image, size: size, shape: "circle" })
157
+ : create({ name: user.name, image: user.image, size: size, shape: "circle" });
158
+ wrap.appendChild(avatar);
159
+ });
160
+
161
+ if (remaining > 0) {
162
+ var extra = create({
163
+ name: "",
164
+ size: size,
165
+ shape: "circle",
166
+ });
167
+ var fallback = extra.querySelector("span");
168
+ if (fallback) {
169
+ fallback.textContent = "+" + remaining;
170
+ }
171
+ wrap.appendChild(extra);
172
+ }
173
+
174
+ return wrap;
175
+ }
176
+
177
+ /**
178
+ * Create a VividAvatarGroup (each avatar uses name-based color).
179
+ * @param {Object} config - Same as createGroup()
180
+ * @returns {HTMLElement}
181
+ */
182
+ function createVividGroup(config) {
183
+ return createGroup(Object.assign({}, config, { vivid: true }));
184
+ }
185
+
186
+ global.Avatar = {
187
+ stringToColor: stringToColor,
188
+ create: create,
189
+ createVivid: createVivid,
190
+ createGroup: createGroup,
191
+ createVividGroup: createVividGroup,
192
+ };
193
+
194
+ console.log("[Avatar] Module loaded successfully");
195
+ })(typeof window !== "undefined" ? window : this);
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Badge Component (vanilla JS)
3
+ * Mirrors React Badge with cva-style variants: variant, color, size, startIcon, endIcon, icon.
4
+ * Use border-border-primary (flow convention) instead of border-borderColor-border-primary.
5
+ */
6
+
7
+ (function (global) {
8
+ "use strict";
9
+
10
+ var BADGE_BASE =
11
+ "inline-flex items-center gap-4 rounded-4 border-1/2 !text-med-12 transition-colors focus:outline-none";
12
+
13
+ var BADGE_COLOR = {
14
+ default: "bg-fill-tertiary-fill-light-gray text-typography-primary-text hover:text-typography-secondary-text border-border-primary ",
15
+ info: "text-info-text-base bg-info-surface-hover border-info-border-base",
16
+ warning: "text-warning-text-base bg-warning-surface-hover border-warning-border-base",
17
+ error: "text-error-text-base bg-error-surface-hover border-error-border-base",
18
+ success: "text-success-text-base bg-success-surface-hover border-success-border-base",
19
+ };
20
+
21
+ var BADGE_SIZE = {
22
+ small: "px-8 py-2",
23
+ medium: "px-8 py-6",
24
+ large: "px-8 py-6",
25
+ };
26
+
27
+ var ICON_BADGE_BASE =
28
+ "flex items-center justify-center p-4 text-typography-primary-text bg-fill-default-fill-gray rounded-4 border-1/2 border-border-primary !text-med-12 transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2";
29
+
30
+ var ICON_BADGE_VARIANT = {
31
+ default: "bg-fill-default-fill-gray",
32
+ primary: "border-none",
33
+ };
34
+
35
+ var ICON_BADGE_COLOR = {
36
+ default: "bg-fill-default-fill-gray",
37
+ info: "text-info-text-base bg-info-surface-hover border-info-surface-hover",
38
+ warning: "text-warning-text-base bg-warning-surface-hover border-warning-surface-hover",
39
+ error: "text-error-text-base bg-error-surface-hover border-error-surface-hover",
40
+ success: "text-success-text-base bg-success-surface-hover border-success-surface-hover",
41
+ };
42
+
43
+ var ICON_WRAPPER_CLASS = "flex size-16 items-center justify-center";
44
+
45
+ function join() {
46
+ return Array.prototype.filter.call(arguments, Boolean).join(" ");
47
+ }
48
+
49
+ /**
50
+ * Create a Badge element
51
+ * @param {Object} config
52
+ * @param {'default'|'primary'} [config.variant]
53
+ * @param {'default'|'info'|'warning'|'error'|'success'} [config.color]
54
+ * @param {'small'|'medium'|'large'} [config.size] - default 'large' (React default)
55
+ * @param {string|HTMLElement} [config.startIcon] - HTML string or element before content
56
+ * @param {string|HTMLElement} [config.endIcon] - HTML string or element after content
57
+ * @param {string|HTMLElement} [config.icon] - if set, render icon-only badge (iconBadgeVariants)
58
+ * @param {string|HTMLElement} [config.content] - main content (text or node); use for non–icon-only badges
59
+ * @param {string} [config.className]
60
+ * @returns {HTMLElement}
61
+ */
62
+ function create(config) {
63
+ var variant = config.variant || "default";
64
+ var color = config.color || "default";
65
+ var size = config.size || "large";
66
+ var className = config.className || "";
67
+
68
+ if (config.icon) {
69
+ var iconBadge = document.createElement("div");
70
+ iconBadge.className = join(
71
+ ICON_BADGE_BASE,
72
+ ICON_BADGE_VARIANT[variant] || ICON_BADGE_VARIANT.default,
73
+ ICON_BADGE_COLOR[color] || ICON_BADGE_COLOR.default,
74
+ className
75
+ );
76
+ var iconContent = config.icon;
77
+ if (typeof iconContent === "string") {
78
+ iconBadge.innerHTML = iconContent;
79
+ } else if (iconContent && iconContent.nodeType === 1) {
80
+ iconBadge.appendChild(iconContent);
81
+ }
82
+ return iconBadge;
83
+ }
84
+
85
+ var badge = document.createElement("div");
86
+ badge.className = join(
87
+ BADGE_BASE,
88
+ BADGE_COLOR[color] || BADGE_COLOR.default,
89
+ BADGE_SIZE[size] || BADGE_SIZE.large,
90
+ className
91
+ );
92
+
93
+ if (config.startIcon) {
94
+ var startWrap = document.createElement("span");
95
+ startWrap.className = ICON_WRAPPER_CLASS;
96
+ if (typeof config.startIcon === "string") {
97
+ startWrap.innerHTML = config.startIcon;
98
+ } else if (config.startIcon && config.startIcon.nodeType === 1) {
99
+ startWrap.appendChild(config.startIcon);
100
+ }
101
+ badge.appendChild(startWrap);
102
+ }
103
+
104
+ if (config.content !== undefined && config.content !== null) {
105
+ var content = config.content;
106
+ if (typeof content === "string") {
107
+ badge.appendChild(document.createTextNode(content));
108
+ } else if (content && content.nodeType === 1) {
109
+ badge.appendChild(content);
110
+ }
111
+ }
112
+
113
+ if (config.endIcon) {
114
+ var endWrap = document.createElement("span");
115
+ endWrap.className =
116
+ typeof config.endIcon === "string"
117
+ ? ICON_WRAPPER_CLASS
118
+ : "flex items-center justify-center shrink-0";
119
+ if (typeof config.endIcon === "string") {
120
+ endWrap.innerHTML = config.endIcon;
121
+ } else if (config.endIcon && config.endIcon.nodeType === 1) {
122
+ endWrap.appendChild(config.endIcon);
123
+ }
124
+ badge.appendChild(endWrap);
125
+ }
126
+
127
+ return badge;
128
+ }
129
+
130
+ global.Badge = {
131
+ create: create,
132
+ };
133
+
134
+ console.log("[Badge] Module loaded successfully");
135
+ })(typeof window !== "undefined" ? window : this);