smartsell-ui-kit 0.0.4 → 0.0.6

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/dist/index.cjs CHANGED
@@ -23,7 +23,6 @@ __export(index_exports, {
23
23
  Button: () => Button,
24
24
  Card: () => Card,
25
25
  ComposableModal: () => ComposableModal,
26
- Field: () => Field,
27
26
  Input: () => Input,
28
27
  Modal: () => Modal,
29
28
  Select: () => Select,
@@ -34,8 +33,66 @@ __export(index_exports, {
34
33
  module.exports = __toCommonJS(index_exports);
35
34
 
36
35
  // src/components/Button.tsx
36
+ var import_react2 = require("react");
37
37
  var import_smartsell_sales_sdk2 = require("smartsell-sales-sdk");
38
38
 
39
+ // src/components/controlSize.ts
40
+ var CONTROL_METRICS_BY_SIZE = {
41
+ sm: {
42
+ height: 30,
43
+ fontSize: 13,
44
+ lineHeight: "16px",
45
+ paddingX: 12,
46
+ paddingY: 6,
47
+ buttonPaddingX: 14,
48
+ selectPaddingRight: 40,
49
+ selectIndicatorOffset: 12
50
+ },
51
+ md: {
52
+ height: 38,
53
+ fontSize: 14,
54
+ lineHeight: "18px",
55
+ paddingX: 16,
56
+ paddingY: 9,
57
+ buttonPaddingX: 18,
58
+ selectPaddingRight: 44,
59
+ selectIndicatorOffset: 16
60
+ },
61
+ lg: {
62
+ height: 46,
63
+ fontSize: 15,
64
+ lineHeight: "18px",
65
+ paddingX: 18,
66
+ paddingY: 13,
67
+ buttonPaddingX: 20,
68
+ selectPaddingRight: 48,
69
+ selectIndicatorOffset: 18
70
+ }
71
+ };
72
+ var getControlMetrics = (size) => CONTROL_METRICS_BY_SIZE[size];
73
+ var getTextInputPadding = (size, options = {}) => {
74
+ var _a, _b;
75
+ const metrics = getControlMetrics(size);
76
+ const leadingInset = (_a = options.leadingInset) != null ? _a : 0;
77
+ const trailingInset = (_b = options.trailingInset) != null ? _b : 0;
78
+ return `${metrics.paddingY}px ${metrics.paddingX + trailingInset}px ${metrics.paddingY}px ${metrics.paddingX + leadingInset}px`;
79
+ };
80
+ var getSelectControlPadding = (size) => {
81
+ const metrics = getControlMetrics(size);
82
+ return `${metrics.paddingY}px ${metrics.selectPaddingRight}px ${metrics.paddingY}px ${metrics.paddingX}px`;
83
+ };
84
+ var getSelectIndicatorOffset = (size) => getControlMetrics(size).selectIndicatorOffset;
85
+ var getButtonSizeStyles = (size) => {
86
+ const metrics = getControlMetrics(size);
87
+ return {
88
+ boxSizing: "border-box",
89
+ height: metrics.height,
90
+ padding: `0 ${metrics.buttonPaddingX}px`,
91
+ fontSize: metrics.fontSize,
92
+ lineHeight: metrics.lineHeight
93
+ };
94
+ };
95
+
39
96
  // src/theme.ts
40
97
  var import_react = require("react");
41
98
  var import_smartsell_sales_sdk = require("smartsell-sales-sdk");
@@ -57,19 +114,9 @@ function useUiKitTheme(sdk) {
57
114
 
58
115
  // src/components/Button.tsx
59
116
  var import_jsx_runtime = require("react/jsx-runtime");
60
- var getSizeStyles = (size) => {
61
- if (size === "sm") {
62
- return { minHeight: 38, padding: "0 14px", fontSize: 13 };
63
- }
64
- if (size === "lg") {
65
- return { minHeight: 50, padding: "0 20px", fontSize: 15 };
66
- }
67
- return { minHeight: 44, padding: "0 18px", fontSize: 14 };
68
- };
69
117
  function Button({
70
118
  sdk,
71
119
  variant = "solid",
72
- tone = "primary",
73
120
  size = "md",
74
121
  fullWidth = false,
75
122
  leadingIcon,
@@ -78,46 +125,55 @@ function Button({
78
125
  disabled,
79
126
  style,
80
127
  type = "button",
128
+ onMouseEnter,
129
+ onMouseLeave,
130
+ onMouseDown,
131
+ onMouseUp,
132
+ onBlur,
133
+ onKeyDown,
134
+ onKeyUp,
135
+ onTouchStart,
136
+ onTouchEnd,
137
+ onTouchCancel,
81
138
  ...rest
82
139
  }) {
83
140
  const { theme } = useUiKitTheme(sdk);
84
- const palette = {
85
- primary: {
86
- background: theme.colors.primary,
87
- foreground: theme.colors.onPrimary,
88
- border: (0, import_smartsell_sales_sdk2.withAlpha)(theme.colors.primary, 0.3)
89
- },
90
- secondary: {
91
- background: theme.colors.secondary,
92
- foreground: theme.colors.onSecondary,
93
- border: (0, import_smartsell_sales_sdk2.withAlpha)(theme.colors.secondary, 0.3)
94
- },
95
- neutral: {
96
- background: theme.colors.surface,
97
- foreground: theme.colors.onSurface,
98
- border: (0, import_smartsell_sales_sdk2.withAlpha)(theme.colors.onSurface, 0.16)
99
- },
100
- danger: {
101
- background: theme.colors.negative,
102
- foreground: "#ffffff",
103
- border: (0, import_smartsell_sales_sdk2.withAlpha)(theme.colors.negative, 0.32)
104
- }
105
- }[tone];
141
+ const [isHovered, setIsHovered] = (0, import_react2.useState)(false);
142
+ const [isPressed, setIsPressed] = (0, import_react2.useState)(false);
106
143
  const variantStyles = {
107
144
  solid: {
108
- backgroundColor: palette.background,
109
- borderColor: palette.border,
110
- color: palette.foreground
145
+ backgroundColor: theme.colors.primary,
146
+ borderColor: (0, import_smartsell_sales_sdk2.withAlpha)(theme.colors.primary, 0.5),
147
+ color: theme.colors.onPrimary
111
148
  },
112
149
  outline: {
113
150
  backgroundColor: "transparent",
114
- borderColor: palette.border,
115
- color: tone === "neutral" ? palette.foreground : palette.background
151
+ borderColor: (0, import_smartsell_sales_sdk2.withAlpha)(theme.colors.text, 0.5),
152
+ color: theme.colors.onSurface
116
153
  },
117
154
  ghost: {
118
155
  backgroundColor: "transparent",
119
156
  borderColor: "transparent",
120
- color: tone === "neutral" ? palette.foreground : palette.background
157
+ color: theme.colors.onSurface
158
+ }
159
+ };
160
+ const interactiveColor = variant === "solid" ? theme.colors.primary : theme.colors.onSurface;
161
+ const isInteractive = !disabled;
162
+ const interactionStyles = {
163
+ solid: {
164
+ transform: isPressed ? "translateY(1px) scale(0.985)" : isHovered ? "translateY(-1px)" : "translateY(0)",
165
+ boxShadow: "none",
166
+ filter: void 0
167
+ },
168
+ outline: {
169
+ transform: isPressed ? "translateY(1px) scale(0.985)" : isHovered ? "translateY(-1px)" : "translateY(0)",
170
+ backgroundColor: isPressed ? (0, import_smartsell_sales_sdk2.withAlpha)(interactiveColor, 0.14) : isHovered ? (0, import_smartsell_sales_sdk2.withAlpha)(interactiveColor, 0.08) : "transparent",
171
+ boxShadow: "none"
172
+ },
173
+ ghost: {
174
+ transform: isPressed ? "translateY(1px) scale(0.985)" : isHovered ? "translateY(-1px)" : "translateY(0)",
175
+ backgroundColor: isPressed ? (0, import_smartsell_sales_sdk2.withAlpha)(interactiveColor, 0.12) : isHovered ? (0, import_smartsell_sales_sdk2.withAlpha)(interactiveColor, 0.06) : "transparent",
176
+ boxShadow: "none"
121
177
  }
122
178
  };
123
179
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
@@ -126,6 +182,56 @@ function Button({
126
182
  ...rest,
127
183
  type,
128
184
  disabled,
185
+ onMouseEnter: (event) => {
186
+ if (isInteractive) {
187
+ setIsHovered(true);
188
+ }
189
+ onMouseEnter == null ? void 0 : onMouseEnter(event);
190
+ },
191
+ onMouseLeave: (event) => {
192
+ setIsHovered(false);
193
+ setIsPressed(false);
194
+ onMouseLeave == null ? void 0 : onMouseLeave(event);
195
+ },
196
+ onMouseDown: (event) => {
197
+ if (isInteractive) {
198
+ setIsPressed(true);
199
+ }
200
+ onMouseDown == null ? void 0 : onMouseDown(event);
201
+ },
202
+ onMouseUp: (event) => {
203
+ setIsPressed(false);
204
+ onMouseUp == null ? void 0 : onMouseUp(event);
205
+ },
206
+ onBlur: (event) => {
207
+ setIsHovered(false);
208
+ setIsPressed(false);
209
+ onBlur == null ? void 0 : onBlur(event);
210
+ },
211
+ onKeyDown: (event) => {
212
+ if (isInteractive && (event.key === " " || event.key === "Enter")) {
213
+ setIsPressed(true);
214
+ }
215
+ onKeyDown == null ? void 0 : onKeyDown(event);
216
+ },
217
+ onKeyUp: (event) => {
218
+ setIsPressed(false);
219
+ onKeyUp == null ? void 0 : onKeyUp(event);
220
+ },
221
+ onTouchStart: (event) => {
222
+ if (isInteractive) {
223
+ setIsPressed(true);
224
+ }
225
+ onTouchStart == null ? void 0 : onTouchStart(event);
226
+ },
227
+ onTouchEnd: (event) => {
228
+ setIsPressed(false);
229
+ onTouchEnd == null ? void 0 : onTouchEnd(event);
230
+ },
231
+ onTouchCancel: (event) => {
232
+ setIsPressed(false);
233
+ onTouchCancel == null ? void 0 : onTouchCancel(event);
234
+ },
129
235
  style: {
130
236
  display: "inline-flex",
131
237
  alignItems: "center",
@@ -138,12 +244,11 @@ function Button({
138
244
  cursor: disabled ? "not-allowed" : "pointer",
139
245
  fontWeight: 700,
140
246
  letterSpacing: "0.01em",
141
- lineHeight: 1,
142
247
  opacity: disabled ? 0.58 : 1,
143
- transition: "transform 160ms ease, opacity 160ms ease, background-color 160ms ease",
144
- boxShadow: variant === "solid" ? `0 14px 28px ${(0, import_smartsell_sales_sdk2.withAlpha)(palette.background, 0.18)}` : "none",
145
- ...getSizeStyles(size),
248
+ transition: "transform 140ms ease, opacity 160ms ease, background-color 160ms ease",
249
+ ...getButtonSizeStyles(size),
146
250
  ...variantStyles[variant],
251
+ ...isInteractive ? interactionStyles[variant] : void 0,
147
252
  ...style
148
253
  },
149
254
  children: [
@@ -158,43 +263,26 @@ function Button({
158
263
  // src/components/Card.tsx
159
264
  var import_smartsell_sales_sdk3 = require("smartsell-sales-sdk");
160
265
  var import_jsx_runtime2 = require("react/jsx-runtime");
161
- var getToneStyles = (tone, sdk) => {
162
- const { theme } = useUiKitTheme(sdk);
163
- const accent = {
164
- default: theme.colors.primary,
165
- primary: theme.colors.primary,
166
- secondary: theme.colors.secondary,
167
- warning: theme.colors.warning
168
- }[tone];
169
- return {
170
- accent,
171
- background: `linear-gradient(160deg, ${(0, import_smartsell_sales_sdk3.withAlpha)(theme.colors.surface, 0.98)}, ${(0, import_smartsell_sales_sdk3.withAlpha)(accent, 0.08)})`,
172
- border: (0, import_smartsell_sales_sdk3.withAlpha)(accent, 0.22)
173
- };
174
- };
175
266
  function Card({
176
267
  sdk,
177
268
  children,
178
269
  eyebrow,
179
270
  title,
180
271
  action,
181
- tone = "default",
182
272
  padded = true,
183
273
  style,
184
274
  ...rest
185
275
  }) {
186
- const { theme, mutedText } = useUiKitTheme(sdk);
187
- const toneStyles = getToneStyles(tone, sdk);
276
+ const { theme } = useUiKitTheme(sdk);
188
277
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
189
278
  "div",
190
279
  {
191
280
  ...rest,
192
281
  style: {
193
282
  borderRadius: 28,
194
- border: `1px solid ${toneStyles.border}`,
195
- background: toneStyles.background,
196
- color: theme.colors.onSurface,
197
- boxShadow: `0 24px 48px ${(0, import_smartsell_sales_sdk3.withAlpha)(theme.colors.onSurface, 0.06)}`,
283
+ border: `1px solid ${(0, import_smartsell_sales_sdk3.withAlpha)(theme.colors.text, 0.5)}`,
284
+ background: `${(0, import_smartsell_sales_sdk3.withAlpha)(theme.colors.background, 0.7)}`,
285
+ color: theme.colors.text,
198
286
  padding: padded ? 24 : void 0,
199
287
  ...style
200
288
  },
@@ -215,7 +303,7 @@ function Card({
215
303
  "span",
216
304
  {
217
305
  style: {
218
- color: toneStyles.accent,
306
+ color: theme.colors.textLight,
219
307
  fontSize: 12,
220
308
  fontWeight: 800,
221
309
  letterSpacing: "0.16em",
@@ -228,7 +316,7 @@ function Card({
228
316
  "div",
229
317
  {
230
318
  style: {
231
- color: theme.colors.onSurface,
319
+ color: theme.colors.text,
232
320
  fontSize: 24,
233
321
  fontWeight: 700,
234
322
  lineHeight: 1.2
@@ -237,7 +325,7 @@ function Card({
237
325
  }
238
326
  ) : null
239
327
  ] }),
240
- action ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: mutedText }, children: action }) : null
328
+ action ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: theme.colors.text }, children: action }) : null
241
329
  ]
242
330
  }
243
331
  ),
@@ -248,11 +336,11 @@ function Card({
248
336
  }
249
337
 
250
338
  // src/components/ComposableModal.tsx
251
- var import_react3 = require("react");
339
+ var import_react4 = require("react");
252
340
  var import_smartsell_sales_sdk4 = require("smartsell-sales-sdk");
253
341
 
254
342
  // src/components/Modal.tsx
255
- var import_react2 = require("react");
343
+ var import_react3 = require("react");
256
344
  var import_jsx_runtime3 = require("react/jsx-runtime");
257
345
  var defaultThemeColors = {
258
346
  background: "#f8fafc",
@@ -308,26 +396,89 @@ var isLikelyMobileViewport = () => {
308
396
  navigator.userAgent
309
397
  );
310
398
  };
399
+ var createTitleId = (title) => {
400
+ if (typeof title === "string" || typeof title === "number") {
401
+ const normalized = String(title).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, "");
402
+ return `smartsell-modal-${normalized || "dialog"}`;
403
+ }
404
+ return "smartsell-modal-dialog";
405
+ };
311
406
  var isLegacyModalProps = (props) => {
312
407
  return "showModal" in props;
313
408
  };
314
- function LegacyActionButton({
315
- label,
316
- onClick,
317
- disabled,
318
- type = "contained",
319
- theme,
320
- style
409
+ var normalizeLegacyAction = (action, fallbackDisabled = false) => {
410
+ var _a, _b, _c;
411
+ return {
412
+ label: action.name,
413
+ onClick: action.onClick,
414
+ appearance: (_a = action.type) != null ? _a : "contained",
415
+ style: (_b = action.style) != null ? _b : { maxWidth: "150px" },
416
+ disabled: (_c = action.disable) != null ? _c : fallbackDisabled
417
+ };
418
+ };
419
+ var normalizeModalProps = (props) => {
420
+ var _a, _b;
421
+ if (!isLegacyModalProps(props)) {
422
+ return props;
423
+ }
424
+ const isBusy = Boolean(props.isLoading);
425
+ const disableAction = Boolean(props.disableActionBtn || props.isLoading);
426
+ return {
427
+ isOpen: props.showModal,
428
+ onClose: props.closeModal,
429
+ title: props.title,
430
+ children: props.children,
431
+ theme: props.theme,
432
+ maximized: props.maximized,
433
+ contentStyle: props.style,
434
+ bodyStyle: props.bodyStyle,
435
+ hideCloseButton: props.hideCloseIcon,
436
+ disableDismiss: isBusy,
437
+ closeOnBackdrop: false,
438
+ closeOnEscape: false,
439
+ isBusy,
440
+ closeAction: props.onlyCloseButton ? {
441
+ label: "Close",
442
+ onClick: props.closeModal,
443
+ appearance: "contained",
444
+ disabled: isBusy
445
+ } : void 0,
446
+ cancelAction: props.onlyCloseButton || !props.cancelButton ? void 0 : {
447
+ label: "Cancel",
448
+ onClick: props.cancelButton,
449
+ appearance: "text",
450
+ style: { maxWidth: "100px" }
451
+ },
452
+ confirmAction: props.onlyCloseButton || props.hideActionButton || !props.action ? void 0 : {
453
+ label: (_a = props.actionNameBtn) != null ? _a : "Save",
454
+ onClick: props.action,
455
+ appearance: "contained",
456
+ style: { maxWidth: "100px" },
457
+ disabled: disableAction
458
+ },
459
+ extraActions: props.onlyCloseButton ? void 0 : (_b = props.additionalActions) == null ? void 0 : _b.map((action) => normalizeLegacyAction(action, disableAction))
460
+ };
461
+ };
462
+ function ModalActionButton({
463
+ action,
464
+ theme
321
465
  }) {
322
466
  var _a, _b;
323
467
  const { colors } = theme;
468
+ const {
469
+ label,
470
+ onClick,
471
+ appearance = "contained",
472
+ disabled = false,
473
+ style
474
+ } = action;
324
475
  const buttonStyle = {
325
476
  width: "100%",
326
477
  display: "flex",
327
478
  alignItems: "center",
328
479
  justifyContent: "center",
329
480
  borderRadius: "0.4rem",
330
- padding: type === "link" ? 0 : "1.3rem",
481
+ padding: appearance === "link" ? 0 : "1.3rem",
331
482
  boxSizing: "border-box",
332
483
  cursor: disabled ? "not-allowed" : "pointer",
333
484
  fontWeight: 700,
@@ -338,17 +489,17 @@ function LegacyActionButton({
338
489
  opacity: disabled ? 0.5 : 1,
339
490
  filter: disabled ? "saturate(0)" : void 0
340
491
  };
341
- if (type === "text") {
492
+ if (appearance === "text") {
342
493
  buttonStyle.background = "none";
343
494
  buttonStyle.border = "1px solid transparent";
344
495
  buttonStyle.color = colors.primary;
345
496
  buttonStyle.boxShadow = "none";
346
- } else if (type === "link") {
497
+ } else if (appearance === "link") {
347
498
  buttonStyle.background = "none";
348
499
  buttonStyle.border = "none";
349
500
  buttonStyle.color = colors.primary;
350
501
  buttonStyle.boxShadow = "none";
351
- } else if (type === "outlined") {
502
+ } else if (appearance === "outlined") {
352
503
  buttonStyle.background = "none";
353
504
  buttonStyle.border = `2px solid ${colors.primary}`;
354
505
  buttonStyle.color = colors.primary;
@@ -384,30 +535,35 @@ function LegacyActionButton({
384
535
  }
385
536
  );
386
537
  }
387
- function StandardModal({
538
+ function UnifiedModal({
388
539
  isOpen,
389
540
  onClose,
390
541
  children,
391
- footer,
392
542
  title,
393
543
  description,
394
544
  headerContent,
545
+ footer,
546
+ confirmAction,
547
+ cancelAction,
548
+ closeAction,
549
+ extraActions,
395
550
  maxWidth,
396
551
  closeOnBackdrop = true,
397
552
  closeOnEscape = true,
398
553
  hideCloseButton = false,
399
554
  hideExpandButton = false,
555
+ disableDismiss = false,
400
556
  maximized,
401
557
  contentStyle,
558
+ bodyStyle,
559
+ isBusy = false,
402
560
  theme
403
561
  }) {
404
- const modalTheme = (0, import_react2.useMemo)(() => resolveTheme(theme), [theme]);
405
- const [isMaximized, setIsMaximized] = (0, import_react2.useState)(maximized != null ? maximized : false);
406
- const titleId = (0, import_react2.useMemo)(
407
- () => `smartsell-modal-${String(title != null ? title : "dialog").toLowerCase().replace(/[^a-z0-9]+/g, "-")}`,
408
- [title]
409
- );
410
- (0, import_react2.useEffect)(() => {
562
+ var _a, _b;
563
+ const modalTheme = (0, import_react3.useMemo)(() => resolveTheme(theme), [theme]);
564
+ const [isMaximized, setIsMaximized] = (0, import_react3.useState)(maximized != null ? maximized : false);
565
+ const titleId = (0, import_react3.useMemo)(() => createTitleId(title), [title]);
566
+ (0, import_react3.useEffect)(() => {
411
567
  if (typeof maximized === "boolean") {
412
568
  setIsMaximized(maximized);
413
569
  return;
@@ -416,14 +572,14 @@ function StandardModal({
416
572
  setIsMaximized(true);
417
573
  }
418
574
  }, [maximized]);
419
- (0, import_react2.useEffect)(() => {
575
+ (0, import_react3.useEffect)(() => {
420
576
  if (!isOpen || typeof window === "undefined" || typeof document === "undefined") {
421
577
  return;
422
578
  }
423
579
  const previousOverflow = document.body.style.overflow;
424
580
  document.body.style.overflow = "hidden";
425
581
  const handleKeyDown = (event) => {
426
- if (closeOnEscape && event.key === "Escape") {
582
+ if (!disableDismiss && closeOnEscape && event.key === "Escape") {
427
583
  onClose();
428
584
  }
429
585
  };
@@ -432,11 +588,11 @@ function StandardModal({
432
588
  document.body.style.overflow = previousOverflow;
433
589
  window.removeEventListener("keydown", handleKeyDown);
434
590
  };
435
- }, [closeOnEscape, isOpen, onClose]);
591
+ }, [closeOnEscape, disableDismiss, isOpen, onClose]);
436
592
  if (!isOpen) {
437
593
  return null;
438
594
  }
439
- const header = headerContent != null ? headerContent : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
595
+ const resolvedHeader = headerContent != null ? headerContent : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
440
596
  title ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
441
597
  "h2",
442
598
  {
@@ -464,6 +620,39 @@ function StandardModal({
464
620
  }
465
621
  ) : null
466
622
  ] });
623
+ let footerContent = footer;
624
+ if (footerContent === void 0) {
625
+ if (closeAction && !closeAction.hidden) {
626
+ footerContent = /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ModalActionButton, { action: closeAction, theme: modalTheme });
627
+ } else {
628
+ const resolvedActions = [
629
+ cancelAction ? { ...cancelAction, appearance: (_a = cancelAction.appearance) != null ? _a : "text" } : void 0,
630
+ ...(extraActions != null ? extraActions : []).map((action) => {
631
+ var _a2;
632
+ return {
633
+ ...action,
634
+ appearance: (_a2 = action.appearance) != null ? _a2 : "contained"
635
+ };
636
+ }),
637
+ confirmAction ? { ...confirmAction, appearance: (_b = confirmAction.appearance) != null ? _b : "contained" } : void 0
638
+ ].reduce((items, action) => {
639
+ if (!action || action.hidden) {
640
+ return items;
641
+ }
642
+ items.push(action);
643
+ return items;
644
+ }, []);
645
+ footerContent = resolvedActions.length > 0 ? resolvedActions.map((action, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
646
+ ModalActionButton,
647
+ {
648
+ action,
649
+ theme: modalTheme
650
+ },
651
+ `modal-action-${index}`
652
+ )) : void 0;
653
+ }
654
+ }
655
+ const shouldRenderFooter = footerContent !== void 0 && footerContent !== null && footerContent !== false;
467
656
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
468
657
  "div",
469
658
  {
@@ -472,7 +661,7 @@ function StandardModal({
472
661
  "aria-modal": "true",
473
662
  role: "dialog",
474
663
  onMouseDown: (event) => {
475
- if (closeOnBackdrop && event.target === event.currentTarget) {
664
+ if (!disableDismiss && closeOnBackdrop && event.target === event.currentTarget) {
476
665
  onClose();
477
666
  }
478
667
  },
@@ -490,6 +679,7 @@ function StandardModal({
490
679
  children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
491
680
  "div",
492
681
  {
682
+ id: isBusy ? "ldg1" : void 0,
493
683
  style: {
494
684
  position: "relative",
495
685
  display: "flex",
@@ -498,12 +688,14 @@ function StandardModal({
498
688
  maxWidth: isMaximized ? "100vw" : normalizeWidth(maxWidth),
499
689
  height: isMaximized ? "100vh" : void 0,
500
690
  maxHeight: isMaximized ? "100vh" : "calc(100vh - 32px)",
691
+ minWidth: isMaximized ? "100vw" : 300,
501
692
  borderRadius: isMaximized ? 0 : 30,
502
693
  border: `1px solid ${modalTheme.borderSoft}`,
503
694
  background: `linear-gradient(180deg, ${modalTheme.surfaceRaised}, ${modalTheme.colors.surface})`,
504
695
  boxShadow: `0 34px 80px ${withAlpha4("#020617", 0.28)}`,
505
696
  color: modalTheme.colors.onSurface,
506
697
  overflow: "hidden",
698
+ opacity: isBusy ? 0.5 : 1,
507
699
  ...contentStyle
508
700
  },
509
701
  children: [
@@ -519,7 +711,7 @@ function StandardModal({
519
711
  borderBottom: `1px solid ${withAlpha4(modalTheme.colors.onSurface, 0.06)}`
520
712
  },
521
713
  children: [
522
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { flex: 1 }, children: header }),
714
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { flex: 1 }, children: resolvedHeader }),
523
715
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 10 }, children: [
524
716
  !hideExpandButton ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
525
717
  "button",
@@ -547,7 +739,7 @@ function StandardModal({
547
739
  {
548
740
  "aria-label": "Close modal",
549
741
  type: "button",
550
- onClick: onClose,
742
+ onClick: disableDismiss ? void 0 : onClose,
551
743
  style: {
552
744
  height: 42,
553
745
  width: 42,
@@ -555,9 +747,10 @@ function StandardModal({
555
747
  border: `1px solid ${modalTheme.borderSoft}`,
556
748
  backgroundColor: "transparent",
557
749
  color: modalTheme.colors.onSurface,
558
- cursor: "pointer",
750
+ cursor: disableDismiss ? "not-allowed" : "pointer",
559
751
  fontSize: 20,
560
- fontWeight: 700
752
+ fontWeight: 700,
753
+ opacity: disableDismiss ? 0.5 : 1
561
754
  },
562
755
  children: "\xD7"
563
756
  }
@@ -573,12 +766,13 @@ function StandardModal({
573
766
  flex: 1,
574
767
  minHeight: 0,
575
768
  overflow: "auto",
576
- padding: 24
769
+ padding: 24,
770
+ ...bodyStyle
577
771
  },
578
772
  children
579
773
  }
580
774
  ),
581
- footer ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
775
+ shouldRenderFooter ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
582
776
  "div",
583
777
  {
584
778
  style: {
@@ -588,7 +782,7 @@ function StandardModal({
588
782
  padding: "16px 24px 24px",
589
783
  borderTop: `1px solid ${withAlpha4(modalTheme.colors.onSurface, 0.06)}`
590
784
  },
591
- children: footer
785
+ children: footerContent
592
786
  }
593
787
  ) : null
594
788
  ]
@@ -597,288 +791,8 @@ function StandardModal({
597
791
  }
598
792
  );
599
793
  }
600
- function LegacyModal({
601
- title,
602
- showModal,
603
- closeModal,
604
- children,
605
- action,
606
- actionNameBtn,
607
- hideActionButton = false,
608
- cancelButton,
609
- disableActionBtn = false,
610
- isLoading = false,
611
- onlyCloseButton = false,
612
- hideCloseIcon = false,
613
- style,
614
- bodyStyle,
615
- additionalActions,
616
- maximized,
617
- theme
618
- }) {
619
- const modalTheme = (0, import_react2.useMemo)(() => resolveTheme(theme), [theme]);
620
- const [isMaximized, setIsMaximized] = (0, import_react2.useState)(maximized != null ? maximized : false);
621
- const resolvedAction = action != null ? action : (() => null);
622
- (0, import_react2.useEffect)(() => {
623
- if (maximized === void 0 && isLikelyMobileViewport()) {
624
- setIsMaximized(true);
625
- }
626
- }, [maximized]);
627
- if (!showModal) {
628
- return null;
629
- }
630
- const actionButtons = () => {
631
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
632
- additionalActions == null ? void 0 : additionalActions.map((item) => {
633
- var _a, _b, _c;
634
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
635
- LegacyActionButton,
636
- {
637
- label: item.name,
638
- onClick: item.onClick,
639
- type: (_a = item.type) != null ? _a : "contained",
640
- style: (_b = item.style) != null ? _b : { maxWidth: "150px" },
641
- theme: modalTheme,
642
- disabled: (_c = item.disable) != null ? _c : disableActionBtn || isLoading
643
- },
644
- item.name
645
- );
646
- }),
647
- !hideActionButton ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
648
- LegacyActionButton,
649
- {
650
- label: actionNameBtn != null ? actionNameBtn : "Save",
651
- onClick: resolvedAction,
652
- type: "contained",
653
- style: { maxWidth: "100px" },
654
- theme: modalTheme,
655
- disabled: disableActionBtn || isLoading
656
- }
657
- ) : null
658
- ] });
659
- };
660
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
661
- "div",
662
- {
663
- "aria-labelledby": "modal-title",
664
- "aria-modal": "true",
665
- role: "dialog",
666
- style: {
667
- background: `${modalTheme.colors.background}90`,
668
- backdropFilter: "blur(2px)",
669
- width: "100%",
670
- height: "100%",
671
- position: "fixed",
672
- zIndex: 999,
673
- top: 0,
674
- left: 0,
675
- display: "flex",
676
- justifyContent: "center",
677
- alignItems: "center",
678
- boxSizing: "border-box"
679
- },
680
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
681
- "div",
682
- {
683
- id: isLoading ? "ldg1" : void 0,
684
- style: {
685
- position: isMaximized ? "fixed" : "relative",
686
- left: isMaximized ? 0 : void 0,
687
- top: isMaximized ? 0 : void 0,
688
- background: modalTheme.colors.background,
689
- display: "flex",
690
- alignItems: "center",
691
- flexDirection: "column",
692
- borderRadius: "0.8rem",
693
- boxSizing: "border-box",
694
- maxHeight: isMaximized ? "100vh" : "80vh",
695
- maxWidth: isMaximized ? "100vw" : "80vw",
696
- minWidth: isMaximized ? "100vw" : 300,
697
- minHeight: isMaximized ? "100vh" : void 0,
698
- width: isMaximized ? "100vw" : void 0,
699
- boxShadow: "0 24px 64px rgba(15, 23, 42, 0.18)",
700
- ...isLoading ? { opacity: 0.5 } : null,
701
- ...style
702
- },
703
- children: [
704
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
705
- "div",
706
- {
707
- style: {
708
- background: modalTheme.colors.surface,
709
- color: modalTheme.colors.onSurface,
710
- position: "absolute",
711
- top: 0,
712
- zIndex: 500,
713
- display: "flex",
714
- justifyContent: "space-between",
715
- alignItems: "center",
716
- width: "100%",
717
- height: "4rem",
718
- padding: "1rem",
719
- boxSizing: "border-box",
720
- borderTopLeftRadius: "0.8rem",
721
- borderTopRightRadius: "0.8rem",
722
- borderBottom: `1px solid ${withAlpha4(modalTheme.colors.onBackground, 0.1)}`
723
- },
724
- children: [
725
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { id: "modal-title", style: { fontWeight: "bold", fontSize: "1.3rem" }, children: title }),
726
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
727
- "div",
728
- {
729
- id: "modal-header-icons",
730
- style: { display: "flex", alignItems: "center", gap: "0.5rem" },
731
- children: [
732
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
733
- "button",
734
- {
735
- "aria-label": isMaximized ? "Minimize modal" : "Maximize modal",
736
- title: isMaximized ? "Minimize" : "Maximize",
737
- type: "button",
738
- onClick: () => setIsMaximized((current) => !current),
739
- style: {
740
- border: "none",
741
- background: "transparent",
742
- color: modalTheme.colors.onSurface,
743
- cursor: "pointer",
744
- fontSize: 18,
745
- lineHeight: 1,
746
- padding: 0
747
- },
748
- children: isMaximized ? "\u25A2" : "\u25A1"
749
- }
750
- ),
751
- !hideCloseIcon ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
752
- "button",
753
- {
754
- "aria-label": "Close modal",
755
- title: "Close",
756
- type: "button",
757
- onClick: isLoading ? void 0 : closeModal,
758
- style: {
759
- border: "none",
760
- background: "transparent",
761
- color: modalTheme.colors.onSurface,
762
- cursor: isLoading ? "not-allowed" : "pointer",
763
- fontSize: 22,
764
- lineHeight: 1,
765
- padding: 0,
766
- opacity: isLoading ? 0.5 : 1
767
- },
768
- children: "\xD7"
769
- }
770
- ) : null
771
- ]
772
- }
773
- )
774
- ]
775
- }
776
- ),
777
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
778
- "div",
779
- {
780
- style: {
781
- scrollbarWidth: "thin",
782
- width: "100%",
783
- maxWidth: "100%",
784
- paddingTop: "4rem",
785
- paddingBottom: "4rem",
786
- overflow: "auto",
787
- ...bodyStyle
788
- },
789
- children
790
- }
791
- ),
792
- onlyCloseButton ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
793
- "div",
794
- {
795
- style: {
796
- background: modalTheme.colors.surface,
797
- color: modalTheme.colors.onSurface,
798
- position: "absolute",
799
- bottom: 0,
800
- width: "100%",
801
- height: "4rem",
802
- padding: "0.5rem",
803
- borderTop: `1px solid ${withAlpha4(modalTheme.colors.onBackground, 0.1)}`,
804
- boxSizing: "border-box",
805
- borderBottomLeftRadius: "0.8rem",
806
- borderBottomRightRadius: "0.8rem"
807
- },
808
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
809
- "div",
810
- {
811
- className: "buttons-footer",
812
- style: { flex: 1, display: "flex", justifyContent: "end" },
813
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
814
- LegacyActionButton,
815
- {
816
- label: "Close",
817
- onClick: closeModal,
818
- theme: modalTheme,
819
- disabled: isLoading
820
- }
821
- )
822
- }
823
- )
824
- }
825
- ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
826
- "div",
827
- {
828
- style: {
829
- background: modalTheme.colors.surface,
830
- color: modalTheme.colors.onSurface,
831
- position: "absolute",
832
- bottom: 0,
833
- width: "100%",
834
- height: "4rem",
835
- padding: "0.5rem",
836
- borderTop: `1px solid ${withAlpha4(modalTheme.colors.onBackground, 0.1)}`,
837
- boxSizing: "border-box",
838
- borderBottomLeftRadius: "0.8rem",
839
- borderBottomRightRadius: "0.8rem"
840
- },
841
- children: cancelButton ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
842
- "div",
843
- {
844
- className: "buttons-footer",
845
- style: { flex: 1, display: "flex", justifyContent: "end" },
846
- children: [
847
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
848
- LegacyActionButton,
849
- {
850
- label: "Cancel",
851
- onClick: cancelButton,
852
- type: "text",
853
- style: { maxWidth: "100px" },
854
- theme: modalTheme,
855
- disabled: false
856
- }
857
- ),
858
- actionButtons()
859
- ]
860
- }
861
- ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
862
- "div",
863
- {
864
- className: "buttons-footer",
865
- style: { flex: 1, display: "flex", justifyContent: "end" },
866
- children: actionButtons()
867
- }
868
- )
869
- }
870
- )
871
- ]
872
- }
873
- )
874
- }
875
- );
876
- }
877
794
  function Modal(props) {
878
- if (isLegacyModalProps(props)) {
879
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LegacyModal, { ...props });
880
- }
881
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StandardModal, { ...props });
795
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(UnifiedModal, { ...normalizeModalProps(props) });
882
796
  }
883
797
 
884
798
  // src/components/ComposableModal.tsx
@@ -912,7 +826,7 @@ function ComposableModal({
912
826
  }) {
913
827
  const theme = useUiKitTheme(sdk);
914
828
  const slotIds = createModalSlotIds(slotBaseId);
915
- const context = (0, import_react3.useMemo)(
829
+ const context = (0, import_react4.useMemo)(
916
830
  () => ({
917
831
  title,
918
832
  description,
@@ -927,7 +841,7 @@ function ComposableModal({
927
841
  [cancelLabel, confirmLabel, description, isBusy, isOpen, onClose, onConfirm, payload, title]
928
842
  );
929
843
  const defaultFooter = hideDefaultFooter ? void 0 : footerFallback != null ? footerFallback : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
930
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { sdk, variant: "outline", tone: "neutral", onClick: onClose, disabled: isBusy, children: cancelLabel }),
844
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { sdk, variant: "outline", onClick: onClose, disabled: isBusy, children: cancelLabel }),
931
845
  onConfirm ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Button, { sdk, onClick: onConfirm, disabled: isBusy, children: confirmLabel }) : null
932
846
  ] });
933
847
  const defaultHeader = headerFallback != null ? headerFallback : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
@@ -979,124 +893,405 @@ function ComposableModal({
979
893
  );
980
894
  }
981
895
 
982
- // src/components/Field.tsx
896
+ // src/components/Input.tsx
897
+ var import_react5 = require("react");
898
+ var import_smartsell_sales_sdk5 = require("smartsell-sales-sdk");
983
899
  var import_jsx_runtime5 = require("react/jsx-runtime");
984
- function Field({
900
+ var PASSWORD_TOGGLE_METRICS_BY_SIZE = {
901
+ sm: {
902
+ buttonSize: 18,
903
+ leftOffset: 8,
904
+ contentGap: 8,
905
+ iconSize: 14
906
+ },
907
+ md: {
908
+ buttonSize: 20,
909
+ leftOffset: 10,
910
+ contentGap: 10,
911
+ iconSize: 16
912
+ },
913
+ lg: {
914
+ buttonSize: 22,
915
+ leftOffset: 12,
916
+ contentGap: 12,
917
+ iconSize: 18
918
+ }
919
+ };
920
+ var getPasswordToggleMetrics = (size) => PASSWORD_TOGGLE_METRICS_BY_SIZE[size];
921
+ function ControlFrame({
985
922
  sdk,
986
923
  label,
987
924
  hint,
988
925
  error,
989
926
  htmlFor,
990
927
  required = false,
928
+ useLabelWrapper = true,
991
929
  children,
992
930
  style
993
931
  }) {
932
+ if (!label && !hint && !error) {
933
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children });
934
+ }
994
935
  const { theme, mutedText } = useUiKitTheme(sdk);
995
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
996
- "label",
997
- {
998
- htmlFor,
999
- style: {
1000
- display: "flex",
1001
- flexDirection: "column",
1002
- gap: 8,
1003
- width: "100%",
1004
- ...style
1005
- },
1006
- children: [
1007
- (label || hint) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
1008
- label ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1009
- "span",
1010
- {
1011
- style: {
1012
- color: theme.colors.onSurface,
1013
- fontSize: 14,
1014
- fontWeight: 700,
1015
- letterSpacing: "0.01em"
1016
- },
1017
- children: [
1018
- label,
1019
- required ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: theme.colors.negative, marginLeft: 4 }, children: "*" }) : null
1020
- ]
1021
- }
1022
- ) : null,
1023
- hint ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1024
- "span",
1025
- {
1026
- style: {
1027
- color: mutedText,
1028
- fontSize: 13,
1029
- lineHeight: 1.45
1030
- },
1031
- children: hint
1032
- }
1033
- ) : null
1034
- ] }),
1035
- children,
1036
- error ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
936
+ const labelStyle = {
937
+ color: theme.colors.onSurface,
938
+ fontSize: 14,
939
+ fontWeight: 700,
940
+ letterSpacing: "0.01em"
941
+ };
942
+ const wrapperStyle = {
943
+ display: "flex",
944
+ flexDirection: "column",
945
+ gap: 8,
946
+ width: "100%",
947
+ ...style
948
+ };
949
+ if (!useLabelWrapper) {
950
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: wrapperStyle, children: [
951
+ label || hint ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
952
+ label ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { htmlFor, style: labelStyle, children: [
953
+ label,
954
+ required ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: theme.colors.negative, marginLeft: 4 }, children: "*" }) : null
955
+ ] }) : null,
956
+ hint ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1037
957
  "span",
1038
958
  {
1039
959
  style: {
1040
- color: theme.colors.negative,
960
+ color: mutedText,
1041
961
  fontSize: 13,
1042
- fontWeight: 600,
1043
962
  lineHeight: 1.45
1044
963
  },
1045
- children: error
964
+ children: hint
1046
965
  }
1047
966
  ) : null
1048
- ]
1049
- }
1050
- );
967
+ ] }) : null,
968
+ children,
969
+ error ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
970
+ "span",
971
+ {
972
+ style: {
973
+ color: theme.colors.negative,
974
+ fontSize: 13,
975
+ fontWeight: 600,
976
+ lineHeight: 1.45
977
+ },
978
+ children: error
979
+ }
980
+ ) : null
981
+ ] });
982
+ }
983
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { htmlFor, style: wrapperStyle, children: [
984
+ label || hint ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
985
+ label ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { style: labelStyle, children: [
986
+ label,
987
+ required ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: { color: theme.colors.negative, marginLeft: 4 }, children: "*" }) : null
988
+ ] }) : null,
989
+ hint ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
990
+ "span",
991
+ {
992
+ style: {
993
+ color: mutedText,
994
+ fontSize: 13,
995
+ lineHeight: 1.45
996
+ },
997
+ children: hint
998
+ }
999
+ ) : null
1000
+ ] }) : null,
1001
+ children,
1002
+ error ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1003
+ "span",
1004
+ {
1005
+ style: {
1006
+ color: theme.colors.negative,
1007
+ fontSize: 13,
1008
+ fontWeight: 600,
1009
+ lineHeight: 1.45
1010
+ },
1011
+ children: error
1012
+ }
1013
+ ) : null
1014
+ ] });
1051
1015
  }
