pixelize-design-library 2.4.2-beta.49 → 2.4.2-beta.50
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/CHANGELOG.md +11 -0
- package/dist/Components/Button/ButtonProps.d.ts +1 -1
- package/dist/Components/Common/iconBox.d.ts +3 -0
- package/dist/Components/Common/iconBox.js +16 -0
- package/dist/Components/DatePicker/DatePickerProps.d.ts +1 -1
- package/dist/Components/Input/TextInput.js +1 -1
- package/dist/Components/Input/TextInputProps.d.ts +1 -1
- package/dist/Components/Input/textInputIconSize.js +2 -12
- package/dist/Components/MultiSelect/MultiSelectProps.d.ts +1 -1
- package/dist/Components/PinInput/PinInputProps.d.ts +1 -1
- package/dist/Components/Search/SearchProps.d.ts +1 -1
- package/dist/Components/SearchSelect/SearchSelectProps.d.ts +1 -1
- package/dist/Components/SegmentedControl/SegmentedControlProps.d.ts +1 -1
- package/dist/Components/Select/SelectProps.d.ts +1 -1
- package/dist/Components/SelectSearch/SelectSearch.js +2 -2
- package/dist/Components/SelectSearch/SelectSearchProps.d.ts +1 -1
- package/dist/Components/SelectV2/SelectV2Props.d.ts +1 -1
- package/dist/Components/Table/components/TableSearch.js +1 -1
- package/dist/Components/Tabs/components/Tab.js +2 -1
- package/dist/Components/Toggle/TableToggle.js +6 -3
- package/dist/esm/Components/Common/iconBox.js +12 -0
- package/dist/esm/Components/Input/TextInput.js +1 -1
- package/dist/esm/Components/Input/textInputIconSize.js +2 -12
- package/dist/esm/Components/SelectSearch/SelectSearch.js +2 -2
- package/dist/esm/Components/Table/components/TableSearch.js +1 -1
- package/dist/esm/Components/Tabs/components/Tab.js +2 -1
- package/dist/esm/Components/Toggle/TableToggle.js +6 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -70,6 +70,17 @@ next major.
|
|
|
70
70
|
|
|
71
71
|
### Fixed
|
|
72
72
|
|
|
73
|
+
- **Icons beside a field are centred at every size and height.** A lone right-hand icon in
|
|
74
|
+
`TextInput` (an `inputRightIcon`, the clear button or the password toggle) sat flush against the
|
|
75
|
+
border while the left one was inset; both now mirror at 6/9/12/15px. `SelectSearch`'s `rightIcon`
|
|
76
|
+
was centred on a 40px box whatever the field size (up to 8px high at `lg`). `Tabs` drew a
|
|
77
|
+
caller's icon at the caller's size inside a token-sized box, leaving it 3–6px off; it is now
|
|
78
|
+
pinned to the size token. `TableSearch`'s clear icon and `TableToggle` had a literal `2rem`
|
|
79
|
+
height and now follow the `sm` control height. `TextInput`'s `height` prop now wins over the
|
|
80
|
+
size token's `minH`, so an explicit height below the token no longer leaves a taller input in a
|
|
81
|
+
shorter group.
|
|
82
|
+
- **`*Props` JSDoc quoted the old control scale.** Eleven components documented "xs 24 · sm 32";
|
|
83
|
+
they now say 28 / 35, and `Common/controlSizeDocs.test.ts` fails if they drift again.
|
|
73
84
|
- **`Table` — a column search only ever matched the page you were looking at.** The per-column
|
|
74
85
|
search ran on `filteredData`, which `useTable` had already sliced to the current page, so a match
|
|
75
86
|
on page 3 was invisible from page 1 and the pager still counted every row. The search now runs
|
|
@@ -11,7 +11,7 @@ export type ButtonProps = LayoutProps & DataAttributes & Pick<ChakraButtonProps,
|
|
|
11
11
|
loadingText?: string;
|
|
12
12
|
/** Defaults to "fit-content", not 100%; the w alias only applies when width is unset — width wins if both are passed. */
|
|
13
13
|
width?: string | number;
|
|
14
|
-
/** Control height xs
|
|
14
|
+
/** Control height xs 28 · sm 35 · md 40 · lg 48 (xl 56); defaults to "sm" via the theme, so a ButtonGroup size still applies. */
|
|
15
15
|
size?: "lg" | "md" | "sm" | "xs" | "xl";
|
|
16
16
|
/** Defaults to "solid"; "gradient" paints the theme's fixed brand gradient. */
|
|
17
17
|
variant?: "solid" | "outline" | "ghost" | "link" | "unstyled" | "gradient";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.iconBoxSx = void 0;
|
|
4
|
+
/** Centres a caller-supplied icon in a fixed box and pins its svg to that size, whatever size the caller gave it. */
|
|
5
|
+
const iconBoxSx = (px) => ({
|
|
6
|
+
display: "inline-flex",
|
|
7
|
+
alignItems: "center",
|
|
8
|
+
justifyContent: "center",
|
|
9
|
+
lineHeight: 0,
|
|
10
|
+
flexShrink: 0,
|
|
11
|
+
"& > svg, & > * svg, & svg": {
|
|
12
|
+
width: `${px}px !important`,
|
|
13
|
+
height: `${px}px !important`,
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
exports.iconBoxSx = iconBoxSx;
|
|
@@ -44,7 +44,7 @@ export type BaseDatePickerProps = {
|
|
|
44
44
|
width?: string | number;
|
|
45
45
|
/** Blocks today in the calendar and in typed input; the single picker preselects tomorrow instead. */
|
|
46
46
|
disableToday?: boolean;
|
|
47
|
-
/** Control-scale height: xs
|
|
47
|
+
/** Control-scale height: xs 28 · sm 35 · md 40 · lg 48px (default `sm`, like TextInput); also scales the calendar/clock icon. */
|
|
48
48
|
size?: "xs" | "sm" | "md" | "lg";
|
|
49
49
|
};
|
|
50
50
|
/** Single-date variant, Date API (default) — `isRange` must be false or omitted; this is the discriminant the DatePickerProps union switches on. */
|
|
@@ -121,7 +121,7 @@ const TextInput = (0, react_1.forwardRef)(({ label, type = "text", id, name, onC
|
|
|
121
121
|
const { showError, showHelper } = (0, fieldMessageStyles_1.fieldMessageVisibility)({ error: isFieldInvalid, errorMessage, helperText });
|
|
122
122
|
const showMessageRow = showCounter || showError || showHelper;
|
|
123
123
|
const describedBy = [ids.describedBy, counterId].filter(Boolean).join(" ") || undefined;
|
|
124
|
-
const content = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [label && ((0, jsx_runtime_1.jsx)(FormLabel_1.TextLabel, { label: label, id: ids.inputId, isInformation: isInformation, informationMessage: informationMessage, isRequired: isFieldRequired })), (0, jsx_runtime_1.jsxs)(react_2.InputGroup, { style: inputGroupStyle, size: size, height: height, children: [inputLeftAddon && ((0, jsx_runtime_1.jsx)(react_2.InputLeftAddon, { sx: (0, TextInput_styles_1.fieldAddonSx)(theme.colors), children: inputLeftAddon })), inputLeftIcon && ((0, jsx_runtime_1.jsx)(react_2.InputLeftElement, { pointerEvents: onLeftIconClick ? "auto" : "none", ...leftElementStyle, height: "100%", display: "flex", alignItems: "center", children: (0, jsx_runtime_1.jsx)(IconSlot, { icon: inputLeftIcon, onClick: onLeftIconClick, ariaLabel: leftIconAriaLabel !== null && leftIconAriaLabel !== void 0 ? leftIconAriaLabel : actionName("left icon action"), sx: iconScaleSx, color: iconColor, isDisabled: isFieldDisabled }) })), (0, jsx_runtime_1.jsx)(react_2.Input, { type: effectiveType, placeholder: placeholder, onChange: onChange, onBlur: onBlur, onFocus: onFocus, value: value, isDisabled: isFieldDisabled, isReadOnly: isFieldReadOnly, name: name, size: size, variant: variant, maxLength: maxLength, ...(height != null && { height }), isInvalid: isFieldInvalid, ref: mergedRef, autoComplete: autoComplete, "aria-busy": isLoading || undefined, ...ids.controlProps, "aria-describedby": describedBy, ...inputStyle, ...props }), (isLoading || rightSlots.length > 0) && ((0, jsx_runtime_1.jsx)(react_2.InputRightElement, { pointerEvents: !isLoading && rightSlots.some((slot) => slot.onClick) ? "auto" : "none", ...rightElementStyle, height: "100%", display: "flex", alignItems: "center", justifyContent: "flex-end", width: !isLoading && rightSlots.length > 1 ? "auto" : undefined, ...(!isLoading && rightSlots.length > 1 ? { pr: 2, gap: 1 } : {}), children: isLoading ? ((0, jsx_runtime_1.jsx)(react_2.Spinner, { size: "xs", color: iconColor })) : (rightSlots.map((slot) => ((0, jsx_runtime_1.jsx)(IconSlot, { icon: slot.icon, onClick: slot.onClick, ariaLabel: slot.ariaLabel, sx: iconScaleSx, color: iconColor, isDisabled: isFieldDisabled }, slot.key)))) })), inputRightAddon && ((0, jsx_runtime_1.jsx)(react_2.InputRightAddon, { sx: (0, TextInput_styles_1.fieldAddonSx)(theme.colors), children: inputRightAddon }))] }), showMessageRow && ((0, jsx_runtime_1.jsxs)(react_2.Flex, { justify: "space-between", align: "flex-start", gap: 2, children: [(0, jsx_runtime_1.jsx)(FieldMessage_1.default, { error: isFieldInvalid, errorMessage: errorMessage, helperText: helperText, helperId: ids.helperId, errorId: ids.errorId }), showCounter && stringValue !== undefined && ((0, jsx_runtime_1.jsxs)(react_2.Text, { id: counterId, flexShrink: 0, ...(0, fieldMessageStyles_1.fieldMessageStyles)(theme.colors), color: isFieldInvalid ? theme.colors.semanticText.error : theme.colors.textMuted, children: [stringValue.length, "/", maxLength] }))] }))] }));
|
|
124
|
+
const content = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [label && ((0, jsx_runtime_1.jsx)(FormLabel_1.TextLabel, { label: label, id: ids.inputId, isInformation: isInformation, informationMessage: informationMessage, isRequired: isFieldRequired })), (0, jsx_runtime_1.jsxs)(react_2.InputGroup, { style: inputGroupStyle, size: size, height: height, children: [inputLeftAddon && ((0, jsx_runtime_1.jsx)(react_2.InputLeftAddon, { sx: (0, TextInput_styles_1.fieldAddonSx)(theme.colors), children: inputLeftAddon })), inputLeftIcon && ((0, jsx_runtime_1.jsx)(react_2.InputLeftElement, { pointerEvents: onLeftIconClick ? "auto" : "none", ...leftElementStyle, height: "100%", display: "flex", alignItems: "center", children: (0, jsx_runtime_1.jsx)(IconSlot, { icon: inputLeftIcon, onClick: onLeftIconClick, ariaLabel: leftIconAriaLabel !== null && leftIconAriaLabel !== void 0 ? leftIconAriaLabel : actionName("left icon action"), sx: iconScaleSx, color: iconColor, isDisabled: isFieldDisabled }) })), (0, jsx_runtime_1.jsx)(react_2.Input, { type: effectiveType, placeholder: placeholder, onChange: onChange, onBlur: onBlur, onFocus: onFocus, value: value, isDisabled: isFieldDisabled, isReadOnly: isFieldReadOnly, name: name, size: size, variant: variant, maxLength: maxLength, ...(height != null && { height, minH: height }), isInvalid: isFieldInvalid, ref: mergedRef, autoComplete: autoComplete, "aria-busy": isLoading || undefined, ...ids.controlProps, "aria-describedby": describedBy, ...inputStyle, ...props }), (isLoading || rightSlots.length > 0) && ((0, jsx_runtime_1.jsx)(react_2.InputRightElement, { pointerEvents: !isLoading && rightSlots.some((slot) => slot.onClick) ? "auto" : "none", ...rightElementStyle, height: "100%", display: "flex", alignItems: "center", justifyContent: !isLoading && rightSlots.length > 1 ? "flex-end" : "center", width: !isLoading && rightSlots.length > 1 ? "auto" : undefined, ...(!isLoading && rightSlots.length > 1 ? { pr: 2, gap: 1 } : {}), children: isLoading ? ((0, jsx_runtime_1.jsx)(react_2.Spinner, { size: "xs", color: iconColor })) : (rightSlots.map((slot) => ((0, jsx_runtime_1.jsx)(IconSlot, { icon: slot.icon, onClick: slot.onClick, ariaLabel: slot.ariaLabel, sx: iconScaleSx, color: iconColor, isDisabled: isFieldDisabled }, slot.key)))) })), inputRightAddon && ((0, jsx_runtime_1.jsx)(react_2.InputRightAddon, { sx: (0, TextInput_styles_1.fieldAddonSx)(theme.colors), children: inputRightAddon }))] }), showMessageRow && ((0, jsx_runtime_1.jsxs)(react_2.Flex, { justify: "space-between", align: "flex-start", gap: 2, children: [(0, jsx_runtime_1.jsx)(FieldMessage_1.default, { error: isFieldInvalid, errorMessage: errorMessage, helperText: helperText, helperId: ids.helperId, errorId: ids.errorId }), showCounter && stringValue !== undefined && ((0, jsx_runtime_1.jsxs)(react_2.Text, { id: counterId, flexShrink: 0, ...(0, fieldMessageStyles_1.fieldMessageStyles)(theme.colors), color: isFieldInvalid ? theme.colors.semanticText.error : theme.colors.textMuted, children: [stringValue.length, "/", maxLength] }))] }))] }));
|
|
125
125
|
return hasParentFormControl ? ((0, jsx_runtime_1.jsx)(react_2.Box, { w: width, minW: minW, maxW: maxW, children: content })) : ((0, jsx_runtime_1.jsx)(react_2.FormControl, { w: width, minW: minW, maxW: maxW, children: content }));
|
|
126
126
|
});
|
|
127
127
|
TextInput.displayName = "TextInput";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { InputProps, SystemProps } from "@chakra-ui/react";
|
|
2
2
|
import type { CSSProperties, ReactNode } from "react";
|
|
3
|
-
/** The library's primary single-line text field (default size `sm`,
|
|
3
|
+
/** The library's primary single-line text field (default size `sm`, 35px; no default placeholder). `type="password"` auto-renders a show/hide toggle unless `inputRightIcon` is set or `isPasswordToggleDisabled` is true. Inside a consumer's own `FormControl`, it detects the ancestor and skips rendering its own, inheriting id/invalid/required/disabled from it. */
|
|
4
4
|
export type TextInputProps = Omit<InputProps, "id" | "name" | "minW" | "maxW" | "autoComplete" | "ref" | "isInvalid"> & {
|
|
5
5
|
label?: string;
|
|
6
6
|
/** Optional — an id is generated when omitted, so the label is always bound. `isRequired` sets `aria-required`, not native `required`. */
|
|
@@ -3,22 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getTextInputIconSizePx = getTextInputIconSizePx;
|
|
4
4
|
exports.getTextInputIconWrapperSx = getTextInputIconWrapperSx;
|
|
5
5
|
const controlSizes_1 = require("../../Theme/tokens/primitives/controlSizes");
|
|
6
|
+
const iconBox_1 = require("../Common/iconBox");
|
|
6
7
|
/** Icon px for a field size, from the shared control scale; unknown sizes fall back to the default size. */
|
|
7
8
|
function getTextInputIconSizePx(size) {
|
|
8
9
|
return controlSizes_1.CONTROL_SIZES[(0, controlSizes_1.isControlSize)(size) ? size : controlSizes_1.DEFAULT_CONTROL_SIZE].iconSize;
|
|
9
10
|
}
|
|
10
11
|
/** Scales SVG icons (e.g. Lucide, which set explicit width/height) in an icon slot to the field size. */
|
|
11
12
|
function getTextInputIconWrapperSx(size) {
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
display: "inline-flex",
|
|
15
|
-
alignItems: "center",
|
|
16
|
-
justifyContent: "center",
|
|
17
|
-
lineHeight: 0,
|
|
18
|
-
flexShrink: 0,
|
|
19
|
-
"& > svg, & > * svg, & svg": {
|
|
20
|
-
width: `${px}px !important`,
|
|
21
|
-
height: `${px}px !important`,
|
|
22
|
-
},
|
|
23
|
-
};
|
|
13
|
+
return (0, iconBox_1.iconBoxSx)(getTextInputIconSizePx(size));
|
|
24
14
|
}
|
|
@@ -18,7 +18,7 @@ export type MultiSelectProps = {
|
|
|
18
18
|
addOnBlur?: boolean;
|
|
19
19
|
/** Marks the field invalid (`aria-invalid` + error border) and swaps `helperText` for `errorMessage`; a rejected email sets this internally too. */
|
|
20
20
|
error?: boolean;
|
|
21
|
-
/** Height on the shared control scale (xs
|
|
21
|
+
/** Height on the shared control scale (xs 28 · sm 35 · md 40 · lg 48px). Defaults to `sm`. */
|
|
22
22
|
size?: "xs" | "sm" | "md" | "lg";
|
|
23
23
|
inputStyle?: object;
|
|
24
24
|
/** Rendered only while `error` is true; a rejected email's internal "Invalid email address" text wins over this until the input changes. */
|
|
@@ -2,7 +2,7 @@ import { PinInputProps } from "@chakra-ui/react";
|
|
|
2
2
|
/** The only pin/OTP component exported from the package. */
|
|
3
3
|
export type ChakraPinInputProps = Pick<PinInputProps, "otp" | "mask" | "defaultValue" | "placeholder" | "manageFocus" | "errorBorderColor" | "focusBorderColor" | "onChange" | "onComplete"> & {
|
|
4
4
|
type?: "alphanumeric" | "number";
|
|
5
|
-
/** Square cell size, aligned to CONTROL_SIZES heights (xs
|
|
5
|
+
/** Square cell size, aligned to CONTROL_SIZES heights (xs 28 · sm 35 · md 40 · lg 48). Defaults to "sm". */
|
|
6
6
|
size?: "xs" | "sm" | "md" | "lg";
|
|
7
7
|
variant?: "flushed" | "outline" | "filled" | "unstyled";
|
|
8
8
|
color?: "gray" | "red" | "orange" | "yellow" | "green" | "teal" | "blue" | "cyan" | "purple" | "pink" | "whiteAlpha" | "blackAlpha" | "primary";
|
|
@@ -15,7 +15,7 @@ export type SearchProps = {
|
|
|
15
15
|
onClear?: () => void;
|
|
16
16
|
/** @deprecated Use `onClear` — same behaviour, consistent casing. */
|
|
17
17
|
onclose?: () => void;
|
|
18
|
-
/** Height on the shared control scale (xs
|
|
18
|
+
/** Height on the shared control scale (xs 28 · sm 35 · md 40 · lg 48px). Defaults to `sm`. */
|
|
19
19
|
size?: ControlSize;
|
|
20
20
|
name?: string;
|
|
21
21
|
/** Disables the input and hides the clear button; the hotkey still focuses it. */
|
|
@@ -38,7 +38,7 @@ export type SearchSelectProps = {
|
|
|
38
38
|
width?: string | number;
|
|
39
39
|
/** Only sets the insideSelect segment's height, not the main field's — that's driven by `size`. */
|
|
40
40
|
height?: string | number;
|
|
41
|
-
/** Height on the shared control scale (xs
|
|
41
|
+
/** Height on the shared control scale (xs 28 · sm 35 · md 40 · lg 48px). Defaults to `sm`. */
|
|
42
42
|
size?: "xs" | "sm" | "md" | "lg";
|
|
43
43
|
/** Blocks opening, typing, chip removal and clearing; renders the shared disabled field look. */
|
|
44
44
|
isDisabled?: boolean;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ControlSize } from "../../Theme/tokens/primitives/controlSizes";
|
|
2
|
-
/** Whole-track height on the shared control scale (sm
|
|
2
|
+
/** Whole-track height on the shared control scale (sm 35 · md 40 · lg 48px); defaults to "sm". */
|
|
3
3
|
export type SegmentedControlSize = Exclude<ControlSize, "xs">;
|
|
4
4
|
/** brandSlide = primary view switcher; underlineSlide = dense toolbar; default = plain buttons. */
|
|
5
5
|
export type SegmentedControlVariant = "default" | "brandSlide" | "underlineSlide";
|
|
@@ -24,7 +24,7 @@ type SelectCommonProps = {
|
|
|
24
24
|
label?: string;
|
|
25
25
|
/** Native: the built-in placeholder `<option>`. Popup: trigger text when nothing is selected. Defaults to "Select Option". */
|
|
26
26
|
placeholder?: string;
|
|
27
|
-
/** Height on the shared control scale (xs
|
|
27
|
+
/** Height on the shared control scale (xs 28 · sm 35 · md 40 · lg 48px). Defaults to `sm`. */
|
|
28
28
|
size?: ControlSize;
|
|
29
29
|
/** Applied to the wrapping FormControl. */
|
|
30
30
|
width?: string | number;
|
|
@@ -228,13 +228,13 @@ function SelectSearch({ options, initialSelectedOption, onOptionSelect, inputOnc
|
|
|
228
228
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
229
229
|
};
|
|
230
230
|
}, [isOpen]);
|
|
231
|
-
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(react_2.FormControl, { isInvalid: error, children: (0, jsx_runtime_1.jsxs)(react_2.Box, { display: "flex", flexDirection: "column", position: "relative", sx: boxStyle, children: [label && ((0, jsx_runtime_1.jsx)(FormLabel_1.TextLabel, { label: label, id: ids.inputId, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), isMultipleSelect && selectedOptions.length > 0 && ((0, jsx_runtime_1.jsx)(react_2.HStack, { spacing: 2, mb: 2, children: selectedOptions.map((option) => ((0, jsx_runtime_1.jsxs)(react_2.Tag, { size: "md", borderRadius: "full", variant: "solid", colorScheme: "primary", children: [(0, jsx_runtime_1.jsx)(react_2.TagLabel, { width: "3.125rem", children: option.label }), (0, jsx_runtime_1.jsx)(react_2.TagCloseButton, { onClick: () => handleRemoveOption(option) })] }, option.id))) })), (0, jsx_runtime_1.jsxs)(react_2.InputGroup, { children: [(0, jsx_runtime_1.jsx)(react_2.Input, { ref: inputRef, ...ids.controlProps, variant: "outline", value: inputValue ? inputValue : "", onClick: openDropdown, onFocus: () => {
|
|
231
|
+
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(react_2.FormControl, { isInvalid: error, children: (0, jsx_runtime_1.jsxs)(react_2.Box, { display: "flex", flexDirection: "column", position: "relative", sx: boxStyle, children: [label && ((0, jsx_runtime_1.jsx)(FormLabel_1.TextLabel, { label: label, id: ids.inputId, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), isMultipleSelect && selectedOptions.length > 0 && ((0, jsx_runtime_1.jsx)(react_2.HStack, { spacing: 2, mb: 2, children: selectedOptions.map((option) => ((0, jsx_runtime_1.jsxs)(react_2.Tag, { size: "md", borderRadius: "full", variant: "solid", colorScheme: "primary", children: [(0, jsx_runtime_1.jsx)(react_2.TagLabel, { width: "3.125rem", children: option.label }), (0, jsx_runtime_1.jsx)(react_2.TagCloseButton, { onClick: () => handleRemoveOption(option) })] }, option.id))) })), (0, jsx_runtime_1.jsxs)(react_2.InputGroup, { size: size, children: [(0, jsx_runtime_1.jsx)(react_2.Input, { ref: inputRef, ...ids.controlProps, variant: "outline", value: inputValue ? inputValue : "", onClick: openDropdown, onFocus: () => {
|
|
232
232
|
if (skipNextInputFocusOpen.current) {
|
|
233
233
|
skipNextInputFocusOpen.current = false;
|
|
234
234
|
return;
|
|
235
235
|
}
|
|
236
236
|
openDropdown();
|
|
237
|
-
}, onChange: (e) => handleInputChange(e.target.value), placeholder: placeholder, onKeyDown: handleKeyDown, name: name, role: "combobox", "aria-autocomplete": "list", "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-controls": listboxId, "aria-required": isRequired || undefined, cursor: "pointer", sx: { ...(0, fieldStyles_1.fieldControlStyles)(theme.colors), ...(0, fieldStyles_1.controlSizeStyles)(size), ...(0, motion_2.reducedMotionSx)() }, style: inputStyle }), rightIcon && ((0, jsx_runtime_1.jsx)(react_2.InputRightElement, { pointerEvents: "none", children: rightIcon, style: { ...rightElementStyle } }))] }), isOpen && ((0, jsx_runtime_1.jsxs)(react_2.Box, { ref: dropdownRef, marginTop: "0.313rem", position: "absolute", top: position === "below" ? "100%" : "auto", bottom: position === "above" ? "100%" : "auto", left: 0, right: 0, border: "0.063rem solid", borderColor: theme.colors.boxborder[200], borderRadius: "xl", boxShadow: theme.shadows.lg, bg: theme.colors.surfaceRaised, maxHeight: "9.375rem", overflowY: "auto", zIndex: 10, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { id: listboxId, role: "listbox", "aria-label": label !== null && label !== void 0 ? label : placeholder, onKeyDown: handleListKeyDown, children: (0, jsx_runtime_1.jsx)(RenderOptions, { isOptionLoading: isOptionLoading, filteredOptions: filteredOptions, loadingText: loadingText, handleOptionClick: handleOptionClick, isProfile: isProfile, isColorOptions: isColorOptions, isOptionSelected: isOptionSelected, activeIndex: activeIndex, optionRefs: optionRefs, size: size, isMultipleSelect: isMultipleSelect }) }), (0, jsx_runtime_1.jsx)("hr", {}), isBottomIcon && ((0, jsx_runtime_1.jsxs)(react_2.Box, { position: "sticky", bottom: 0, background: theme.colors.surfaceRaised, display: "flex", alignItems: "center", pl: "1rem", cursor: "pointer", onClick: handleBottomClick, borderColor: theme.colors.boxborder[200], zIndex: 1, borderTop: `1px solid ${theme.colors.boxborder[200]}`, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { children: BottomIcon ? BottomIcon : (0, jsx_runtime_1.jsx)(lucide_react_1.PlusIcon, { size: "1rem" }) }), (0, jsx_runtime_1.jsx)(react_2.Box, { fontSize: "0.875rem", color: BottomTextColor
|
|
237
|
+
}, onChange: (e) => handleInputChange(e.target.value), placeholder: placeholder, onKeyDown: handleKeyDown, name: name, role: "combobox", "aria-autocomplete": "list", "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-controls": listboxId, "aria-required": isRequired || undefined, cursor: "pointer", sx: { ...(0, fieldStyles_1.fieldControlStyles)(theme.colors), ...(0, fieldStyles_1.controlSizeStyles)(size), ...(0, motion_2.reducedMotionSx)() }, style: inputStyle }), rightIcon && ((0, jsx_runtime_1.jsx)(react_2.InputRightElement, { pointerEvents: "none", height: "100%", display: "flex", alignItems: "center", children: rightIcon, style: { ...rightElementStyle } }))] }), isOpen && ((0, jsx_runtime_1.jsxs)(react_2.Box, { ref: dropdownRef, marginTop: "0.313rem", position: "absolute", top: position === "below" ? "100%" : "auto", bottom: position === "above" ? "100%" : "auto", left: 0, right: 0, border: "0.063rem solid", borderColor: theme.colors.boxborder[200], borderRadius: "xl", boxShadow: theme.shadows.lg, bg: theme.colors.surfaceRaised, maxHeight: "9.375rem", overflowY: "auto", zIndex: 10, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { id: listboxId, role: "listbox", "aria-label": label !== null && label !== void 0 ? label : placeholder, onKeyDown: handleListKeyDown, children: (0, jsx_runtime_1.jsx)(RenderOptions, { isOptionLoading: isOptionLoading, filteredOptions: filteredOptions, loadingText: loadingText, handleOptionClick: handleOptionClick, isProfile: isProfile, isColorOptions: isColorOptions, isOptionSelected: isOptionSelected, activeIndex: activeIndex, optionRefs: optionRefs, size: size, isMultipleSelect: isMultipleSelect }) }), (0, jsx_runtime_1.jsx)("hr", {}), isBottomIcon && ((0, jsx_runtime_1.jsxs)(react_2.Box, { position: "sticky", bottom: 0, background: theme.colors.surfaceRaised, display: "flex", alignItems: "center", pl: "1rem", cursor: "pointer", onClick: handleBottomClick, borderColor: theme.colors.boxborder[200], zIndex: 1, borderTop: `1px solid ${theme.colors.boxborder[200]}`, children: [(0, jsx_runtime_1.jsx)(react_2.Box, { children: BottomIcon ? BottomIcon : (0, jsx_runtime_1.jsx)(lucide_react_1.PlusIcon, { size: "1rem" }) }), (0, jsx_runtime_1.jsx)(react_2.Box, { fontSize: "0.875rem", color: BottomTextColor
|
|
238
238
|
? BottomTextColor
|
|
239
239
|
: theme.colors.accentText, padding: "8px 8px", children: BottomText || "Add New" })] }))] })), (0, jsx_runtime_1.jsx)(FieldMessage_1.default, { error: error, errorMessage: errorMessage, helperText: helperText, helperId: ids.helperId, errorId: ids.errorId })] }) }) }));
|
|
240
240
|
}
|
|
@@ -49,7 +49,7 @@ export type SelectSearchProps = {
|
|
|
49
49
|
errorMessage?: string | undefined;
|
|
50
50
|
/** Hint under the field; replaced by `errorMessage` while `error` is true. */
|
|
51
51
|
helperText?: string;
|
|
52
|
-
/** Height on the shared control scale (xs
|
|
52
|
+
/** Height on the shared control scale (xs 28 · sm 35 · md 40 · lg 48px). Defaults to `sm`. */
|
|
53
53
|
size?: ControlSize;
|
|
54
54
|
/** Shows a sticky "Add New"-style footer row in the popup; required for all Bottom* props. */
|
|
55
55
|
isBottomIcon?: boolean | undefined;
|
|
@@ -33,7 +33,7 @@ type SelectV2CommonProps = {
|
|
|
33
33
|
isReadOnly?: boolean;
|
|
34
34
|
/** Label asterisk + `aria-required` only; never blocks an empty submit. */
|
|
35
35
|
isRequired?: boolean;
|
|
36
|
-
/** Shared control scale (xs
|
|
36
|
+
/** Shared control scale (xs 28 · sm 35 · md 40 · lg 48px). Defaults to `sm`. */
|
|
37
37
|
size?: ControlSize;
|
|
38
38
|
/** Shows a type-ahead filter input at the top of the popup. Defaults to true. */
|
|
39
39
|
isSearchable?: boolean;
|
|
@@ -30,6 +30,6 @@ const TableSearch = ({ onSearch }) => {
|
|
|
30
30
|
setQuery(value);
|
|
31
31
|
handleDebounce(value);
|
|
32
32
|
};
|
|
33
|
-
return ((0, jsx_runtime_1.jsxs)(react_2.Box, { display: "flex", alignItems: "center", gap: "2", children: [!showInput && ((0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: "Search", placement: "top", children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": "Search", icon: (0, jsx_runtime_1.jsx)(react_2.Icon, { as: lucide_react_1.Search, transform: "scaleX(-1)", boxSize: 5 }), variant: "unstyled", minW: "auto", h: "auto", display: "flex", cursor: "pointer", color: colors.text[500], onClick: handleSearchClick, _hover: { color: colors.accentText } }) })), showInput ? ((0, jsx_runtime_1.jsxs)(react_2.InputGroup, { maxW: "12.5rem", children: [(0, jsx_runtime_1.jsx)(react_2.Input, { placeholder: "Search...", value: query, onChange: handleInputChange, size: "sm", borderRadius: "lg", borderColor: colors.boxborder[500], _focus: { borderColor: colors.accentText }, autoFocus: true }), (0, jsx_runtime_1.jsx)(react_2.InputRightElement, { display: "flex", alignItems: "center", height: "
|
|
33
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Box, { display: "flex", alignItems: "center", gap: "2", children: [!showInput && ((0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: "Search", placement: "top", children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": "Search", icon: (0, jsx_runtime_1.jsx)(react_2.Icon, { as: lucide_react_1.Search, transform: "scaleX(-1)", boxSize: 5 }), variant: "unstyled", minW: "auto", h: "auto", display: "flex", cursor: "pointer", color: colors.text[500], onClick: handleSearchClick, _hover: { color: colors.accentText } }) })), showInput ? ((0, jsx_runtime_1.jsxs)(react_2.InputGroup, { size: "sm", maxW: "12.5rem", children: [(0, jsx_runtime_1.jsx)(react_2.Input, { placeholder: "Search...", value: query, onChange: handleInputChange, size: "sm", borderRadius: "lg", borderColor: colors.boxborder[500], _focus: { borderColor: colors.accentText }, autoFocus: true }), (0, jsx_runtime_1.jsx)(react_2.InputRightElement, { display: "flex", alignItems: "center", height: "100%", children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": "Clear search", icon: (0, jsx_runtime_1.jsx)(react_2.Icon, { as: lucide_react_1.X }), variant: "unstyled", minW: "auto", h: "auto", display: "flex", color: colors.text[500], cursor: "pointer", onClick: handleSearchClick }) })] })) : null] }));
|
|
34
34
|
};
|
|
35
35
|
exports.default = TableSearch;
|
|
@@ -13,6 +13,7 @@ const color_1 = require("../../../Theme/tokens/builders/color");
|
|
|
13
13
|
const motion_1 = require("../../../Theme/tokens/primitives/motion");
|
|
14
14
|
const motion_2 = require("../../../Theme/chakra/motion");
|
|
15
15
|
const controlSizes_1 = require("../../../Theme/tokens/primitives/controlSizes");
|
|
16
|
+
const iconBox_1 = require("../../Common/iconBox");
|
|
16
17
|
const tabStyles_1 = require("../tabStyles");
|
|
17
18
|
const TabsContext_1 = require("../TabsContext");
|
|
18
19
|
const CountBadge_1 = __importDefault(require("./CountBadge"));
|
|
@@ -44,6 +45,6 @@ const Tab = ({ value, children, icon, count, isDisabled }) => {
|
|
|
44
45
|
? { borderLeft: "0.125rem solid", borderLeftColor: (_c = style.indicator) !== null && _c !== void 0 ? _c : "transparent" }
|
|
45
46
|
: { borderBottom: "0.125rem solid", borderBottomColor: (_d = style.indicator) !== null && _d !== void 0 ? _d : "transparent" }
|
|
46
47
|
: {};
|
|
47
|
-
return ((0, jsx_runtime_1.jsxs)(react_2.Box, { as: "button", type: "button", ref: ref, role: "tab", id: (0, TabsContext_1.tabId)(ctx.baseId, value), "aria-selected": isSelected, "aria-disabled": isDisabled || undefined, "aria-controls": ctx.hasPanels ? (0, TabsContext_1.panelId)(ctx.baseId, value) : undefined, "data-value": value, tabIndex: isDisabled ? -1 : isFocusTarget ? 0 : -1, disabled: isDisabled, onClick: () => !isDisabled && ctx.select(value), onFocus: () => ctx.focusTab(value), display: "flex", alignItems: "center", justifyContent: "center", gap: "0.375rem", flexShrink: 0, flex: ctx.isFitted ? 1 : undefined, w: isVertical ? "100%" : undefined, h: isVertical ? "auto" : spec.height, minH: spec.height, py: isVertical ? "0.5rem" : undefined, px: spec.paddingX, fontSize: spec.fontSize, fontWeight: isSelected ? 600 : 500, whiteSpace: "nowrap", cursor: isDisabled ? "not-allowed" : "pointer", opacity: isDisabled ? 0.5 : 1, borderRadius: isLine ? "none" : "lg", bg: style.bg, color: style.color, ...borderProps, transition: (0, motion_1.transitionFor)(["background-color", "color", "border-color"]), sx: { _focusVisible: focusRing, [focusRing_styles_1.FOCUS_VISIBLE_OVER_STATE]: focusRing, ...(0, motion_2.reducedMotionSx)() }, _hover: !isDisabled ? { bg: style.hoverBg, color: style.hoverColor } : undefined, children: [icon ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", "aria-hidden": true,
|
|
48
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Box, { as: "button", type: "button", ref: ref, role: "tab", id: (0, TabsContext_1.tabId)(ctx.baseId, value), "aria-selected": isSelected, "aria-disabled": isDisabled || undefined, "aria-controls": ctx.hasPanels ? (0, TabsContext_1.panelId)(ctx.baseId, value) : undefined, "data-value": value, tabIndex: isDisabled ? -1 : isFocusTarget ? 0 : -1, disabled: isDisabled, onClick: () => !isDisabled && ctx.select(value), onFocus: () => ctx.focusTab(value), display: "flex", alignItems: "center", justifyContent: "center", gap: "0.375rem", flexShrink: 0, flex: ctx.isFitted ? 1 : undefined, w: isVertical ? "100%" : undefined, h: isVertical ? "auto" : spec.height, minH: spec.height, py: isVertical ? "0.5rem" : undefined, px: spec.paddingX, fontSize: spec.fontSize, fontWeight: isSelected ? 600 : 500, whiteSpace: "nowrap", cursor: isDisabled ? "not-allowed" : "pointer", opacity: isDisabled ? 0.5 : 1, borderRadius: isLine ? "none" : "lg", bg: style.bg, color: style.color, ...borderProps, transition: (0, motion_1.transitionFor)(["background-color", "color", "border-color"]), sx: { _focusVisible: focusRing, [focusRing_styles_1.FOCUS_VISIBLE_OVER_STATE]: focusRing, ...(0, motion_2.reducedMotionSx)() }, _hover: !isDisabled ? { bg: style.hoverBg, color: style.hoverColor } : undefined, children: [icon ? ((0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", "aria-hidden": true, boxSize: `${spec.iconSize}px`, sx: (0, iconBox_1.iconBoxSx)(spec.iconSize), children: icon })) : null, (0, jsx_runtime_1.jsx)(react_2.Box, { as: "span", children: children }), count !== undefined ? ((0, jsx_runtime_1.jsx)(CountBadge_1.default, { count: count, colors: colors, scale: scale, surface: ctx.variant === "solid" && isSelected ? style.bg : canvas, size: ctx.size })) : null] }));
|
|
48
49
|
};
|
|
49
50
|
exports.default = Tab;
|
|
@@ -11,7 +11,10 @@ const outlineRung_1 = require("../../Theme/tokens/builders/outlineRung");
|
|
|
11
11
|
const filledSurface_1 = require("../../Theme/tokens/builders/filledSurface");
|
|
12
12
|
const ToolTip_1 = __importDefault(require("../ToolTip/ToolTip"));
|
|
13
13
|
const useSlidingPill_1 = require("../SegmentedControl/useSlidingPill");
|
|
14
|
+
const controlSizes_1 = require("../../Theme/tokens/primitives/controlSizes");
|
|
14
15
|
const MODES = ["grid", "list"];
|
|
16
|
+
const TRACK_HEIGHT = controlSizes_1.CONTROL_SIZES.sm.height;
|
|
17
|
+
const SEGMENT_HEIGHT = `calc(${TRACK_HEIGHT} - 0.25rem)`;
|
|
15
18
|
/** Two icon-only IconButtons (Grid/List), aria-pressed marks the active one; shares variant with SegmentedControl (see MODULE.md). */
|
|
16
19
|
const TableToggle = ({ value, onChange, variant = "default" }) => {
|
|
17
20
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
@@ -32,7 +35,7 @@ const TableToggle = ({ value, onChange, variant = "default" }) => {
|
|
|
32
35
|
p: isUnderlineSlide ? "0" : "0.125rem",
|
|
33
36
|
borderRadius: isUnderlineSlide ? "none" : "lg",
|
|
34
37
|
borderBottom: isUnderlineSlide ? `0.0625rem solid ${colors.boxborder[200]}` : undefined,
|
|
35
|
-
height:
|
|
38
|
+
height: TRACK_HEIGHT,
|
|
36
39
|
gap: isUnderlineSlide ? "0" : "0.125rem",
|
|
37
40
|
width: "6.3rem",
|
|
38
41
|
position: "relative",
|
|
@@ -50,7 +53,7 @@ const TableToggle = ({ value, onChange, variant = "default" }) => {
|
|
|
50
53
|
? colors.accentText
|
|
51
54
|
: restInk,
|
|
52
55
|
borderRadius: isUnderlineSlide ? "none" : "lg",
|
|
53
|
-
height:
|
|
56
|
+
height: SEGMENT_HEIGHT,
|
|
54
57
|
border: hasIndicator ? "none" : "1px solid",
|
|
55
58
|
borderColor: hasIndicator
|
|
56
59
|
? "transparent"
|
|
@@ -75,7 +78,7 @@ const TableToggle = ({ value, onChange, variant = "default" }) => {
|
|
|
75
78
|
transition: "color 0.2s ease-in-out",
|
|
76
79
|
}),
|
|
77
80
|
};
|
|
78
|
-
return ((0, jsx_runtime_1.jsxs)(react_1.Box, { ref: trackRef, ...styles.container, children: [isBrandSlide && pill && ((0, jsx_runtime_1.jsx)(react_1.Box, { "aria-hidden": "true", position: "absolute", top: "0.125rem", left: 0, h:
|
|
81
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.Box, { ref: trackRef, ...styles.container, children: [isBrandSlide && pill && ((0, jsx_runtime_1.jsx)(react_1.Box, { "aria-hidden": "true", position: "absolute", top: "0.125rem", left: 0, h: SEGMENT_HEIGHT, w: `${pill.width}px`, borderRadius: "lg", bg: brandFill.fill, boxShadow: `0 0.125rem 0.5rem ${colors.boxShadow.primary}`, transform: `translateX(${pill.left}px)`, transition: "transform 0.24s cubic-bezier(0.2, 0.8, 0.2, 1), width 0.24s cubic-bezier(0.2, 0.8, 0.2, 1)" })), isUnderlineSlide && pill && ((0, jsx_runtime_1.jsx)(react_1.Box, { "aria-hidden": "true", position: "absolute", bottom: "-0.0625rem", left: 0, h: "0.125rem", w: `${pill.width}px`, borderRadius: "full", bg: colors.primary[500], transform: `translateX(${pill.left}px)`, transition: "transform 0.24s cubic-bezier(0.2, 0.8, 0.2, 1), width 0.24s cubic-bezier(0.2, 0.8, 0.2, 1)" })), (0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: "Grid View", placement: "top", fontSize: 12, hasArrow: true, children: (0, jsx_runtime_1.jsx)(react_1.IconButton, { ref: (node) => {
|
|
79
82
|
refs.current[0] = node;
|
|
80
83
|
}, "aria-label": "Grid View", "aria-pressed": value === "grid", icon: (0, jsx_runtime_1.jsx)(lucide_react_1.Table2, { size: "1.25rem" }), variant: "ghost", onClick: () => onChange("grid"), ...styles.button("grid") }) }), (0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: "List View", placement: "top", fontSize: 12, hasArrow: true, children: (0, jsx_runtime_1.jsx)(react_1.IconButton, { ref: (node) => {
|
|
81
84
|
refs.current[1] = node;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Centres a caller-supplied icon in a fixed box and pins its svg to that size, whatever size the caller gave it. */
|
|
2
|
+
export const iconBoxSx = (px) => ({
|
|
3
|
+
display: "inline-flex",
|
|
4
|
+
alignItems: "center",
|
|
5
|
+
justifyContent: "center",
|
|
6
|
+
lineHeight: 0,
|
|
7
|
+
flexShrink: 0,
|
|
8
|
+
"& > svg, & > * svg, & svg": {
|
|
9
|
+
width: `${px}px !important`,
|
|
10
|
+
height: `${px}px !important`,
|
|
11
|
+
},
|
|
12
|
+
});
|
|
@@ -83,7 +83,7 @@ const TextInput = forwardRef(({ label, type = "text", id, name, onChange, onBlur
|
|
|
83
83
|
const { showError, showHelper } = fieldMessageVisibility({ error: isFieldInvalid, errorMessage, helperText });
|
|
84
84
|
const showMessageRow = showCounter || showError || showHelper;
|
|
85
85
|
const describedBy = [ids.describedBy, counterId].filter(Boolean).join(" ") || undefined;
|
|
86
|
-
const content = (_jsxs(_Fragment, { children: [label && (_jsx(TextLabel, { label: label, id: ids.inputId, isInformation: isInformation, informationMessage: informationMessage, isRequired: isFieldRequired })), _jsxs(InputGroup, { style: inputGroupStyle, size: size, height: height, children: [inputLeftAddon && (_jsx(InputLeftAddon, { sx: fieldAddonSx(theme.colors), children: inputLeftAddon })), inputLeftIcon && (_jsx(InputLeftElement, { pointerEvents: onLeftIconClick ? "auto" : "none", ...leftElementStyle, height: "100%", display: "flex", alignItems: "center", children: _jsx(IconSlot, { icon: inputLeftIcon, onClick: onLeftIconClick, ariaLabel: leftIconAriaLabel !== null && leftIconAriaLabel !== void 0 ? leftIconAriaLabel : actionName("left icon action"), sx: iconScaleSx, color: iconColor, isDisabled: isFieldDisabled }) })), _jsx(Input, { type: effectiveType, placeholder: placeholder, onChange: onChange, onBlur: onBlur, onFocus: onFocus, value: value, isDisabled: isFieldDisabled, isReadOnly: isFieldReadOnly, name: name, size: size, variant: variant, maxLength: maxLength, ...(height != null && { height }), isInvalid: isFieldInvalid, ref: mergedRef, autoComplete: autoComplete, "aria-busy": isLoading || undefined, ...ids.controlProps, "aria-describedby": describedBy, ...inputStyle, ...props }), (isLoading || rightSlots.length > 0) && (_jsx(InputRightElement, { pointerEvents: !isLoading && rightSlots.some((slot) => slot.onClick) ? "auto" : "none", ...rightElementStyle, height: "100%", display: "flex", alignItems: "center", justifyContent: "flex-end", width: !isLoading && rightSlots.length > 1 ? "auto" : undefined, ...(!isLoading && rightSlots.length > 1 ? { pr: 2, gap: 1 } : {}), children: isLoading ? (_jsx(Spinner, { size: "xs", color: iconColor })) : (rightSlots.map((slot) => (_jsx(IconSlot, { icon: slot.icon, onClick: slot.onClick, ariaLabel: slot.ariaLabel, sx: iconScaleSx, color: iconColor, isDisabled: isFieldDisabled }, slot.key)))) })), inputRightAddon && (_jsx(InputRightAddon, { sx: fieldAddonSx(theme.colors), children: inputRightAddon }))] }), showMessageRow && (_jsxs(Flex, { justify: "space-between", align: "flex-start", gap: 2, children: [_jsx(FieldMessage, { error: isFieldInvalid, errorMessage: errorMessage, helperText: helperText, helperId: ids.helperId, errorId: ids.errorId }), showCounter && stringValue !== undefined && (_jsxs(Text, { id: counterId, flexShrink: 0, ...fieldMessageStyles(theme.colors), color: isFieldInvalid ? theme.colors.semanticText.error : theme.colors.textMuted, children: [stringValue.length, "/", maxLength] }))] }))] }));
|
|
86
|
+
const content = (_jsxs(_Fragment, { children: [label && (_jsx(TextLabel, { label: label, id: ids.inputId, isInformation: isInformation, informationMessage: informationMessage, isRequired: isFieldRequired })), _jsxs(InputGroup, { style: inputGroupStyle, size: size, height: height, children: [inputLeftAddon && (_jsx(InputLeftAddon, { sx: fieldAddonSx(theme.colors), children: inputLeftAddon })), inputLeftIcon && (_jsx(InputLeftElement, { pointerEvents: onLeftIconClick ? "auto" : "none", ...leftElementStyle, height: "100%", display: "flex", alignItems: "center", children: _jsx(IconSlot, { icon: inputLeftIcon, onClick: onLeftIconClick, ariaLabel: leftIconAriaLabel !== null && leftIconAriaLabel !== void 0 ? leftIconAriaLabel : actionName("left icon action"), sx: iconScaleSx, color: iconColor, isDisabled: isFieldDisabled }) })), _jsx(Input, { type: effectiveType, placeholder: placeholder, onChange: onChange, onBlur: onBlur, onFocus: onFocus, value: value, isDisabled: isFieldDisabled, isReadOnly: isFieldReadOnly, name: name, size: size, variant: variant, maxLength: maxLength, ...(height != null && { height, minH: height }), isInvalid: isFieldInvalid, ref: mergedRef, autoComplete: autoComplete, "aria-busy": isLoading || undefined, ...ids.controlProps, "aria-describedby": describedBy, ...inputStyle, ...props }), (isLoading || rightSlots.length > 0) && (_jsx(InputRightElement, { pointerEvents: !isLoading && rightSlots.some((slot) => slot.onClick) ? "auto" : "none", ...rightElementStyle, height: "100%", display: "flex", alignItems: "center", justifyContent: !isLoading && rightSlots.length > 1 ? "flex-end" : "center", width: !isLoading && rightSlots.length > 1 ? "auto" : undefined, ...(!isLoading && rightSlots.length > 1 ? { pr: 2, gap: 1 } : {}), children: isLoading ? (_jsx(Spinner, { size: "xs", color: iconColor })) : (rightSlots.map((slot) => (_jsx(IconSlot, { icon: slot.icon, onClick: slot.onClick, ariaLabel: slot.ariaLabel, sx: iconScaleSx, color: iconColor, isDisabled: isFieldDisabled }, slot.key)))) })), inputRightAddon && (_jsx(InputRightAddon, { sx: fieldAddonSx(theme.colors), children: inputRightAddon }))] }), showMessageRow && (_jsxs(Flex, { justify: "space-between", align: "flex-start", gap: 2, children: [_jsx(FieldMessage, { error: isFieldInvalid, errorMessage: errorMessage, helperText: helperText, helperId: ids.helperId, errorId: ids.errorId }), showCounter && stringValue !== undefined && (_jsxs(Text, { id: counterId, flexShrink: 0, ...fieldMessageStyles(theme.colors), color: isFieldInvalid ? theme.colors.semanticText.error : theme.colors.textMuted, children: [stringValue.length, "/", maxLength] }))] }))] }));
|
|
87
87
|
return hasParentFormControl ? (_jsx(Box, { w: width, minW: minW, maxW: maxW, children: content })) : (_jsx(FormControl, { w: width, minW: minW, maxW: maxW, children: content }));
|
|
88
88
|
});
|
|
89
89
|
TextInput.displayName = "TextInput";
|
|
@@ -1,20 +1,10 @@
|
|
|
1
1
|
import { CONTROL_SIZES, DEFAULT_CONTROL_SIZE, isControlSize, } from "../../Theme/tokens/primitives/controlSizes.js";
|
|
2
|
+
import { iconBoxSx } from "../Common/iconBox.js";
|
|
2
3
|
/** Icon px for a field size, from the shared control scale; unknown sizes fall back to the default size. */
|
|
3
4
|
export function getTextInputIconSizePx(size) {
|
|
4
5
|
return CONTROL_SIZES[isControlSize(size) ? size : DEFAULT_CONTROL_SIZE].iconSize;
|
|
5
6
|
}
|
|
6
7
|
/** Scales SVG icons (e.g. Lucide, which set explicit width/height) in an icon slot to the field size. */
|
|
7
8
|
export function getTextInputIconWrapperSx(size) {
|
|
8
|
-
|
|
9
|
-
return {
|
|
10
|
-
display: "inline-flex",
|
|
11
|
-
alignItems: "center",
|
|
12
|
-
justifyContent: "center",
|
|
13
|
-
lineHeight: 0,
|
|
14
|
-
flexShrink: 0,
|
|
15
|
-
"& > svg, & > * svg, & svg": {
|
|
16
|
-
width: `${px}px !important`,
|
|
17
|
-
height: `${px}px !important`,
|
|
18
|
-
},
|
|
19
|
-
};
|
|
9
|
+
return iconBoxSx(getTextInputIconSizePx(size));
|
|
20
10
|
}
|
|
@@ -222,13 +222,13 @@ export default function SelectSearch({ options, initialSelectedOption, onOptionS
|
|
|
222
222
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
223
223
|
};
|
|
224
224
|
}, [isOpen]);
|
|
225
|
-
return (_jsx(_Fragment, { children: _jsx(FormControl, { isInvalid: error, children: _jsxs(Box, { display: "flex", flexDirection: "column", position: "relative", sx: boxStyle, children: [label && (_jsx(TextLabel, { label: label, id: ids.inputId, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), isMultipleSelect && selectedOptions.length > 0 && (_jsx(HStack, { spacing: 2, mb: 2, children: selectedOptions.map((option) => (_jsxs(Tag, { size: "md", borderRadius: "full", variant: "solid", colorScheme: "primary", children: [_jsx(TagLabel, { width: "3.125rem", children: option.label }), _jsx(TagCloseButton, { onClick: () => handleRemoveOption(option) })] }, option.id))) })), _jsxs(InputGroup, { children: [_jsx(Input, { ref: inputRef, ...ids.controlProps, variant: "outline", value: inputValue ? inputValue : "", onClick: openDropdown, onFocus: () => {
|
|
225
|
+
return (_jsx(_Fragment, { children: _jsx(FormControl, { isInvalid: error, children: _jsxs(Box, { display: "flex", flexDirection: "column", position: "relative", sx: boxStyle, children: [label && (_jsx(TextLabel, { label: label, id: ids.inputId, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), isMultipleSelect && selectedOptions.length > 0 && (_jsx(HStack, { spacing: 2, mb: 2, children: selectedOptions.map((option) => (_jsxs(Tag, { size: "md", borderRadius: "full", variant: "solid", colorScheme: "primary", children: [_jsx(TagLabel, { width: "3.125rem", children: option.label }), _jsx(TagCloseButton, { onClick: () => handleRemoveOption(option) })] }, option.id))) })), _jsxs(InputGroup, { size: size, children: [_jsx(Input, { ref: inputRef, ...ids.controlProps, variant: "outline", value: inputValue ? inputValue : "", onClick: openDropdown, onFocus: () => {
|
|
226
226
|
if (skipNextInputFocusOpen.current) {
|
|
227
227
|
skipNextInputFocusOpen.current = false;
|
|
228
228
|
return;
|
|
229
229
|
}
|
|
230
230
|
openDropdown();
|
|
231
|
-
}, onChange: (e) => handleInputChange(e.target.value), placeholder: placeholder, onKeyDown: handleKeyDown, name: name, role: "combobox", "aria-autocomplete": "list", "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-controls": listboxId, "aria-required": isRequired || undefined, cursor: "pointer", sx: { ...fieldControlStyles(theme.colors), ...controlSizeStyles(size), ...reducedMotionSx() }, style: inputStyle }), rightIcon && (_jsx(InputRightElement, { pointerEvents: "none", children: rightIcon, style: { ...rightElementStyle } }))] }), isOpen && (_jsxs(Box, { ref: dropdownRef, marginTop: "0.313rem", position: "absolute", top: position === "below" ? "100%" : "auto", bottom: position === "above" ? "100%" : "auto", left: 0, right: 0, border: "0.063rem solid", borderColor: theme.colors.boxborder[200], borderRadius: "xl", boxShadow: theme.shadows.lg, bg: theme.colors.surfaceRaised, maxHeight: "9.375rem", overflowY: "auto", zIndex: 10, children: [_jsx(Box, { id: listboxId, role: "listbox", "aria-label": label !== null && label !== void 0 ? label : placeholder, onKeyDown: handleListKeyDown, children: _jsx(RenderOptions, { isOptionLoading: isOptionLoading, filteredOptions: filteredOptions, loadingText: loadingText, handleOptionClick: handleOptionClick, isProfile: isProfile, isColorOptions: isColorOptions, isOptionSelected: isOptionSelected, activeIndex: activeIndex, optionRefs: optionRefs, size: size, isMultipleSelect: isMultipleSelect }) }), _jsx("hr", {}), isBottomIcon && (_jsxs(Box, { position: "sticky", bottom: 0, background: theme.colors.surfaceRaised, display: "flex", alignItems: "center", pl: "1rem", cursor: "pointer", onClick: handleBottomClick, borderColor: theme.colors.boxborder[200], zIndex: 1, borderTop: `1px solid ${theme.colors.boxborder[200]}`, children: [_jsx(Box, { children: BottomIcon ? BottomIcon : _jsx(PlusIcon, { size: "1rem" }) }), _jsx(Box, { fontSize: "0.875rem", color: BottomTextColor
|
|
231
|
+
}, onChange: (e) => handleInputChange(e.target.value), placeholder: placeholder, onKeyDown: handleKeyDown, name: name, role: "combobox", "aria-autocomplete": "list", "aria-haspopup": "listbox", "aria-expanded": isOpen, "aria-controls": listboxId, "aria-required": isRequired || undefined, cursor: "pointer", sx: { ...fieldControlStyles(theme.colors), ...controlSizeStyles(size), ...reducedMotionSx() }, style: inputStyle }), rightIcon && (_jsx(InputRightElement, { pointerEvents: "none", height: "100%", display: "flex", alignItems: "center", children: rightIcon, style: { ...rightElementStyle } }))] }), isOpen && (_jsxs(Box, { ref: dropdownRef, marginTop: "0.313rem", position: "absolute", top: position === "below" ? "100%" : "auto", bottom: position === "above" ? "100%" : "auto", left: 0, right: 0, border: "0.063rem solid", borderColor: theme.colors.boxborder[200], borderRadius: "xl", boxShadow: theme.shadows.lg, bg: theme.colors.surfaceRaised, maxHeight: "9.375rem", overflowY: "auto", zIndex: 10, children: [_jsx(Box, { id: listboxId, role: "listbox", "aria-label": label !== null && label !== void 0 ? label : placeholder, onKeyDown: handleListKeyDown, children: _jsx(RenderOptions, { isOptionLoading: isOptionLoading, filteredOptions: filteredOptions, loadingText: loadingText, handleOptionClick: handleOptionClick, isProfile: isProfile, isColorOptions: isColorOptions, isOptionSelected: isOptionSelected, activeIndex: activeIndex, optionRefs: optionRefs, size: size, isMultipleSelect: isMultipleSelect }) }), _jsx("hr", {}), isBottomIcon && (_jsxs(Box, { position: "sticky", bottom: 0, background: theme.colors.surfaceRaised, display: "flex", alignItems: "center", pl: "1rem", cursor: "pointer", onClick: handleBottomClick, borderColor: theme.colors.boxborder[200], zIndex: 1, borderTop: `1px solid ${theme.colors.boxborder[200]}`, children: [_jsx(Box, { children: BottomIcon ? BottomIcon : _jsx(PlusIcon, { size: "1rem" }) }), _jsx(Box, { fontSize: "0.875rem", color: BottomTextColor
|
|
232
232
|
? BottomTextColor
|
|
233
233
|
: theme.colors.accentText, padding: "8px 8px", children: BottomText || "Add New" })] }))] })), _jsx(FieldMessage, { error: error, errorMessage: errorMessage, helperText: helperText, helperId: ids.helperId, errorId: ids.errorId })] }) }) }));
|
|
234
234
|
}
|
|
@@ -25,6 +25,6 @@ const TableSearch = ({ onSearch }) => {
|
|
|
25
25
|
setQuery(value);
|
|
26
26
|
handleDebounce(value);
|
|
27
27
|
};
|
|
28
|
-
return (_jsxs(Box, { display: "flex", alignItems: "center", gap: "2", children: [!showInput && (_jsx(ToolTip, { label: "Search", placement: "top", children: _jsx(IconButton, { "aria-label": "Search", icon: _jsx(Icon, { as: Search, transform: "scaleX(-1)", boxSize: 5 }), variant: "unstyled", minW: "auto", h: "auto", display: "flex", cursor: "pointer", color: colors.text[500], onClick: handleSearchClick, _hover: { color: colors.accentText } }) })), showInput ? (_jsxs(InputGroup, { maxW: "12.5rem", children: [_jsx(Input, { placeholder: "Search...", value: query, onChange: handleInputChange, size: "sm", borderRadius: "lg", borderColor: colors.boxborder[500], _focus: { borderColor: colors.accentText }, autoFocus: true }), _jsx(InputRightElement, { display: "flex", alignItems: "center", height: "
|
|
28
|
+
return (_jsxs(Box, { display: "flex", alignItems: "center", gap: "2", children: [!showInput && (_jsx(ToolTip, { label: "Search", placement: "top", children: _jsx(IconButton, { "aria-label": "Search", icon: _jsx(Icon, { as: Search, transform: "scaleX(-1)", boxSize: 5 }), variant: "unstyled", minW: "auto", h: "auto", display: "flex", cursor: "pointer", color: colors.text[500], onClick: handleSearchClick, _hover: { color: colors.accentText } }) })), showInput ? (_jsxs(InputGroup, { size: "sm", maxW: "12.5rem", children: [_jsx(Input, { placeholder: "Search...", value: query, onChange: handleInputChange, size: "sm", borderRadius: "lg", borderColor: colors.boxborder[500], _focus: { borderColor: colors.accentText }, autoFocus: true }), _jsx(InputRightElement, { display: "flex", alignItems: "center", height: "100%", children: _jsx(IconButton, { "aria-label": "Clear search", icon: _jsx(Icon, { as: X }), variant: "unstyled", minW: "auto", h: "auto", display: "flex", color: colors.text[500], cursor: "pointer", onClick: handleSearchClick }) })] })) : null] }));
|
|
29
29
|
};
|
|
30
30
|
export default TableSearch;
|
|
@@ -8,6 +8,7 @@ import { compositeOver } from "../../../Theme/tokens/builders/color.js";
|
|
|
8
8
|
import { transitionFor } from "../../../Theme/tokens/primitives/motion.js";
|
|
9
9
|
import { reducedMotionSx } from "../../../Theme/chakra/motion.js";
|
|
10
10
|
import { CONTROL_SIZES } from "../../../Theme/tokens/primitives/controlSizes.js";
|
|
11
|
+
import { iconBoxSx } from "../../Common/iconBox.js";
|
|
11
12
|
import { resolveTabStyle, scaleForColorScheme } from "../tabStyles.js";
|
|
12
13
|
import { panelId, tabId, useTabsContext } from "../TabsContext.js";
|
|
13
14
|
import CountBadge from "./CountBadge.js";
|
|
@@ -39,6 +40,6 @@ const Tab = ({ value, children, icon, count, isDisabled }) => {
|
|
|
39
40
|
? { borderLeft: "0.125rem solid", borderLeftColor: (_c = style.indicator) !== null && _c !== void 0 ? _c : "transparent" }
|
|
40
41
|
: { borderBottom: "0.125rem solid", borderBottomColor: (_d = style.indicator) !== null && _d !== void 0 ? _d : "transparent" }
|
|
41
42
|
: {};
|
|
42
|
-
return (_jsxs(Box, { as: "button", type: "button", ref: ref, role: "tab", id: tabId(ctx.baseId, value), "aria-selected": isSelected, "aria-disabled": isDisabled || undefined, "aria-controls": ctx.hasPanels ? panelId(ctx.baseId, value) : undefined, "data-value": value, tabIndex: isDisabled ? -1 : isFocusTarget ? 0 : -1, disabled: isDisabled, onClick: () => !isDisabled && ctx.select(value), onFocus: () => ctx.focusTab(value), display: "flex", alignItems: "center", justifyContent: "center", gap: "0.375rem", flexShrink: 0, flex: ctx.isFitted ? 1 : undefined, w: isVertical ? "100%" : undefined, h: isVertical ? "auto" : spec.height, minH: spec.height, py: isVertical ? "0.5rem" : undefined, px: spec.paddingX, fontSize: spec.fontSize, fontWeight: isSelected ? 600 : 500, whiteSpace: "nowrap", cursor: isDisabled ? "not-allowed" : "pointer", opacity: isDisabled ? 0.5 : 1, borderRadius: isLine ? "none" : "lg", bg: style.bg, color: style.color, ...borderProps, transition: transitionFor(["background-color", "color", "border-color"]), sx: { _focusVisible: focusRing, [FOCUS_VISIBLE_OVER_STATE]: focusRing, ...reducedMotionSx() }, _hover: !isDisabled ? { bg: style.hoverBg, color: style.hoverColor } : undefined, children: [icon ? (_jsx(Box, { as: "span", "aria-hidden": true,
|
|
43
|
+
return (_jsxs(Box, { as: "button", type: "button", ref: ref, role: "tab", id: tabId(ctx.baseId, value), "aria-selected": isSelected, "aria-disabled": isDisabled || undefined, "aria-controls": ctx.hasPanels ? panelId(ctx.baseId, value) : undefined, "data-value": value, tabIndex: isDisabled ? -1 : isFocusTarget ? 0 : -1, disabled: isDisabled, onClick: () => !isDisabled && ctx.select(value), onFocus: () => ctx.focusTab(value), display: "flex", alignItems: "center", justifyContent: "center", gap: "0.375rem", flexShrink: 0, flex: ctx.isFitted ? 1 : undefined, w: isVertical ? "100%" : undefined, h: isVertical ? "auto" : spec.height, minH: spec.height, py: isVertical ? "0.5rem" : undefined, px: spec.paddingX, fontSize: spec.fontSize, fontWeight: isSelected ? 600 : 500, whiteSpace: "nowrap", cursor: isDisabled ? "not-allowed" : "pointer", opacity: isDisabled ? 0.5 : 1, borderRadius: isLine ? "none" : "lg", bg: style.bg, color: style.color, ...borderProps, transition: transitionFor(["background-color", "color", "border-color"]), sx: { _focusVisible: focusRing, [FOCUS_VISIBLE_OVER_STATE]: focusRing, ...reducedMotionSx() }, _hover: !isDisabled ? { bg: style.hoverBg, color: style.hoverColor } : undefined, children: [icon ? (_jsx(Box, { as: "span", "aria-hidden": true, boxSize: `${spec.iconSize}px`, sx: iconBoxSx(spec.iconSize), children: icon })) : null, _jsx(Box, { as: "span", children: children }), count !== undefined ? (_jsx(CountBadge, { count: count, colors: colors, scale: scale, surface: ctx.variant === "solid" && isSelected ? style.bg : canvas, size: ctx.size })) : null] }));
|
|
43
44
|
};
|
|
44
45
|
export default Tab;
|
|
@@ -6,7 +6,10 @@ import { AA_NON_TEXT, liftToContrast } from "../../Theme/tokens/builders/outline
|
|
|
6
6
|
import { resolveFilledSurface } from "../../Theme/tokens/builders/filledSurface.js";
|
|
7
7
|
import ToolTip from "../ToolTip/ToolTip.js";
|
|
8
8
|
import { useSlidingPill } from "../SegmentedControl/useSlidingPill.js";
|
|
9
|
+
import { CONTROL_SIZES } from "../../Theme/tokens/primitives/controlSizes.js";
|
|
9
10
|
const MODES = ["grid", "list"];
|
|
11
|
+
const TRACK_HEIGHT = CONTROL_SIZES.sm.height;
|
|
12
|
+
const SEGMENT_HEIGHT = `calc(${TRACK_HEIGHT} - 0.25rem)`;
|
|
10
13
|
/** Two icon-only IconButtons (Grid/List), aria-pressed marks the active one; shares variant with SegmentedControl (see MODULE.md). */
|
|
11
14
|
const TableToggle = ({ value, onChange, variant = "default" }) => {
|
|
12
15
|
const theme = useCustomTheme();
|
|
@@ -27,7 +30,7 @@ const TableToggle = ({ value, onChange, variant = "default" }) => {
|
|
|
27
30
|
p: isUnderlineSlide ? "0" : "0.125rem",
|
|
28
31
|
borderRadius: isUnderlineSlide ? "none" : "lg",
|
|
29
32
|
borderBottom: isUnderlineSlide ? `0.0625rem solid ${colors.boxborder[200]}` : undefined,
|
|
30
|
-
height:
|
|
33
|
+
height: TRACK_HEIGHT,
|
|
31
34
|
gap: isUnderlineSlide ? "0" : "0.125rem",
|
|
32
35
|
width: "6.3rem",
|
|
33
36
|
position: "relative",
|
|
@@ -45,7 +48,7 @@ const TableToggle = ({ value, onChange, variant = "default" }) => {
|
|
|
45
48
|
? colors.accentText
|
|
46
49
|
: restInk,
|
|
47
50
|
borderRadius: isUnderlineSlide ? "none" : "lg",
|
|
48
|
-
height:
|
|
51
|
+
height: SEGMENT_HEIGHT,
|
|
49
52
|
border: hasIndicator ? "none" : "1px solid",
|
|
50
53
|
borderColor: hasIndicator
|
|
51
54
|
? "transparent"
|
|
@@ -70,7 +73,7 @@ const TableToggle = ({ value, onChange, variant = "default" }) => {
|
|
|
70
73
|
transition: "color 0.2s ease-in-out",
|
|
71
74
|
}),
|
|
72
75
|
};
|
|
73
|
-
return (_jsxs(Box, { ref: trackRef, ...styles.container, children: [isBrandSlide && pill && (_jsx(Box, { "aria-hidden": "true", position: "absolute", top: "0.125rem", left: 0, h:
|
|
76
|
+
return (_jsxs(Box, { ref: trackRef, ...styles.container, children: [isBrandSlide && pill && (_jsx(Box, { "aria-hidden": "true", position: "absolute", top: "0.125rem", left: 0, h: SEGMENT_HEIGHT, w: `${pill.width}px`, borderRadius: "lg", bg: brandFill.fill, boxShadow: `0 0.125rem 0.5rem ${colors.boxShadow.primary}`, transform: `translateX(${pill.left}px)`, transition: "transform 0.24s cubic-bezier(0.2, 0.8, 0.2, 1), width 0.24s cubic-bezier(0.2, 0.8, 0.2, 1)" })), isUnderlineSlide && pill && (_jsx(Box, { "aria-hidden": "true", position: "absolute", bottom: "-0.0625rem", left: 0, h: "0.125rem", w: `${pill.width}px`, borderRadius: "full", bg: colors.primary[500], transform: `translateX(${pill.left}px)`, transition: "transform 0.24s cubic-bezier(0.2, 0.8, 0.2, 1), width 0.24s cubic-bezier(0.2, 0.8, 0.2, 1)" })), _jsx(ToolTip, { label: "Grid View", placement: "top", fontSize: 12, hasArrow: true, children: _jsx(IconButton, { ref: (node) => {
|
|
74
77
|
refs.current[0] = node;
|
|
75
78
|
}, "aria-label": "Grid View", "aria-pressed": value === "grid", icon: _jsx(Table2, { size: "1.25rem" }), variant: "ghost", onClick: () => onChange("grid"), ...styles.button("grid") }) }), _jsx(ToolTip, { label: "List View", placement: "top", fontSize: 12, hasArrow: true, children: _jsx(IconButton, { ref: (node) => {
|
|
76
79
|
refs.current[1] = node;
|
package/package.json
CHANGED