@superleapai/flow-ui 2.5.0 → 2.5.1
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/components/checkbox-group.js +209 -0
- package/components/file-input.js +26 -12
- package/core/flow.js +35 -76
- package/core/superleapClient.js +12 -0
- package/dist/output.css +1 -1
- package/dist/superleap-flow.js +681 -383
- package/dist/superleap-flow.js.map +1 -1
- package/dist/superleap-flow.min.js +2 -2
- package/index.d.ts +2 -0
- package/index.js +5 -1
- package/package.json +1 -1
- package/components/card-select.js +0 -283
package/index.d.ts
CHANGED
|
@@ -84,6 +84,8 @@ declare module "@superleapai/flow-ui" {
|
|
|
84
84
|
getSdk(): any;
|
|
85
85
|
isAvailable(): boolean;
|
|
86
86
|
getDefaultConfig(): SuperLeapConfig;
|
|
87
|
+
/** Current base URL from merged config (null if not initialized). Used by file-input and other components. */
|
|
88
|
+
getBaseUrl(): string | null;
|
|
87
89
|
|
|
88
90
|
// Bridge Methods (from crm.js)
|
|
89
91
|
|
package/index.js
CHANGED
|
@@ -88,6 +88,7 @@
|
|
|
88
88
|
require("./components/phone-input/phone-utils.js");
|
|
89
89
|
require("./components/phone-input/phone-input.js");
|
|
90
90
|
require("./components/checkbox.js");
|
|
91
|
+
require("./components/checkbox-group.js");
|
|
91
92
|
require("./components/radio-group.js");
|
|
92
93
|
require("./components/table.js");
|
|
93
94
|
require("./components/tabs.js");
|
|
@@ -102,6 +103,7 @@
|
|
|
102
103
|
getSdk: global.superleapClient.getSdk,
|
|
103
104
|
isAvailable: global.superleapClient.isAvailable,
|
|
104
105
|
getDefaultConfig: global.superleapClient.getDefaultConfig,
|
|
106
|
+
getBaseUrl: global.superleapClient.getBaseUrl,
|
|
105
107
|
}
|
|
106
108
|
: null;
|
|
107
109
|
|
|
@@ -117,6 +119,7 @@
|
|
|
117
119
|
getSdk: window.superleapClient.getSdk,
|
|
118
120
|
isAvailable: window.superleapClient.isAvailable,
|
|
119
121
|
getDefaultConfig: window.superleapClient.getDefaultConfig,
|
|
122
|
+
getBaseUrl: window.superleapClient.getBaseUrl,
|
|
120
123
|
}
|
|
121
124
|
: null;
|
|
122
125
|
|
|
@@ -164,8 +167,8 @@
|
|
|
164
167
|
"FileInput",
|
|
165
168
|
"PhoneInput",
|
|
166
169
|
"Checkbox",
|
|
170
|
+
"CheckboxGroup",
|
|
167
171
|
"RadioGroup",
|
|
168
|
-
"CardSelect",
|
|
169
172
|
"SuperleapTable",
|
|
170
173
|
"Tabs",
|
|
171
174
|
"Steps",
|
|
@@ -198,6 +201,7 @@
|
|
|
198
201
|
getSdk: client.getSdk.bind(client),
|
|
199
202
|
isAvailable: client.isAvailable.bind(client),
|
|
200
203
|
getDefaultConfig: client.getDefaultConfig.bind(client),
|
|
204
|
+
getBaseUrl: client.getBaseUrl.bind(client),
|
|
201
205
|
// Bridge methods (from crm.js)
|
|
202
206
|
connect: client.connect ? client.connect.bind(client) : undefined,
|
|
203
207
|
isConnected: client.isConnected
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superleapai/flow-ui",
|
|
3
|
-
"version": "2.5.
|
|
3
|
+
"version": "2.5.1",
|
|
4
4
|
"description": "A reusable design system for building multi-step forms with comprehensive UI components. Single file, clean globals, SDK included. Only FlowUI and SuperLeap exposed.",
|
|
5
5
|
"main": "dist/superleap-flow.min.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CardSelect Component (vanilla JS)
|
|
3
|
-
* Full-width clickable card selection with icon, title, description, and check indicator.
|
|
4
|
-
* Drop-in replacement / upgrade to RadioGroup when visual card UI is preferred.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
(function (global) {
|
|
8
|
-
"use strict";
|
|
9
|
-
|
|
10
|
-
var COLORS = {
|
|
11
|
-
selectedBorder: "#175259",
|
|
12
|
-
unselectedBorder: "#e5e7eb",
|
|
13
|
-
selectedBg: "#f0f9f8",
|
|
14
|
-
unselectedBg: "#ffffff",
|
|
15
|
-
selectedShadow: "0px 0px 0px 2px #e9f7f5",
|
|
16
|
-
unselectedShadow: "0px 1.5px 4px -1px rgba(10,9,11,0.07)",
|
|
17
|
-
hoverBorder: "#9ca3af",
|
|
18
|
-
hoverShadow: "0px 5px 13px -5px rgba(10,9,11,0.05), 0px 2px 4px -1px rgba(10,9,11,0.02)",
|
|
19
|
-
iconSelectedBg: "#d0ede9",
|
|
20
|
-
iconUnselectedBg: "#f3f4f6",
|
|
21
|
-
iconSelectedColor: "#175259",
|
|
22
|
-
iconUnselectedColor: "#6b7280",
|
|
23
|
-
titleSelected: "#175259",
|
|
24
|
-
titleUnselected: "#111827",
|
|
25
|
-
descSelected: "#35b18b",
|
|
26
|
-
descUnselected: "#6b7280",
|
|
27
|
-
checkBorderSelected: "#175259",
|
|
28
|
-
checkBorderUnselected: "#d1d5db",
|
|
29
|
-
checkBgSelected: "#175259",
|
|
30
|
-
checkBgUnselected: "transparent",
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
var CHECK_ICON =
|
|
34
|
-
'<svg width="10" height="10" viewBox="0 0 10 10" fill="none"><path d="M2 5l2.5 2.5L8 3" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>';
|
|
35
|
-
|
|
36
|
-
function join() {
|
|
37
|
-
return Array.prototype.filter.call(arguments, Boolean).join(" ");
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function applyCardStyles(card, isSelected) {
|
|
41
|
-
card.style.borderColor = isSelected ? COLORS.selectedBorder : COLORS.unselectedBorder;
|
|
42
|
-
card.style.background = isSelected ? COLORS.selectedBg : COLORS.unselectedBg;
|
|
43
|
-
card.style.boxShadow = isSelected ? COLORS.selectedShadow : COLORS.unselectedShadow;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function applyIconStyles(iconWrapper, isSelected) {
|
|
47
|
-
iconWrapper.style.background = isSelected ? COLORS.iconSelectedBg : COLORS.iconUnselectedBg;
|
|
48
|
-
iconWrapper.style.color = isSelected ? COLORS.iconSelectedColor : COLORS.iconUnselectedColor;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function applyTitleStyles(titleEl, isSelected) {
|
|
52
|
-
titleEl.style.color = isSelected ? COLORS.titleSelected : COLORS.titleUnselected;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function applyDescStyles(descEl, isSelected) {
|
|
56
|
-
descEl.style.color = isSelected ? COLORS.descSelected : COLORS.descUnselected;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function applyCheckStyles(checkEl, isSelected) {
|
|
60
|
-
checkEl.style.borderColor = isSelected ? COLORS.checkBorderSelected : COLORS.checkBorderUnselected;
|
|
61
|
-
checkEl.style.background = isSelected ? COLORS.checkBgSelected : COLORS.checkBgUnselected;
|
|
62
|
-
checkEl.innerHTML = isSelected ? CHECK_ICON : "";
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Create a card select component
|
|
67
|
-
* @param {Object} config
|
|
68
|
-
* @param {string} [config.name] - name attribute for the group (used for id generation)
|
|
69
|
-
* @param {Array} config.options - array of { value, label, description?, icon?, disabled? }
|
|
70
|
-
* @param {string} [config.defaultValue] - initial selected value
|
|
71
|
-
* @param {string} [config.value] - controlled value (takes priority over defaultValue)
|
|
72
|
-
* @param {boolean} [config.disabled] - disable all cards
|
|
73
|
-
* @param {string} [config.className] - extra class on wrapper
|
|
74
|
-
* @param {Function} [config.onChange] - change handler (receives selected value)
|
|
75
|
-
* @returns {HTMLElement} wrapper element with getValue/setValue/setDisabled API
|
|
76
|
-
*/
|
|
77
|
-
function create(config) {
|
|
78
|
-
var opts = config || {};
|
|
79
|
-
var name = opts.name || "card-select-" + Math.random().toString(36).substr(2, 9);
|
|
80
|
-
var options = opts.options || [];
|
|
81
|
-
var defaultValue = opts.defaultValue;
|
|
82
|
-
var selectedValue = opts.value !== undefined ? opts.value : defaultValue;
|
|
83
|
-
var disabled = !!opts.disabled;
|
|
84
|
-
var className = opts.className || "";
|
|
85
|
-
var onChange = opts.onChange;
|
|
86
|
-
|
|
87
|
-
// Wrapper container
|
|
88
|
-
var wrapper = document.createElement("div");
|
|
89
|
-
wrapper.setAttribute("role", "radiogroup");
|
|
90
|
-
wrapper.setAttribute("dir", "ltr");
|
|
91
|
-
wrapper.className = join("flex flex-col gap-3 w-full", className);
|
|
92
|
-
|
|
93
|
-
function updateAllCards(newValue) {
|
|
94
|
-
var cards = wrapper.querySelectorAll("[data-card-value]");
|
|
95
|
-
cards.forEach(function (card) {
|
|
96
|
-
var cv = card.dataset.cardValue;
|
|
97
|
-
var active = cv === newValue;
|
|
98
|
-
applyCardStyles(card, active);
|
|
99
|
-
card.setAttribute("aria-checked", active ? "true" : "false");
|
|
100
|
-
var iw = card.querySelector("[data-icon]");
|
|
101
|
-
var titleEl = card.querySelector("[data-title]");
|
|
102
|
-
var descEl = card.querySelector("[data-desc]");
|
|
103
|
-
var checkEl = card.querySelector("[data-check]");
|
|
104
|
-
if (iw) applyIconStyles(iw, active);
|
|
105
|
-
if (titleEl) applyTitleStyles(titleEl, active);
|
|
106
|
-
if (descEl) applyDescStyles(descEl, active);
|
|
107
|
-
if (checkEl) applyCheckStyles(checkEl, active);
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
options.forEach(function (option, index) {
|
|
112
|
-
var optionValue = option.value;
|
|
113
|
-
var optionLabel = option.label || option.value;
|
|
114
|
-
var optionDesc = option.description || "";
|
|
115
|
-
var optionIcon = option.icon || "";
|
|
116
|
-
var optionDisabled = disabled || !!option.disabled;
|
|
117
|
-
var isSelected = optionValue === selectedValue;
|
|
118
|
-
|
|
119
|
-
// Card element
|
|
120
|
-
var card = document.createElement("div");
|
|
121
|
-
card.dataset.cardValue = optionValue;
|
|
122
|
-
card.id = name + "-card-" + index;
|
|
123
|
-
card.setAttribute("role", "radio");
|
|
124
|
-
card.setAttribute("aria-checked", isSelected ? "true" : "false");
|
|
125
|
-
card.setAttribute("tabindex", optionDisabled ? "-1" : "0");
|
|
126
|
-
|
|
127
|
-
card.style.cssText = [
|
|
128
|
-
"display: flex",
|
|
129
|
-
"align-items: flex-start",
|
|
130
|
-
"gap: 16px",
|
|
131
|
-
"padding: 18px 20px",
|
|
132
|
-
"border-radius: 10px",
|
|
133
|
-
"border: 1.5px solid " + (isSelected ? COLORS.selectedBorder : COLORS.unselectedBorder),
|
|
134
|
-
"background: " + (isSelected ? COLORS.selectedBg : COLORS.unselectedBg),
|
|
135
|
-
"cursor: " + (optionDisabled ? "not-allowed" : "pointer"),
|
|
136
|
-
"transition: border-color 0.15s, background 0.15s, box-shadow 0.15s",
|
|
137
|
-
"box-shadow: " + (isSelected ? COLORS.selectedShadow : COLORS.unselectedShadow),
|
|
138
|
-
"user-select: none",
|
|
139
|
-
optionDisabled ? "opacity: 0.5" : "",
|
|
140
|
-
].filter(Boolean).join("; ");
|
|
141
|
-
|
|
142
|
-
// Icon wrapper (only rendered when icon is provided)
|
|
143
|
-
if (optionIcon) {
|
|
144
|
-
var iconWrapper = document.createElement("div");
|
|
145
|
-
iconWrapper.dataset.icon = "";
|
|
146
|
-
iconWrapper.style.cssText = [
|
|
147
|
-
"flex-shrink: 0",
|
|
148
|
-
"width: 44px",
|
|
149
|
-
"height: 44px",
|
|
150
|
-
"border-radius: 8px",
|
|
151
|
-
"background: " + (isSelected ? COLORS.iconSelectedBg : COLORS.iconUnselectedBg),
|
|
152
|
-
"display: flex",
|
|
153
|
-
"align-items: center",
|
|
154
|
-
"justify-content: center",
|
|
155
|
-
"color: " + (isSelected ? COLORS.iconSelectedColor : COLORS.iconUnselectedColor),
|
|
156
|
-
"transition: background 0.15s, color 0.15s",
|
|
157
|
-
].join("; ");
|
|
158
|
-
iconWrapper.innerHTML = optionIcon;
|
|
159
|
-
card.appendChild(iconWrapper);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Text wrapper
|
|
163
|
-
var textWrapper = document.createElement("div");
|
|
164
|
-
textWrapper.style.cssText = "display: flex; flex-direction: column; gap: 4px; flex: 1;";
|
|
165
|
-
|
|
166
|
-
var titleEl = document.createElement("span");
|
|
167
|
-
titleEl.dataset.title = "";
|
|
168
|
-
titleEl.textContent = optionLabel;
|
|
169
|
-
titleEl.style.cssText = [
|
|
170
|
-
"font-size: 14px",
|
|
171
|
-
"font-weight: 600",
|
|
172
|
-
"color: " + (isSelected ? COLORS.titleSelected : COLORS.titleUnselected),
|
|
173
|
-
"line-height: 1.4",
|
|
174
|
-
"transition: color 0.15s",
|
|
175
|
-
].join("; ");
|
|
176
|
-
textWrapper.appendChild(titleEl);
|
|
177
|
-
|
|
178
|
-
if (optionDesc) {
|
|
179
|
-
var descEl = document.createElement("span");
|
|
180
|
-
descEl.dataset.desc = "";
|
|
181
|
-
descEl.textContent = optionDesc;
|
|
182
|
-
descEl.style.cssText = [
|
|
183
|
-
"font-size: 12px",
|
|
184
|
-
"color: " + (isSelected ? COLORS.descSelected : COLORS.descUnselected),
|
|
185
|
-
"line-height: 1.5",
|
|
186
|
-
"transition: color 0.15s",
|
|
187
|
-
].join("; ");
|
|
188
|
-
textWrapper.appendChild(descEl);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
card.appendChild(textWrapper);
|
|
192
|
-
|
|
193
|
-
// Check indicator (radio circle in top-right)
|
|
194
|
-
var checkEl = document.createElement("div");
|
|
195
|
-
checkEl.dataset.check = "";
|
|
196
|
-
checkEl.style.cssText = [
|
|
197
|
-
"flex-shrink: 0",
|
|
198
|
-
"width: 18px",
|
|
199
|
-
"height: 18px",
|
|
200
|
-
"border-radius: 50%",
|
|
201
|
-
"border: 2px solid " + (isSelected ? COLORS.checkBorderSelected : COLORS.checkBorderUnselected),
|
|
202
|
-
"background: " + (isSelected ? COLORS.checkBgSelected : COLORS.checkBgUnselected),
|
|
203
|
-
"display: flex",
|
|
204
|
-
"align-items: center",
|
|
205
|
-
"justify-content: center",
|
|
206
|
-
"margin-top: 2px",
|
|
207
|
-
"transition: all 0.15s",
|
|
208
|
-
].join("; ");
|
|
209
|
-
if (isSelected) {
|
|
210
|
-
checkEl.innerHTML = CHECK_ICON;
|
|
211
|
-
}
|
|
212
|
-
card.appendChild(checkEl);
|
|
213
|
-
|
|
214
|
-
// Hover and focus styles
|
|
215
|
-
if (!optionDisabled) {
|
|
216
|
-
card.addEventListener("mouseenter", function () {
|
|
217
|
-
if (card.getAttribute("aria-checked") !== "true") {
|
|
218
|
-
card.style.borderColor = COLORS.hoverBorder;
|
|
219
|
-
card.style.boxShadow = COLORS.hoverShadow;
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
card.addEventListener("mouseleave", function () {
|
|
223
|
-
if (card.getAttribute("aria-checked") !== "true") {
|
|
224
|
-
card.style.borderColor = COLORS.unselectedBorder;
|
|
225
|
-
card.style.boxShadow = COLORS.unselectedShadow;
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
// Click handler
|
|
230
|
-
card.addEventListener("click", function () {
|
|
231
|
-
if (optionDisabled || disabled) return;
|
|
232
|
-
selectedValue = optionValue;
|
|
233
|
-
updateAllCards(selectedValue);
|
|
234
|
-
if (typeof onChange === "function") {
|
|
235
|
-
onChange(selectedValue);
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
// Keyboard support
|
|
240
|
-
card.addEventListener("keydown", function (e) {
|
|
241
|
-
if (optionDisabled || disabled) return;
|
|
242
|
-
if (e.key === " " || e.key === "Enter") {
|
|
243
|
-
e.preventDefault();
|
|
244
|
-
card.click();
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
wrapper.appendChild(card);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
// Public API
|
|
253
|
-
wrapper.getValue = function () {
|
|
254
|
-
return selectedValue !== undefined ? selectedValue : null;
|
|
255
|
-
};
|
|
256
|
-
|
|
257
|
-
wrapper.setValue = function (newValue) {
|
|
258
|
-
selectedValue = newValue;
|
|
259
|
-
updateAllCards(newValue);
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
wrapper.setDisabled = function (isDisabled) {
|
|
263
|
-
disabled = !!isDisabled;
|
|
264
|
-
wrapper.querySelectorAll("[data-card-value]").forEach(function (card) {
|
|
265
|
-
card.style.cursor = disabled ? "not-allowed" : "pointer";
|
|
266
|
-
card.style.opacity = disabled ? "0.5" : "1";
|
|
267
|
-
card.setAttribute("tabindex", disabled ? "-1" : "0");
|
|
268
|
-
});
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
return wrapper;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
var CardSelect = {
|
|
275
|
-
create: create,
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
if (typeof module !== "undefined" && module.exports) {
|
|
279
|
-
module.exports = CardSelect;
|
|
280
|
-
} else {
|
|
281
|
-
global.CardSelect = CardSelect;
|
|
282
|
-
}
|
|
283
|
-
})(typeof window !== "undefined" ? window : this);
|