1052
-
1053
- // src/components/Input.tsx
1054
- var import_smartsell_sales_sdk5 = require("smartsell-sales-sdk");
1055
- var import_jsx_runtime6 = require("react/jsx-runtime");
1056
- var getPadding = (size) => {
1057
- if (size === "sm") return "10px 12px";
1058
- if (size === "lg") return "16px 18px";
1059
- return "13px 16px";
1060
- };
1061
1016
  function Input({
1062
1017
  sdk,
1063
1018
  label,
1064
1019
  hint,
1065
1020
  error,
1066
1021
  controlSize = "md",
1022
+ showPasswordToggle = false,
1067
1023
  id,
1068
1024
  disabled,
1069
1025
  style,
1026
+ type = "text",
1070
1027
  ...rest
1071
1028
  }) {
1072
1029
  const { theme, borderSoft, focusRing, surfaceMuted } = useUiKitTheme(sdk);
1030
+ const controlMetrics = getControlMetrics(controlSize);
1031
+ const passwordToggleMetrics = getPasswordToggleMetrics(controlSize);
1032
+ const [isPasswordVisible, setIsPasswordVisible] = (0, import_react5.useState)(false);
1033
+ const isPasswordField = type === "password";
1034
+ const canTogglePasswordVisibility = isPasswordField && showPasswordToggle;
1035
+ const passwordToggleInset = Math.max(
1036
+ 0,
1037
+ passwordToggleMetrics.leftOffset + passwordToggleMetrics.buttonSize + passwordToggleMetrics.contentGap - controlMetrics.paddingX
1038
+ );
1039
+ const leadingInset = Number(canTogglePasswordVisibility) * passwordToggleInset;
1040
+ const resolvedType = canTogglePasswordVisibility ? isPasswordVisible ? "text" : "password" : type;
1073
1041
  const inputStyle = {
1074
1042
  width: "100%",
1043
+ boxSizing: "border-box",
1044
+ height: controlMetrics.height,
1075
1045
  borderRadius: 16,
1076
- border: `1px solid ${error ? theme.colors.negative : borderSoft}`,
1077
- padding: getPadding(controlSize),
1046
+ border: `1px solid ${error ? theme.colors.negative : (0, import_smartsell_sales_sdk5.withAlpha)(theme.colors.textLight, 0.5)}`,
1047
+ backgroundColor: theme.colors.surface,
1048
+ color: theme.colors.text,
1049
+ cursor: disabled ? "not-allowed" : "text",
1050
+ opacity: disabled ? 0.7 : 1,
1051
+ padding: getTextInputPadding(controlSize, { leadingInset }),
1078
1052
  outline: "none",
1079
- color: theme.colors.onSurface,
1080
- backgroundColor: disabled ? surfaceMuted : theme.colors.surface,
1053
+ fontSize: controlMetrics.fontSize,
1054
+ lineHeight: controlMetrics.lineHeight,
1081
1055
  boxShadow: error ? `0 0 0 3px ${(0, import_smartsell_sales_sdk5.withAlpha)(theme.colors.negative, 0.12)}` : `0 0 0 0 ${focusRing}`,
1082
1056
  transition: "border-color 160ms ease, box-shadow 160ms ease, background-color 160ms ease",
1083
1057
  ...style
1084
1058
  };
1085
- const input = /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { ...rest, id, disabled, style: inputStyle });
1086
- if (!label && !hint && !error) {
1087
- return input;
1088
- }
1089
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Field, { sdk, label, hint, error, htmlFor: id, children: input });
1090
- }
1091
-
1092
- // src/components/Select.tsx
1059
+ const input = canTogglePasswordVisibility ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { position: "relative", width: "100%" }, children: [
1060
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1061
+ "button",
1062
+ {
1063
+ type: "button",
1064
+ "aria-label": isPasswordVisible ? "Hide password" : "Show password",
1065
+ "aria-pressed": isPasswordVisible,
1066
+ disabled,
1067
+ onMouseDown: (event) => {
1068
+ event.preventDefault();
1069
+ },
1070
+ onClick: () => {
1071
+ setIsPasswordVisible((currentValue) => !currentValue);
1072
+ },
1073
+ style: {
1074
+ position: "absolute",
1075
+ top: "50%",
1076
+ left: passwordToggleMetrics.leftOffset,
1077
+ transform: "translateY(-50%)",
1078
+ zIndex: 1,
1079
+ width: passwordToggleMetrics.buttonSize,
1080
+ height: passwordToggleMetrics.buttonSize,
1081
+ display: "inline-flex",
1082
+ alignItems: "center",
1083
+ justifyContent: "center",
1084
+ border: "none",
1085
+ padding: 0,
1086
+ margin: 0,
1087
+ borderRadius: 999,
1088
+ backgroundColor: "transparent",
1089
+ color: isPasswordVisible ? theme.colors.primary : theme.colors.textLight,
1090
+ cursor: disabled ? "not-allowed" : "pointer",
1091
+ opacity: disabled ? 0.5 : 1
1092
+ },
1093
+ children: isPasswordVisible ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1094
+ "svg",
1095
+ {
1096
+ width: passwordToggleMetrics.iconSize,
1097
+ height: passwordToggleMetrics.iconSize,
1098
+ viewBox: "0 0 20 20",
1099
+ fill: "none",
1100
+ "aria-hidden": "true",
1101
+ children: [
1102
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1103
+ "path",
1104
+ {
1105
+ d: "M2.5 3.5L17.5 16.5",
1106
+ stroke: "currentColor",
1107
+ strokeWidth: "1.8",
1108
+ strokeLinecap: "round"
1109
+ }
1110
+ ),
1111
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1112
+ "path",
1113
+ {
1114
+ d: "M8.825 8.786a2 2 0 0 0 2.389 2.389",
1115
+ stroke: "currentColor",
1116
+ strokeWidth: "1.8",
1117
+ strokeLinecap: "round",
1118
+ strokeLinejoin: "round"
1119
+ }
1120
+ ),
1121
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1122
+ "path",
1123
+ {
1124
+ d: "M4.42 6.774C3.422 7.73 2.777 8.815 2.5 9.375c1.182 2.39 3.934 5.625 7.5 5.625 1.155 0 2.224-.34 3.166-.847",
1125
+ stroke: "currentColor",
1126
+ strokeWidth: "1.8",
1127
+ strokeLinecap: "round",
1128
+ strokeLinejoin: "round"
1129
+ }
1130
+ ),
1131
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1132
+ "path",
1133
+ {
1134
+ d: "M7.043 4.455A7.7 7.7 0 0 1 10 3.75c3.566 0 6.318 3.235 7.5 5.625-.39.787-1.504 2.588-3.259 3.986",
1135
+ stroke: "currentColor",
1136
+ strokeWidth: "1.8",
1137
+ strokeLinecap: "round",
1138
+ strokeLinejoin: "round"
1139
+ }
1140
+ )
1141
+ ]
1142
+ }
1143
+ ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1144
+ "svg",
1145
+ {
1146
+ width: passwordToggleMetrics.iconSize,
1147
+ height: passwordToggleMetrics.iconSize,
1148
+ viewBox: "0 0 20 20",
1149
+ fill: "none",
1150
+ "aria-hidden": "true",
1151
+ children: [
1152
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1153
+ "path",
1154
+ {
1155
+ d: "M2.5 10c1.182-2.39 3.934-5.625 7.5-5.625S16.318 7.61 17.5 10c-1.182 2.39-3.934 5.625-7.5 5.625S3.682 12.39 2.5 10Z",
1156
+ stroke: "currentColor",
1157
+ strokeWidth: "1.8",
1158
+ strokeLinecap: "round",
1159
+ strokeLinejoin: "round"
1160
+ }
1161
+ ),
1162
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("circle", { cx: "10", cy: "10", r: "2.25", stroke: "currentColor", strokeWidth: "1.8" })
1163
+ ]
1164
+ }
1165
+ )
1166
+ }
1167
+ ),
1168
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { ...rest, id, type: resolvedType, disabled, style: inputStyle })
1169
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { ...rest, id, type: resolvedType, disabled, style: inputStyle });
1170
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ControlFrame, { sdk, label, hint, error, htmlFor: id, required: rest.required, children: input });
1171
+ }
1172
+
1173
+ // src/components/Select.tsx
1174
+ var import_react6 = require("react");
1093
1175
  var import_smartsell_sales_sdk6 = require("smartsell-sales-sdk");
