smartsell-ui-kit 0.0.5 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -24
- package/dist/chunk-YWH2VIAD.js +573 -0
- package/dist/chunk-YWH2VIAD.js.map +1 -0
- package/dist/index.cjs +2554 -674
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +71 -42
- package/dist/index.d.ts +71 -42
- package/dist/index.js +2190 -237
- package/dist/index.js.map +1 -1
- package/dist/{modal-BDeh1TYW.d.cts → modal-B2lmASXk.d.cts} +31 -16
- package/dist/{modal-BDeh1TYW.d.ts → modal-B2lmASXk.d.ts} +31 -16
- package/dist/modal.cjs +293 -355
- package/dist/modal.cjs.map +1 -1
- package/dist/modal.d.cts +2 -2
- package/dist/modal.d.ts +2 -2
- package/dist/modal.js +1 -1
- package/package.json +6 -11
- package/dist/chunk-BI3QBKFG.js +0 -634
- package/dist/chunk-BI3QBKFG.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,20 +1,124 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Modal
|
|
3
|
-
|
|
2
|
+
Modal,
|
|
3
|
+
withAlpha
|
|
4
|
+
} from "./chunk-YWH2VIAD.js";
|
|
4
5
|
|
|
5
6
|
// src/components/Button.tsx
|
|
6
7
|
import { useState } from "react";
|
|
7
|
-
|
|
8
|
+
|
|
9
|
+
// src/components/controlSize.ts
|
|
10
|
+
var CONTROL_METRICS_BY_SIZE = {
|
|
11
|
+
sm: {
|
|
12
|
+
height: 30,
|
|
13
|
+
fontSize: 13,
|
|
14
|
+
lineHeight: "16px",
|
|
15
|
+
paddingX: 12,
|
|
16
|
+
paddingY: 6,
|
|
17
|
+
buttonPaddingX: 14,
|
|
18
|
+
selectPaddingRight: 40,
|
|
19
|
+
selectIndicatorOffset: 12
|
|
20
|
+
},
|
|
21
|
+
md: {
|
|
22
|
+
height: 38,
|
|
23
|
+
fontSize: 14,
|
|
24
|
+
lineHeight: "18px",
|
|
25
|
+
paddingX: 16,
|
|
26
|
+
paddingY: 9,
|
|
27
|
+
buttonPaddingX: 18,
|
|
28
|
+
selectPaddingRight: 44,
|
|
29
|
+
selectIndicatorOffset: 16
|
|
30
|
+
},
|
|
31
|
+
lg: {
|
|
32
|
+
height: 46,
|
|
33
|
+
fontSize: 15,
|
|
34
|
+
lineHeight: "18px",
|
|
35
|
+
paddingX: 18,
|
|
36
|
+
paddingY: 13,
|
|
37
|
+
buttonPaddingX: 20,
|
|
38
|
+
selectPaddingRight: 48,
|
|
39
|
+
selectIndicatorOffset: 18
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
var getControlMetrics = (size) => CONTROL_METRICS_BY_SIZE[size];
|
|
43
|
+
var getTextInputPadding = (size, options = {}) => {
|
|
44
|
+
var _a, _b;
|
|
45
|
+
const metrics = getControlMetrics(size);
|
|
46
|
+
const leadingInset = (_a = options.leadingInset) != null ? _a : 0;
|
|
47
|
+
const trailingInset = (_b = options.trailingInset) != null ? _b : 0;
|
|
48
|
+
return `${metrics.paddingY}px ${metrics.paddingX + trailingInset}px ${metrics.paddingY}px ${metrics.paddingX + leadingInset}px`;
|
|
49
|
+
};
|
|
50
|
+
var getSelectControlPadding = (size) => {
|
|
51
|
+
const metrics = getControlMetrics(size);
|
|
52
|
+
return `${metrics.paddingY}px ${metrics.selectPaddingRight}px ${metrics.paddingY}px ${metrics.paddingX}px`;
|
|
53
|
+
};
|
|
54
|
+
var getSelectIndicatorOffset = (size) => getControlMetrics(size).selectIndicatorOffset;
|
|
55
|
+
var getButtonSizeStyles = (size) => {
|
|
56
|
+
const metrics = getControlMetrics(size);
|
|
57
|
+
return {
|
|
58
|
+
boxSizing: "border-box",
|
|
59
|
+
height: metrics.height,
|
|
60
|
+
padding: `0 ${metrics.buttonPaddingX}px`,
|
|
61
|
+
fontSize: metrics.fontSize,
|
|
62
|
+
lineHeight: metrics.lineHeight
|
|
63
|
+
};
|
|
64
|
+
};
|
|
8
65
|
|
|
9
66
|
// src/theme.ts
|
|
10
67
|
import { useMemo } from "react";
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
68
|
+
import { useThemeValue } from "smartsell-theme";
|
|
69
|
+
var DEFAULT_THEME_COLORS = {
|
|
70
|
+
primary: "#111827",
|
|
71
|
+
secondary: "#6b7280",
|
|
72
|
+
background: "#f8fafc",
|
|
73
|
+
surface: "#ffffff",
|
|
74
|
+
text: "#111827",
|
|
75
|
+
textLight: "#6b7280",
|
|
76
|
+
positive: "#16a34a",
|
|
77
|
+
negative: "#dc2626",
|
|
78
|
+
warning: "#d97706",
|
|
79
|
+
info: "#2563eb",
|
|
80
|
+
onPrimary: "#ffffff"
|
|
81
|
+
};
|
|
82
|
+
function normalizeUiKitTheme(theme) {
|
|
83
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
84
|
+
const colors = theme.colors;
|
|
85
|
+
const primary = (_a = colors.primary) != null ? _a : DEFAULT_THEME_COLORS.primary;
|
|
86
|
+
const background = (_b = colors.background) != null ? _b : DEFAULT_THEME_COLORS.background;
|
|
87
|
+
const surface = (_c = colors.surface) != null ? _c : background;
|
|
88
|
+
const text = (_f = (_e = (_d = colors.text) != null ? _d : colors.onSurface) != null ? _e : colors.onBackground) != null ? _f : DEFAULT_THEME_COLORS.text;
|
|
89
|
+
const textLight = (_h = (_g = colors.textLight) != null ? _g : colors.onSurfaceLight) != null ? _h : text;
|
|
90
|
+
const normalizedColors = {
|
|
91
|
+
...theme.colors,
|
|
92
|
+
primary,
|
|
93
|
+
primaryLight: (_i = colors.primaryLight) != null ? _i : primary,
|
|
94
|
+
primaryDark: (_j = colors.primaryDark) != null ? _j : primary,
|
|
95
|
+
secondary: (_k = colors.secondary) != null ? _k : DEFAULT_THEME_COLORS.secondary,
|
|
96
|
+
background,
|
|
97
|
+
backgroundLight: (_l = colors.backgroundLight) != null ? _l : background,
|
|
98
|
+
surface,
|
|
99
|
+
text,
|
|
100
|
+
textLight,
|
|
101
|
+
positive: (_m = colors.positive) != null ? _m : DEFAULT_THEME_COLORS.positive,
|
|
102
|
+
negative: (_n = colors.negative) != null ? _n : DEFAULT_THEME_COLORS.negative,
|
|
103
|
+
warning: (_o = colors.warning) != null ? _o : DEFAULT_THEME_COLORS.warning,
|
|
104
|
+
info: (_p = colors.info) != null ? _p : DEFAULT_THEME_COLORS.info,
|
|
105
|
+
onPrimary: (_q = colors.onPrimary) != null ? _q : DEFAULT_THEME_COLORS.onPrimary,
|
|
106
|
+
onSecondary: (_r = colors.onSecondary) != null ? _r : text,
|
|
107
|
+
onBackground: (_s = colors.onBackground) != null ? _s : text,
|
|
108
|
+
onSurface: (_t = colors.onSurface) != null ? _t : text,
|
|
109
|
+
onSurfaceLight: (_u = colors.onSurfaceLight) != null ? _u : textLight,
|
|
110
|
+
onWarning: (_v = colors.onWarning) != null ? _v : text
|
|
111
|
+
};
|
|
112
|
+
return {
|
|
113
|
+
...theme,
|
|
114
|
+
colors: normalizedColors,
|
|
115
|
+
color: normalizedColors
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function useUiKitTheme() {
|
|
119
|
+
const activeTheme = useThemeValue();
|
|
17
120
|
return useMemo(() => {
|
|
121
|
+
const theme = normalizeUiKitTheme(activeTheme);
|
|
18
122
|
return {
|
|
19
123
|
theme,
|
|
20
124
|
borderSoft: withAlpha(theme.colors.onSurface, 0.1),
|
|
@@ -25,24 +129,13 @@ function useUiKitTheme(sdk) {
|
|
|
25
129
|
focusRing: withAlpha(theme.colors.primary, 0.22),
|
|
26
130
|
mutedText: withAlpha(theme.colors.onSurface, 0.72)
|
|
27
131
|
};
|
|
28
|
-
}, [
|
|
132
|
+
}, [activeTheme]);
|
|
29
133
|
}
|
|
30
134
|
|
|
31
135
|
// src/components/Button.tsx
|
|
32
136
|
import { jsxs } from "react/jsx-runtime";
|
|
33
|
-
var getSizeStyles = (size) => {
|
|
34
|
-
if (size === "sm") {
|
|
35
|
-
return { minHeight: 38, padding: "0 14px", fontSize: 13 };
|
|
36
|
-
}
|
|
37
|
-
if (size === "lg") {
|
|
38
|
-
return { minHeight: 50, padding: "0 20px", fontSize: 15 };
|
|
39
|
-
}
|
|
40
|
-
return { minHeight: 44, padding: "0 18px", fontSize: 14 };
|
|
41
|
-
};
|
|
42
137
|
function Button({
|
|
43
|
-
sdk,
|
|
44
138
|
variant = "solid",
|
|
45
|
-
tone = "primary",
|
|
46
139
|
size = "md",
|
|
47
140
|
fullWidth = false,
|
|
48
141
|
leadingIcon,
|
|
@@ -63,64 +156,42 @@ function Button({
|
|
|
63
156
|
onTouchCancel,
|
|
64
157
|
...rest
|
|
65
158
|
}) {
|
|
66
|
-
const { theme } = useUiKitTheme(
|
|
159
|
+
const { theme } = useUiKitTheme();
|
|
67
160
|
const [isHovered, setIsHovered] = useState(false);
|
|
68
161
|
const [isPressed, setIsPressed] = useState(false);
|
|
69
|
-
const palette = {
|
|
70
|
-
primary: {
|
|
71
|
-
background: theme.colors.primary,
|
|
72
|
-
foreground: theme.colors.onPrimary,
|
|
73
|
-
border: withAlpha2(theme.colors.primary, 0.3)
|
|
74
|
-
},
|
|
75
|
-
secondary: {
|
|
76
|
-
background: theme.colors.secondary,
|
|
77
|
-
foreground: theme.colors.onSecondary,
|
|
78
|
-
border: withAlpha2(theme.colors.secondary, 0.3)
|
|
79
|
-
},
|
|
80
|
-
neutral: {
|
|
81
|
-
background: theme.colors.surface,
|
|
82
|
-
foreground: theme.colors.onSurface,
|
|
83
|
-
border: withAlpha2(theme.colors.onSurface, 0.16)
|
|
84
|
-
},
|
|
85
|
-
danger: {
|
|
86
|
-
background: theme.colors.negative,
|
|
87
|
-
foreground: "#ffffff",
|
|
88
|
-
border: withAlpha2(theme.colors.negative, 0.32)
|
|
89
|
-
}
|
|
90
|
-
}[tone];
|
|
91
162
|
const variantStyles = {
|
|
92
163
|
solid: {
|
|
93
|
-
backgroundColor:
|
|
94
|
-
borderColor:
|
|
95
|
-
color:
|
|
164
|
+
backgroundColor: theme.colors.primary,
|
|
165
|
+
borderColor: withAlpha(theme.colors.primary, 0.5),
|
|
166
|
+
color: theme.colors.onPrimary
|
|
96
167
|
},
|
|
97
168
|
outline: {
|
|
98
169
|
backgroundColor: "transparent",
|
|
99
|
-
borderColor:
|
|
100
|
-
color:
|
|
170
|
+
borderColor: withAlpha(theme.colors.text, 0.5),
|
|
171
|
+
color: theme.colors.onSurface
|
|
101
172
|
},
|
|
102
173
|
ghost: {
|
|
103
174
|
backgroundColor: "transparent",
|
|
104
175
|
borderColor: "transparent",
|
|
105
|
-
color:
|
|
176
|
+
color: theme.colors.onSurface
|
|
106
177
|
}
|
|
107
178
|
};
|
|
108
|
-
const interactiveColor =
|
|
179
|
+
const interactiveColor = variant === "solid" ? theme.colors.primary : theme.colors.onSurface;
|
|
109
180
|
const isInteractive = !disabled;
|
|
110
181
|
const interactionStyles = {
|
|
111
182
|
solid: {
|
|
112
183
|
transform: isPressed ? "translateY(1px) scale(0.985)" : isHovered ? "translateY(-1px)" : "translateY(0)",
|
|
113
|
-
boxShadow:
|
|
114
|
-
filter:
|
|
184
|
+
boxShadow: "none",
|
|
185
|
+
filter: void 0
|
|
115
186
|
},
|
|
116
187
|
outline: {
|
|
117
188
|
transform: isPressed ? "translateY(1px) scale(0.985)" : isHovered ? "translateY(-1px)" : "translateY(0)",
|
|
118
|
-
backgroundColor: isPressed ?
|
|
119
|
-
boxShadow:
|
|
189
|
+
backgroundColor: isPressed ? withAlpha(interactiveColor, 0.14) : isHovered ? withAlpha(interactiveColor, 0.08) : "transparent",
|
|
190
|
+
boxShadow: "none"
|
|
120
191
|
},
|
|
121
192
|
ghost: {
|
|
122
193
|
transform: isPressed ? "translateY(1px) scale(0.985)" : isHovered ? "translateY(-1px)" : "translateY(0)",
|
|
123
|
-
backgroundColor: isPressed ?
|
|
194
|
+
backgroundColor: isPressed ? withAlpha(interactiveColor, 0.12) : isHovered ? withAlpha(interactiveColor, 0.06) : "transparent",
|
|
124
195
|
boxShadow: "none"
|
|
125
196
|
}
|
|
126
197
|
};
|
|
@@ -192,10 +263,9 @@ function Button({
|
|
|
192
263
|
cursor: disabled ? "not-allowed" : "pointer",
|
|
193
264
|
fontWeight: 700,
|
|
194
265
|
letterSpacing: "0.01em",
|
|
195
|
-
lineHeight: 1,
|
|
196
266
|
opacity: disabled ? 0.58 : 1,
|
|
197
|
-
transition: "transform 140ms ease, opacity 160ms ease, background-color 160ms ease
|
|
198
|
-
...
|
|
267
|
+
transition: "transform 140ms ease, opacity 160ms ease, background-color 160ms ease",
|
|
268
|
+
...getButtonSizeStyles(size),
|
|
199
269
|
...variantStyles[variant],
|
|
200
270
|
...isInteractive ? interactionStyles[variant] : void 0,
|
|
201
271
|
...style
|
|
@@ -210,45 +280,26 @@ function Button({
|
|
|
210
280
|
}
|
|
211
281
|
|
|
212
282
|
// src/components/Card.tsx
|
|
213
|
-
import { withAlpha as withAlpha3 } from "smartsell-sales-sdk";
|
|
214
283
|
import { jsx, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
215
|
-
var getToneStyles = (tone, sdk) => {
|
|
216
|
-
const { theme } = useUiKitTheme(sdk);
|
|
217
|
-
const accent = {
|
|
218
|
-
default: theme.colors.primary,
|
|
219
|
-
primary: theme.colors.primary,
|
|
220
|
-
secondary: theme.colors.secondary,
|
|
221
|
-
warning: theme.colors.warning
|
|
222
|
-
}[tone];
|
|
223
|
-
return {
|
|
224
|
-
accent,
|
|
225
|
-
background: `linear-gradient(160deg, ${withAlpha3(theme.colors.surface, 0.98)}, ${withAlpha3(accent, 0.08)})`,
|
|
226
|
-
border: withAlpha3(accent, 0.22)
|
|
227
|
-
};
|
|
228
|
-
};
|
|
229
284
|
function Card({
|
|
230
|
-
sdk,
|
|
231
285
|
children,
|
|
232
286
|
eyebrow,
|
|
233
287
|
title,
|
|
234
288
|
action,
|
|
235
|
-
tone = "default",
|
|
236
289
|
padded = true,
|
|
237
290
|
style,
|
|
238
291
|
...rest
|
|
239
292
|
}) {
|
|
240
|
-
const { theme
|
|
241
|
-
const toneStyles = getToneStyles(tone, sdk);
|
|
293
|
+
const { theme } = useUiKitTheme();
|
|
242
294
|
return /* @__PURE__ */ jsxs2(
|
|
243
295
|
"div",
|
|
244
296
|
{
|
|
245
297
|
...rest,
|
|
246
298
|
style: {
|
|
247
299
|
borderRadius: 28,
|
|
248
|
-
border: `1px solid ${
|
|
249
|
-
background:
|
|
250
|
-
color: theme.colors.
|
|
251
|
-
boxShadow: `0 24px 48px ${withAlpha3(theme.colors.onSurface, 0.06)}`,
|
|
300
|
+
border: `1px solid ${withAlpha(theme.colors.text, 0.5)}`,
|
|
301
|
+
background: `${withAlpha(theme.colors.background, 0.7)}`,
|
|
302
|
+
color: theme.colors.text,
|
|
252
303
|
padding: padded ? 24 : void 0,
|
|
253
304
|
...style
|
|
254
305
|
},
|
|
@@ -269,7 +320,7 @@ function Card({
|
|
|
269
320
|
"span",
|
|
270
321
|
{
|
|
271
322
|
style: {
|
|
272
|
-
color:
|
|
323
|
+
color: theme.colors.textLight,
|
|
273
324
|
fontSize: 12,
|
|
274
325
|
fontWeight: 800,
|
|
275
326
|
letterSpacing: "0.16em",
|
|
@@ -282,7 +333,7 @@ function Card({
|
|
|
282
333
|
"div",
|
|
283
334
|
{
|
|
284
335
|
style: {
|
|
285
|
-
color: theme.colors.
|
|
336
|
+
color: theme.colors.text,
|
|
286
337
|
fontSize: 24,
|
|
287
338
|
fontWeight: 700,
|
|
288
339
|
lineHeight: 1.2
|
|
@@ -291,7 +342,7 @@ function Card({
|
|
|
291
342
|
}
|
|
292
343
|
) : null
|
|
293
344
|
] }),
|
|
294
|
-
action ? /* @__PURE__ */ jsx("div", { style: { color:
|
|
345
|
+
action ? /* @__PURE__ */ jsx("div", { style: { color: theme.colors.text }, children: action }) : null
|
|
295
346
|
]
|
|
296
347
|
}
|
|
297
348
|
),
|
|
@@ -301,22 +352,265 @@ function Card({
|
|
|
301
352
|
);
|
|
302
353
|
}
|
|
303
354
|
|
|
355
|
+
// src/components/Checkbox.tsx
|
|
356
|
+
import { useEffect, useId, useRef, useState as useState2 } from "react";
|
|
357
|
+
import { jsx as jsx2, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
358
|
+
var CHECKBOX_SIZE_BY_CONTROL_SIZE = {
|
|
359
|
+
sm: 18,
|
|
360
|
+
md: 20,
|
|
361
|
+
lg: 22
|
|
362
|
+
};
|
|
363
|
+
var getCheckboxSize = (controlSize) => CHECKBOX_SIZE_BY_CONTROL_SIZE[controlSize];
|
|
364
|
+
function CheckIcon({ size, color }) {
|
|
365
|
+
return /* @__PURE__ */ jsx2("svg", { width: size, height: size, viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(
|
|
366
|
+
"path",
|
|
367
|
+
{
|
|
368
|
+
d: "M5.75 10.25L8.5 13l5.75-6",
|
|
369
|
+
stroke: color,
|
|
370
|
+
strokeWidth: "1.8",
|
|
371
|
+
strokeLinecap: "round",
|
|
372
|
+
strokeLinejoin: "round"
|
|
373
|
+
}
|
|
374
|
+
) });
|
|
375
|
+
}
|
|
376
|
+
function MixedIcon({ size, color }) {
|
|
377
|
+
return /* @__PURE__ */ jsx2("svg", { width: size, height: size, viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx2("path", { d: "M5.5 10H14.5", stroke: color, strokeWidth: "1.8", strokeLinecap: "round" }) });
|
|
378
|
+
}
|
|
379
|
+
function CheckboxIndicator({
|
|
380
|
+
checked,
|
|
381
|
+
indeterminate = false,
|
|
382
|
+
disabled = false,
|
|
383
|
+
size = 20,
|
|
384
|
+
checkedColor,
|
|
385
|
+
iconColor,
|
|
386
|
+
uncheckedBorderColor,
|
|
387
|
+
uncheckedBackgroundColor = "transparent",
|
|
388
|
+
style
|
|
389
|
+
}) {
|
|
390
|
+
const isActive = checked || indeterminate;
|
|
391
|
+
return /* @__PURE__ */ jsxs3(
|
|
392
|
+
"span",
|
|
393
|
+
{
|
|
394
|
+
"aria-hidden": "true",
|
|
395
|
+
style: {
|
|
396
|
+
width: size,
|
|
397
|
+
height: size,
|
|
398
|
+
borderRadius: 999,
|
|
399
|
+
boxSizing: "border-box",
|
|
400
|
+
flexShrink: 0,
|
|
401
|
+
display: "inline-flex",
|
|
402
|
+
alignItems: "center",
|
|
403
|
+
justifyContent: "center",
|
|
404
|
+
border: `1.5px solid ${isActive ? checkedColor : uncheckedBorderColor}`,
|
|
405
|
+
backgroundColor: isActive ? checkedColor : uncheckedBackgroundColor,
|
|
406
|
+
opacity: disabled ? 0.45 : 1,
|
|
407
|
+
transition: "background-color 140ms ease, border-color 140ms ease, opacity 140ms ease",
|
|
408
|
+
...style
|
|
409
|
+
},
|
|
410
|
+
children: [
|
|
411
|
+
indeterminate ? /* @__PURE__ */ jsx2(MixedIcon, { size: Math.max(10, size - 6), color: iconColor }) : null,
|
|
412
|
+
!indeterminate && checked ? /* @__PURE__ */ jsx2(CheckIcon, { size: Math.max(10, size - 6), color: iconColor }) : null
|
|
413
|
+
]
|
|
414
|
+
}
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
function Checkbox({
|
|
418
|
+
label,
|
|
419
|
+
hint,
|
|
420
|
+
error,
|
|
421
|
+
controlSize = "md",
|
|
422
|
+
id,
|
|
423
|
+
checked,
|
|
424
|
+
defaultChecked,
|
|
425
|
+
disabled,
|
|
426
|
+
indeterminate = false,
|
|
427
|
+
required,
|
|
428
|
+
className,
|
|
429
|
+
style,
|
|
430
|
+
onChange,
|
|
431
|
+
onFocus,
|
|
432
|
+
onBlur,
|
|
433
|
+
...rest
|
|
434
|
+
}) {
|
|
435
|
+
const { theme, mutedText } = useUiKitTheme();
|
|
436
|
+
const controlMetrics = getControlMetrics(controlSize);
|
|
437
|
+
const indicatorSize = getCheckboxSize(controlSize);
|
|
438
|
+
const resolvedId = id != null ? id : `ss-checkbox-${useId().replace(/:/g, "")}`;
|
|
439
|
+
const inputRef = useRef(null);
|
|
440
|
+
const [isFocused, setIsFocused] = useState2(false);
|
|
441
|
+
const [internalChecked, setInternalChecked] = useState2(Boolean(defaultChecked));
|
|
442
|
+
const isControlled = checked !== void 0;
|
|
443
|
+
const resolvedChecked = isControlled ? Boolean(checked) : internalChecked;
|
|
444
|
+
useEffect(() => {
|
|
445
|
+
if (!inputRef.current) {
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
inputRef.current.indeterminate = indeterminate;
|
|
449
|
+
}, [indeterminate, resolvedChecked]);
|
|
450
|
+
return /* @__PURE__ */ jsx2(
|
|
451
|
+
"div",
|
|
452
|
+
{
|
|
453
|
+
className,
|
|
454
|
+
style: {
|
|
455
|
+
width: "100%",
|
|
456
|
+
display: "flex",
|
|
457
|
+
flexDirection: "column",
|
|
458
|
+
gap: 6,
|
|
459
|
+
...style
|
|
460
|
+
},
|
|
461
|
+
children: /* @__PURE__ */ jsxs3(
|
|
462
|
+
"label",
|
|
463
|
+
{
|
|
464
|
+
htmlFor: resolvedId,
|
|
465
|
+
style: {
|
|
466
|
+
display: "inline-flex",
|
|
467
|
+
alignItems: label || hint ? "flex-start" : "center",
|
|
468
|
+
gap: 10,
|
|
469
|
+
width: label || hint || error ? "100%" : "auto",
|
|
470
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
471
|
+
opacity: disabled ? 0.7 : 1,
|
|
472
|
+
userSelect: "none"
|
|
473
|
+
},
|
|
474
|
+
children: [
|
|
475
|
+
/* @__PURE__ */ jsxs3(
|
|
476
|
+
"span",
|
|
477
|
+
{
|
|
478
|
+
style: {
|
|
479
|
+
position: "relative",
|
|
480
|
+
display: "inline-flex",
|
|
481
|
+
alignItems: "center",
|
|
482
|
+
justifyContent: "center",
|
|
483
|
+
flexShrink: 0,
|
|
484
|
+
padding: 2,
|
|
485
|
+
marginTop: label || hint ? 1 : 0,
|
|
486
|
+
borderRadius: 999,
|
|
487
|
+
boxShadow: isFocused ? `0 0 0 3px ${withAlpha(theme.colors.primary, 0.16)}` : "none",
|
|
488
|
+
transition: "box-shadow 140ms ease"
|
|
489
|
+
},
|
|
490
|
+
children: [
|
|
491
|
+
/* @__PURE__ */ jsx2(
|
|
492
|
+
"input",
|
|
493
|
+
{
|
|
494
|
+
...rest,
|
|
495
|
+
ref: inputRef,
|
|
496
|
+
id: resolvedId,
|
|
497
|
+
type: "checkbox",
|
|
498
|
+
checked: resolvedChecked,
|
|
499
|
+
disabled,
|
|
500
|
+
required,
|
|
501
|
+
onChange: (event) => {
|
|
502
|
+
if (!isControlled) {
|
|
503
|
+
setInternalChecked(event.currentTarget.checked);
|
|
504
|
+
}
|
|
505
|
+
onChange == null ? void 0 : onChange(event);
|
|
506
|
+
},
|
|
507
|
+
onFocus: (event) => {
|
|
508
|
+
setIsFocused(true);
|
|
509
|
+
onFocus == null ? void 0 : onFocus(event);
|
|
510
|
+
},
|
|
511
|
+
onBlur: (event) => {
|
|
512
|
+
setIsFocused(false);
|
|
513
|
+
onBlur == null ? void 0 : onBlur(event);
|
|
514
|
+
},
|
|
515
|
+
style: {
|
|
516
|
+
position: "absolute",
|
|
517
|
+
inset: 0,
|
|
518
|
+
width: "100%",
|
|
519
|
+
height: "100%",
|
|
520
|
+
margin: 0,
|
|
521
|
+
opacity: 0,
|
|
522
|
+
cursor: disabled ? "not-allowed" : "pointer"
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
),
|
|
526
|
+
/* @__PURE__ */ jsx2(
|
|
527
|
+
CheckboxIndicator,
|
|
528
|
+
{
|
|
529
|
+
checked: resolvedChecked,
|
|
530
|
+
indeterminate,
|
|
531
|
+
disabled,
|
|
532
|
+
size: indicatorSize,
|
|
533
|
+
checkedColor: theme.colors.primary,
|
|
534
|
+
iconColor: theme.colors.onPrimary,
|
|
535
|
+
uncheckedBorderColor: withAlpha(theme.colors.onSurface, 0.24),
|
|
536
|
+
uncheckedBackgroundColor: theme.colors.surface
|
|
537
|
+
}
|
|
538
|
+
)
|
|
539
|
+
]
|
|
540
|
+
}
|
|
541
|
+
),
|
|
542
|
+
label || hint || error ? /* @__PURE__ */ jsxs3(
|
|
543
|
+
"span",
|
|
544
|
+
{
|
|
545
|
+
style: {
|
|
546
|
+
display: "flex",
|
|
547
|
+
flexDirection: "column",
|
|
548
|
+
gap: 4,
|
|
549
|
+
minWidth: 0
|
|
550
|
+
},
|
|
551
|
+
children: [
|
|
552
|
+
label ? /* @__PURE__ */ jsxs3(
|
|
553
|
+
"span",
|
|
554
|
+
{
|
|
555
|
+
style: {
|
|
556
|
+
color: theme.colors.onSurface,
|
|
557
|
+
fontSize: controlMetrics.fontSize,
|
|
558
|
+
lineHeight: controlMetrics.lineHeight,
|
|
559
|
+
fontWeight: 600
|
|
560
|
+
},
|
|
561
|
+
children: [
|
|
562
|
+
label,
|
|
563
|
+
required ? /* @__PURE__ */ jsx2("span", { style: { color: theme.colors.negative, marginLeft: 4 }, children: "*" }) : null
|
|
564
|
+
]
|
|
565
|
+
}
|
|
566
|
+
) : null,
|
|
567
|
+
hint ? /* @__PURE__ */ jsx2(
|
|
568
|
+
"span",
|
|
569
|
+
{
|
|
570
|
+
style: {
|
|
571
|
+
color: mutedText,
|
|
572
|
+
fontSize: 13,
|
|
573
|
+
lineHeight: 1.45
|
|
574
|
+
},
|
|
575
|
+
children: hint
|
|
576
|
+
}
|
|
577
|
+
) : null,
|
|
578
|
+
error ? /* @__PURE__ */ jsx2(
|
|
579
|
+
"span",
|
|
580
|
+
{
|
|
581
|
+
style: {
|
|
582
|
+
color: theme.colors.negative,
|
|
583
|
+
fontSize: 13,
|
|
584
|
+
lineHeight: 1.45,
|
|
585
|
+
fontWeight: 600
|
|
586
|
+
},
|
|
587
|
+
children: error
|
|
588
|
+
}
|
|
589
|
+
) : null
|
|
590
|
+
]
|
|
591
|
+
}
|
|
592
|
+
) : null
|
|
593
|
+
]
|
|
594
|
+
}
|
|
595
|
+
)
|
|
596
|
+
}
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
|
|
304
600
|
// src/components/ComposableModal.tsx
|
|
305
601
|
import { useMemo as useMemo2 } from "react";
|
|
306
|
-
import {
|
|
307
|
-
import { Fragment, jsx as jsx2, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
602
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
308
603
|
var createModalSlotIds = (slotBaseId) => ({
|
|
309
604
|
header: `${slotBaseId}:modal-header`,
|
|
310
605
|
body: `${slotBaseId}:modal-body`,
|
|
311
606
|
footer: `${slotBaseId}:modal-footer`
|
|
312
607
|
});
|
|
313
608
|
function ComposableModal({
|
|
314
|
-
sdk,
|
|
315
609
|
isOpen,
|
|
316
610
|
onClose,
|
|
317
611
|
title,
|
|
318
|
-
description,
|
|
319
612
|
slotBaseId,
|
|
613
|
+
renderSlot,
|
|
320
614
|
payload,
|
|
321
615
|
onConfirm,
|
|
322
616
|
confirmLabel = "Confirm",
|
|
@@ -332,12 +626,11 @@ function ComposableModal({
|
|
|
332
626
|
footerFallback,
|
|
333
627
|
children
|
|
334
628
|
}) {
|
|
335
|
-
const theme = useUiKitTheme(
|
|
629
|
+
const theme = useUiKitTheme();
|
|
336
630
|
const slotIds = createModalSlotIds(slotBaseId);
|
|
337
631
|
const context = useMemo2(
|
|
338
632
|
() => ({
|
|
339
633
|
title,
|
|
340
|
-
description,
|
|
341
634
|
payload,
|
|
342
635
|
close: onClose,
|
|
343
636
|
confirm: onConfirm,
|
|
@@ -346,48 +639,44 @@ function ComposableModal({
|
|
|
346
639
|
isOpen,
|
|
347
640
|
isBusy
|
|
348
641
|
}),
|
|
349
|
-
[cancelLabel, confirmLabel,
|
|
642
|
+
[cancelLabel, confirmLabel, isBusy, isOpen, onClose, onConfirm, payload, title]
|
|
350
643
|
);
|
|
351
|
-
const defaultFooter = hideDefaultFooter ? void 0 : footerFallback != null ? footerFallback : /* @__PURE__ */
|
|
352
|
-
/* @__PURE__ */
|
|
353
|
-
onConfirm ? /* @__PURE__ */
|
|
354
|
-
] });
|
|
355
|
-
const defaultHeader = headerFallback != null ? headerFallback : /* @__PURE__ */ jsxs3("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
356
|
-
/* @__PURE__ */ jsx2(
|
|
357
|
-
"h2",
|
|
358
|
-
{
|
|
359
|
-
style: {
|
|
360
|
-
margin: 0,
|
|
361
|
-
fontSize: 30,
|
|
362
|
-
fontWeight: 800,
|
|
363
|
-
lineHeight: 1.1
|
|
364
|
-
},
|
|
365
|
-
children: title
|
|
366
|
-
}
|
|
367
|
-
),
|
|
368
|
-
description ? /* @__PURE__ */ jsx2(
|
|
369
|
-
"p",
|
|
370
|
-
{
|
|
371
|
-
style: {
|
|
372
|
-
margin: 0,
|
|
373
|
-
fontSize: 15,
|
|
374
|
-
lineHeight: 1.6,
|
|
375
|
-
opacity: 0.78
|
|
376
|
-
},
|
|
377
|
-
children: description
|
|
378
|
-
}
|
|
379
|
-
) : null
|
|
644
|
+
const defaultFooter = hideDefaultFooter ? void 0 : footerFallback != null ? footerFallback : /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
645
|
+
/* @__PURE__ */ jsx3(Button, { variant: "outline", onClick: onClose, disabled: isBusy, children: cancelLabel }),
|
|
646
|
+
onConfirm ? /* @__PURE__ */ jsx3(Button, { onClick: onConfirm, disabled: isBusy, children: confirmLabel }) : null
|
|
380
647
|
] });
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
648
|
+
const defaultHeader = headerFallback != null ? headerFallback : /* @__PURE__ */ jsx3(
|
|
649
|
+
"h2",
|
|
650
|
+
{
|
|
651
|
+
style: {
|
|
652
|
+
margin: 0,
|
|
653
|
+
fontSize: 30,
|
|
654
|
+
fontWeight: 800,
|
|
655
|
+
lineHeight: 1.1
|
|
656
|
+
},
|
|
657
|
+
children: title
|
|
658
|
+
}
|
|
659
|
+
);
|
|
660
|
+
const renderSlotContent = (id, slotChildren) => {
|
|
661
|
+
if (!renderSlot) {
|
|
662
|
+
return slotChildren;
|
|
663
|
+
}
|
|
664
|
+
return renderSlot({
|
|
665
|
+
id,
|
|
666
|
+
context,
|
|
667
|
+
children: slotChildren
|
|
668
|
+
});
|
|
669
|
+
};
|
|
670
|
+
const headerContent = renderSlotContent(slotIds.header, defaultHeader);
|
|
671
|
+
const bodyContent = renderSlotContent(slotIds.body, children);
|
|
672
|
+
const footerContent = renderSlotContent(slotIds.footer, defaultFooter);
|
|
673
|
+
return /* @__PURE__ */ jsx3(
|
|
385
674
|
Modal,
|
|
386
675
|
{
|
|
387
676
|
isOpen,
|
|
388
677
|
onClose,
|
|
389
678
|
title,
|
|
390
|
-
|
|
679
|
+
isBusy,
|
|
391
680
|
headerContent,
|
|
392
681
|
footer: footerContent,
|
|
393
682
|
theme,
|
|
@@ -401,166 +690,1829 @@ function ComposableModal({
|
|
|
401
690
|
);
|
|
402
691
|
}
|
|
403
692
|
|
|
404
|
-
// src/components/
|
|
405
|
-
import {
|
|
406
|
-
|
|
407
|
-
|
|
693
|
+
// src/components/DatePicker.tsx
|
|
694
|
+
import {
|
|
695
|
+
useEffect as useEffect2,
|
|
696
|
+
useMemo as useMemo3,
|
|
697
|
+
useRef as useRef2,
|
|
698
|
+
useState as useState4
|
|
699
|
+
} from "react";
|
|
700
|
+
|
|
701
|
+
// src/components/Input.tsx
|
|
702
|
+
import { useState as useState3 } from "react";
|
|
703
|
+
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
704
|
+
var PASSWORD_TOGGLE_METRICS_BY_SIZE = {
|
|
705
|
+
sm: {
|
|
706
|
+
buttonSize: 18,
|
|
707
|
+
leftOffset: 8,
|
|
708
|
+
contentGap: 8,
|
|
709
|
+
iconSize: 14
|
|
710
|
+
},
|
|
711
|
+
md: {
|
|
712
|
+
buttonSize: 20,
|
|
713
|
+
leftOffset: 10,
|
|
714
|
+
contentGap: 10,
|
|
715
|
+
iconSize: 16
|
|
716
|
+
},
|
|
717
|
+
lg: {
|
|
718
|
+
buttonSize: 22,
|
|
719
|
+
leftOffset: 12,
|
|
720
|
+
contentGap: 12,
|
|
721
|
+
iconSize: 18
|
|
722
|
+
}
|
|
723
|
+
};
|
|
724
|
+
var getPasswordToggleMetrics = (size) => PASSWORD_TOGGLE_METRICS_BY_SIZE[size];
|
|
725
|
+
function ControlFrame({
|
|
408
726
|
label,
|
|
409
727
|
hint,
|
|
410
728
|
error,
|
|
411
729
|
htmlFor,
|
|
412
730
|
required = false,
|
|
731
|
+
useLabelWrapper = true,
|
|
413
732
|
children,
|
|
414
733
|
style
|
|
415
734
|
}) {
|
|
416
|
-
const { theme, mutedText } = useUiKitTheme(
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
required ? /* @__PURE__ */ jsx3("span", { style: { color: theme.colors.negative, marginLeft: 4 }, children: "*" }) : null
|
|
442
|
-
]
|
|
443
|
-
}
|
|
444
|
-
) : null,
|
|
445
|
-
hint ? /* @__PURE__ */ jsx3(
|
|
446
|
-
"span",
|
|
447
|
-
{
|
|
448
|
-
style: {
|
|
449
|
-
color: mutedText,
|
|
450
|
-
fontSize: 13,
|
|
451
|
-
lineHeight: 1.45
|
|
452
|
-
},
|
|
453
|
-
children: hint
|
|
454
|
-
}
|
|
455
|
-
) : null
|
|
456
|
-
] }),
|
|
457
|
-
children,
|
|
458
|
-
error ? /* @__PURE__ */ jsx3(
|
|
735
|
+
const { theme, mutedText } = useUiKitTheme();
|
|
736
|
+
if (!label && !hint && !error) {
|
|
737
|
+
return /* @__PURE__ */ jsx4(Fragment2, { children });
|
|
738
|
+
}
|
|
739
|
+
const labelStyle = {
|
|
740
|
+
color: theme.colors.onSurface,
|
|
741
|
+
fontSize: 14,
|
|
742
|
+
fontWeight: 700,
|
|
743
|
+
letterSpacing: "0.01em"
|
|
744
|
+
};
|
|
745
|
+
const wrapperStyle = {
|
|
746
|
+
display: "flex",
|
|
747
|
+
flexDirection: "column",
|
|
748
|
+
gap: 8,
|
|
749
|
+
width: "100%",
|
|
750
|
+
...style
|
|
751
|
+
};
|
|
752
|
+
if (!useLabelWrapper) {
|
|
753
|
+
return /* @__PURE__ */ jsxs5("div", { style: wrapperStyle, children: [
|
|
754
|
+
label || hint ? /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
|
|
755
|
+
label ? /* @__PURE__ */ jsxs5("label", { htmlFor, style: labelStyle, children: [
|
|
756
|
+
label,
|
|
757
|
+
required ? /* @__PURE__ */ jsx4("span", { style: { color: theme.colors.negative, marginLeft: 4 }, children: "*" }) : null
|
|
758
|
+
] }) : null,
|
|
759
|
+
hint ? /* @__PURE__ */ jsx4(
|
|
459
760
|
"span",
|
|
460
761
|
{
|
|
461
762
|
style: {
|
|
462
|
-
color:
|
|
763
|
+
color: mutedText,
|
|
463
764
|
fontSize: 13,
|
|
464
|
-
fontWeight: 600,
|
|
465
765
|
lineHeight: 1.45
|
|
466
766
|
},
|
|
467
|
-
children:
|
|
767
|
+
children: hint
|
|
468
768
|
}
|
|
469
769
|
) : null
|
|
470
|
-
]
|
|
471
|
-
|
|
472
|
-
|
|
770
|
+
] }) : null,
|
|
771
|
+
children,
|
|
772
|
+
error ? /* @__PURE__ */ jsx4(
|
|
773
|
+
"span",
|
|
774
|
+
{
|
|
775
|
+
style: {
|
|
776
|
+
color: theme.colors.negative,
|
|
777
|
+
fontSize: 13,
|
|
778
|
+
fontWeight: 600,
|
|
779
|
+
lineHeight: 1.45
|
|
780
|
+
},
|
|
781
|
+
children: error
|
|
782
|
+
}
|
|
783
|
+
) : null
|
|
784
|
+
] });
|
|
785
|
+
}
|
|
786
|
+
return /* @__PURE__ */ jsxs5("label", { htmlFor, style: wrapperStyle, children: [
|
|
787
|
+
label || hint ? /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
|
|
788
|
+
label ? /* @__PURE__ */ jsxs5("span", { style: labelStyle, children: [
|
|
789
|
+
label,
|
|
790
|
+
required ? /* @__PURE__ */ jsx4("span", { style: { color: theme.colors.negative, marginLeft: 4 }, children: "*" }) : null
|
|
791
|
+
] }) : null,
|
|
792
|
+
hint ? /* @__PURE__ */ jsx4(
|
|
793
|
+
"span",
|
|
794
|
+
{
|
|
795
|
+
style: {
|
|
796
|
+
color: mutedText,
|
|
797
|
+
fontSize: 13,
|
|
798
|
+
lineHeight: 1.45
|
|
799
|
+
},
|
|
800
|
+
children: hint
|
|
801
|
+
}
|
|
802
|
+
) : null
|
|
803
|
+
] }) : null,
|
|
804
|
+
children,
|
|
805
|
+
error ? /* @__PURE__ */ jsx4(
|
|
806
|
+
"span",
|
|
807
|
+
{
|
|
808
|
+
style: {
|
|
809
|
+
color: theme.colors.negative,
|
|
810
|
+
fontSize: 13,
|
|
811
|
+
fontWeight: 600,
|
|
812
|
+
lineHeight: 1.45
|
|
813
|
+
},
|
|
814
|
+
children: error
|
|
815
|
+
}
|
|
816
|
+
) : null
|
|
817
|
+
] });
|
|
473
818
|
}
|
|
474
|
-
|
|
475
|
-
// src/components/Input.tsx
|
|
476
|
-
import { withAlpha as withAlpha4 } from "smartsell-sales-sdk";
|
|
477
|
-
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
478
|
-
var getPadding = (size) => {
|
|
479
|
-
if (size === "sm") return "10px 12px";
|
|
480
|
-
if (size === "lg") return "16px 18px";
|
|
481
|
-
return "13px 16px";
|
|
482
|
-
};
|
|
483
819
|
function Input({
|
|
484
|
-
sdk,
|
|
485
820
|
label,
|
|
486
821
|
hint,
|
|
487
822
|
error,
|
|
488
823
|
controlSize = "md",
|
|
824
|
+
showPasswordToggle = false,
|
|
489
825
|
id,
|
|
490
826
|
disabled,
|
|
491
827
|
style,
|
|
828
|
+
type = "text",
|
|
492
829
|
...rest
|
|
493
830
|
}) {
|
|
494
|
-
const { theme,
|
|
831
|
+
const { theme, focusRing } = useUiKitTheme();
|
|
832
|
+
const controlMetrics = getControlMetrics(controlSize);
|
|
833
|
+
const passwordToggleMetrics = getPasswordToggleMetrics(controlSize);
|
|
834
|
+
const [isPasswordVisible, setIsPasswordVisible] = useState3(false);
|
|
835
|
+
const isPasswordField = type === "password";
|
|
836
|
+
const canTogglePasswordVisibility = isPasswordField && showPasswordToggle;
|
|
837
|
+
const passwordToggleInset = Math.max(
|
|
838
|
+
0,
|
|
839
|
+
passwordToggleMetrics.leftOffset + passwordToggleMetrics.buttonSize + passwordToggleMetrics.contentGap - controlMetrics.paddingX
|
|
840
|
+
);
|
|
841
|
+
const leadingInset = Number(canTogglePasswordVisibility) * passwordToggleInset;
|
|
842
|
+
const resolvedType = canTogglePasswordVisibility ? isPasswordVisible ? "text" : "password" : type;
|
|
495
843
|
const inputStyle = {
|
|
496
844
|
width: "100%",
|
|
845
|
+
boxSizing: "border-box",
|
|
846
|
+
height: controlMetrics.height,
|
|
497
847
|
borderRadius: 16,
|
|
498
|
-
border: `1px solid ${error ? theme.colors.negative :
|
|
499
|
-
|
|
848
|
+
border: `1px solid ${error ? theme.colors.negative : withAlpha(theme.colors.textLight, 0.5)}`,
|
|
849
|
+
backgroundColor: theme.colors.surface,
|
|
850
|
+
color: theme.colors.text,
|
|
851
|
+
cursor: disabled ? "not-allowed" : "text",
|
|
852
|
+
opacity: disabled ? 0.7 : 1,
|
|
853
|
+
padding: getTextInputPadding(controlSize, { leadingInset }),
|
|
500
854
|
outline: "none",
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
boxShadow: error ? `0 0 0 3px ${
|
|
855
|
+
fontSize: controlMetrics.fontSize,
|
|
856
|
+
lineHeight: controlMetrics.lineHeight,
|
|
857
|
+
boxShadow: error ? `0 0 0 3px ${withAlpha(theme.colors.negative, 0.12)}` : `0 0 0 0 ${focusRing}`,
|
|
504
858
|
transition: "border-color 160ms ease, box-shadow 160ms ease, background-color 160ms ease",
|
|
505
859
|
...style
|
|
506
860
|
};
|
|
507
|
-
const input = /* @__PURE__ */
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
861
|
+
const input = canTogglePasswordVisibility ? /* @__PURE__ */ jsxs5("div", { style: { position: "relative", width: "100%" }, children: [
|
|
862
|
+
/* @__PURE__ */ jsx4(
|
|
863
|
+
"button",
|
|
864
|
+
{
|
|
865
|
+
type: "button",
|
|
866
|
+
"aria-label": isPasswordVisible ? "Hide password" : "Show password",
|
|
867
|
+
"aria-pressed": isPasswordVisible,
|
|
868
|
+
disabled,
|
|
869
|
+
onMouseDown: (event) => {
|
|
870
|
+
event.preventDefault();
|
|
871
|
+
},
|
|
872
|
+
onClick: () => {
|
|
873
|
+
setIsPasswordVisible((currentValue) => !currentValue);
|
|
874
|
+
},
|
|
875
|
+
style: {
|
|
876
|
+
position: "absolute",
|
|
877
|
+
top: "50%",
|
|
878
|
+
left: passwordToggleMetrics.leftOffset,
|
|
879
|
+
transform: "translateY(-50%)",
|
|
880
|
+
zIndex: 1,
|
|
881
|
+
width: passwordToggleMetrics.buttonSize,
|
|
882
|
+
height: passwordToggleMetrics.buttonSize,
|
|
883
|
+
display: "inline-flex",
|
|
884
|
+
alignItems: "center",
|
|
885
|
+
justifyContent: "center",
|
|
886
|
+
border: "none",
|
|
887
|
+
padding: 0,
|
|
888
|
+
margin: 0,
|
|
889
|
+
borderRadius: 999,
|
|
890
|
+
backgroundColor: "transparent",
|
|
891
|
+
color: isPasswordVisible ? theme.colors.primary : theme.colors.textLight,
|
|
892
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
893
|
+
opacity: disabled ? 0.5 : 1
|
|
894
|
+
},
|
|
895
|
+
children: isPasswordVisible ? /* @__PURE__ */ jsxs5(
|
|
896
|
+
"svg",
|
|
897
|
+
{
|
|
898
|
+
width: passwordToggleMetrics.iconSize,
|
|
899
|
+
height: passwordToggleMetrics.iconSize,
|
|
900
|
+
viewBox: "0 0 20 20",
|
|
901
|
+
fill: "none",
|
|
902
|
+
"aria-hidden": "true",
|
|
903
|
+
children: [
|
|
904
|
+
/* @__PURE__ */ jsx4(
|
|
905
|
+
"path",
|
|
906
|
+
{
|
|
907
|
+
d: "M2.5 3.5L17.5 16.5",
|
|
908
|
+
stroke: "currentColor",
|
|
909
|
+
strokeWidth: "1.8",
|
|
910
|
+
strokeLinecap: "round"
|
|
911
|
+
}
|
|
912
|
+
),
|
|
913
|
+
/* @__PURE__ */ jsx4(
|
|
914
|
+
"path",
|
|
915
|
+
{
|
|
916
|
+
d: "M8.825 8.786a2 2 0 0 0 2.389 2.389",
|
|
917
|
+
stroke: "currentColor",
|
|
918
|
+
strokeWidth: "1.8",
|
|
919
|
+
strokeLinecap: "round",
|
|
920
|
+
strokeLinejoin: "round"
|
|
921
|
+
}
|
|
922
|
+
),
|
|
923
|
+
/* @__PURE__ */ jsx4(
|
|
924
|
+
"path",
|
|
925
|
+
{
|
|
926
|
+
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",
|
|
927
|
+
stroke: "currentColor",
|
|
928
|
+
strokeWidth: "1.8",
|
|
929
|
+
strokeLinecap: "round",
|
|
930
|
+
strokeLinejoin: "round"
|
|
931
|
+
}
|
|
932
|
+
),
|
|
933
|
+
/* @__PURE__ */ jsx4(
|
|
934
|
+
"path",
|
|
935
|
+
{
|
|
936
|
+
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",
|
|
937
|
+
stroke: "currentColor",
|
|
938
|
+
strokeWidth: "1.8",
|
|
939
|
+
strokeLinecap: "round",
|
|
940
|
+
strokeLinejoin: "round"
|
|
941
|
+
}
|
|
942
|
+
)
|
|
943
|
+
]
|
|
944
|
+
}
|
|
945
|
+
) : /* @__PURE__ */ jsxs5(
|
|
946
|
+
"svg",
|
|
947
|
+
{
|
|
948
|
+
width: passwordToggleMetrics.iconSize,
|
|
949
|
+
height: passwordToggleMetrics.iconSize,
|
|
950
|
+
viewBox: "0 0 20 20",
|
|
951
|
+
fill: "none",
|
|
952
|
+
"aria-hidden": "true",
|
|
953
|
+
children: [
|
|
954
|
+
/* @__PURE__ */ jsx4(
|
|
955
|
+
"path",
|
|
956
|
+
{
|
|
957
|
+
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",
|
|
958
|
+
stroke: "currentColor",
|
|
959
|
+
strokeWidth: "1.8",
|
|
960
|
+
strokeLinecap: "round",
|
|
961
|
+
strokeLinejoin: "round"
|
|
962
|
+
}
|
|
963
|
+
),
|
|
964
|
+
/* @__PURE__ */ jsx4("circle", { cx: "10", cy: "10", r: "2.25", stroke: "currentColor", strokeWidth: "1.8" })
|
|
965
|
+
]
|
|
966
|
+
}
|
|
967
|
+
)
|
|
968
|
+
}
|
|
969
|
+
),
|
|
970
|
+
/* @__PURE__ */ jsx4("input", { ...rest, id, type: resolvedType, disabled, style: inputStyle })
|
|
971
|
+
] }) : /* @__PURE__ */ jsx4("input", { ...rest, id, type: resolvedType, disabled, style: inputStyle });
|
|
972
|
+
return /* @__PURE__ */ jsx4(ControlFrame, { label, hint, error, htmlFor: id, required: rest.required, children: input });
|
|
512
973
|
}
|
|
513
974
|
|
|
514
|
-
// src/components/
|
|
515
|
-
import {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
if (size === "lg") return "16px 18px";
|
|
520
|
-
return "13px 16px";
|
|
975
|
+
// src/components/DatePicker.tsx
|
|
976
|
+
import { jsx as jsx5, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
977
|
+
var DEFAULT_FORMAT_BY_MODE = {
|
|
978
|
+
date: "DD/MM/YYYY",
|
|
979
|
+
datetime: "DD/MM/YYYY HH:mm"
|
|
521
980
|
};
|
|
522
|
-
|
|
523
|
-
|
|
981
|
+
var HTML_DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
982
|
+
var HTML_DATETIME_PATTERN = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::\d{2})?$/;
|
|
983
|
+
var FORMAT_TOKENS = [
|
|
984
|
+
{
|
|
985
|
+
token: "YYYY",
|
|
986
|
+
key: "year",
|
|
987
|
+
pattern: "(\\d{4})",
|
|
988
|
+
formatter: (date) => String(date.getFullYear())
|
|
989
|
+
},
|
|
990
|
+
{
|
|
991
|
+
token: "MM",
|
|
992
|
+
key: "month",
|
|
993
|
+
pattern: "(\\d{1,2})",
|
|
994
|
+
formatter: (date) => padNumber(date.getMonth() + 1)
|
|
995
|
+
},
|
|
996
|
+
{
|
|
997
|
+
token: "DD",
|
|
998
|
+
key: "day",
|
|
999
|
+
pattern: "(\\d{1,2})",
|
|
1000
|
+
formatter: (date) => padNumber(date.getDate())
|
|
1001
|
+
},
|
|
1002
|
+
{
|
|
1003
|
+
token: "HH",
|
|
1004
|
+
key: "hour",
|
|
1005
|
+
pattern: "(\\d{1,2})",
|
|
1006
|
+
formatter: (date) => padNumber(date.getHours())
|
|
1007
|
+
},
|
|
1008
|
+
{
|
|
1009
|
+
token: "mm",
|
|
1010
|
+
key: "minute",
|
|
1011
|
+
pattern: "(\\d{1,2})",
|
|
1012
|
+
formatter: (date) => padNumber(date.getMinutes())
|
|
1013
|
+
}
|
|
1014
|
+
];
|
|
1015
|
+
var ACCESSORY_METRICS_BY_SIZE = {
|
|
1016
|
+
sm: {
|
|
1017
|
+
buttonSize: 18,
|
|
1018
|
+
iconSize: 14,
|
|
1019
|
+
rightOffset: 8,
|
|
1020
|
+
clusterGap: 6,
|
|
1021
|
+
contentGap: 8
|
|
1022
|
+
},
|
|
1023
|
+
md: {
|
|
1024
|
+
buttonSize: 20,
|
|
1025
|
+
iconSize: 16,
|
|
1026
|
+
rightOffset: 10,
|
|
1027
|
+
clusterGap: 8,
|
|
1028
|
+
contentGap: 10
|
|
1029
|
+
},
|
|
1030
|
+
lg: {
|
|
1031
|
+
buttonSize: 22,
|
|
1032
|
+
iconSize: 18,
|
|
1033
|
+
rightOffset: 12,
|
|
1034
|
+
clusterGap: 8,
|
|
1035
|
+
contentGap: 12
|
|
1036
|
+
}
|
|
1037
|
+
};
|
|
1038
|
+
function padNumber(value, length = 2) {
|
|
1039
|
+
return String(value).padStart(length, "0");
|
|
1040
|
+
}
|
|
1041
|
+
function escapeRegExp(value) {
|
|
1042
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1043
|
+
}
|
|
1044
|
+
function isValidDateInstance(value) {
|
|
1045
|
+
return !Number.isNaN(value.getTime());
|
|
1046
|
+
}
|
|
1047
|
+
function createValidatedDate(year, month, day, hour = 0, minute = 0) {
|
|
1048
|
+
const nextDate = new Date(year, month - 1, day, hour, minute, 0, 0);
|
|
1049
|
+
if (!isValidDateInstance(nextDate)) {
|
|
1050
|
+
return null;
|
|
1051
|
+
}
|
|
1052
|
+
if (nextDate.getFullYear() !== year || nextDate.getMonth() !== month - 1 || nextDate.getDate() !== day || nextDate.getHours() !== hour || nextDate.getMinutes() !== minute) {
|
|
1053
|
+
return null;
|
|
1054
|
+
}
|
|
1055
|
+
return nextDate;
|
|
1056
|
+
}
|
|
1057
|
+
function normalizeDatePrecision(date, mode) {
|
|
1058
|
+
if (mode === "date") {
|
|
1059
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0);
|
|
1060
|
+
}
|
|
1061
|
+
return new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), 0, 0);
|
|
1062
|
+
}
|
|
1063
|
+
function toLocalInputValue(date, mode) {
|
|
1064
|
+
const normalizedDate = normalizeDatePrecision(date, mode);
|
|
1065
|
+
const datePart = `${normalizedDate.getFullYear()}-${padNumber(normalizedDate.getMonth() + 1)}-${padNumber(normalizedDate.getDate())}`;
|
|
1066
|
+
if (mode === "date") {
|
|
1067
|
+
return datePart;
|
|
1068
|
+
}
|
|
1069
|
+
return `${datePart}T${padNumber(normalizedDate.getHours())}:${padNumber(normalizedDate.getMinutes())}`;
|
|
1070
|
+
}
|
|
1071
|
+
function parseHtmlDateLikeValue(value) {
|
|
1072
|
+
const trimmedValue = value.trim();
|
|
1073
|
+
const dateMatch = HTML_DATE_PATTERN.exec(trimmedValue);
|
|
1074
|
+
if (dateMatch) {
|
|
1075
|
+
return createValidatedDate(
|
|
1076
|
+
Number(dateMatch[1]),
|
|
1077
|
+
Number(dateMatch[2]),
|
|
1078
|
+
Number(dateMatch[3])
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
1081
|
+
const datetimeMatch = HTML_DATETIME_PATTERN.exec(trimmedValue);
|
|
1082
|
+
if (datetimeMatch) {
|
|
1083
|
+
return createValidatedDate(
|
|
1084
|
+
Number(datetimeMatch[1]),
|
|
1085
|
+
Number(datetimeMatch[2]),
|
|
1086
|
+
Number(datetimeMatch[3]),
|
|
1087
|
+
Number(datetimeMatch[4]),
|
|
1088
|
+
Number(datetimeMatch[5])
|
|
1089
|
+
);
|
|
1090
|
+
}
|
|
1091
|
+
return null;
|
|
1092
|
+
}
|
|
1093
|
+
function parseFormattedDateValue(value, format, mode) {
|
|
1094
|
+
const orderedParts = [];
|
|
1095
|
+
let expression = "^";
|
|
1096
|
+
for (let index = 0; index < format.length; ) {
|
|
1097
|
+
const token = FORMAT_TOKENS.find(({ token: currentToken }) => format.startsWith(currentToken, index));
|
|
1098
|
+
if (token) {
|
|
1099
|
+
expression += token.pattern;
|
|
1100
|
+
orderedParts.push(token.key);
|
|
1101
|
+
index += token.token.length;
|
|
1102
|
+
continue;
|
|
1103
|
+
}
|
|
1104
|
+
expression += escapeRegExp(format[index]);
|
|
1105
|
+
index += 1;
|
|
1106
|
+
}
|
|
1107
|
+
expression += "$";
|
|
1108
|
+
const match = new RegExp(expression).exec(value.trim());
|
|
1109
|
+
if (!match) {
|
|
1110
|
+
return null;
|
|
1111
|
+
}
|
|
1112
|
+
const resolvedParts = {
|
|
1113
|
+
year: 0,
|
|
1114
|
+
month: 1,
|
|
1115
|
+
day: 1,
|
|
1116
|
+
hour: 0,
|
|
1117
|
+
minute: 0
|
|
1118
|
+
};
|
|
1119
|
+
orderedParts.forEach((key, index) => {
|
|
1120
|
+
resolvedParts[key] = Number(match[index + 1]);
|
|
1121
|
+
});
|
|
1122
|
+
if (!resolvedParts.year || !resolvedParts.month || !resolvedParts.day) {
|
|
1123
|
+
return null;
|
|
1124
|
+
}
|
|
1125
|
+
return createValidatedDate(
|
|
1126
|
+
resolvedParts.year,
|
|
1127
|
+
resolvedParts.month,
|
|
1128
|
+
resolvedParts.day,
|
|
1129
|
+
mode === "datetime" ? resolvedParts.hour : 0,
|
|
1130
|
+
mode === "datetime" ? resolvedParts.minute : 0
|
|
1131
|
+
);
|
|
1132
|
+
}
|
|
1133
|
+
function parseDateValue(value, mode, format) {
|
|
1134
|
+
if (value == null || value === "") {
|
|
1135
|
+
return null;
|
|
1136
|
+
}
|
|
1137
|
+
if (value instanceof Date) {
|
|
1138
|
+
return isValidDateInstance(value) ? normalizeDatePrecision(value, mode) : null;
|
|
1139
|
+
}
|
|
1140
|
+
if (typeof value !== "string") {
|
|
1141
|
+
return null;
|
|
1142
|
+
}
|
|
1143
|
+
const parsedFormattedDate = parseFormattedDateValue(value, format, mode);
|
|
1144
|
+
if (parsedFormattedDate) {
|
|
1145
|
+
return normalizeDatePrecision(parsedFormattedDate, mode);
|
|
1146
|
+
}
|
|
1147
|
+
const parsedHtmlDate = parseHtmlDateLikeValue(value);
|
|
1148
|
+
if (parsedHtmlDate) {
|
|
1149
|
+
return normalizeDatePrecision(parsedHtmlDate, mode);
|
|
1150
|
+
}
|
|
1151
|
+
const parsedNativeDate = new Date(value);
|
|
1152
|
+
return isValidDateInstance(parsedNativeDate) ? normalizeDatePrecision(parsedNativeDate, mode) : null;
|
|
1153
|
+
}
|
|
1154
|
+
function formatDateValue(date, format) {
|
|
1155
|
+
return FORMAT_TOKENS.reduce((currentFormat, token) => {
|
|
1156
|
+
return currentFormat.split(token.token).join(token.formatter(date));
|
|
1157
|
+
}, format);
|
|
1158
|
+
}
|
|
1159
|
+
function getLaterDate(leftDate, rightDate) {
|
|
1160
|
+
if (!leftDate) return rightDate;
|
|
1161
|
+
if (!rightDate) return leftDate;
|
|
1162
|
+
return leftDate.getTime() >= rightDate.getTime() ? leftDate : rightDate;
|
|
1163
|
+
}
|
|
1164
|
+
function getEarlierDate(leftDate, rightDate) {
|
|
1165
|
+
if (!leftDate) return rightDate;
|
|
1166
|
+
if (!rightDate) return leftDate;
|
|
1167
|
+
return leftDate.getTime() <= rightDate.getTime() ? leftDate : rightDate;
|
|
1168
|
+
}
|
|
1169
|
+
function CalendarIcon({ size }) {
|
|
1170
|
+
return /* @__PURE__ */ jsxs6("svg", { width: size, height: size, viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: [
|
|
1171
|
+
/* @__PURE__ */ jsx5("rect", { x: "3", y: "4.5", width: "14", height: "12.5", rx: "3", stroke: "currentColor", strokeWidth: "1.6" }),
|
|
1172
|
+
/* @__PURE__ */ jsx5("path", { d: "M6.25 2.75V6", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round" }),
|
|
1173
|
+
/* @__PURE__ */ jsx5("path", { d: "M13.75 2.75V6", stroke: "currentColor", strokeWidth: "1.6", strokeLinecap: "round" }),
|
|
1174
|
+
/* @__PURE__ */ jsx5("path", { d: "M3 7.5H17", stroke: "currentColor", strokeWidth: "1.6" }),
|
|
1175
|
+
/* @__PURE__ */ jsx5("circle", { cx: "10", cy: "11.5", r: "1.2", fill: "currentColor" })
|
|
1176
|
+
] });
|
|
1177
|
+
}
|
|
1178
|
+
function ClearIcon({ size }) {
|
|
1179
|
+
return /* @__PURE__ */ jsxs6("svg", { width: size, height: size, viewBox: "0 0 20 20", fill: "none", "aria-hidden": "true", children: [
|
|
1180
|
+
/* @__PURE__ */ jsx5("path", { d: "M5 5L15 15", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" }),
|
|
1181
|
+
/* @__PURE__ */ jsx5("path", { d: "M15 5L5 15", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" })
|
|
1182
|
+
] });
|
|
1183
|
+
}
|
|
1184
|
+
function DatePicker({
|
|
524
1185
|
label,
|
|
525
1186
|
hint,
|
|
526
1187
|
error,
|
|
527
1188
|
controlSize = "md",
|
|
1189
|
+
value,
|
|
1190
|
+
defaultValue,
|
|
1191
|
+
onChange,
|
|
1192
|
+
mode = "date",
|
|
1193
|
+
format,
|
|
1194
|
+
allowPastDates = true,
|
|
1195
|
+
allowFutureDates = true,
|
|
1196
|
+
minDate,
|
|
1197
|
+
maxDate,
|
|
1198
|
+
minuteStep = 5,
|
|
1199
|
+
clearable = true,
|
|
1200
|
+
showPickerButton = true,
|
|
1201
|
+
isDateUnavailable,
|
|
1202
|
+
invalidDateMessage,
|
|
1203
|
+
unavailableDateMessage,
|
|
1204
|
+
pickerButtonLabel,
|
|
1205
|
+
clearButtonLabel,
|
|
528
1206
|
id,
|
|
1207
|
+
name,
|
|
529
1208
|
disabled,
|
|
1209
|
+
readOnly,
|
|
1210
|
+
required,
|
|
530
1211
|
style,
|
|
531
|
-
|
|
1212
|
+
className,
|
|
1213
|
+
placeholder,
|
|
1214
|
+
onBlur,
|
|
1215
|
+
onFocus,
|
|
1216
|
+
onKeyDown,
|
|
532
1217
|
...rest
|
|
533
1218
|
}) {
|
|
534
|
-
|
|
535
|
-
const
|
|
1219
|
+
var _a;
|
|
1220
|
+
const { theme, focusRing } = useUiKitTheme();
|
|
1221
|
+
const controlMetrics = getControlMetrics(controlSize);
|
|
1222
|
+
const accessoryMetrics = ACCESSORY_METRICS_BY_SIZE[controlSize];
|
|
1223
|
+
const generatedIdRef = useRef2();
|
|
1224
|
+
const visibleInputRef = useRef2(null);
|
|
1225
|
+
const nativeInputRef = useRef2(null);
|
|
1226
|
+
const [internalError, setInternalError] = useState4();
|
|
1227
|
+
const resolvedFormat = (format == null ? void 0 : format.trim()) ? format : DEFAULT_FORMAT_BY_MODE[mode];
|
|
1228
|
+
const isControlled = value !== void 0;
|
|
1229
|
+
const nativePickerType = mode === "datetime" ? "datetime-local" : "date";
|
|
1230
|
+
if (!generatedIdRef.current) {
|
|
1231
|
+
generatedIdRef.current = `ss-date-picker-${Math.random().toString(36).slice(2, 10)}`;
|
|
1232
|
+
}
|
|
1233
|
+
const resolvedId = id != null ? id : generatedIdRef.current;
|
|
1234
|
+
const normalizedDefaultValue = useMemo3(() => {
|
|
1235
|
+
const parsedDefaultValue = parseDateValue(defaultValue, mode, resolvedFormat);
|
|
1236
|
+
return parsedDefaultValue ? toLocalInputValue(parsedDefaultValue, mode) : null;
|
|
1237
|
+
}, [defaultValue, mode, resolvedFormat]);
|
|
1238
|
+
const [uncontrolledValue, setUncontrolledValue] = useState4(normalizedDefaultValue);
|
|
1239
|
+
const committedDate = useMemo3(() => {
|
|
1240
|
+
const sourceValue = isControlled ? value : uncontrolledValue;
|
|
1241
|
+
return parseDateValue(sourceValue, mode, resolvedFormat);
|
|
1242
|
+
}, [isControlled, mode, resolvedFormat, uncontrolledValue, value]);
|
|
1243
|
+
const committedValue = committedDate ? toLocalInputValue(committedDate, mode) : null;
|
|
1244
|
+
const committedDisplayValue = committedDate ? formatDateValue(committedDate, resolvedFormat) : "";
|
|
1245
|
+
const [draftValue, setDraftValue] = useState4(committedDisplayValue);
|
|
1246
|
+
useEffect2(() => {
|
|
1247
|
+
setDraftValue(committedDisplayValue);
|
|
1248
|
+
setInternalError(void 0);
|
|
1249
|
+
}, [committedDisplayValue]);
|
|
1250
|
+
useEffect2(() => {
|
|
1251
|
+
if (!isControlled) {
|
|
1252
|
+
setUncontrolledValue((currentValue) => {
|
|
1253
|
+
if (currentValue == null) {
|
|
1254
|
+
return currentValue;
|
|
1255
|
+
}
|
|
1256
|
+
const parsedCurrentValue = parseDateValue(currentValue, mode, resolvedFormat);
|
|
1257
|
+
return parsedCurrentValue ? toLocalInputValue(parsedCurrentValue, mode) : null;
|
|
1258
|
+
});
|
|
1259
|
+
}
|
|
1260
|
+
}, [isControlled, mode, resolvedFormat]);
|
|
1261
|
+
const parsedMinDate = useMemo3(() => {
|
|
1262
|
+
const explicitMinDate = parseDateValue(minDate, mode, resolvedFormat);
|
|
1263
|
+
const guardedMinDate = allowPastDates ? null : normalizeDatePrecision(/* @__PURE__ */ new Date(), mode);
|
|
1264
|
+
return getLaterDate(explicitMinDate, guardedMinDate);
|
|
1265
|
+
}, [allowPastDates, minDate, mode, resolvedFormat]);
|
|
1266
|
+
const parsedMaxDate = useMemo3(() => {
|
|
1267
|
+
const explicitMaxDate = parseDateValue(maxDate, mode, resolvedFormat);
|
|
1268
|
+
const guardedMaxDate = allowFutureDates ? null : normalizeDatePrecision(/* @__PURE__ */ new Date(), mode);
|
|
1269
|
+
return getEarlierDate(explicitMaxDate, guardedMaxDate);
|
|
1270
|
+
}, [allowFutureDates, maxDate, mode, resolvedFormat]);
|
|
1271
|
+
const hasExternalError = error !== void 0 && error !== null && error !== "";
|
|
1272
|
+
const hasConfigurationConflict = Boolean(parsedMinDate && parsedMaxDate && parsedMinDate.getTime() > parsedMaxDate.getTime());
|
|
1273
|
+
const derivedError = hasConfigurationConflict ? "Current date rules do not allow any selection." : internalError;
|
|
1274
|
+
const resolvedError = hasExternalError ? error : derivedError;
|
|
1275
|
+
const hasAnyValue = draftValue.trim().length > 0 || Boolean(committedValue);
|
|
1276
|
+
const canOpenPicker = showPickerButton && !disabled && !readOnly && !hasConfigurationConflict;
|
|
1277
|
+
const canClear = clearable && !disabled && !readOnly && !required && hasAnyValue;
|
|
1278
|
+
const visibleButtonCount = Number(canOpenPicker) + Number(canClear);
|
|
1279
|
+
const trailingInset = visibleButtonCount > 0 ? Math.max(
|
|
1280
|
+
0,
|
|
1281
|
+
accessoryMetrics.rightOffset + visibleButtonCount * accessoryMetrics.buttonSize + (visibleButtonCount - 1) * accessoryMetrics.clusterGap + accessoryMetrics.contentGap - controlMetrics.paddingX
|
|
1282
|
+
) : 0;
|
|
1283
|
+
const getValidationMessage = (parsedDate) => {
|
|
1284
|
+
if (parsedMinDate && parsedDate.getTime() < parsedMinDate.getTime()) {
|
|
1285
|
+
return `Choose a value on or after ${formatDateValue(parsedMinDate, resolvedFormat)}.`;
|
|
1286
|
+
}
|
|
1287
|
+
if (parsedMaxDate && parsedDate.getTime() > parsedMaxDate.getTime()) {
|
|
1288
|
+
return `Choose a value on or before ${formatDateValue(parsedMaxDate, resolvedFormat)}.`;
|
|
1289
|
+
}
|
|
1290
|
+
if (mode === "datetime" && minuteStep > 1 && parsedDate.getMinutes() % minuteStep !== 0) {
|
|
1291
|
+
return `Minutes must use ${minuteStep}-minute intervals.`;
|
|
1292
|
+
}
|
|
1293
|
+
if (isDateUnavailable == null ? void 0 : isDateUnavailable(parsedDate)) {
|
|
1294
|
+
return unavailableDateMessage != null ? unavailableDateMessage : "This date is not available.";
|
|
1295
|
+
}
|
|
1296
|
+
return void 0;
|
|
1297
|
+
};
|
|
1298
|
+
const emitChange = (nextValue, context) => {
|
|
1299
|
+
onChange == null ? void 0 : onChange(nextValue, context);
|
|
1300
|
+
};
|
|
1301
|
+
const commitValue = (nextValue, reason) => {
|
|
1302
|
+
if (hasConfigurationConflict) {
|
|
1303
|
+
setInternalError("Current date rules do not allow any selection.");
|
|
1304
|
+
return false;
|
|
1305
|
+
}
|
|
1306
|
+
if (!nextValue) {
|
|
1307
|
+
if (!isControlled) {
|
|
1308
|
+
setUncontrolledValue(null);
|
|
1309
|
+
}
|
|
1310
|
+
setDraftValue("");
|
|
1311
|
+
setInternalError(void 0);
|
|
1312
|
+
emitChange(null, {
|
|
1313
|
+
reason,
|
|
1314
|
+
date: null,
|
|
1315
|
+
nativeValue: "",
|
|
1316
|
+
displayValue: ""
|
|
1317
|
+
});
|
|
1318
|
+
return true;
|
|
1319
|
+
}
|
|
1320
|
+
const parsedDate = parseHtmlDateLikeValue(nextValue);
|
|
1321
|
+
if (!parsedDate) {
|
|
1322
|
+
setInternalError(invalidDateMessage != null ? invalidDateMessage : `Enter a valid value using ${resolvedFormat}.`);
|
|
1323
|
+
return false;
|
|
1324
|
+
}
|
|
1325
|
+
const normalizedDate = normalizeDatePrecision(parsedDate, mode);
|
|
1326
|
+
const validationMessage = getValidationMessage(normalizedDate);
|
|
1327
|
+
if (validationMessage) {
|
|
1328
|
+
setInternalError(validationMessage);
|
|
1329
|
+
return false;
|
|
1330
|
+
}
|
|
1331
|
+
const normalizedValue = toLocalInputValue(normalizedDate, mode);
|
|
1332
|
+
const displayValue = formatDateValue(normalizedDate, resolvedFormat);
|
|
1333
|
+
if (!isControlled) {
|
|
1334
|
+
setUncontrolledValue(normalizedValue);
|
|
1335
|
+
}
|
|
1336
|
+
setDraftValue(displayValue);
|
|
1337
|
+
setInternalError(void 0);
|
|
1338
|
+
emitChange(normalizedValue, {
|
|
1339
|
+
reason,
|
|
1340
|
+
date: normalizedDate,
|
|
1341
|
+
nativeValue: normalizedValue,
|
|
1342
|
+
displayValue
|
|
1343
|
+
});
|
|
1344
|
+
return true;
|
|
1345
|
+
};
|
|
1346
|
+
const commitDraftValue = () => {
|
|
1347
|
+
var _a2, _b;
|
|
1348
|
+
const trimmedDraftValue = draftValue.trim();
|
|
1349
|
+
if (!trimmedDraftValue) {
|
|
1350
|
+
return commitValue(null, "clear");
|
|
1351
|
+
}
|
|
1352
|
+
const parsedDraftDate = (_b = (_a2 = parseFormattedDateValue(trimmedDraftValue, resolvedFormat, mode)) != null ? _a2 : parseHtmlDateLikeValue(trimmedDraftValue)) != null ? _b : parseDateValue(trimmedDraftValue, mode, resolvedFormat);
|
|
1353
|
+
if (!parsedDraftDate) {
|
|
1354
|
+
setInternalError(invalidDateMessage != null ? invalidDateMessage : `Enter a valid value using ${resolvedFormat}.`);
|
|
1355
|
+
return false;
|
|
1356
|
+
}
|
|
1357
|
+
return commitValue(toLocalInputValue(parsedDraftDate, mode), "input");
|
|
1358
|
+
};
|
|
1359
|
+
const openNativePicker = () => {
|
|
1360
|
+
var _a2, _b;
|
|
1361
|
+
if (!canOpenPicker || !nativeInputRef.current) {
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1364
|
+
const parsedDraftDate = draftValue.trim() ? (_a2 = parseFormattedDateValue(draftValue, resolvedFormat, mode)) != null ? _a2 : parseHtmlDateLikeValue(draftValue) : null;
|
|
1365
|
+
if (parsedDraftDate) {
|
|
1366
|
+
nativeInputRef.current.value = toLocalInputValue(parsedDraftDate, mode);
|
|
1367
|
+
}
|
|
1368
|
+
const pickerInput = nativeInputRef.current;
|
|
1369
|
+
try {
|
|
1370
|
+
if (pickerInput.showPicker) {
|
|
1371
|
+
pickerInput.showPicker();
|
|
1372
|
+
return;
|
|
1373
|
+
}
|
|
1374
|
+
pickerInput.focus();
|
|
1375
|
+
} catch {
|
|
1376
|
+
(_b = visibleInputRef.current) == null ? void 0 : _b.focus();
|
|
1377
|
+
}
|
|
1378
|
+
};
|
|
1379
|
+
const inputStyle = {
|
|
536
1380
|
width: "100%",
|
|
1381
|
+
boxSizing: "border-box",
|
|
1382
|
+
height: controlMetrics.height,
|
|
537
1383
|
borderRadius: 16,
|
|
538
|
-
border: `1px solid ${
|
|
539
|
-
|
|
1384
|
+
border: `1px solid ${resolvedError ? theme.colors.negative : withAlpha(theme.colors.textLight, 0.5)}`,
|
|
1385
|
+
backgroundColor: theme.colors.surface,
|
|
1386
|
+
color: theme.colors.text,
|
|
1387
|
+
cursor: disabled ? "not-allowed" : readOnly ? "default" : "text",
|
|
1388
|
+
opacity: disabled ? 0.7 : 1,
|
|
1389
|
+
padding: getTextInputPadding(controlSize, { trailingInset }),
|
|
540
1390
|
outline: "none",
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
boxShadow:
|
|
1391
|
+
fontSize: controlMetrics.fontSize,
|
|
1392
|
+
lineHeight: controlMetrics.lineHeight,
|
|
1393
|
+
boxShadow: resolvedError ? `0 0 0 3px ${withAlpha(theme.colors.negative, 0.12)}` : `0 0 0 0 ${focusRing}`,
|
|
544
1394
|
transition: "border-color 160ms ease, box-shadow 160ms ease, background-color 160ms ease",
|
|
545
1395
|
...style
|
|
546
1396
|
};
|
|
547
|
-
const
|
|
548
|
-
|
|
549
|
-
|
|
1397
|
+
const accessoryButtonStyle = {
|
|
1398
|
+
width: accessoryMetrics.buttonSize,
|
|
1399
|
+
height: accessoryMetrics.buttonSize,
|
|
1400
|
+
border: "none",
|
|
1401
|
+
padding: 0,
|
|
1402
|
+
margin: 0,
|
|
1403
|
+
display: "inline-flex",
|
|
1404
|
+
alignItems: "center",
|
|
1405
|
+
justifyContent: "center",
|
|
1406
|
+
borderRadius: 999,
|
|
1407
|
+
backgroundColor: "transparent",
|
|
1408
|
+
color: theme.colors.textLight,
|
|
1409
|
+
cursor: disabled || readOnly ? "not-allowed" : "pointer",
|
|
1410
|
+
opacity: disabled ? 0.5 : 1
|
|
1411
|
+
};
|
|
1412
|
+
const input = /* @__PURE__ */ jsxs6("div", { style: { position: "relative", width: "100%" }, children: [
|
|
1413
|
+
/* @__PURE__ */ jsx5(
|
|
1414
|
+
"input",
|
|
1415
|
+
{
|
|
1416
|
+
...rest,
|
|
1417
|
+
ref: visibleInputRef,
|
|
1418
|
+
id: resolvedId,
|
|
1419
|
+
className,
|
|
1420
|
+
type: "text",
|
|
1421
|
+
value: draftValue,
|
|
1422
|
+
disabled,
|
|
1423
|
+
readOnly,
|
|
1424
|
+
required,
|
|
1425
|
+
placeholder: placeholder != null ? placeholder : resolvedFormat,
|
|
1426
|
+
autoComplete: (_a = rest.autoComplete) != null ? _a : "off",
|
|
1427
|
+
spellCheck: false,
|
|
1428
|
+
"aria-invalid": Boolean(resolvedError),
|
|
1429
|
+
onChange: (event) => {
|
|
1430
|
+
setDraftValue(event.target.value);
|
|
1431
|
+
setInternalError(void 0);
|
|
1432
|
+
},
|
|
1433
|
+
onFocus: (event) => {
|
|
1434
|
+
setInternalError(void 0);
|
|
1435
|
+
onFocus == null ? void 0 : onFocus(event);
|
|
1436
|
+
},
|
|
1437
|
+
onBlur: (event) => {
|
|
1438
|
+
commitDraftValue();
|
|
1439
|
+
onBlur == null ? void 0 : onBlur(event);
|
|
1440
|
+
},
|
|
1441
|
+
onKeyDown: (event) => {
|
|
1442
|
+
onKeyDown == null ? void 0 : onKeyDown(event);
|
|
1443
|
+
if (event.defaultPrevented) {
|
|
1444
|
+
return;
|
|
1445
|
+
}
|
|
1446
|
+
if (event.key === "Enter") {
|
|
1447
|
+
event.preventDefault();
|
|
1448
|
+
commitDraftValue();
|
|
1449
|
+
return;
|
|
1450
|
+
}
|
|
1451
|
+
if (event.key === "Escape") {
|
|
1452
|
+
event.preventDefault();
|
|
1453
|
+
setDraftValue(committedDisplayValue);
|
|
1454
|
+
setInternalError(void 0);
|
|
1455
|
+
}
|
|
1456
|
+
},
|
|
1457
|
+
style: inputStyle
|
|
1458
|
+
}
|
|
1459
|
+
),
|
|
1460
|
+
/* @__PURE__ */ jsx5(
|
|
1461
|
+
"input",
|
|
1462
|
+
{
|
|
1463
|
+
ref: nativeInputRef,
|
|
1464
|
+
tabIndex: -1,
|
|
1465
|
+
"aria-hidden": "true",
|
|
1466
|
+
name,
|
|
1467
|
+
type: nativePickerType,
|
|
1468
|
+
value: committedValue != null ? committedValue : "",
|
|
1469
|
+
min: parsedMinDate ? toLocalInputValue(parsedMinDate, mode) : void 0,
|
|
1470
|
+
max: parsedMaxDate ? toLocalInputValue(parsedMaxDate, mode) : void 0,
|
|
1471
|
+
step: mode === "datetime" ? Math.max(1, minuteStep) * 60 : void 0,
|
|
1472
|
+
disabled: disabled || readOnly || hasConfigurationConflict,
|
|
1473
|
+
onChange: (event) => {
|
|
1474
|
+
commitValue(event.target.value || null, "picker");
|
|
1475
|
+
},
|
|
1476
|
+
style: {
|
|
1477
|
+
position: "absolute",
|
|
1478
|
+
width: 1,
|
|
1479
|
+
height: 1,
|
|
1480
|
+
padding: 0,
|
|
1481
|
+
margin: -1,
|
|
1482
|
+
overflow: "hidden",
|
|
1483
|
+
clip: "rect(0, 0, 0, 0)",
|
|
1484
|
+
whiteSpace: "nowrap",
|
|
1485
|
+
border: 0,
|
|
1486
|
+
opacity: 0,
|
|
1487
|
+
pointerEvents: "none"
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
),
|
|
1491
|
+
visibleButtonCount > 0 ? /* @__PURE__ */ jsxs6(
|
|
1492
|
+
"div",
|
|
1493
|
+
{
|
|
1494
|
+
style: {
|
|
1495
|
+
position: "absolute",
|
|
1496
|
+
top: "50%",
|
|
1497
|
+
right: accessoryMetrics.rightOffset,
|
|
1498
|
+
transform: "translateY(-50%)",
|
|
1499
|
+
display: "inline-flex",
|
|
1500
|
+
alignItems: "center",
|
|
1501
|
+
gap: accessoryMetrics.clusterGap
|
|
1502
|
+
},
|
|
1503
|
+
children: [
|
|
1504
|
+
canClear ? /* @__PURE__ */ jsx5(
|
|
1505
|
+
"button",
|
|
1506
|
+
{
|
|
1507
|
+
type: "button",
|
|
1508
|
+
"aria-label": clearButtonLabel != null ? clearButtonLabel : "Clear date",
|
|
1509
|
+
disabled: disabled || readOnly,
|
|
1510
|
+
onMouseDown: (event) => {
|
|
1511
|
+
event.preventDefault();
|
|
1512
|
+
},
|
|
1513
|
+
onClick: () => {
|
|
1514
|
+
var _a2;
|
|
1515
|
+
commitValue(null, "clear");
|
|
1516
|
+
(_a2 = visibleInputRef.current) == null ? void 0 : _a2.focus();
|
|
1517
|
+
},
|
|
1518
|
+
style: accessoryButtonStyle,
|
|
1519
|
+
children: /* @__PURE__ */ jsx5(ClearIcon, { size: accessoryMetrics.iconSize })
|
|
1520
|
+
}
|
|
1521
|
+
) : null,
|
|
1522
|
+
canOpenPicker ? /* @__PURE__ */ jsx5(
|
|
1523
|
+
"button",
|
|
1524
|
+
{
|
|
1525
|
+
type: "button",
|
|
1526
|
+
"aria-label": pickerButtonLabel != null ? pickerButtonLabel : mode === "datetime" ? "Open date and time picker" : "Open date picker",
|
|
1527
|
+
disabled: disabled || readOnly || hasConfigurationConflict,
|
|
1528
|
+
onMouseDown: (event) => {
|
|
1529
|
+
event.preventDefault();
|
|
1530
|
+
},
|
|
1531
|
+
onClick: openNativePicker,
|
|
1532
|
+
style: accessoryButtonStyle,
|
|
1533
|
+
children: /* @__PURE__ */ jsx5(CalendarIcon, { size: accessoryMetrics.iconSize })
|
|
1534
|
+
}
|
|
1535
|
+
) : null
|
|
1536
|
+
]
|
|
1537
|
+
}
|
|
1538
|
+
) : null
|
|
1539
|
+
] });
|
|
1540
|
+
return /* @__PURE__ */ jsx5(
|
|
1541
|
+
ControlFrame,
|
|
1542
|
+
{
|
|
1543
|
+
label,
|
|
1544
|
+
hint,
|
|
1545
|
+
error: resolvedError,
|
|
1546
|
+
htmlFor: resolvedId,
|
|
1547
|
+
required,
|
|
1548
|
+
children: input
|
|
1549
|
+
}
|
|
1550
|
+
);
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
// src/components/Select.tsx
|
|
1554
|
+
import {
|
|
1555
|
+
Children,
|
|
1556
|
+
isValidElement,
|
|
1557
|
+
useEffect as useEffect3,
|
|
1558
|
+
useId as useId2,
|
|
1559
|
+
useRef as useRef3,
|
|
1560
|
+
useState as useState5
|
|
1561
|
+
} from "react";
|
|
1562
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1563
|
+
var MENU_OFFSET = 8;
|
|
1564
|
+
var MENU_MAX_HEIGHT = 280;
|
|
1565
|
+
var getOptionPadding = (size) => {
|
|
1566
|
+
if (size === "sm") return "10px 12px";
|
|
1567
|
+
if (size === "lg") return "14px 16px";
|
|
1568
|
+
return "12px 14px";
|
|
1569
|
+
};
|
|
1570
|
+
function getTextContent(node) {
|
|
1571
|
+
if (node == null || typeof node === "boolean") {
|
|
1572
|
+
return "";
|
|
1573
|
+
}
|
|
1574
|
+
if (typeof node === "string" || typeof node === "number") {
|
|
1575
|
+
return String(node);
|
|
1576
|
+
}
|
|
1577
|
+
if (Array.isArray(node)) {
|
|
1578
|
+
return node.map(getTextContent).join("");
|
|
1579
|
+
}
|
|
1580
|
+
if (isValidElement(node)) {
|
|
1581
|
+
return getTextContent(node.props.children);
|
|
1582
|
+
}
|
|
1583
|
+
return "";
|
|
1584
|
+
}
|
|
1585
|
+
function normalizeSelectValue(value) {
|
|
1586
|
+
if (Array.isArray(value)) {
|
|
1587
|
+
return value.length > 0 ? normalizeSelectValue(value[0]) : "";
|
|
1588
|
+
}
|
|
1589
|
+
return value == null ? "" : String(value);
|
|
1590
|
+
}
|
|
1591
|
+
function normalizeSelectValues(value) {
|
|
1592
|
+
if (Array.isArray(value)) {
|
|
1593
|
+
return value.map((item) => normalizeSelectValue(item));
|
|
1594
|
+
}
|
|
1595
|
+
if (value == null) {
|
|
1596
|
+
return [];
|
|
1597
|
+
}
|
|
1598
|
+
return [normalizeSelectValue(value)];
|
|
1599
|
+
}
|
|
1600
|
+
function buildOption(keyPrefix, index, props, groupLabel, groupDisabled = false) {
|
|
1601
|
+
var _a;
|
|
1602
|
+
const rawValue = props.value !== void 0 ? props.value : getTextContent(props.children).trim();
|
|
1603
|
+
const normalizedValue = normalizeSelectValue(rawValue);
|
|
1604
|
+
return {
|
|
1605
|
+
key: `${keyPrefix}-${index}-${normalizedValue}`,
|
|
1606
|
+
value: normalizedValue,
|
|
1607
|
+
label: (_a = props.children) != null ? _a : normalizedValue,
|
|
1608
|
+
disabled: groupDisabled || Boolean(props.disabled)
|
|
1609
|
+
};
|
|
1610
|
+
}
|
|
1611
|
+
function parseSelectChildren(children) {
|
|
1612
|
+
const groups = [];
|
|
1613
|
+
const standaloneOptions = [];
|
|
1614
|
+
let optionIndex = 0;
|
|
1615
|
+
let groupIndex = 0;
|
|
1616
|
+
const flushStandaloneOptions = () => {
|
|
1617
|
+
if (standaloneOptions.length === 0) {
|
|
1618
|
+
return;
|
|
1619
|
+
}
|
|
1620
|
+
groups.push({
|
|
1621
|
+
key: `standalone-${groups.length}`,
|
|
1622
|
+
options: [...standaloneOptions]
|
|
1623
|
+
});
|
|
1624
|
+
standaloneOptions.length = 0;
|
|
1625
|
+
};
|
|
1626
|
+
Children.forEach(children, (child) => {
|
|
1627
|
+
if (!isValidElement(child)) {
|
|
1628
|
+
return;
|
|
1629
|
+
}
|
|
1630
|
+
if (child.type === "option") {
|
|
1631
|
+
standaloneOptions.push(buildOption("option", optionIndex, child.props));
|
|
1632
|
+
optionIndex += 1;
|
|
1633
|
+
return;
|
|
1634
|
+
}
|
|
1635
|
+
if (child.type !== "optgroup") {
|
|
1636
|
+
return;
|
|
1637
|
+
}
|
|
1638
|
+
flushStandaloneOptions();
|
|
1639
|
+
const groupOptions = [];
|
|
1640
|
+
let groupOptionIndex = 0;
|
|
1641
|
+
Children.forEach(child.props.children, (optionChild) => {
|
|
1642
|
+
if (!isValidElement(optionChild) || optionChild.type !== "option") {
|
|
1643
|
+
return;
|
|
1644
|
+
}
|
|
1645
|
+
groupOptions.push(
|
|
1646
|
+
buildOption(
|
|
1647
|
+
`group-${groupIndex}-option`,
|
|
1648
|
+
groupOptionIndex,
|
|
1649
|
+
optionChild.props,
|
|
1650
|
+
child.props.label,
|
|
1651
|
+
Boolean(child.props.disabled)
|
|
1652
|
+
)
|
|
1653
|
+
);
|
|
1654
|
+
groupOptionIndex += 1;
|
|
1655
|
+
});
|
|
1656
|
+
if (groupOptions.length > 0) {
|
|
1657
|
+
groups.push({
|
|
1658
|
+
key: `group-${groupIndex}`,
|
|
1659
|
+
label: child.props.label,
|
|
1660
|
+
options: groupOptions
|
|
1661
|
+
});
|
|
1662
|
+
groupIndex += 1;
|
|
1663
|
+
}
|
|
1664
|
+
});
|
|
1665
|
+
flushStandaloneOptions();
|
|
1666
|
+
return groups;
|
|
1667
|
+
}
|
|
1668
|
+
function filterSelectGroups(groups, query) {
|
|
1669
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
1670
|
+
if (!normalizedQuery) {
|
|
1671
|
+
return groups;
|
|
550
1672
|
}
|
|
551
|
-
return
|
|
1673
|
+
return groups.map((group) => ({
|
|
1674
|
+
...group,
|
|
1675
|
+
options: group.options.filter((option) => {
|
|
1676
|
+
const optionText = getTextContent(option.label).trim().toLowerCase();
|
|
1677
|
+
return optionText.includes(normalizedQuery);
|
|
1678
|
+
})
|
|
1679
|
+
})).filter((group) => group.options.length > 0);
|
|
1680
|
+
}
|
|
1681
|
+
function Select({
|
|
1682
|
+
label,
|
|
1683
|
+
hint,
|
|
1684
|
+
error,
|
|
1685
|
+
controlSize = "md",
|
|
1686
|
+
id,
|
|
1687
|
+
disabled,
|
|
1688
|
+
style,
|
|
1689
|
+
children,
|
|
1690
|
+
value,
|
|
1691
|
+
defaultValue,
|
|
1692
|
+
onChange,
|
|
1693
|
+
onFocus,
|
|
1694
|
+
onBlur,
|
|
1695
|
+
onKeyDown,
|
|
1696
|
+
onClick,
|
|
1697
|
+
autoFocus,
|
|
1698
|
+
className,
|
|
1699
|
+
isMulti,
|
|
1700
|
+
isFilterable,
|
|
1701
|
+
multiple,
|
|
1702
|
+
...rest
|
|
1703
|
+
}) {
|
|
1704
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1705
|
+
const { theme, mutedText, surfaceRaised } = useUiKitTheme();
|
|
1706
|
+
const generatedId = useId2().replace(/:/g, "");
|
|
1707
|
+
const resolvedId = id != null ? id : `ss-select-${generatedId}`;
|
|
1708
|
+
const isMultiSelect = Boolean(isMulti || multiple);
|
|
1709
|
+
const hasFilter = Boolean(isFilterable);
|
|
1710
|
+
const groups = parseSelectChildren(children);
|
|
1711
|
+
const flatOptions = groups.flatMap((group) => group.options);
|
|
1712
|
+
const enabledOptions = flatOptions.filter((option) => !option.disabled);
|
|
1713
|
+
const isControlled = value !== void 0;
|
|
1714
|
+
const fallbackValues = defaultValue !== void 0 ? normalizeSelectValues(defaultValue) : isMultiSelect ? [] : ((_a = enabledOptions[0]) == null ? void 0 : _a.value) ? [enabledOptions[0].value] : [];
|
|
1715
|
+
const [uncontrolledValues, setUncontrolledValues] = useState5(fallbackValues);
|
|
1716
|
+
const [isOpen, setIsOpen] = useState5(false);
|
|
1717
|
+
const [filterQuery, setFilterQuery] = useState5("");
|
|
1718
|
+
const [menuPlacement, setMenuPlacement] = useState5("bottom");
|
|
1719
|
+
const [isPlacementResolved, setIsPlacementResolved] = useState5(false);
|
|
1720
|
+
const [highlightedValue, setHighlightedValue] = useState5((_d = (_c = fallbackValues[0]) != null ? _c : (_b = enabledOptions[0]) == null ? void 0 : _b.value) != null ? _d : "");
|
|
1721
|
+
const shellRef = useRef3(null);
|
|
1722
|
+
const buttonRef = useRef3(null);
|
|
1723
|
+
const menuRef = useRef3(null);
|
|
1724
|
+
const searchInputRef = useRef3(null);
|
|
1725
|
+
const hiddenSelectRef = useRef3(null);
|
|
1726
|
+
const selectedValues = isControlled ? normalizeSelectValues(value) : uncontrolledValues;
|
|
1727
|
+
const selectedValue = (_e = selectedValues[0]) != null ? _e : "";
|
|
1728
|
+
const selectedOptions = flatOptions.filter((option) => selectedValues.includes(option.value));
|
|
1729
|
+
const selectedOption = (_f = selectedOptions[0]) != null ? _f : null;
|
|
1730
|
+
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;
|
|
1731
|
+
const displayContent = displayLabel != null ? displayLabel : "\xA0";
|
|
1732
|
+
const visibleGroups = hasFilter ? filterSelectGroups(groups, filterQuery) : groups;
|
|
1733
|
+
const visibleOptions = visibleGroups.flatMap((group) => group.options);
|
|
1734
|
+
const visibleEnabledOptions = visibleOptions.filter((option) => !option.disabled);
|
|
1735
|
+
const visibleEnabledValues = visibleEnabledOptions.map((option) => option.value);
|
|
1736
|
+
const selectedValuesKey = selectedValues.join("\0");
|
|
1737
|
+
const visibleEnabledValuesKey = visibleEnabledValues.join("\0");
|
|
1738
|
+
const indicatorOffset = getSelectIndicatorOffset(controlSize);
|
|
1739
|
+
const controlMetrics = getControlMetrics(controlSize);
|
|
1740
|
+
const listboxId = `${resolvedId}-listbox`;
|
|
1741
|
+
const scrollbarThumbColor = withAlpha(theme.colors.onSurface, 0.22);
|
|
1742
|
+
const scrollbarThumbHoverColor = withAlpha(theme.colors.onSurface, 0.32);
|
|
1743
|
+
const highlightedOption = (_h = visibleOptions.find((option) => option.value === highlightedValue)) != null ? _h : null;
|
|
1744
|
+
const optionHoverBackground = withAlpha(theme.colors.primary, 1);
|
|
1745
|
+
const optionSelectedBackground = withAlpha(theme.colors.primary, 1);
|
|
1746
|
+
const triggerShadow = error ? `0 0 0 3px ${withAlpha(theme.colors.negative, 0.12)}` : "none";
|
|
1747
|
+
const buttonPassthroughProps = Object.fromEntries(
|
|
1748
|
+
Object.entries(rest).filter(([key]) => key.startsWith("aria-") || key.startsWith("data-"))
|
|
1749
|
+
);
|
|
1750
|
+
useEffect3(() => {
|
|
1751
|
+
var _a2, _b2, _c2, _d2;
|
|
1752
|
+
if (isControlled) {
|
|
1753
|
+
return;
|
|
1754
|
+
}
|
|
1755
|
+
const invalidValues = uncontrolledValues.filter(
|
|
1756
|
+
(currentValue) => !flatOptions.some((option) => option.value === currentValue)
|
|
1757
|
+
);
|
|
1758
|
+
if (invalidValues.length === 0) {
|
|
1759
|
+
return;
|
|
1760
|
+
}
|
|
1761
|
+
const nextValues = defaultValue !== void 0 ? normalizeSelectValues(defaultValue).filter(
|
|
1762
|
+
(currentValue) => flatOptions.some((option) => option.value === currentValue)
|
|
1763
|
+
) : isMultiSelect ? [] : ((_a2 = enabledOptions[0]) == null ? void 0 : _a2.value) ? [enabledOptions[0].value] : [];
|
|
1764
|
+
setUncontrolledValues(nextValues);
|
|
1765
|
+
setHighlightedValue((_d2 = (_c2 = nextValues[0]) != null ? _c2 : (_b2 = enabledOptions[0]) == null ? void 0 : _b2.value) != null ? _d2 : "");
|
|
1766
|
+
}, [children, defaultValue, enabledOptions, flatOptions, isControlled, isMultiSelect, uncontrolledValues]);
|
|
1767
|
+
useEffect3(() => {
|
|
1768
|
+
var _a2, _b2, _c2;
|
|
1769
|
+
if (!isOpen) {
|
|
1770
|
+
setMenuPlacement("bottom");
|
|
1771
|
+
setIsPlacementResolved(false);
|
|
1772
|
+
return;
|
|
1773
|
+
}
|
|
1774
|
+
const nextHighlightedValue = (_c2 = (_b2 = [...selectedValues].reverse().find((currentValue) => visibleEnabledValues.includes(currentValue))) != null ? _b2 : (_a2 = visibleEnabledOptions[0]) == null ? void 0 : _a2.value) != null ? _c2 : "";
|
|
1775
|
+
setHighlightedValue(nextHighlightedValue);
|
|
1776
|
+
}, [isOpen, selectedValuesKey, visibleEnabledValuesKey]);
|
|
1777
|
+
useEffect3(() => {
|
|
1778
|
+
var _a2;
|
|
1779
|
+
if (!isOpen || !hasFilter) {
|
|
1780
|
+
return;
|
|
1781
|
+
}
|
|
1782
|
+
(_a2 = searchInputRef.current) == null ? void 0 : _a2.focus();
|
|
1783
|
+
}, [hasFilter, isOpen]);
|
|
1784
|
+
useEffect3(() => {
|
|
1785
|
+
if (!isOpen) {
|
|
1786
|
+
return;
|
|
1787
|
+
}
|
|
1788
|
+
const frameId = window.requestAnimationFrame(() => {
|
|
1789
|
+
var _a2;
|
|
1790
|
+
const triggerRect = (_a2 = buttonRef.current) == null ? void 0 : _a2.getBoundingClientRect();
|
|
1791
|
+
const menuElement = menuRef.current;
|
|
1792
|
+
if (!triggerRect || !menuElement) {
|
|
1793
|
+
setMenuPlacement("bottom");
|
|
1794
|
+
setIsPlacementResolved(true);
|
|
1795
|
+
return;
|
|
1796
|
+
}
|
|
1797
|
+
const measuredMenuHeight = menuElement.getBoundingClientRect().height;
|
|
1798
|
+
const menuHeight = Math.min(measuredMenuHeight || menuElement.scrollHeight, MENU_MAX_HEIGHT);
|
|
1799
|
+
const availableBelow = window.innerHeight - triggerRect.bottom - MENU_OFFSET;
|
|
1800
|
+
const availableAbove = triggerRect.top - MENU_OFFSET;
|
|
1801
|
+
const nextPlacement = availableBelow < menuHeight && availableAbove >= menuHeight ? "top" : "bottom";
|
|
1802
|
+
setMenuPlacement(nextPlacement);
|
|
1803
|
+
setIsPlacementResolved(true);
|
|
1804
|
+
});
|
|
1805
|
+
return () => {
|
|
1806
|
+
window.cancelAnimationFrame(frameId);
|
|
1807
|
+
};
|
|
1808
|
+
}, [isOpen, visibleOptions.length]);
|
|
1809
|
+
useEffect3(() => {
|
|
1810
|
+
if (isOpen) {
|
|
1811
|
+
return;
|
|
1812
|
+
}
|
|
1813
|
+
setFilterQuery("");
|
|
1814
|
+
}, [isOpen]);
|
|
1815
|
+
useEffect3(() => {
|
|
1816
|
+
if (!isOpen) {
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
const handlePointerDown = (event) => {
|
|
1820
|
+
var _a2;
|
|
1821
|
+
if ((_a2 = shellRef.current) == null ? void 0 : _a2.contains(event.target)) {
|
|
1822
|
+
return;
|
|
1823
|
+
}
|
|
1824
|
+
setIsOpen(false);
|
|
1825
|
+
};
|
|
1826
|
+
document.addEventListener("pointerdown", handlePointerDown);
|
|
1827
|
+
return () => {
|
|
1828
|
+
document.removeEventListener("pointerdown", handlePointerDown);
|
|
1829
|
+
};
|
|
1830
|
+
}, [isOpen]);
|
|
1831
|
+
useEffect3(() => {
|
|
1832
|
+
var _a2;
|
|
1833
|
+
if (isControlled) {
|
|
1834
|
+
return;
|
|
1835
|
+
}
|
|
1836
|
+
const form = (_a2 = hiddenSelectRef.current) == null ? void 0 : _a2.form;
|
|
1837
|
+
if (!form) {
|
|
1838
|
+
return;
|
|
1839
|
+
}
|
|
1840
|
+
const handleReset = () => {
|
|
1841
|
+
queueMicrotask(() => {
|
|
1842
|
+
var _a3, _b2, _c2, _d2;
|
|
1843
|
+
const nextValues = defaultValue !== void 0 ? normalizeSelectValues(defaultValue) : isMultiSelect ? [] : ((_a3 = enabledOptions[0]) == null ? void 0 : _a3.value) ? [enabledOptions[0].value] : [];
|
|
1844
|
+
setUncontrolledValues(nextValues);
|
|
1845
|
+
setHighlightedValue((_d2 = (_c2 = nextValues[0]) != null ? _c2 : (_b2 = enabledOptions[0]) == null ? void 0 : _b2.value) != null ? _d2 : "");
|
|
1846
|
+
setIsOpen(false);
|
|
1847
|
+
});
|
|
1848
|
+
};
|
|
1849
|
+
form.addEventListener("reset", handleReset);
|
|
1850
|
+
return () => {
|
|
1851
|
+
form.removeEventListener("reset", handleReset);
|
|
1852
|
+
};
|
|
1853
|
+
}, [defaultValue, enabledOptions, isControlled, isMultiSelect]);
|
|
1854
|
+
const syncHiddenSelect = (nextValues) => {
|
|
1855
|
+
var _a2, _b2;
|
|
1856
|
+
const selectElement = hiddenSelectRef.current;
|
|
1857
|
+
if (!selectElement) {
|
|
1858
|
+
return;
|
|
1859
|
+
}
|
|
1860
|
+
if (isMultiSelect) {
|
|
1861
|
+
Array.from(selectElement.options).forEach((optionElement) => {
|
|
1862
|
+
optionElement.selected = nextValues.includes(optionElement.value);
|
|
1863
|
+
});
|
|
1864
|
+
} else {
|
|
1865
|
+
const descriptor = Object.getOwnPropertyDescriptor(HTMLSelectElement.prototype, "value");
|
|
1866
|
+
if (descriptor == null ? void 0 : descriptor.set) {
|
|
1867
|
+
descriptor.set.call(selectElement, (_a2 = nextValues[0]) != null ? _a2 : "");
|
|
1868
|
+
} else {
|
|
1869
|
+
selectElement.value = (_b2 = nextValues[0]) != null ? _b2 : "";
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
selectElement.dispatchEvent(new Event("change", { bubbles: true }));
|
|
1873
|
+
};
|
|
1874
|
+
const updateMultiSelection = (nextValues) => {
|
|
1875
|
+
var _a2, _b2, _c2;
|
|
1876
|
+
if (!isMultiSelect || disabled) {
|
|
1877
|
+
return;
|
|
1878
|
+
}
|
|
1879
|
+
if (!isControlled) {
|
|
1880
|
+
setUncontrolledValues(nextValues);
|
|
1881
|
+
}
|
|
1882
|
+
setHighlightedValue((_c2 = (_b2 = nextValues[nextValues.length - 1]) != null ? _b2 : (_a2 = enabledOptions[0]) == null ? void 0 : _a2.value) != null ? _c2 : "");
|
|
1883
|
+
syncHiddenSelect(nextValues);
|
|
1884
|
+
};
|
|
1885
|
+
const toggleVisibleSelection = (checked) => {
|
|
1886
|
+
if (!isMultiSelect || disabled || visibleEnabledValues.length === 0) {
|
|
1887
|
+
return;
|
|
1888
|
+
}
|
|
1889
|
+
const nextValues = checked ? Array.from(/* @__PURE__ */ new Set([...selectedValues, ...visibleEnabledValues])) : selectedValues.filter((currentValue) => !visibleEnabledValues.includes(currentValue));
|
|
1890
|
+
updateMultiSelection(nextValues);
|
|
1891
|
+
};
|
|
1892
|
+
const commitSelection = (nextValue) => {
|
|
1893
|
+
var _a2;
|
|
1894
|
+
if (disabled) {
|
|
1895
|
+
if (!isMultiSelect) {
|
|
1896
|
+
setIsOpen(false);
|
|
1897
|
+
}
|
|
1898
|
+
return;
|
|
1899
|
+
}
|
|
1900
|
+
if (isMultiSelect) {
|
|
1901
|
+
const nextValues = selectedValues.includes(nextValue) ? selectedValues.filter((currentValue) => currentValue !== nextValue) : [...selectedValues, nextValue];
|
|
1902
|
+
updateMultiSelection(nextValues);
|
|
1903
|
+
return;
|
|
1904
|
+
}
|
|
1905
|
+
if (nextValue === selectedValue) {
|
|
1906
|
+
setIsOpen(false);
|
|
1907
|
+
return;
|
|
1908
|
+
}
|
|
1909
|
+
if (!isControlled) {
|
|
1910
|
+
setUncontrolledValues([nextValue]);
|
|
1911
|
+
}
|
|
1912
|
+
setHighlightedValue(nextValue);
|
|
1913
|
+
setIsOpen(false);
|
|
1914
|
+
syncHiddenSelect([nextValue]);
|
|
1915
|
+
(_a2 = buttonRef.current) == null ? void 0 : _a2.focus();
|
|
1916
|
+
};
|
|
1917
|
+
const handleHiddenSelectChange = (event) => {
|
|
1918
|
+
var _a2, _b2, _c2;
|
|
1919
|
+
const nextValues = isMultiSelect ? Array.from(event.currentTarget.selectedOptions, (option) => option.value) : [event.currentTarget.value];
|
|
1920
|
+
if (!isControlled) {
|
|
1921
|
+
setUncontrolledValues(nextValues);
|
|
1922
|
+
}
|
|
1923
|
+
setHighlightedValue((_c2 = (_b2 = nextValues[nextValues.length - 1]) != null ? _b2 : (_a2 = enabledOptions[0]) == null ? void 0 : _a2.value) != null ? _c2 : "");
|
|
1924
|
+
onChange == null ? void 0 : onChange(event);
|
|
1925
|
+
};
|
|
1926
|
+
const visibleSelectedCount = visibleEnabledValues.filter((currentValue) => selectedValues.includes(currentValue)).length;
|
|
1927
|
+
const hasSomeVisibleSelected = visibleSelectedCount > 0 && visibleSelectedCount < visibleEnabledValues.length;
|
|
1928
|
+
const hasAllVisibleSelected = visibleEnabledValues.length > 0 && visibleSelectedCount === visibleEnabledValues.length;
|
|
1929
|
+
const canToggleVisibleSelection = !disabled && visibleEnabledValues.length > 0;
|
|
1930
|
+
const bulkToggleControl = isMultiSelect ? /* @__PURE__ */ jsx6(
|
|
1931
|
+
"button",
|
|
1932
|
+
{
|
|
1933
|
+
type: "button",
|
|
1934
|
+
role: "checkbox",
|
|
1935
|
+
"aria-label": "Toggle all visible options",
|
|
1936
|
+
"aria-checked": hasAllVisibleSelected ? true : hasSomeVisibleSelected ? "mixed" : false,
|
|
1937
|
+
disabled: !canToggleVisibleSelection,
|
|
1938
|
+
onMouseDown: (event) => {
|
|
1939
|
+
event.preventDefault();
|
|
1940
|
+
event.stopPropagation();
|
|
1941
|
+
},
|
|
1942
|
+
onClick: (event) => {
|
|
1943
|
+
event.stopPropagation();
|
|
1944
|
+
toggleVisibleSelection(!hasAllVisibleSelected);
|
|
1945
|
+
},
|
|
1946
|
+
style: {
|
|
1947
|
+
width: 20,
|
|
1948
|
+
height: 20,
|
|
1949
|
+
padding: 0,
|
|
1950
|
+
margin: 0,
|
|
1951
|
+
display: "inline-flex",
|
|
1952
|
+
alignItems: "center",
|
|
1953
|
+
justifyContent: "center",
|
|
1954
|
+
flexShrink: 0,
|
|
1955
|
+
border: "none",
|
|
1956
|
+
background: "transparent",
|
|
1957
|
+
cursor: canToggleVisibleSelection ? "pointer" : "not-allowed",
|
|
1958
|
+
opacity: canToggleVisibleSelection ? 1 : 0.45
|
|
1959
|
+
},
|
|
1960
|
+
children: /* @__PURE__ */ jsx6(
|
|
1961
|
+
CheckboxIndicator,
|
|
1962
|
+
{
|
|
1963
|
+
checked: hasAllVisibleSelected,
|
|
1964
|
+
indeterminate: hasSomeVisibleSelected,
|
|
1965
|
+
disabled: !canToggleVisibleSelection,
|
|
1966
|
+
checkedColor: theme.colors.secondary,
|
|
1967
|
+
iconColor: theme.colors.surface,
|
|
1968
|
+
uncheckedBorderColor: withAlpha(theme.colors.onSurface, 0.22),
|
|
1969
|
+
uncheckedBackgroundColor: theme.colors.surface
|
|
1970
|
+
}
|
|
1971
|
+
)
|
|
1972
|
+
}
|
|
1973
|
+
) : null;
|
|
1974
|
+
const moveHighlight = (direction) => {
|
|
1975
|
+
if (visibleEnabledOptions.length === 0) {
|
|
1976
|
+
return;
|
|
1977
|
+
}
|
|
1978
|
+
const currentIndex = visibleEnabledOptions.findIndex((option) => option.value === highlightedValue);
|
|
1979
|
+
if (currentIndex === -1) {
|
|
1980
|
+
setHighlightedValue(
|
|
1981
|
+
direction === 1 ? visibleEnabledOptions[0].value : visibleEnabledOptions[visibleEnabledOptions.length - 1].value
|
|
1982
|
+
);
|
|
1983
|
+
return;
|
|
1984
|
+
}
|
|
1985
|
+
const nextIndex = Math.max(0, Math.min(visibleEnabledOptions.length - 1, currentIndex + direction));
|
|
1986
|
+
setHighlightedValue(visibleEnabledOptions[nextIndex].value);
|
|
1987
|
+
};
|
|
1988
|
+
const handleTriggerClick = (event) => {
|
|
1989
|
+
onClick == null ? void 0 : onClick(event);
|
|
1990
|
+
if (event.defaultPrevented || disabled || flatOptions.length === 0) {
|
|
1991
|
+
return;
|
|
1992
|
+
}
|
|
1993
|
+
setIsOpen((current) => !current);
|
|
1994
|
+
};
|
|
1995
|
+
const handleTriggerFocus = (event) => {
|
|
1996
|
+
onFocus == null ? void 0 : onFocus(event);
|
|
1997
|
+
};
|
|
1998
|
+
const handleTriggerBlur = (event) => {
|
|
1999
|
+
var _a2;
|
|
2000
|
+
const nextTarget = event.relatedTarget;
|
|
2001
|
+
if (!((_a2 = shellRef.current) == null ? void 0 : _a2.contains(nextTarget))) {
|
|
2002
|
+
setIsOpen(false);
|
|
2003
|
+
}
|
|
2004
|
+
onBlur == null ? void 0 : onBlur(event);
|
|
2005
|
+
};
|
|
2006
|
+
const handleTriggerKeyDown = (event) => {
|
|
2007
|
+
var _a2, _b2, _c2;
|
|
2008
|
+
onKeyDown == null ? void 0 : onKeyDown(event);
|
|
2009
|
+
if (event.defaultPrevented || disabled || visibleEnabledOptions.length === 0) {
|
|
2010
|
+
return;
|
|
2011
|
+
}
|
|
2012
|
+
if (event.key === "ArrowDown") {
|
|
2013
|
+
event.preventDefault();
|
|
2014
|
+
if (!isOpen) {
|
|
2015
|
+
setIsOpen(true);
|
|
2016
|
+
setHighlightedValue((_a2 = selectedOption == null ? void 0 : selectedOption.value) != null ? _a2 : visibleEnabledOptions[0].value);
|
|
2017
|
+
return;
|
|
2018
|
+
}
|
|
2019
|
+
moveHighlight(1);
|
|
2020
|
+
return;
|
|
2021
|
+
}
|
|
2022
|
+
if (event.key === "ArrowUp") {
|
|
2023
|
+
event.preventDefault();
|
|
2024
|
+
if (!isOpen) {
|
|
2025
|
+
setIsOpen(true);
|
|
2026
|
+
setHighlightedValue((_b2 = selectedOption == null ? void 0 : selectedOption.value) != null ? _b2 : visibleEnabledOptions[visibleEnabledOptions.length - 1].value);
|
|
2027
|
+
return;
|
|
2028
|
+
}
|
|
2029
|
+
moveHighlight(-1);
|
|
2030
|
+
return;
|
|
2031
|
+
}
|
|
2032
|
+
if (event.key === "Home" && isOpen) {
|
|
2033
|
+
event.preventDefault();
|
|
2034
|
+
setHighlightedValue(visibleEnabledOptions[0].value);
|
|
2035
|
+
return;
|
|
2036
|
+
}
|
|
2037
|
+
if (event.key === "End" && isOpen) {
|
|
2038
|
+
event.preventDefault();
|
|
2039
|
+
setHighlightedValue(visibleEnabledOptions[visibleEnabledOptions.length - 1].value);
|
|
2040
|
+
return;
|
|
2041
|
+
}
|
|
2042
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
2043
|
+
event.preventDefault();
|
|
2044
|
+
if (!isOpen) {
|
|
2045
|
+
setIsOpen(true);
|
|
2046
|
+
setHighlightedValue((_c2 = selectedOption == null ? void 0 : selectedOption.value) != null ? _c2 : visibleEnabledOptions[0].value);
|
|
2047
|
+
return;
|
|
2048
|
+
}
|
|
2049
|
+
if (highlightedOption && !highlightedOption.disabled) {
|
|
2050
|
+
commitSelection(highlightedOption.value);
|
|
2051
|
+
}
|
|
2052
|
+
return;
|
|
2053
|
+
}
|
|
2054
|
+
if (event.key === "Escape" && isOpen) {
|
|
2055
|
+
event.preventDefault();
|
|
2056
|
+
setIsOpen(false);
|
|
2057
|
+
return;
|
|
2058
|
+
}
|
|
2059
|
+
if (event.key === "Tab") {
|
|
2060
|
+
setIsOpen(false);
|
|
2061
|
+
}
|
|
2062
|
+
};
|
|
2063
|
+
const handleFilterKeyDown = (event) => {
|
|
2064
|
+
var _a2;
|
|
2065
|
+
if (event.key === "ArrowDown") {
|
|
2066
|
+
event.preventDefault();
|
|
2067
|
+
moveHighlight(1);
|
|
2068
|
+
return;
|
|
2069
|
+
}
|
|
2070
|
+
if (event.key === "ArrowUp") {
|
|
2071
|
+
event.preventDefault();
|
|
2072
|
+
moveHighlight(-1);
|
|
2073
|
+
return;
|
|
2074
|
+
}
|
|
2075
|
+
if (event.key === "Enter") {
|
|
2076
|
+
event.preventDefault();
|
|
2077
|
+
if (highlightedOption && !highlightedOption.disabled) {
|
|
2078
|
+
commitSelection(highlightedOption.value);
|
|
2079
|
+
}
|
|
2080
|
+
return;
|
|
2081
|
+
}
|
|
2082
|
+
if (event.key === "Escape") {
|
|
2083
|
+
event.preventDefault();
|
|
2084
|
+
setIsOpen(false);
|
|
2085
|
+
(_a2 = buttonRef.current) == null ? void 0 : _a2.focus();
|
|
2086
|
+
return;
|
|
2087
|
+
}
|
|
2088
|
+
if (event.key === "Tab") {
|
|
2089
|
+
setIsOpen(false);
|
|
2090
|
+
}
|
|
2091
|
+
};
|
|
2092
|
+
const select = /* @__PURE__ */ jsxs7("div", { ref: shellRef, style: { position: "relative", width: "100%" }, children: [
|
|
2093
|
+
/* @__PURE__ */ jsxs7(
|
|
2094
|
+
"button",
|
|
2095
|
+
{
|
|
2096
|
+
...buttonPassthroughProps,
|
|
2097
|
+
id: resolvedId,
|
|
2098
|
+
ref: buttonRef,
|
|
2099
|
+
type: "button",
|
|
2100
|
+
className,
|
|
2101
|
+
title: rest.title,
|
|
2102
|
+
disabled: disabled || flatOptions.length === 0,
|
|
2103
|
+
autoFocus,
|
|
2104
|
+
tabIndex: rest.tabIndex,
|
|
2105
|
+
role: "combobox",
|
|
2106
|
+
"aria-controls": listboxId,
|
|
2107
|
+
"aria-expanded": isOpen,
|
|
2108
|
+
"aria-haspopup": "listbox",
|
|
2109
|
+
"aria-invalid": error ? true : rest["aria-invalid"],
|
|
2110
|
+
"aria-required": rest.required,
|
|
2111
|
+
onClick: handleTriggerClick,
|
|
2112
|
+
onFocus: handleTriggerFocus,
|
|
2113
|
+
onBlur: handleTriggerBlur,
|
|
2114
|
+
onKeyDown: handleTriggerKeyDown,
|
|
2115
|
+
style: {
|
|
2116
|
+
width: "100%",
|
|
2117
|
+
boxSizing: "border-box",
|
|
2118
|
+
height: controlMetrics.height,
|
|
2119
|
+
borderRadius: 16,
|
|
2120
|
+
border: `1px solid ${error ? theme.colors.negative : withAlpha(theme.colors.textLight, 0.5)}`,
|
|
2121
|
+
backgroundColor: theme.colors.surface,
|
|
2122
|
+
color: displayLabel ? theme.colors.onSurface : mutedText,
|
|
2123
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
2124
|
+
opacity: disabled ? 0.7 : 1,
|
|
2125
|
+
padding: getSelectControlPadding(controlSize),
|
|
2126
|
+
outline: "none",
|
|
2127
|
+
font: "inherit",
|
|
2128
|
+
fontSize: controlMetrics.fontSize,
|
|
2129
|
+
lineHeight: controlMetrics.lineHeight,
|
|
2130
|
+
transition: "border-color 160ms ease, box-shadow 160ms ease, background-color 160ms ease",
|
|
2131
|
+
display: "flex",
|
|
2132
|
+
alignItems: "center",
|
|
2133
|
+
justifyContent: "space-between",
|
|
2134
|
+
gap: 12,
|
|
2135
|
+
minWidth: 0,
|
|
2136
|
+
textAlign: "left",
|
|
2137
|
+
...style
|
|
2138
|
+
},
|
|
2139
|
+
children: [
|
|
2140
|
+
/* @__PURE__ */ jsx6(
|
|
2141
|
+
"span",
|
|
2142
|
+
{
|
|
2143
|
+
style: {
|
|
2144
|
+
display: "block",
|
|
2145
|
+
flex: "1 1 auto",
|
|
2146
|
+
minWidth: 0,
|
|
2147
|
+
overflow: "hidden",
|
|
2148
|
+
textOverflow: "ellipsis",
|
|
2149
|
+
whiteSpace: "nowrap"
|
|
2150
|
+
},
|
|
2151
|
+
children: displayContent
|
|
2152
|
+
}
|
|
2153
|
+
),
|
|
2154
|
+
/* @__PURE__ */ jsx6(
|
|
2155
|
+
"span",
|
|
2156
|
+
{
|
|
2157
|
+
"aria-hidden": "true",
|
|
2158
|
+
style: {
|
|
2159
|
+
position: "absolute",
|
|
2160
|
+
right: indicatorOffset,
|
|
2161
|
+
top: "50%",
|
|
2162
|
+
transform: `translateY(-50%) rotate(${isOpen ? 180 : 0}deg)`,
|
|
2163
|
+
transformOrigin: "center",
|
|
2164
|
+
color: disabled ? withAlpha(theme.colors.onSurface, 0.42) : mutedText,
|
|
2165
|
+
display: "flex",
|
|
2166
|
+
alignItems: "center",
|
|
2167
|
+
justifyContent: "center",
|
|
2168
|
+
pointerEvents: "none",
|
|
2169
|
+
transition: "transform 160ms ease, color 160ms ease"
|
|
2170
|
+
},
|
|
2171
|
+
children: /* @__PURE__ */ jsx6("svg", { width: "18", height: "18", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx6(
|
|
2172
|
+
"path",
|
|
2173
|
+
{
|
|
2174
|
+
d: "M5.75 7.75L10 12l4.25-4.25",
|
|
2175
|
+
stroke: "currentColor",
|
|
2176
|
+
strokeWidth: "1.8",
|
|
2177
|
+
strokeLinecap: "round",
|
|
2178
|
+
strokeLinejoin: "round"
|
|
2179
|
+
}
|
|
2180
|
+
) })
|
|
2181
|
+
}
|
|
2182
|
+
)
|
|
2183
|
+
]
|
|
2184
|
+
}
|
|
2185
|
+
),
|
|
2186
|
+
/* @__PURE__ */ jsx6(
|
|
2187
|
+
"select",
|
|
2188
|
+
{
|
|
2189
|
+
...rest,
|
|
2190
|
+
id: `${resolvedId}-native`,
|
|
2191
|
+
ref: hiddenSelectRef,
|
|
2192
|
+
name: rest.name,
|
|
2193
|
+
disabled,
|
|
2194
|
+
multiple: isMultiSelect,
|
|
2195
|
+
value: isMultiSelect ? selectedValues : selectedValue,
|
|
2196
|
+
onChange: handleHiddenSelectChange,
|
|
2197
|
+
tabIndex: -1,
|
|
2198
|
+
"aria-hidden": "true",
|
|
2199
|
+
style: {
|
|
2200
|
+
position: "absolute",
|
|
2201
|
+
width: 1,
|
|
2202
|
+
height: 1,
|
|
2203
|
+
padding: 0,
|
|
2204
|
+
margin: 0,
|
|
2205
|
+
border: 0,
|
|
2206
|
+
opacity: 0,
|
|
2207
|
+
pointerEvents: "none",
|
|
2208
|
+
clipPath: "inset(50%)"
|
|
2209
|
+
},
|
|
2210
|
+
children
|
|
2211
|
+
}
|
|
2212
|
+
),
|
|
2213
|
+
isOpen ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
|
|
2214
|
+
/* @__PURE__ */ jsx6("style", { children: `
|
|
2215
|
+
#${listboxId} {
|
|
2216
|
+
scrollbar-width: thin;
|
|
2217
|
+
scrollbar-color: ${scrollbarThumbColor} transparent;
|
|
2218
|
+
}
|
|
2219
|
+
|
|
2220
|
+
#${listboxId}::-webkit-scrollbar {
|
|
2221
|
+
width: 8px;
|
|
2222
|
+
}
|
|
2223
|
+
|
|
2224
|
+
#${listboxId}::-webkit-scrollbar-track {
|
|
2225
|
+
background: transparent;
|
|
2226
|
+
}
|
|
2227
|
+
|
|
2228
|
+
#${listboxId}::-webkit-scrollbar-thumb {
|
|
2229
|
+
background: ${scrollbarThumbColor};
|
|
2230
|
+
border-radius: 999px;
|
|
2231
|
+
border: 2px solid transparent;
|
|
2232
|
+
background-clip: padding-box;
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
#${listboxId}::-webkit-scrollbar-thumb:hover {
|
|
2236
|
+
background: ${scrollbarThumbHoverColor};
|
|
2237
|
+
background-clip: padding-box;
|
|
2238
|
+
}
|
|
2239
|
+
` }),
|
|
2240
|
+
/* @__PURE__ */ jsxs7(
|
|
2241
|
+
"div",
|
|
2242
|
+
{
|
|
2243
|
+
ref: menuRef,
|
|
2244
|
+
style: {
|
|
2245
|
+
position: "absolute",
|
|
2246
|
+
top: menuPlacement === "bottom" ? `calc(100% + ${MENU_OFFSET}px)` : "auto",
|
|
2247
|
+
bottom: menuPlacement === "top" ? `calc(100% + ${MENU_OFFSET}px)` : "auto",
|
|
2248
|
+
left: 0,
|
|
2249
|
+
right: 0,
|
|
2250
|
+
zIndex: 30,
|
|
2251
|
+
maxHeight: MENU_MAX_HEIGHT,
|
|
2252
|
+
overflow: "hidden",
|
|
2253
|
+
boxSizing: "border-box",
|
|
2254
|
+
borderRadius: 20,
|
|
2255
|
+
border: `1px solid ${withAlpha(theme.colors.textLight, 0.5)}`,
|
|
2256
|
+
backgroundColor: surfaceRaised,
|
|
2257
|
+
// boxShadow: `0 10px 24px ${withAlpha(theme.colors.onSurface, 0.08)}`,
|
|
2258
|
+
padding: 8,
|
|
2259
|
+
backdropFilter: "blur(6px)",
|
|
2260
|
+
visibility: isPlacementResolved ? "visible" : "hidden",
|
|
2261
|
+
display: "flex",
|
|
2262
|
+
flexDirection: "column",
|
|
2263
|
+
gap: 4
|
|
2264
|
+
},
|
|
2265
|
+
children: [
|
|
2266
|
+
hasFilter ? /* @__PURE__ */ jsxs7(
|
|
2267
|
+
"div",
|
|
2268
|
+
{
|
|
2269
|
+
style: {
|
|
2270
|
+
display: "flex",
|
|
2271
|
+
alignItems: "center",
|
|
2272
|
+
justifyContent: "flex-start",
|
|
2273
|
+
gap: 8,
|
|
2274
|
+
padding: "4px 4px 10px",
|
|
2275
|
+
borderBottom: `1px solid ${withAlpha(theme.colors.onSurface, 0.08)}`,
|
|
2276
|
+
flexShrink: 0
|
|
2277
|
+
},
|
|
2278
|
+
children: [
|
|
2279
|
+
bulkToggleControl,
|
|
2280
|
+
/* @__PURE__ */ jsx6(
|
|
2281
|
+
"input",
|
|
2282
|
+
{
|
|
2283
|
+
ref: searchInputRef,
|
|
2284
|
+
type: "search",
|
|
2285
|
+
value: filterQuery,
|
|
2286
|
+
onChange: (event) => {
|
|
2287
|
+
setFilterQuery(event.currentTarget.value);
|
|
2288
|
+
},
|
|
2289
|
+
onKeyDown: handleFilterKeyDown,
|
|
2290
|
+
onMouseDown: (event) => {
|
|
2291
|
+
event.stopPropagation();
|
|
2292
|
+
},
|
|
2293
|
+
placeholder: "Search options",
|
|
2294
|
+
"aria-label": "Search options",
|
|
2295
|
+
style: {
|
|
2296
|
+
flex: "1 1 auto",
|
|
2297
|
+
width: "100%",
|
|
2298
|
+
border: `1px solid ${withAlpha(theme.colors.textLight, 0.5)}`,
|
|
2299
|
+
backgroundColor: theme.colors.surface,
|
|
2300
|
+
padding: "8px 12px",
|
|
2301
|
+
borderRadius: 12,
|
|
2302
|
+
font: "inherit",
|
|
2303
|
+
fontSize: 12,
|
|
2304
|
+
lineHeight: 1.4,
|
|
2305
|
+
color: theme.colors.textLight,
|
|
2306
|
+
outline: "none",
|
|
2307
|
+
boxSizing: "border-box"
|
|
2308
|
+
}
|
|
2309
|
+
}
|
|
2310
|
+
)
|
|
2311
|
+
]
|
|
2312
|
+
}
|
|
2313
|
+
) : isMultiSelect ? /* @__PURE__ */ jsx6(
|
|
2314
|
+
"div",
|
|
2315
|
+
{
|
|
2316
|
+
style: {
|
|
2317
|
+
display: "flex",
|
|
2318
|
+
alignItems: "center",
|
|
2319
|
+
justifyContent: "flex-start",
|
|
2320
|
+
padding: "4px 4px 10px",
|
|
2321
|
+
borderBottom: `1px solid ${withAlpha(theme.colors.onSurface, 0.08)}`,
|
|
2322
|
+
flexShrink: 0
|
|
2323
|
+
},
|
|
2324
|
+
children: bulkToggleControl
|
|
2325
|
+
}
|
|
2326
|
+
) : null,
|
|
2327
|
+
/* @__PURE__ */ jsx6(
|
|
2328
|
+
"div",
|
|
2329
|
+
{
|
|
2330
|
+
id: listboxId,
|
|
2331
|
+
role: "listbox",
|
|
2332
|
+
"aria-labelledby": resolvedId,
|
|
2333
|
+
"aria-multiselectable": isMultiSelect || void 0,
|
|
2334
|
+
style: {
|
|
2335
|
+
overflowY: "auto",
|
|
2336
|
+
overflowX: "hidden",
|
|
2337
|
+
minHeight: 0,
|
|
2338
|
+
flex: "1 1 auto"
|
|
2339
|
+
},
|
|
2340
|
+
children: visibleGroups.length === 0 ? /* @__PURE__ */ jsx6(
|
|
2341
|
+
"div",
|
|
2342
|
+
{
|
|
2343
|
+
style: {
|
|
2344
|
+
padding: "14px 12px",
|
|
2345
|
+
color: mutedText,
|
|
2346
|
+
fontSize: 13,
|
|
2347
|
+
textAlign: "center"
|
|
2348
|
+
},
|
|
2349
|
+
children: "No options found."
|
|
2350
|
+
}
|
|
2351
|
+
) : visibleGroups.map((group) => /* @__PURE__ */ jsxs7(
|
|
2352
|
+
"div",
|
|
2353
|
+
{
|
|
2354
|
+
style: {
|
|
2355
|
+
display: "flex",
|
|
2356
|
+
flexDirection: "column",
|
|
2357
|
+
gap: 4,
|
|
2358
|
+
marginTop: group.label ? 4 : 0
|
|
2359
|
+
},
|
|
2360
|
+
children: [
|
|
2361
|
+
group.label ? /* @__PURE__ */ jsx6(
|
|
2362
|
+
"span",
|
|
2363
|
+
{
|
|
2364
|
+
style: {
|
|
2365
|
+
padding: "6px 8px 2px",
|
|
2366
|
+
color: mutedText,
|
|
2367
|
+
fontSize: 11,
|
|
2368
|
+
fontWeight: 800,
|
|
2369
|
+
letterSpacing: "0.08em",
|
|
2370
|
+
textTransform: "uppercase"
|
|
2371
|
+
},
|
|
2372
|
+
children: group.label
|
|
2373
|
+
}
|
|
2374
|
+
) : null,
|
|
2375
|
+
group.options.map((option) => {
|
|
2376
|
+
const isSelected = selectedValues.includes(option.value);
|
|
2377
|
+
const isHighlighted = option.value === highlightedValue;
|
|
2378
|
+
const isActive = isSelected || isHighlighted;
|
|
2379
|
+
return /* @__PURE__ */ jsxs7(
|
|
2380
|
+
"div",
|
|
2381
|
+
{
|
|
2382
|
+
role: "option",
|
|
2383
|
+
"aria-selected": isSelected,
|
|
2384
|
+
"aria-disabled": option.disabled,
|
|
2385
|
+
onMouseEnter: () => {
|
|
2386
|
+
if (!option.disabled) {
|
|
2387
|
+
setHighlightedValue(option.value);
|
|
2388
|
+
}
|
|
2389
|
+
},
|
|
2390
|
+
onMouseDown: (event) => {
|
|
2391
|
+
event.preventDefault();
|
|
2392
|
+
},
|
|
2393
|
+
onClick: () => {
|
|
2394
|
+
if (!option.disabled) {
|
|
2395
|
+
commitSelection(option.value);
|
|
2396
|
+
}
|
|
2397
|
+
},
|
|
2398
|
+
style: {
|
|
2399
|
+
display: "flex",
|
|
2400
|
+
alignItems: "center",
|
|
2401
|
+
justifyContent: "space-between",
|
|
2402
|
+
gap: 12,
|
|
2403
|
+
width: "100%",
|
|
2404
|
+
minWidth: 0,
|
|
2405
|
+
boxSizing: "border-box",
|
|
2406
|
+
borderRadius: 14,
|
|
2407
|
+
padding: getOptionPadding(controlSize),
|
|
2408
|
+
cursor: option.disabled ? "not-allowed" : "pointer",
|
|
2409
|
+
color: option.disabled ? withAlpha(theme.colors.onSurface, 0.38) : isActive ? theme.colors.onPrimary : theme.colors.onSurface,
|
|
2410
|
+
backgroundColor: isSelected ? optionSelectedBackground : isHighlighted ? optionHoverBackground : "transparent",
|
|
2411
|
+
fontWeight: isSelected ? 700 : 500,
|
|
2412
|
+
transition: "background-color 140ms ease, color 140ms ease"
|
|
2413
|
+
},
|
|
2414
|
+
children: [
|
|
2415
|
+
/* @__PURE__ */ jsxs7(
|
|
2416
|
+
"span",
|
|
2417
|
+
{
|
|
2418
|
+
style: {
|
|
2419
|
+
display: "flex",
|
|
2420
|
+
alignItems: "center",
|
|
2421
|
+
gap: 10,
|
|
2422
|
+
flex: "1 1 auto",
|
|
2423
|
+
minWidth: 0
|
|
2424
|
+
},
|
|
2425
|
+
children: [
|
|
2426
|
+
isMultiSelect ? /* @__PURE__ */ jsx6(
|
|
2427
|
+
CheckboxIndicator,
|
|
2428
|
+
{
|
|
2429
|
+
checked: isSelected,
|
|
2430
|
+
disabled: option.disabled,
|
|
2431
|
+
size: 16,
|
|
2432
|
+
checkedColor: isActive ? theme.colors.onPrimary : theme.colors.primary,
|
|
2433
|
+
iconColor: isActive ? theme.colors.primary : theme.colors.onPrimary,
|
|
2434
|
+
uncheckedBorderColor: isActive ? theme.colors.onPrimary : withAlpha(theme.colors.onSurface, 0.26),
|
|
2435
|
+
uncheckedBackgroundColor: "transparent"
|
|
2436
|
+
}
|
|
2437
|
+
) : null,
|
|
2438
|
+
/* @__PURE__ */ jsx6(
|
|
2439
|
+
"span",
|
|
2440
|
+
{
|
|
2441
|
+
style: {
|
|
2442
|
+
display: "block",
|
|
2443
|
+
flex: "1 1 auto",
|
|
2444
|
+
minWidth: 0,
|
|
2445
|
+
overflow: "hidden",
|
|
2446
|
+
textOverflow: "ellipsis",
|
|
2447
|
+
whiteSpace: "nowrap"
|
|
2448
|
+
},
|
|
2449
|
+
children: option.label
|
|
2450
|
+
}
|
|
2451
|
+
)
|
|
2452
|
+
]
|
|
2453
|
+
}
|
|
2454
|
+
),
|
|
2455
|
+
!isMultiSelect && isSelected ? /* @__PURE__ */ jsx6(
|
|
2456
|
+
"span",
|
|
2457
|
+
{
|
|
2458
|
+
"aria-hidden": "true",
|
|
2459
|
+
style: {
|
|
2460
|
+
display: "flex",
|
|
2461
|
+
alignItems: "center",
|
|
2462
|
+
justifyContent: "center",
|
|
2463
|
+
color: theme.colors.primary,
|
|
2464
|
+
flexShrink: 0
|
|
2465
|
+
},
|
|
2466
|
+
children: /* @__PURE__ */ jsx6("svg", { width: "16", height: "16", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx6(
|
|
2467
|
+
"path",
|
|
2468
|
+
{
|
|
2469
|
+
d: "M5.75 10.25L8.5 13l5.75-6",
|
|
2470
|
+
stroke: "currentColor",
|
|
2471
|
+
strokeWidth: "1.8",
|
|
2472
|
+
strokeLinecap: "round",
|
|
2473
|
+
strokeLinejoin: "round"
|
|
2474
|
+
}
|
|
2475
|
+
) })
|
|
2476
|
+
}
|
|
2477
|
+
) : null
|
|
2478
|
+
]
|
|
2479
|
+
},
|
|
2480
|
+
option.key
|
|
2481
|
+
);
|
|
2482
|
+
})
|
|
2483
|
+
]
|
|
2484
|
+
},
|
|
2485
|
+
group.key
|
|
2486
|
+
))
|
|
2487
|
+
}
|
|
2488
|
+
)
|
|
2489
|
+
]
|
|
2490
|
+
}
|
|
2491
|
+
)
|
|
2492
|
+
] }) : null
|
|
2493
|
+
] });
|
|
2494
|
+
return /* @__PURE__ */ jsx6(
|
|
2495
|
+
ControlFrame,
|
|
2496
|
+
{
|
|
2497
|
+
label,
|
|
2498
|
+
hint,
|
|
2499
|
+
error,
|
|
2500
|
+
htmlFor: resolvedId,
|
|
2501
|
+
required: rest.required,
|
|
2502
|
+
useLabelWrapper: false,
|
|
2503
|
+
children: select
|
|
2504
|
+
}
|
|
2505
|
+
);
|
|
552
2506
|
}
|
|
553
2507
|
|
|
554
2508
|
// src/components/Textarea.tsx
|
|
555
|
-
import {
|
|
556
|
-
|
|
557
|
-
var getPadding3 = (size) => {
|
|
2509
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
2510
|
+
var getPadding = (size) => {
|
|
558
2511
|
if (size === "sm") return "10px 12px";
|
|
559
2512
|
if (size === "lg") return "16px 18px";
|
|
560
2513
|
return "13px 16px";
|
|
561
2514
|
};
|
|
562
2515
|
function Textarea({
|
|
563
|
-
sdk,
|
|
564
2516
|
label,
|
|
565
2517
|
hint,
|
|
566
2518
|
error,
|
|
@@ -571,31 +2523,32 @@ function Textarea({
|
|
|
571
2523
|
rows = 5,
|
|
572
2524
|
...rest
|
|
573
2525
|
}) {
|
|
574
|
-
const { theme,
|
|
2526
|
+
const { theme, focusRing } = useUiKitTheme();
|
|
575
2527
|
const textareaStyle = {
|
|
2528
|
+
border: `1px solid ${error ? theme.colors.negative : withAlpha(theme.colors.textLight, 0.5)}`,
|
|
2529
|
+
backgroundColor: theme.colors.surface,
|
|
2530
|
+
color: theme.colors.text,
|
|
2531
|
+
cursor: disabled ? "not-allowed" : "text",
|
|
2532
|
+
opacity: disabled ? 0.7 : 1,
|
|
576
2533
|
width: "100%",
|
|
2534
|
+
boxSizing: "border-box",
|
|
577
2535
|
borderRadius: 16,
|
|
578
|
-
|
|
579
|
-
padding: getPadding3(controlSize),
|
|
2536
|
+
padding: getPadding(controlSize),
|
|
580
2537
|
outline: "none",
|
|
581
|
-
|
|
582
|
-
backgroundColor: disabled ? surfaceMuted : theme.colors.surface,
|
|
583
|
-
boxShadow: error ? `0 0 0 3px ${withAlpha6(theme.colors.negative, 0.12)}` : `0 0 0 0 ${focusRing}`,
|
|
2538
|
+
boxShadow: error ? `0 0 0 3px ${withAlpha(theme.colors.negative, 0.12)}` : `0 0 0 0 ${focusRing}`,
|
|
584
2539
|
transition: "border-color 160ms ease, box-shadow 160ms ease, background-color 160ms ease",
|
|
585
2540
|
resize: "vertical",
|
|
586
2541
|
...style
|
|
587
2542
|
};
|
|
588
|
-
const textarea = /* @__PURE__ */
|
|
589
|
-
|
|
590
|
-
return textarea;
|
|
591
|
-
}
|
|
592
|
-
return /* @__PURE__ */ jsx6(Field, { sdk, label, hint, error, htmlFor: id, children: textarea });
|
|
2543
|
+
const textarea = /* @__PURE__ */ jsx7("textarea", { ...rest, id, disabled, rows, style: textareaStyle });
|
|
2544
|
+
return /* @__PURE__ */ jsx7(ControlFrame, { label, hint, error, htmlFor: id, required: rest.required, children: textarea });
|
|
593
2545
|
}
|
|
594
2546
|
export {
|
|
595
2547
|
Button,
|
|
596
2548
|
Card,
|
|
2549
|
+
Checkbox,
|
|
597
2550
|
ComposableModal,
|
|
598
|
-
|
|
2551
|
+
DatePicker,
|
|
599
2552
|
Input,
|
|
600
2553
|
Modal,
|
|
601
2554
|
Select,
|