1094
- var import_jsx_runtime7 = require("react/jsx-runtime");
1095
- var getPadding2 = (size) => {
1176
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1177
+ var MENU_OFFSET = 8;
1178
+ var MENU_MAX_HEIGHT = 280;
1179
+ var getOptionPadding = (size) => {
1096
1180
  if (size === "sm") return "10px 12px";
1097
- if (size === "lg") return "16px 18px";
1098
- return "13px 16px";
1181
+ if (size === "lg") return "14px 16px";
1182
+ return "12px 14px";
1099
1183
  };
1184
+ function getTextContent(node) {
1185
+ if (node == null || typeof node === "boolean") {
1186
+ return "";
1187
+ }
1188
+ if (typeof node === "string" || typeof node === "number") {
1189
+ return String(node);
1190
+ }
1191
+ if (Array.isArray(node)) {
1192
+ return node.map(getTextContent).join("");
1193
+ }
1194
+ if ((0, import_react6.isValidElement)(node)) {
1195
+ return getTextContent(node.props.children);
1196
+ }
1197
+ return "";
1198
+ }
1199
+ function normalizeSelectValue(value) {
1200
+ if (Array.isArray(value)) {
1201
+ return value.length > 0 ? normalizeSelectValue(value[0]) : "";
1202
+ }
1203
+ return value == null ? "" : String(value);
1204
+ }
1205
+ function normalizeSelectValues(value) {
1206
+ if (Array.isArray(value)) {
1207
+ return value.map((item) => normalizeSelectValue(item));
1208
+ }
1209
+ if (value == null) {
1210
+ return [];
1211
+ }
1212
+ return [normalizeSelectValue(value)];
1213
+ }
1214
+ function buildOption(keyPrefix, index, props, groupLabel, groupDisabled = false) {
1215
+ var _a;
1216
+ const rawValue = props.value !== void 0 ? props.value : getTextContent(props.children).trim();
1217
+ const normalizedValue = normalizeSelectValue(rawValue);
1218
+ return {
1219
+ key: `${keyPrefix}-${index}-${normalizedValue}`,
1220
+ value: normalizedValue,
1221
+ label: (_a = props.children) != null ? _a : normalizedValue,
1222
+ disabled: groupDisabled || Boolean(props.disabled)
1223
+ };
1224
+ }
1225
+ function parseSelectChildren(children) {
1226
+ const groups = [];
1227
+ const standaloneOptions = [];
1228
+ let optionIndex = 0;
1229
+ let groupIndex = 0;
1230
+ const flushStandaloneOptions = () => {
1231
+ if (standaloneOptions.length === 0) {
1232
+ return;
1233
+ }
1234
+ groups.push({
1235
+ key: `standalone-${groups.length}`,
1236
+ options: [...standaloneOptions]
1237
+ });
1238
+ standaloneOptions.length = 0;
1239
+ };
1240
+ import_react6.Children.forEach(children, (child) => {
1241
+ if (!(0, import_react6.isValidElement)(child)) {
1242
+ return;
1243
+ }
1244
+ if (child.type === "option") {
1245
+ standaloneOptions.push(buildOption("option", optionIndex, child.props));
1246
+ optionIndex += 1;
1247
+ return;
1248
+ }
1249
+ if (child.type !== "optgroup") {
1250
+ return;
1251
+ }
1252
+ flushStandaloneOptions();
1253
+ const groupOptions = [];
1254
+ let groupOptionIndex = 0;
1255
+ import_react6.Children.forEach(child.props.children, (optionChild) => {
1256
+ if (!(0, import_react6.isValidElement)(optionChild) || optionChild.type !== "option") {
1257
+ return;
1258
+ }
1259
+ groupOptions.push(
1260
+ buildOption(
1261
+ `group-${groupIndex}-option`,
1262
+ groupOptionIndex,
1263
+ optionChild.props,
1264
+ child.props.label,
1265
+ Boolean(child.props.disabled)
1266
+ )
1267
+ );
1268
+ groupOptionIndex += 1;
1269
+ });
1270
+ if (groupOptions.length > 0) {
1271
+ groups.push({
1272
+ key: `group-${groupIndex}`,
1273
+ label: child.props.label,
1274
+ options: groupOptions
1275
+ });
1276
+ groupIndex += 1;
1277
+ }
1278
+ });
1279
+ flushStandaloneOptions();
1280
+ return groups;
1281
+ }
1282
+ function filterSelectGroups(groups, query) {
1283
+ const normalizedQuery = query.trim().toLowerCase();
1284
+ if (!normalizedQuery) {
1285
+ return groups;
1286
+ }
1287
+ return groups.map((group) => ({
1288
+ ...group,
1289
+ options: group.options.filter((option) => {
1290
+ const optionText = getTextContent(option.label).trim().toLowerCase();
1291
+ return optionText.includes(normalizedQuery);
1292
+ })
1293
+ })).filter((group) => group.options.length > 0);
1294
+ }
1100
1295
  function Select({
1101
1296
  sdk,
1102
1297
  label,
@@ -1107,32 +1302,845 @@ function Select({
1107
1302
  disabled,
1108
1303
  style,
1109
1304
  children,
1305
+ value,
1306
+ defaultValue,
1307
+ onChange,
1308
+ onFocus,
1309
+ onBlur,
1310
+ onKeyDown,
1311
+ onClick,
1312
+ autoFocus,
1313
+ className,
1314
+ isMulti,
1315
+ isFilterable,
1316
+ multiple,
1110
1317
  ...rest
1111
1318
  }) {
1112
- const { theme, borderSoft, focusRing, surfaceMuted } = useUiKitTheme(sdk);
1113
- const selectStyle = {
1114
- width: "100%",
1115
- borderRadius: 16,
1116
- border: `1px solid ${error ? theme.colors.negative : borderSoft}`,
1117
- padding: getPadding2(controlSize),
1118
- outline: "none",
1119
- color: theme.colors.onSurface,
1120
- backgroundColor: disabled ? surfaceMuted : theme.colors.surface,
1121
- boxShadow: error ? `0 0 0 3px ${(0, import_smartsell_sales_sdk6.withAlpha)(theme.colors.negative, 0.12)}` : `0 0 0 0 ${focusRing}`,
1122
- transition: "border-color 160ms ease, box-shadow 160ms ease, background-color 160ms ease",
1123
- ...style
1319
+ var _a, _b, _c, _d, _e, _f, _g, _h;
1320
+ const { theme, borderSoft, mutedText, surfaceMuted, surfaceRaised } = useUiKitTheme(sdk);
1321
+ const generatedId = (0, import_react6.useId)().replace(/:/g, "");
1322
+ const resolvedId = id != null ? id : `ss-select-${generatedId}`;
1323
+ const isMultiSelect = Boolean(isMulti || multiple);
1324
+ const hasFilter = Boolean(isFilterable);
1325
+ const groups = parseSelectChildren(children);
1326
+ const flatOptions = groups.flatMap((group) => group.options);
1327
+ const enabledOptions = flatOptions.filter((option) => !option.disabled);
1328
+ const isControlled = value !== void 0;
1329
+ const fallbackValues = defaultValue !== void 0 ? normalizeSelectValues(defaultValue) : isMultiSelect ? [] : ((_a = enabledOptions[0]) == null ? void 0 : _a.value) ? [enabledOptions[0].value] : [];
1330
+ const [uncontrolledValues, setUncontrolledValues] = (0, import_react6.useState)(fallbackValues);
1331
+ const [isOpen, setIsOpen] = (0, import_react6.useState)(false);
1332
+ const [filterQuery, setFilterQuery] = (0, import_react6.useState)("");
1333
+ const [menuPlacement, setMenuPlacement] = (0, import_react6.useState)("bottom");
1334
+ const [isPlacementResolved, setIsPlacementResolved] = (0, import_react6.useState)(false);
1335
+ const [highlightedValue, setHighlightedValue] = (0, import_react6.useState)((_d = (_c = fallbackValues[0]) != null ? _c : (_b = enabledOptions[0]) == null ? void 0 : _b.value) != null ? _d : "");
1336
+ const shellRef = (0, import_react6.useRef)(null);
1337
+ const buttonRef = (0, import_react6.useRef)(null);
1338
+ const menuRef = (0, import_react6.useRef)(null);
1339
+ const searchInputRef = (0, import_react6.useRef)(null);
1340
+ const hiddenSelectRef = (0, import_react6.useRef)(null);
1341
+ const selectedValues = isControlled ? normalizeSelectValues(value) : uncontrolledValues;
1342
+ const selectedValue = (_e = selectedValues[0]) != null ? _e : "";
1343
+ const selectedOptions = flatOptions.filter((option) => selectedValues.includes(option.value));
1344
+ const selectedOption = (_f = selectedOptions[0]) != null ? _f : null;
1345
+ const displayLabel = isMultiSelect ? selectedOptions.length > 0 ? selectedOptions.map((option) => getTextContent(option.label).trim() || option.value).join(", ") : null : (_g = selectedOption == null ? void 0 : selectedOption.label) != null ? _g : selectedValue ? selectedValue : null;
1346
+ const displayContent = displayLabel != null ? displayLabel : "\xA0";
1347
+ const visibleGroups = hasFilter ? filterSelectGroups(groups, filterQuery) : groups;
1348
+ const visibleOptions = visibleGroups.flatMap((group) => group.options);
1349
+ const visibleEnabledOptions = visibleOptions.filter((option) => !option.disabled);
1350
+ const visibleEnabledValues = visibleEnabledOptions.map((option) => option.value);
1351
+ const selectedValuesKey = selectedValues.join("\0");
1352
+ const visibleEnabledValuesKey = visibleEnabledValues.join("\0");
1353
+ const indicatorOffset = getSelectIndicatorOffset(controlSize);
1354
+ const controlMetrics = getControlMetrics(controlSize);
1355
+ const listboxId = `${resolvedId}-listbox`;
1356
+ const scrollbarThumbColor = (0, import_smartsell_sales_sdk6.withAlpha)(theme.colors.onSurface, 0.22);
1357
+ const scrollbarThumbHoverColor = (0, import_smartsell_sales_sdk6.withAlpha)(theme.colors.onSurface, 0.32);
1358
+ const highlightedOption = (_h = visibleOptions.find((option) => option.value === highlightedValue)) != null ? _h : null;
1359
+ const optionHoverBackground = (0, import_smartsell_sales_sdk6.withAlpha)(theme.colors.primary, 1);
1360
+ const optionSelectedBackground = (0, import_smartsell_sales_sdk6.withAlpha)(theme.colors.primary, 1);
1361
+ const triggerShadow = error ? `0 0 0 3px ${(0, import_smartsell_sales_sdk6.withAlpha)(theme.colors.negative, 0.12)}` : "none";
1362
+ const buttonPassthroughProps = Object.fromEntries(
1363
+ Object.entries(rest).filter(([key]) => key.startsWith("aria-") || key.startsWith("data-"))
1364
+ );
1365
+ (0, import_react6.useEffect)(() => {
1366
+ var _a2, _b2, _c2, _d2;
1367
+ if (isControlled) {
1368
+ return;
1369
+ }
1370
+ const invalidValues = uncontrolledValues.filter(
1371
+ (currentValue) => !flatOptions.some((option) => option.value === currentValue)
1372
+ );
1373
+ if (invalidValues.length === 0) {
1374
+ return;
1375
+ }
1376
+ const nextValues = defaultValue !== void 0 ? normalizeSelectValues(defaultValue).filter(
1377
+ (currentValue) => flatOptions.some((option) => option.value === currentValue)
1378
+ ) : isMultiSelect ? [] : ((_a2 = enabledOptions[0]) == null ? void 0 : _a2.value) ? [enabledOptions[0].value] : [];
1379
+ setUncontrolledValues(nextValues);
1380
+ setHighlightedValue((_d2 = (_c2 = nextValues[0]) != null ? _c2 : (_b2 = enabledOptions[0]) == null ? void 0 : _b2.value) != null ? _d2 : "");
1381
+ }, [children, defaultValue, enabledOptions, flatOptions, isControlled, isMultiSelect, uncontrolledValues]);
1382
+ (0, import_react6.useEffect)(() => {
1383
+ var _a2, _b2, _c2;
1384
+ if (!isOpen) {
1385
+ setMenuPlacement("bottom");
1386
+ setIsPlacementResolved(false);
1387
+ return;
1388
+ }
1389
+ const nextHighlightedValue = (_c2 = (_b2 = [...selectedValues].reverse().find((currentValue) => visibleEnabledValues.includes(currentValue))) != null ? _b2 : (_a2 = visibleEnabledOptions[0]) == null ? void 0 : _a2.value) != null ? _c2 : "";
1390
+ setHighlightedValue(nextHighlightedValue);
1391
+ }, [isOpen, selectedValuesKey, visibleEnabledValuesKey]);
1392
+ (0, import_react6.useEffect)(() => {
1393
+ var _a2;
1394
+ if (!isOpen || !hasFilter) {
1395
+ return;
1396
+ }
1397
+ (_a2 = searchInputRef.current) == null ? void 0 : _a2.focus();
1398
+ }, [hasFilter, isOpen]);
1399
+ (0, import_react6.useEffect)(() => {
1400
+ if (!isOpen) {
1401
+ return;
1402
+ }
1403
+ const frameId = window.requestAnimationFrame(() => {
1404
+ var _a2;
1405
+ const triggerRect = (_a2 = buttonRef.current) == null ? void 0 : _a2.getBoundingClientRect();
1406
+ const menuElement = menuRef.current;
1407
+ if (!triggerRect || !menuElement) {
1408
+ setMenuPlacement("bottom");
1409
+ setIsPlacementResolved(true);
1410
+ return;
1411
+ }
1412
+ const measuredMenuHeight = menuElement.getBoundingClientRect().height;
1413
+ const menuHeight = Math.min(measuredMenuHeight || menuElement.scrollHeight, MENU_MAX_HEIGHT);
1414
+ const availableBelow = window.innerHeight - triggerRect.bottom - MENU_OFFSET;
1415
+ const availableAbove = triggerRect.top - MENU_OFFSET;
1416
+ const nextPlacement = availableBelow < menuHeight && availableAbove >= menuHeight ? "top" : "bottom";
1417
+ setMenuPlacement(nextPlacement);
1418
+ setIsPlacementResolved(true);
1419
+ });
1420
+ return () => {
1421
+ window.cancelAnimationFrame(frameId);
1422
+ };
1423
+ }, [isOpen, visibleOptions.length]);
1424
+ (0, import_react6.useEffect)(() => {
1425
+ if (isOpen) {
1426
+ return;
1427
+ }
1428
+ setFilterQuery("");
1429
+ }, [isOpen]);
1430
+ (0, import_react6.useEffect)(() => {
1431
+ if (!isOpen) {
1432
+ return;
1433
+ }
1434
+ const handlePointerDown = (event) => {
1435
+ var _a2;
1436
+ if ((_a2 = shellRef.current) == null ? void 0 : _a2.contains(event.target)) {
1437
+ return;
1438
+ }
1439
+ setIsOpen(false);
1440
+ };
1441
+ document.addEventListener("pointerdown", handlePointerDown);
1442
+ return () => {
1443
+ document.removeEventListener("pointerdown", handlePointerDown);
1444
+ };
1445
+ }, [isOpen]);
1446
+ (0, import_react6.useEffect)(() => {
1447
+ var _a2;
1448
+ if (isControlled) {
1449
+ return;
1450
+ }
1451
+ const form = (_a2 = hiddenSelectRef.current) == null ? void 0 : _a2.form;
1452
+ if (!form) {
1453
+ return;
1454
+ }
1455
+ const handleReset = () => {
1456
+ queueMicrotask(() => {
1457
+ var _a3, _b2, _c2, _d2;
1458
+ const nextValues = defaultValue !== void 0 ? normalizeSelectValues(defaultValue) : isMultiSelect ? [] : ((_a3 = enabledOptions[0]) == null ? void 0 : _a3.value) ? [enabledOptions[0].value] : [];
1459
+ setUncontrolledValues(nextValues);
1460
+ setHighlightedValue((_d2 = (_c2 = nextValues[0]) != null ? _c2 : (_b2 = enabledOptions[0]) == null ? void 0 : _b2.value) != null ? _d2 : "");
1461
+ setIsOpen(false);
1462
+ });
1463
+ };
1464
+ form.addEventListener("reset", handleReset);
1465
+ return () => {
1466
+ form.removeEventListener("reset", handleReset);
1467
+ };
1468
+ }, [defaultValue, enabledOptions, isControlled, isMultiSelect]);
1469
+ const syncHiddenSelect = (nextValues) => {
1470
+ var _a2, _b2;
1471
+ const selectElement = hiddenSelectRef.current;
1472
+ if (!selectElement) {
1473
+ return;
1474
+ }
1475
+ if (isMultiSelect) {
1476
+ Array.from(selectElement.options).forEach((optionElement) => {
1477
+ optionElement.selected = nextValues.includes(optionElement.value);
1478
+ });
1479
+ } else {
1480
+ const descriptor = Object.getOwnPropertyDescriptor(HTMLSelectElement.prototype, "value");
1481
+ if (descriptor == null ? void 0 : descriptor.set) {
1482
+ descriptor.set.call(selectElement, (_a2 = nextValues[0]) != null ? _a2 : "");
1483
+ } else {
1484
+ selectElement.value = (_b2 = nextValues[0]) != null ? _b2 : "";
1485
+ }
1486
+ }
1487
+ selectElement.dispatchEvent(new Event("change", { bubbles: true }));
1124
1488
  };
1125
- const select = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("select", { ...rest, id, disabled, style: selectStyle, children });
1126
- if (!label && !hint && !error) {
1127
- return select;
1128
- }
1129
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Field, { sdk, label, hint, error, htmlFor: id, children: select });
1489
+ const updateMultiSelection = (nextValues) => {
1490
+ var _a2, _b2, _c2;
1491
+ if (!isMultiSelect || disabled) {
1492
+ return;
1493
+ }
1494
+ if (!isControlled) {
1495
+ setUncontrolledValues(nextValues);
1496
+ }
1497
+ setHighlightedValue((_c2 = (_b2 = nextValues[nextValues.length - 1]) != null ? _b2 : (_a2 = enabledOptions[0]) == null ? void 0 : _a2.value) != null ? _c2 : "");
1498
+ syncHiddenSelect(nextValues);
1499
+ };
1500
+ const toggleVisibleSelection = (checked) => {
1501
+ if (!isMultiSelect || disabled || visibleEnabledValues.length === 0) {
1502
+ return;
1503
+ }
1504
+ const nextValues = checked ? Array.from(/* @__PURE__ */ new Set([...selectedValues, ...visibleEnabledValues])) : selectedValues.filter((currentValue) => !visibleEnabledValues.includes(currentValue));
1505
+ updateMultiSelection(nextValues);
1506
+ };
1507
+ const commitSelection = (nextValue) => {
1508
+ var _a2;
1509
+ if (disabled) {
1510
+ if (!isMultiSelect) {
1511
+ setIsOpen(false);
1512
+ }
1513
+ return;
1514
+ }
1515
+ if (isMultiSelect) {
1516
+ const nextValues = selectedValues.includes(nextValue) ? selectedValues.filter((currentValue) => currentValue !== nextValue) : [...selectedValues, nextValue];
1517
+ updateMultiSelection(nextValues);
1518
+ return;
1519
+ }
1520
+ if (nextValue === selectedValue) {
1521
+ setIsOpen(false);
1522
+ return;
1523
+ }
1524
+ if (!isControlled) {
1525
+ setUncontrolledValues([nextValue]);
1526
+ }
1527
+ setHighlightedValue(nextValue);
1528
+ setIsOpen(false);
1529
+ syncHiddenSelect([nextValue]);
1530
+ (_a2 = buttonRef.current) == null ? void 0 : _a2.focus();
1531
+ };
1532
+ const handleHiddenSelectChange = (event) => {
1533
+ var _a2, _b2, _c2;
1534
+ const nextValues = isMultiSelect ? Array.from(event.currentTarget.selectedOptions, (option) => option.value) : [event.currentTarget.value];
1535
+ if (!isControlled) {
1536
+ setUncontrolledValues(nextValues);
1537
+ }
1538
+ setHighlightedValue((_c2 = (_b2 = nextValues[nextValues.length - 1]) != null ? _b2 : (_a2 = enabledOptions[0]) == null ? void 0 : _a2.value) != null ? _c2 : "");
1539
+ onChange == null ? void 0 : onChange(event);
1540
+ };
1541
+ const visibleSelectedCount = visibleEnabledValues.filter((currentValue) => selectedValues.includes(currentValue)).length;
1542
+ const hasSomeVisibleSelected = visibleSelectedCount > 0 && visibleSelectedCount < visibleEnabledValues.length;
1543
+ const hasAllVisibleSelected = visibleEnabledValues.length > 0 && visibleSelectedCount === visibleEnabledValues.length;
1544
+ const canToggleVisibleSelection = !disabled && visibleEnabledValues.length > 0;
1545
+ const bulkToggleControl = isMultiSelect ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1546
+ "button",
1547
+ {
1548
+ type: "button",
1549
+ role: "checkbox",
1550
+ "aria-label": "Toggle all visible options",
1551
+ "aria-checked": hasAllVisibleSelected ? true : hasSomeVisibleSelected ? "mixed" : false,
1552
+ disabled: !canToggleVisibleSelection,
1553
+ onMouseDown: (event) => {
1554
+ event.preventDefault();
1555
+ event.stopPropagation();
1556
+ },
1557
+ onClick: (event) => {
1558
+ event.stopPropagation();
1559
+ toggleVisibleSelection(!hasAllVisibleSelected);
1560
+ },
1561
+ style: {
1562
+ width: 20,
1563
+ height: 20,
1564
+ padding: 0,
1565
+ margin: 0,
1566
+ borderRadius: 999,
1567
+ border: `1.5px solid ${hasAllVisibleSelected || hasSomeVisibleSelected ? theme.colors.secondary : (0, import_smartsell_sales_sdk6.withAlpha)(theme.colors.onSurface, 0.22)}`,
1568
+ backgroundColor: hasAllVisibleSelected || hasSomeVisibleSelected ? theme.colors.secondary : theme.colors.surface,
1569
+ display: "inline-flex",
1570
+ alignItems: "center",
1571
+ justifyContent: "center",
1572
+ flexShrink: 0,
1573
+ cursor: canToggleVisibleSelection ? "pointer" : "not-allowed",
1574
+ opacity: canToggleVisibleSelection ? 1 : 0.45
1575
+ },
1576
+ children: hasAllVisibleSelected ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1577
+ "span",
1578
+ {
1579
+ "aria-hidden": "true",
1580
+ style: {
1581
+ width: 8,
1582
+ height: 8,
1583
+ borderRadius: 999,
1584
+ backgroundColor: theme.colors.surface
1585
+ }
1586
+ }
1587
+ ) : hasSomeVisibleSelected ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1588
+ "span",
1589
+ {
1590
+ "aria-hidden": "true",
1591
+ style: {
1592
+ width: 8,
1593
+ height: 2,
1594
+ borderRadius: 999,
1595
+ backgroundColor: theme.colors.surface
1596
+ }
1597
+ }
1598
+ ) : null
1599
+ }
1600
+ ) : null;
1601
+ const moveHighlight = (direction) => {
1602
+ if (visibleEnabledOptions.length === 0) {
1603
+ return;
1604
+ }
1605
+ const currentIndex = visibleEnabledOptions.findIndex((option) => option.value === highlightedValue);
1606
+ if (currentIndex === -1) {
1607
+ setHighlightedValue(
1608
+ direction === 1 ? visibleEnabledOptions[0].value : visibleEnabledOptions[visibleEnabledOptions.length - 1].value
1609
+ );
1610
+ return;
1611
+ }
1612
+ const nextIndex = Math.max(0, Math.min(visibleEnabledOptions.length - 1, currentIndex + direction));
1613
+ setHighlightedValue(visibleEnabledOptions[nextIndex].value);
1614
+ };
1615
+ const handleTriggerClick = (event) => {
1616
+ onClick == null ? void 0 : onClick(event);
1617
+ if (event.defaultPrevented || disabled || flatOptions.length === 0) {
1618
+ return;
1619
+ }
1620
+ setIsOpen((current) => !current);
1621
+ };
1622
+ const handleTriggerFocus = (event) => {
1623
+ onFocus == null ? void 0 : onFocus(event);
1624
+ };
1625
+ const handleTriggerBlur = (event) => {
1626
+ var _a2;
1627
+ const nextTarget = event.relatedTarget;
1628
+ if (!((_a2 = shellRef.current) == null ? void 0 : _a2.contains(nextTarget))) {
1629
+ setIsOpen(false);
1630
+ }
1631
+ onBlur == null ? void 0 : onBlur(event);
1632
+ };
1633
+ const handleTriggerKeyDown = (event) => {
1634
+ var _a2, _b2, _c2;
1635
+ onKeyDown == null ? void 0 : onKeyDown(event);
1636
+ if (event.defaultPrevented || disabled || visibleEnabledOptions.length === 0) {
1637
+ return;
1638
+ }
1639
+ if (event.key === "ArrowDown") {
1640
+ event.preventDefault();
1641
+ if (!isOpen) {
1642
+ setIsOpen(true);
1643
+ setHighlightedValue((_a2 = selectedOption == null ? void 0 : selectedOption.value) != null ? _a2 : visibleEnabledOptions[0].value);
1644
+ return;
1645
+ }
1646
+ moveHighlight(1);
1647
+ return;
1648
+ }
1649
+ if (event.key === "ArrowUp") {
1650
+ event.preventDefault();
1651
+ if (!isOpen) {
1652
+ setIsOpen(true);
1653
+ setHighlightedValue((_b2 = selectedOption == null ? void 0 : selectedOption.value) != null ? _b2 : visibleEnabledOptions[visibleEnabledOptions.length - 1].value);
1654
+ return;
1655
+ }
1656
+ moveHighlight(-1);
1657
+ return;
1658
+ }
1659
+ if (event.key === "Home" && isOpen) {
1660
+ event.preventDefault();
1661
+ setHighlightedValue(visibleEnabledOptions[0].value);
1662
+ return;
1663
+ }
1664
+ if (event.key === "End" && isOpen) {
1665
+ event.preventDefault();
1666
+ setHighlightedValue(visibleEnabledOptions[visibleEnabledOptions.length - 1].value);
1667
+ return;
1668
+ }
1669
+ if (event.key === "Enter" || event.key === " ") {
1670
+ event.preventDefault();
1671
+ if (!isOpen) {
1672
+ setIsOpen(true);
1673
+ setHighlightedValue((_c2 = selectedOption == null ? void 0 : selectedOption.value) != null ? _c2 : visibleEnabledOptions[0].value);
1674
+ return;
1675
+ }
1676
+ if (highlightedOption && !highlightedOption.disabled) {
1677
+ commitSelection(highlightedOption.value);
1678
+ }
1679
+ return;
1680
+ }
1681
+ if (event.key === "Escape" && isOpen) {
1682
+ event.preventDefault();
1683
+ setIsOpen(false);
1684
+ return;
1685
+ }
1686
+ if (event.key === "Tab") {
1687
+ setIsOpen(false);
1688
+ }
1689
+ };
1690
+ const handleFilterKeyDown = (event) => {
1691
+ var _a2;
1692
+ if (event.key === "ArrowDown") {
1693
+ event.preventDefault();
1694
+ moveHighlight(1);
1695
+ return;
1696
+ }
1697
+ if (event.key === "ArrowUp") {
1698
+ event.preventDefault();
1699
+ moveHighlight(-1);
1700
+ return;
1701
+ }
1702
+ if (event.key === "Enter") {
1703
+ event.preventDefault();
1704
+ if (highlightedOption && !highlightedOption.disabled) {
1705
+ commitSelection(highlightedOption.value);
1706
+ }
1707
+ return;
1708
+ }
1709
+ if (event.key === "Escape") {
1710
+ event.preventDefault();
1711
+ setIsOpen(false);
1712
+ (_a2 = buttonRef.current) == null ? void 0 : _a2.focus();
1713
+ return;
1714
+ }
1715
+ if (event.key === "Tab") {
1716
+ setIsOpen(false);
1717
+ }
1718
+ };
1719
+ const select = /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: shellRef, style: { position: "relative", width: "100%" }, children: [
1720
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1721
+ "button",
1722
+ {
1723
+ ...buttonPassthroughProps,
1724
+ id: resolvedId,
1725
+ ref: buttonRef,
1726
+ type: "button",
1727
+ className,
1728
+ title: rest.title,
1729
+ disabled: disabled || flatOptions.length === 0,
1730
+ autoFocus,
1731
+ tabIndex: rest.tabIndex,
1732
+ role: "combobox",
1733
+ "aria-controls": listboxId,
1734
+ "aria-expanded": isOpen,
1735
+ "aria-haspopup": "listbox",
1736
+ "aria-invalid": error ? true : rest["aria-invalid"],
1737
+ "aria-required": rest.required,
1738
+ onClick: handleTriggerClick,
1739
+ onFocus: handleTriggerFocus,
1740
+ onBlur: handleTriggerBlur,
1741
+ onKeyDown: handleTriggerKeyDown,
1742
+ style: {
1743
+ width: "100%",
1744
+ boxSizing: "border-box",
1745
+ height: controlMetrics.height,
1746
+ borderRadius: 16,
1747
+ border: `1px solid ${error ? theme.colors.negative : (0, import_smartsell_sales_sdk6.withAlpha)(theme.colors.textLight, 0.5)}`,
1748
+ backgroundColor: theme.colors.surface,
1749
+ color: displayLabel ? theme.colors.onSurface : mutedText,
1750
+ cursor: disabled ? "not-allowed" : "pointer",
1751
+ opacity: disabled ? 0.7 : 1,
1752
+ padding: getSelectControlPadding(controlSize),
1753
+ outline: "none",
1754
+ font: "inherit",
1755
+ fontSize: controlMetrics.fontSize,
1756
+ lineHeight: controlMetrics.lineHeight,
1757
+ transition: "border-color 160ms ease, box-shadow 160ms ease, background-color 160ms ease",
1758
+ display: "flex",
1759
+ alignItems: "center",
1760
+ justifyContent: "space-between",
1761
+ gap: 12,
1762
+ minWidth: 0,
1763
+ textAlign: "left",
1764
+ ...style
1765
+ },
1766
+ children: [
1767
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1768
+ "span",
1769
+ {
1770
+ style: {
1771
+ display: "block",
1772
+ flex: "1 1 auto",
1773
+ minWidth: 0,
1774
+ overflow: "hidden",
1775
+ textOverflow: "ellipsis",
1776
+ whiteSpace: "nowrap"
1777
+ },
1778
+ children: displayContent
1779
+ }
1780
+ ),
1781
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1782
+ "span",
1783
+ {
1784
+ "aria-hidden": "true",
1785
+ style: {
1786
+ position: "absolute",
1787
+ right: indicatorOffset,
1788
+ top: "50%",
1789
+ transform: `translateY(-50%) rotate(${isOpen ? 180 : 0}deg)`,
1790
+ transformOrigin: "center",
1791
+ color: disabled ? (0, import_smartsell_sales_sdk6.withAlpha)(theme.colors.onSurface, 0.42) : mutedText,
1792
+ display: "flex",
1793
+ alignItems: "center",
1794
+ justifyContent: "center",
1795
+ pointerEvents: "none",
1796
+ transition: "transform 160ms ease, color 160ms ease"
1797
+ },
1798
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "18", height: "18", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1799
+ "path",
1800
+ {
1801
+ d: "M5.75 7.75L10 12l4.25-4.25",
1802
+ stroke: "currentColor",
1803
+ strokeWidth: "1.8",
1804
+ strokeLinecap: "round",
1805
+ strokeLinejoin: "round"
1806
+ }
1807
+ ) })
1808
+ }
1809
+ )
1810
+ ]
1811
+ }
1812
+ ),
1813
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1814
+ "select",
1815
+ {
1816
+ ...rest,
1817
+ id: `${resolvedId}-native`,
1818
+ ref: hiddenSelectRef,
1819
+ name: rest.name,
1820
+ disabled,
1821
+ multiple: isMultiSelect,
1822
+ value: isMultiSelect ? selectedValues : selectedValue,
1823
+ onChange: handleHiddenSelectChange,
1824
+ tabIndex: -1,
1825
+ "aria-hidden": "true",
1826
+ style: {
1827
+ position: "absolute",
1828
+ width: 1,
1829
+ height: 1,
1830
+ padding: 0,
1831
+ margin: 0,
1832
+ border: 0,
1833
+ opacity: 0,
1834
+ pointerEvents: "none",
1835
+ clipPath: "inset(50%)"
1836
+ },
1837
+ children
1838
+ }
1839
+ ),
1840
+ isOpen ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
1841
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("style", { children: `
1842
+ #${listboxId} {
1843
+ scrollbar-width: thin;
1844
+ scrollbar-color: ${scrollbarThumbColor} transparent;
1845
+ }
1846
+
1847
+ #${listboxId}::-webkit-scrollbar {
1848
+ width: 8px;
1849
+ }
1850
+
1851
+ #${listboxId}::-webkit-scrollbar-track {
1852
+ background: transparent;
1853
+ }
1854
+
1855
+ #${listboxId}::-webkit-scrollbar-thumb {
1856
+ background: ${scrollbarThumbColor};
1857
+ border-radius: 999px;
1858
+ border: 2px solid transparent;
1859
+ background-clip: padding-box;
1860
+ }
1861
+
1862
+ #${listboxId}::-webkit-scrollbar-thumb:hover {
1863
+ background: ${scrollbarThumbHoverColor};
1864
+ background-clip: padding-box;
1865
+ }
1866
+ ` }),
1867
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1868
+ "div",
1869
+ {
1870
+ ref: menuRef,
1871
+ style: {
1872
+ position: "absolute",
1873
+ top: menuPlacement === "bottom" ? `calc(100% + ${MENU_OFFSET}px)` : "auto",
1874
+ bottom: menuPlacement === "top" ? `calc(100% + ${MENU_OFFSET}px)` : "auto",
1875
+ left: 0,
1876
+ right: 0,
1877
+ zIndex: 30,
1878
+ maxHeight: MENU_MAX_HEIGHT,
1879
+ overflow: "hidden",
1880
+ boxSizing: "border-box",
1881
+ borderRadius: 20,
1882
+ border: `1px solid ${(0, import_smartsell_sales_sdk6.withAlpha)(theme.colors.textLight, 0.5)}`,
1883
+ backgroundColor: surfaceRaised,
1884
+ // boxShadow: `0 10px 24px ${withAlpha(theme.colors.onSurface, 0.08)}`,
1885
+ padding: 8,
1886
+ backdropFilter: "blur(6px)",
1887
+ visibility: isPlacementResolved ? "visible" : "hidden",
1888
+ display: "flex",
1889
+ flexDirection: "column",
1890
+ gap: 4
1891
+ },
1892
+ children: [
1893
+ hasFilter ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1894
+ "div",
1895
+ {
1896
+ style: {
1897
+ display: "flex",
1898
+ alignItems: "center",
1899
+ justifyContent: "flex-start",
1900
+ gap: 8,
1901
+ padding: "4px 4px 10px",
1902
+ borderBottom: `1px solid ${(0, import_smartsell_sales_sdk6.withAlpha)(theme.colors.onSurface, 0.08)}`,
1903
+ flexShrink: 0
1904
+ },
1905
+ children: [
1906
+ bulkToggleControl,
1907
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1908
+ "input",
1909
+ {
1910
+ ref: searchInputRef,
1911
+ type: "search",
1912
+ value: filterQuery,
1913
+ onChange: (event) => {
1914
+ setFilterQuery(event.currentTarget.value);
1915
+ },
1916
+ onKeyDown: handleFilterKeyDown,
1917
+ onMouseDown: (event) => {
1918
+ event.stopPropagation();
1919
+ },
1920
+ placeholder: "Search options",
1921
+ "aria-label": "Search options",
1922
+ style: {
1923
+ flex: "1 1 auto",
1924
+ width: "100%",
1925
+ border: `1px solid ${(0, import_smartsell_sales_sdk6.withAlpha)(theme.colors.textLight, 0.5)}`,
1926
+ backgroundColor: theme.colors.surface,
1927
+ padding: "8px 12px",
1928
+ borderRadius: 12,
1929
+ font: "inherit",
1930
+ fontSize: 12,
1931
+ lineHeight: 1.4,
1932
+ color: theme.colors.textLight,
1933
+ outline: "none",
1934
+ boxSizing: "border-box"
1935
+ }
1936
+ }
1937
+ )
1938
+ ]
1939
+ }
1940
+ ) : isMultiSelect ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1941
+ "div",
1942
+ {
1943
+ style: {
1944
+ display: "flex",
1945
+ alignItems: "center",
1946
+ justifyContent: "flex-start",
1947
+ padding: "4px 4px 10px",
1948
+ borderBottom: `1px solid ${(0, import_smartsell_sales_sdk6.withAlpha)(theme.colors.onSurface, 0.08)}`,
1949
+ flexShrink: 0
1950
+ },
1951
+ children: bulkToggleControl
1952
+ }
1953
+ ) : null,
1954
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1955
+ "div",
1956
+ {
1957
+ id: listboxId,
1958
+ role: "listbox",
1959
+ "aria-labelledby": resolvedId,
1960
+ "aria-multiselectable": isMultiSelect || void 0,
1961
+ style: {
1962
+ overflowY: "auto",
1963
+ overflowX: "hidden",
1964
+ minHeight: 0,
1965
+ flex: "1 1 auto"
1966
+ },
1967
+ children: visibleGroups.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1968
+ "div",
1969
+ {
1970
+ style: {
1971
+ padding: "14px 12px",
1972
+ color: mutedText,
1973
+ fontSize: 13,
1974
+ textAlign: "center"
1975
+ },
1976
+ children: "No options found."
1977
+ }
1978
+ ) : visibleGroups.map((group) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1979
+ "div",
1980
+ {
1981
+ style: {
1982
+ display: "flex",
1983
+ flexDirection: "column",
1984
+ gap: 4,
1985
+ marginTop: group.label ? 4 : 0
1986
+ },
1987
+ children: [
1988
+ group.label ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1989
+ "span",
1990
+ {
1991
+ style: {
1992
+ padding: "6px 8px 2px",
1993
+ color: mutedText,
1994
+ fontSize: 11,
1995
+ fontWeight: 800,
1996
+ letterSpacing: "0.08em",
1997
+ textTransform: "uppercase"
1998
+ },
1999
+ children: group.label
2000
+ }
2001
+ ) : null,
2002
+ group.options.map((option) => {
2003
+ const isSelected = selectedValues.includes(option.value);
2004
+ const isHighlighted = option.value === highlightedValue;
2005
+ const isActive = isSelected || isHighlighted;
2006
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2007
+ "div",
2008
+ {
2009
+ role: "option",
2010
+ "aria-selected": isSelected,
2011
+ "aria-disabled": option.disabled,
2012
+ onMouseEnter: () => {
2013
+ if (!option.disabled) {
2014
+ setHighlightedValue(option.value);
2015
+ }
2016
+ },
2017
+ onMouseDown: (event) => {
2018
+ event.preventDefault();
2019
+ },
2020
+ onClick: () => {
2021
+ if (!option.disabled) {
2022
+ commitSelection(option.value);
2023
+ }
2024
+ },
2025
+ style: {
2026
+ display: "flex",
2027
+ alignItems: "center",
2028
+ justifyContent: "space-between",
2029
+ gap: 12,
2030
+ width: "100%",
2031
+ minWidth: 0,
2032
+ boxSizing: "border-box",
2033
+ borderRadius: 14,
2034
+ padding: getOptionPadding(controlSize),
2035
+ cursor: option.disabled ? "not-allowed" : "pointer",
2036
+ color: option.disabled ? (0, import_smartsell_sales_sdk6.withAlpha)(theme.colors.onSurface, 0.38) : isActive ? theme.colors.onPrimary : theme.colors.onSurface,
2037
+ backgroundColor: isSelected ? optionSelectedBackground : isHighlighted ? optionHoverBackground : "transparent",
2038
+ fontWeight: isSelected ? 700 : 500,
2039
+ transition: "background-color 140ms ease, color 140ms ease"
2040
+ },
2041
+ children: [
2042
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2043
+ "span",
2044
+ {
2045
+ style: {
2046
+ display: "flex",
2047
+ alignItems: "center",
2048
+ gap: 10,
2049
+ flex: "1 1 auto",
2050
+ minWidth: 0
2051
+ },
2052
+ children: [
2053
+ isMultiSelect ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2054
+ "span",
2055
+ {
2056
+ "aria-hidden": "true",
2057
+ style: {
2058
+ width: 10,
2059
+ height: 10,
2060
+ borderRadius: 999,
2061
+ flexShrink: 0,
2062
+ border: `1.5px solid ${isSelected ? theme.colors.secondary : "currentColor"}`,
2063
+ backgroundColor: isSelected ? theme.colors.secondary : "transparent",
2064
+ opacity: option.disabled ? 0.45 : 1,
2065
+ transition: "background-color 140ms ease, border-color 140ms ease, opacity 140ms ease"
2066
+ }
2067
+ }
2068
+ ) : null,
2069
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2070
+ "span",
2071
+ {
2072
+ style: {
2073
+ display: "block",
2074
+ flex: "1 1 auto",
2075
+ minWidth: 0,
2076
+ overflow: "hidden",
2077
+ textOverflow: "ellipsis",
2078
+ whiteSpace: "nowrap"
2079
+ },
2080
+ children: option.label
2081
+ }
2082
+ )
2083
+ ]
2084
+ }
2085
+ ),
2086
+ isSelected ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2087
+ "span",
2088
+ {
2089
+ "aria-hidden": "true",
2090
+ style: {
2091
+ display: "flex",
2092
+ alignItems: "center",
2093
+ justifyContent: "center",
2094
+ color: theme.colors.primary,
2095
+ flexShrink: 0
2096
+ },
2097
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2098
+ "path",
2099
+ {
2100
+ d: "M5.75 10.25L8.5 13l5.75-6",
2101
+ stroke: "currentColor",
2102
+ strokeWidth: "1.8",
2103
+ strokeLinecap: "round",
2104
+ strokeLinejoin: "round"
2105
+ }
2106
+ ) })
2107
+ }
2108
+ ) : null
2109
+ ]
2110
+ },
2111
+ option.key
2112
+ );
2113
+ })
2114
+ ]
2115
+ },
2116
+ group.key
2117
+ ))
2118
+ }
2119
+ )
2120
+ ]
2121
+ }
2122
+ )
2123
+ ] }) : null
2124
+ ] });
2125
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2126
+ ControlFrame,
2127
+ {
2128
+ sdk,
2129
+ label,
2130
+ hint,
2131
+ error,
2132
+ htmlFor: resolvedId,
2133
+ required: rest.required,
2134
+ useLabelWrapper: false,
2135
+ children: select
2136
+ }
2137
+ );
1130
2138
  }
1131
2139
 
1132
2140
  // src/components/Textarea.tsx
1133
2141
  var import_smartsell_sales_sdk7 = require("smartsell-sales-sdk");
1134
- var import_jsx_runtime8 = require("react/jsx-runtime");
1135
- var getPadding3 = (size) => {
2142
+ var import_jsx_runtime7 = require("react/jsx-runtime");
2143
+ var getPadding = (size) => {
1136
2144
  if (size === "sm") return "10px 12px";
1137
2145
  if (size === "lg") return "16px 18px";
1138
2146
  return "13px 16px";
@@ -1151,30 +2159,29 @@ function Textarea({
1151
2159
  }) {
1152
2160
  const { theme, borderSoft, focusRing, surfaceMuted } = useUiKitTheme(sdk);
1153
2161
  const textareaStyle = {
2162
+ border: `1px solid ${error ? theme.colors.negative : (0, import_smartsell_sales_sdk7.withAlpha)(theme.colors.textLight, 0.5)}`,
2163
+ backgroundColor: theme.colors.surface,
2164
+ color: theme.colors.text,
2165
+ cursor: disabled ? "not-allowed" : "text",
2166
+ opacity: disabled ? 0.7 : 1,
1154
2167
  width: "100%",
2168
+ boxSizing: "border-box",
1155
2169
  borderRadius: 16,
1156
- border: `1px solid ${error ? theme.colors.negative : borderSoft}`,
1157
- padding: getPadding3(controlSize),
2170
+ padding: getPadding(controlSize),
1158
2171
  outline: "none",
1159
- color: theme.colors.onSurface,
1160
- backgroundColor: disabled ? surfaceMuted : theme.colors.surface,
1161
2172
  boxShadow: error ? `0 0 0 3px ${(0, import_smartsell_sales_sdk7.withAlpha)(theme.colors.negative, 0.12)}` : `0 0 0 0 ${focusRing}`,
1162
2173
  transition: "border-color 160ms ease, box-shadow 160ms ease, background-color 160ms ease",
1163
2174
  resize: "vertical",
1164
2175
  ...style
1165
2176
  };
1166
- const textarea = /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("textarea", { ...rest, id, disabled, rows, style: textareaStyle });
1167
- if (!label && !hint && !error) {
1168
- return textarea;
1169
- }
1170
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Field, { sdk, label, hint, error, htmlFor: id, children: textarea });
2177
+ const textarea = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("textarea", { ...rest, id, disabled, rows, style: textareaStyle });
2178
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ControlFrame, { sdk, label, hint, error, htmlFor: id, required: rest.required, children: textarea });
1171
2179
  }
1172
2180
  // Annotate the CommonJS export names for ESM import in node:
1173
2181
  0 && (module.exports = {
1174
2182
  Button,
1175
2183
  Card,
1176
2184
  ComposableModal,
1177
- Field,
1178
2185
  Input,
1179
2186
  Modal,
1180
2187
  Select,