pixelize-design-library 2.4.2-beta.44 → 2.4.2-beta.46
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 +75 -0
- package/COMPONENT-GOTCHAS.md +58 -1
- package/dist/Components/Common/fieldStyles.d.ts +1 -1
- package/dist/Components/Common/fieldStyles.js +4 -4
- package/dist/Components/DatePicker/CalendarPanel.js +2 -5
- package/dist/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.js +2 -4
- package/dist/Components/FilterSidebar/FilterSidebar.js +2 -1
- package/dist/Components/Header/HeaderActions.d.ts +2 -0
- package/dist/Components/Header/HeaderActions.js +2 -2
- package/dist/Components/Input/TextInput.styles.js +1 -1
- package/dist/Components/KanbanBoard/KanbanActions/KanbanActions.js +1 -1
- package/dist/Components/KanbanBoard/KanbanBoardProps.d.ts +2 -0
- package/dist/Components/MultiSelect/MultiSelect.d.ts +1 -1
- package/dist/Components/MultiSelect/MultiSelect.js +23 -12
- package/dist/Components/MultiSelect/MultiSelectProps.d.ts +2 -0
- package/dist/Components/NotificationBell/notificationHelpers.d.ts +5 -2
- package/dist/Components/NotificationBell/notificationHelpers.js +13 -4
- package/dist/Components/PinInput/PinInput.js +2 -4
- package/dist/Components/SearchSelect/SearchSelect.js +1 -1
- package/dist/Components/SegmentedControl/SegmentedControl.d.ts +1 -1
- package/dist/Components/SegmentedControl/SegmentedControl.js +33 -16
- package/dist/Components/SegmentedControl/SegmentedControlProps.d.ts +2 -0
- package/dist/Components/SegmentedControl/segmentedInk.d.ts +11 -0
- package/dist/Components/SegmentedControl/segmentedInk.js +27 -0
- package/dist/Components/Select/SelectPopup.js +13 -4
- package/dist/Components/Select/optionRowInk.d.ts +3 -0
- package/dist/Components/Select/optionRowInk.js +6 -0
- package/dist/Components/SideBar/SecondaryBar.js +5 -4
- package/dist/Components/SideBar/SideBar.js +6 -5
- package/dist/Components/SideBar/SideBarProps.d.ts +2 -0
- package/dist/Components/SideBar/components/MenuItemBox.js +5 -4
- package/dist/Components/SideBar/components/MenuItems.js +1 -1
- package/dist/Components/SideBar/components/MenuPopoverContent.js +4 -3
- package/dist/Components/SideBar/sidebarScale.d.ts +15 -0
- package/dist/Components/SideBar/sidebarScale.js +18 -0
- package/dist/Components/Switch/Switch.d.ts +2 -2
- package/dist/Components/Switch/Switch.js +3 -3
- package/dist/Components/Switch/SwitchProps.d.ts +2 -0
- package/dist/Components/Table/components/Pagination.d.ts +1 -1
- package/dist/Components/Table/components/Pagination.js +12 -4
- package/dist/Components/Table/filters/SelectOperationControls.js +9 -1
- package/dist/Components/Table/filters/TextOperationControls.js +8 -1
- package/dist/Components/Table/hooks/useTable.d.ts +2 -1
- package/dist/Components/Table/hooks/useTable.js +5 -3
- package/dist/Components/Tabs/components/Tab.js +11 -1
- package/dist/Theme/chakra/focusRing.styles.d.ts +17 -1
- package/dist/Theme/chakra/focusRing.styles.js +16 -1
- package/dist/Theme/provider/ThemeSwitcher.js +15 -8
- package/dist/esm/Components/Common/fieldStyles.js +5 -5
- package/dist/esm/Components/DatePicker/CalendarPanel.js +2 -5
- package/dist/esm/Components/EmailCards/VerifyEmailOtp/VerifyEmailOtp.js +2 -4
- package/dist/esm/Components/FilterSidebar/FilterSidebar.js +2 -1
- package/dist/esm/Components/Header/HeaderActions.js +2 -2
- package/dist/esm/Components/Input/TextInput.styles.js +2 -2
- package/dist/esm/Components/KanbanBoard/KanbanActions/KanbanActions.js +1 -1
- package/dist/esm/Components/MultiSelect/MultiSelect.js +23 -12
- package/dist/esm/Components/NotificationBell/notificationHelpers.js +13 -4
- package/dist/esm/Components/PinInput/PinInput.js +2 -4
- package/dist/esm/Components/SearchSelect/SearchSelect.js +1 -1
- package/dist/esm/Components/SegmentedControl/SegmentedControl.js +32 -15
- package/dist/esm/Components/SegmentedControl/segmentedInk.js +20 -0
- package/dist/esm/Components/Select/SelectPopup.js +14 -5
- package/dist/esm/Components/Select/optionRowInk.js +2 -0
- package/dist/esm/Components/SideBar/SecondaryBar.js +5 -4
- package/dist/esm/Components/SideBar/SideBar.js +6 -5
- package/dist/esm/Components/SideBar/components/MenuItemBox.js +5 -4
- package/dist/esm/Components/SideBar/components/MenuItems.js +1 -1
- package/dist/esm/Components/SideBar/components/MenuPopoverContent.js +4 -3
- package/dist/esm/Components/SideBar/sidebarScale.js +15 -0
- package/dist/esm/Components/Switch/Switch.js +3 -3
- package/dist/esm/Components/Table/components/Pagination.js +13 -5
- package/dist/esm/Components/Table/filters/SelectOperationControls.js +8 -3
- package/dist/esm/Components/Table/filters/TextOperationControls.js +6 -2
- package/dist/esm/Components/Table/hooks/useTable.js +4 -3
- package/dist/esm/Components/Tabs/components/Tab.js +12 -2
- package/dist/esm/Theme/chakra/focusRing.styles.js +13 -0
- package/dist/esm/Theme/provider/ThemeSwitcher.js +16 -9
- package/package.json +1 -1
|
@@ -40,18 +40,26 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
40
40
|
const react_1 = __importStar(require("react"));
|
|
41
41
|
const react_2 = require("@chakra-ui/react");
|
|
42
42
|
const table_1 = require("../../../Utils/table");
|
|
43
|
+
const Select_1 = __importDefault(require("../../Select/Select"));
|
|
44
|
+
const useTable_1 = require("../hooks/useTable");
|
|
43
45
|
const useCustomTheme_1 = require("../../../Theme/useCustomTheme");
|
|
44
46
|
const ToolTip_1 = __importDefault(require("../../ToolTip/ToolTip"));
|
|
45
47
|
const lucide_react_1 = require("lucide-react");
|
|
46
48
|
const Pagination = react_1.default.memo(({ paginationText, handlePageSizeChange, rowsPerPage, currentPage, pages, setCurrentPage, dataLength, isServerPagination, paginationSelectOptions, }) => {
|
|
47
|
-
const computedOptions = (0, react_1.useMemo)(() =>
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
const computedOptions = (0, react_1.useMemo)(() => {
|
|
50
|
+
if (paginationSelectOptions && paginationSelectOptions.length) {
|
|
51
|
+
return paginationSelectOptions;
|
|
52
|
+
}
|
|
53
|
+
const sizes = new Set((0, table_1.pageSizeCalculation)(dataLength));
|
|
54
|
+
sizes.add(useTable_1.DEFAULT_PAGE_SIZE);
|
|
55
|
+
sizes.add(rowsPerPage);
|
|
56
|
+
return [...sizes].sort((a, b) => a - b);
|
|
57
|
+
}, [paginationSelectOptions, dataLength, rowsPerPage]);
|
|
50
58
|
const theme = (0, useCustomTheme_1.useCustomTheme)();
|
|
51
59
|
// const isLeftDisabled = currentPage === 0;
|
|
52
60
|
// const isRightDisabled = currentPage >= pages - 1;
|
|
53
61
|
const isLeftDisabled = dataLength === 0 || currentPage === 0;
|
|
54
62
|
const isRightDisabled = dataLength === 0 || currentPage >= pages - 1;
|
|
55
|
-
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { justify: "flex-end", align: "center", flexWrap: "nowrap", children: [(!isServerPagination || paginationSelectOptions) && ((0, jsx_runtime_1.
|
|
63
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Flex, { justify: "flex-end", align: "center", flexWrap: "nowrap", children: [(!isServerPagination || paginationSelectOptions) && ((0, jsx_runtime_1.jsx)(Select_1.default, { native: false, isSearchable: false, "aria-label": "Rows per page", onChange: (option) => option && handlePageSizeChange(Number(option.id)), value: rowsPerPage, size: "xs", width: "4.5rem", isDisabled: dataLength === 0, options: computedOptions.map((size) => ({ id: size, label: String(size) })) })), dataLength > 0 && ((0, jsx_runtime_1.jsxs)(react_2.Flex, { w: "100%", children: [(0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: "First", placement: "top", children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": "first-page", color: isLeftDisabled ? theme.colors.textMuted : theme.colors.text[500], rounded: "full", variant: isLeftDisabled ? "plain" : "ghost", onClick: () => setCurrentPage(0), _hover: !isLeftDisabled ? { color: theme.colors.accentText } : {}, children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronsLeft, {}) }) }), (0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: "Previous", placement: "top", children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": "previous-page", color: isLeftDisabled ? theme.colors.textMuted : theme.colors.text[500], rounded: "full", variant: isLeftDisabled ? "plain" : "ghost", onClick: () => currentPage > 0 && setCurrentPage(currentPage - 1), _hover: !isLeftDisabled ? { color: theme.colors.accentText } : {}, children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronLeft, {}) }) }), (0, jsx_runtime_1.jsx)(react_2.Text, { mt: 3, fontSize: 12, whiteSpace: "nowrap", color: theme.colors.text[500], children: paginationText }), (0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: "Next", placement: "top", children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": "next-page", color: isRightDisabled ? theme.colors.textMuted : theme.colors.text[500], rounded: "full", variant: isRightDisabled ? "plain" : "ghost", onClick: () => currentPage < pages - 1 && setCurrentPage(currentPage + 1), _hover: !isRightDisabled ? { color: theme.colors.accentText } : {}, children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, {}) }) }), (0, jsx_runtime_1.jsx)(ToolTip_1.default, { label: "Last", placement: "top", children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": "last-page", color: isRightDisabled ? theme.colors.textMuted : theme.colors.text[500], rounded: "full", variant: isRightDisabled ? "plain" : "ghost", onClick: () => setCurrentPage(pages - 1), _hover: !isRightDisabled ? { color: theme.colors.accentText } : {}, children: (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronsRight, {}) }) })] }))] }));
|
|
56
64
|
});
|
|
57
65
|
exports.default = Pagination;
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.SelectOperationControls = SelectOperationControls;
|
|
4
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
8
|
const react_1 = require("@chakra-ui/react");
|
|
9
|
+
const Select_1 = __importDefault(require("../../Select/Select"));
|
|
10
|
+
const OPERATOR_OPTIONS = [
|
|
11
|
+
{ id: "is", label: "is" },
|
|
12
|
+
{ id: "is not", label: "is not" },
|
|
13
|
+
];
|
|
6
14
|
function SelectOperationControls({ operator, onOperatorChange, size = "xs", ml = "1.25rem", mt = 2, }) {
|
|
7
|
-
return ((0, jsx_runtime_1.jsx)(react_1.VStack, { spacing: 2, align: "stretch", mt: mt, ml: ml, children: (0, jsx_runtime_1.
|
|
15
|
+
return ((0, jsx_runtime_1.jsx)(react_1.VStack, { spacing: 2, align: "stretch", mt: mt, ml: ml, children: (0, jsx_runtime_1.jsx)(Select_1.default, { native: false, isSearchable: false, "aria-label": "Operator", size: size, width: "90px", options: OPERATOR_OPTIONS, value: operator, onChange: (option) => option && onOperatorChange(String(option.id)) }) }));
|
|
8
16
|
}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.requiresValue = exports.TEXT_OPERATORS = void 0;
|
|
4
7
|
exports.TextOperationControls = TextOperationControls;
|
|
5
8
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
9
|
const react_1 = require("@chakra-ui/react");
|
|
10
|
+
const react_2 = require("react");
|
|
11
|
+
const Select_1 = __importDefault(require("../../Select/Select"));
|
|
12
|
+
const TextInput_1 = __importDefault(require("../../Input/TextInput"));
|
|
7
13
|
exports.TEXT_OPERATORS = [
|
|
8
14
|
"is",
|
|
9
15
|
"is not",
|
|
@@ -17,5 +23,6 @@ exports.TEXT_OPERATORS = [
|
|
|
17
23
|
const requiresValue = (op) => !(op === "is empty" || op === "is not empty");
|
|
18
24
|
exports.requiresValue = requiresValue;
|
|
19
25
|
function TextOperationControls({ operator, value, onOperatorChange, onValueChange, size = "xs", ml = "1.25rem", mt = 2, }) {
|
|
20
|
-
|
|
26
|
+
const options = (0, react_2.useMemo)(() => exports.TEXT_OPERATORS.map((op) => ({ id: op, label: op })), []);
|
|
27
|
+
return ((0, jsx_runtime_1.jsxs)(react_1.VStack, { spacing: 2, align: "stretch", mt: mt, ml: ml, children: [(0, jsx_runtime_1.jsx)(Select_1.default, { native: false, isSearchable: false, "aria-label": "Operator", size: size, width: "110px", options: options, value: operator, onChange: (option) => option && onOperatorChange(String(option.id)) }), (0, exports.requiresValue)(operator) && ((0, jsx_runtime_1.jsx)(TextInput_1.default, { size: size, placeholder: "Type here", value: value, onChange: (e) => onValueChange(e.target.value), width: "100%" }))] }));
|
|
21
28
|
}
|
|
@@ -13,6 +13,7 @@ type UseTableProps = {
|
|
|
13
13
|
onNoOfRowsPerPageChange?: (noOfRows: number) => void;
|
|
14
14
|
defaultVisibleColumns?: number;
|
|
15
15
|
};
|
|
16
|
+
export declare const DEFAULT_PAGE_SIZE = 20;
|
|
16
17
|
declare const useTable: ({ data, isPagination, selections, onSelection, tablePreferences, savePreferences, noOfRowsPerPage, isServerPagination, totalRecords, columns, onNoOfRowsPerPageChange, defaultVisibleColumns, }: UseTableProps) => {
|
|
17
18
|
tableData: DataObject[];
|
|
18
19
|
isContent: boolean;
|
|
@@ -26,7 +27,7 @@ declare const useTable: ({ data, isPagination, selections, onSelection, tablePre
|
|
|
26
27
|
endRow: number;
|
|
27
28
|
selection: (string | number)[];
|
|
28
29
|
columnsSort: ColumnSortingProps[];
|
|
29
|
-
handlePageSizeChange: (
|
|
30
|
+
handlePageSizeChange: (size: number) => void;
|
|
30
31
|
pages: number;
|
|
31
32
|
currentPage: number;
|
|
32
33
|
rowsPerPage: number;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_PAGE_SIZE = void 0;
|
|
3
4
|
const react_1 = require("react");
|
|
4
5
|
const table_1 = require("../../../Utils/table");
|
|
5
|
-
|
|
6
|
+
exports.DEFAULT_PAGE_SIZE = 20;
|
|
7
|
+
const defaultPageSize = exports.DEFAULT_PAGE_SIZE;
|
|
6
8
|
const mergeColumnWithPreference = (pref, originalCol) => {
|
|
7
9
|
var _a;
|
|
8
10
|
if (!pref || typeof pref !== "object") {
|
|
@@ -102,8 +104,8 @@ const useTable = ({ data, isPagination, selections, onSelection, tablePreference
|
|
|
102
104
|
const sortedData = (0, table_1.SortMultiColumnData)(tableData, columnsSort);
|
|
103
105
|
return sortedData.slice(startRow, endRow);
|
|
104
106
|
}, [columnsSort, startRow, endRow, tableData, isServerPagination]);
|
|
105
|
-
const handlePageSizeChange = (
|
|
106
|
-
const value = Number(
|
|
107
|
+
const handlePageSizeChange = (size) => {
|
|
108
|
+
const value = Number(size);
|
|
107
109
|
setRowsPerPage(value !== 0 ? value : defaultPageSize);
|
|
108
110
|
if (onNoOfRowsPerPageChange) {
|
|
109
111
|
onNoOfRowsPerPageChange(value !== 0 ? value : defaultPageSize);
|
|
@@ -8,6 +8,8 @@ const react_1 = require("react");
|
|
|
8
8
|
const react_2 = require("@chakra-ui/react");
|
|
9
9
|
const useCustomTheme_1 = require("../../../Theme/useCustomTheme");
|
|
10
10
|
const focusRing_styles_1 = require("../../../Theme/chakra/focusRing.styles");
|
|
11
|
+
const outlineRung_1 = require("../../../Theme/tokens/builders/outlineRung");
|
|
12
|
+
const color_1 = require("../../../Theme/tokens/builders/color");
|
|
11
13
|
const motion_1 = require("../../../Theme/tokens/primitives/motion");
|
|
12
14
|
const motion_2 = require("../../../Theme/chakra/motion");
|
|
13
15
|
const controlSizes_1 = require("../../../Theme/tokens/primitives/controlSizes");
|
|
@@ -27,6 +29,14 @@ const Tab = ({ value, children, icon, count, isDisabled }) => {
|
|
|
27
29
|
const scale = (0, tabStyles_1.scaleForColorScheme)(colors, ctx.colorScheme);
|
|
28
30
|
const style = (0, tabStyles_1.resolveTabStyle)(colors, scale, canvas, ctx.variant, isSelected);
|
|
29
31
|
const spec = controlSizes_1.CONTROL_SIZES[ctx.size];
|
|
32
|
+
// The list scrolls on both axes, so an outer ring is clipped into arcs; a negative offset draws it
|
|
33
|
+
// inside the tab, clear of its own border rather than thickening it.
|
|
34
|
+
const focusRing = {
|
|
35
|
+
outline: `1px solid ${(0, outlineRung_1.liftToContrast)(colors.primary[500],
|
|
36
|
+
// subtle/ghost fills are translucent tints; contrast has no meaning until they are flattened.
|
|
37
|
+
style.bg === "transparent" ? canvas : (0, color_1.compositeOver)(style.bg, canvas), outlineRung_1.AA_NON_TEXT)}`,
|
|
38
|
+
outlineOffset: "-2px",
|
|
39
|
+
};
|
|
30
40
|
const borderProps = ctx.variant === "outline"
|
|
31
41
|
? { border: "1px solid", borderColor: (_b = style.border) !== null && _b !== void 0 ? _b : "transparent" }
|
|
32
42
|
: isLine
|
|
@@ -34,6 +44,6 @@ const Tab = ({ value, children, icon, count, isDisabled }) => {
|
|
|
34
44
|
? { borderLeft: "0.125rem solid", borderLeftColor: (_c = style.indicator) !== null && _c !== void 0 ? _c : "transparent" }
|
|
35
45
|
: { borderBottom: "0.125rem solid", borderBottomColor: (_d = style.indicator) !== null && _d !== void 0 ? _d : "transparent" }
|
|
36
46
|
: {};
|
|
37
|
-
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: {
|
|
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, display: "inline-flex", flexShrink: 0, boxSize: `${spec.iconSize}px`, 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] }));
|
|
38
48
|
};
|
|
39
49
|
exports.default = Tab;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FocusRingTokens } from "../tokens/types";
|
|
1
|
+
import type { BrandScale, FocusRingTokens } from "../tokens/types";
|
|
2
2
|
/** Inner band, in the surface tone: separates the ring from the control's own fill. */
|
|
3
3
|
export declare const FOCUS_HALO_WIDTH = 2;
|
|
4
4
|
/** Outer edge of the brand band. The band itself is the 2px between halo and ring. */
|
|
@@ -6,6 +6,9 @@ export declare const FOCUS_RING_WIDTH = 4;
|
|
|
6
6
|
type WithFocusRing = {
|
|
7
7
|
focusRing: FocusRingTokens;
|
|
8
8
|
};
|
|
9
|
+
type WithBrandGlow = {
|
|
10
|
+
primary: BrandScale;
|
|
11
|
+
};
|
|
9
12
|
export declare const focusRingShadow: (colors: WithFocusRing) => string;
|
|
10
13
|
export declare const FOCUS_VISIBLE_OVER_STATE = "&:hover:focus-visible, &:active:focus-visible, &[data-active]:focus-visible";
|
|
11
14
|
export declare const focusVisibleRing: (colors: WithFocusRing) => {
|
|
@@ -13,6 +16,19 @@ export declare const focusVisibleRing: (colors: WithFocusRing) => {
|
|
|
13
16
|
outlineOffset: string;
|
|
14
17
|
boxShadow: string;
|
|
15
18
|
};
|
|
19
|
+
/** Blurred, never a flat band: a band has a hard outer edge at every opacity and reads as a second border. */
|
|
20
|
+
export declare const FOCUS_GLOW_BLUR = 6;
|
|
21
|
+
/** Negative spread keeps the bloom tight to the border instead of haloing the whole control. */
|
|
22
|
+
export declare const FOCUS_GLOW_SPREAD = -1;
|
|
23
|
+
/** Step on `primary.opacity`. Safe to raise because a blur has no edge to sharpen. */
|
|
24
|
+
export declare const FOCUS_GLOW_ALPHA = 32;
|
|
25
|
+
export declare const focusGlowShadow: (colors: WithBrandGlow) => string;
|
|
26
|
+
/** Field focus: the brand border is the indicator, this only makes it findable. */
|
|
27
|
+
export declare const fieldFocusVisible: (colors: WithBrandGlow) => {
|
|
28
|
+
outline: string;
|
|
29
|
+
outlineOffset: string;
|
|
30
|
+
boxShadow: string;
|
|
31
|
+
};
|
|
16
32
|
/** Both selectors a control needs to keep the ring on top of its own hover/active styling. */
|
|
17
33
|
export declare const focusVisibleStyles: (colors: WithFocusRing) => {
|
|
18
34
|
_focusVisible: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.focusVisibleStyles = exports.focusVisibleRing = exports.FOCUS_VISIBLE_OVER_STATE = exports.focusRingShadow = exports.FOCUS_RING_WIDTH = exports.FOCUS_HALO_WIDTH = void 0;
|
|
3
|
+
exports.focusVisibleStyles = exports.fieldFocusVisible = exports.focusGlowShadow = exports.FOCUS_GLOW_ALPHA = exports.FOCUS_GLOW_SPREAD = exports.FOCUS_GLOW_BLUR = exports.focusVisibleRing = exports.FOCUS_VISIBLE_OVER_STATE = exports.focusRingShadow = exports.FOCUS_RING_WIDTH = exports.FOCUS_HALO_WIDTH = void 0;
|
|
4
4
|
// Web binding for the focusRing token pair — colors come from tokens/builders/focusRing.ts; CSS shape is web-only.
|
|
5
5
|
/** Inner band, in the surface tone: separates the ring from the control's own fill. */
|
|
6
6
|
exports.FOCUS_HALO_WIDTH = 2;
|
|
@@ -19,6 +19,21 @@ const focusVisibleRing = (colors) => ({
|
|
|
19
19
|
boxShadow: (0, exports.focusRingShadow)(colors),
|
|
20
20
|
});
|
|
21
21
|
exports.focusVisibleRing = focusVisibleRing;
|
|
22
|
+
/** Blurred, never a flat band: a band has a hard outer edge at every opacity and reads as a second border. */
|
|
23
|
+
exports.FOCUS_GLOW_BLUR = 6;
|
|
24
|
+
/** Negative spread keeps the bloom tight to the border instead of haloing the whole control. */
|
|
25
|
+
exports.FOCUS_GLOW_SPREAD = -1;
|
|
26
|
+
/** Step on `primary.opacity`. Safe to raise because a blur has no edge to sharpen. */
|
|
27
|
+
exports.FOCUS_GLOW_ALPHA = 32;
|
|
28
|
+
const focusGlowShadow = (colors) => `0 0 ${exports.FOCUS_GLOW_BLUR}px ${exports.FOCUS_GLOW_SPREAD}px ${colors.primary.opacity[exports.FOCUS_GLOW_ALPHA]}`;
|
|
29
|
+
exports.focusGlowShadow = focusGlowShadow;
|
|
30
|
+
/** Field focus: the brand border is the indicator, this only makes it findable. */
|
|
31
|
+
const fieldFocusVisible = (colors) => ({
|
|
32
|
+
outline: "2px solid transparent",
|
|
33
|
+
outlineOffset: "2px",
|
|
34
|
+
boxShadow: (0, exports.focusGlowShadow)(colors),
|
|
35
|
+
});
|
|
36
|
+
exports.fieldFocusVisible = fieldFocusVisible;
|
|
22
37
|
/** Both selectors a control needs to keep the ring on top of its own hover/active styling. */
|
|
23
38
|
const focusVisibleStyles = (colors) => {
|
|
24
39
|
const ring = (0, exports.focusVisibleRing)(colors);
|
|
@@ -8,6 +8,8 @@ const lucide_react_1 = require("lucide-react");
|
|
|
8
8
|
const index_1 = require("../index");
|
|
9
9
|
const useCustomTheme_1 = require("../useCustomTheme");
|
|
10
10
|
const useThemeMode_1 = require("./useThemeMode");
|
|
11
|
+
const focusRing_styles_1 = require("../chakra/focusRing.styles");
|
|
12
|
+
const outlineRung_1 = require("../tokens/builders/outlineRung");
|
|
11
13
|
const MODE_OPTIONS = [
|
|
12
14
|
{ value: "light", label: "Light", Icon: lucide_react_1.Sun },
|
|
13
15
|
{ value: "system", label: "System", Icon: lucide_react_1.Monitor },
|
|
@@ -37,25 +39,30 @@ const useSwitcherColors = () => {
|
|
|
37
39
|
borderColor: colors.boxborder[200],
|
|
38
40
|
// NOTE: menuBg lives in Menu.styles.ts — re-pushing it via `sx` flickers on every render.
|
|
39
41
|
menuColor: colors.text[900],
|
|
42
|
+
focusRing: (0, focusRing_styles_1.focusVisibleRing)(colors),
|
|
40
43
|
};
|
|
41
44
|
};
|
|
42
45
|
const BrandMenu = ({ size }) => {
|
|
43
46
|
const { brand, setBrand } = (0, useThemeMode_1.useThemeMode)();
|
|
44
|
-
const { mutedColor, menuColor } = useSwitcherColors();
|
|
47
|
+
const { mutedColor, menuColor, focusRing } = useSwitcherColors();
|
|
45
48
|
const brands = Object.keys(index_1.brandThemes);
|
|
46
|
-
return ((0, jsx_runtime_1.jsxs)(react_2.Menu, { children: [(0, jsx_runtime_1.jsx)(react_2.MenuButton, { as: react_2.Button, size: SIZES[size].control, variant: "ghost", color: mutedColor, borderRadius: "full", fontWeight: 500, "aria-label": `Brand theme, current ${toBrandLabel(brand)}`, _focusVisible:
|
|
49
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Menu, { children: [(0, jsx_runtime_1.jsx)(react_2.MenuButton, { as: react_2.Button, size: SIZES[size].control, variant: "ghost", color: mutedColor, borderRadius: "full", fontWeight: 500, "aria-label": `Brand theme, current ${toBrandLabel(brand)}`, _focusVisible: focusRing, children: (0, jsx_runtime_1.jsxs)(react_2.HStack, { spacing: 2, children: [(0, jsx_runtime_1.jsx)(BrandSwatch, { brand: brand }), (0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", children: toBrandLabel(brand) })] }) }), (0, jsx_runtime_1.jsx)(react_2.MenuList, { minW: "9rem", color: menuColor, children: (0, jsx_runtime_1.jsx)(react_2.MenuOptionGroup, { title: "Brand", type: "radio", value: brand, onChange: (value) => setBrand(value), children: brands.map((option) => ((0, jsx_runtime_1.jsx)(react_2.MenuItemOption, { value: option, children: (0, jsx_runtime_1.jsxs)(react_2.HStack, { spacing: 2, children: [(0, jsx_runtime_1.jsx)(BrandSwatch, { brand: option }), (0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", children: toBrandLabel(option) })] }) }, option))) }) })] }));
|
|
47
50
|
};
|
|
48
51
|
const IconVariant = ({ size, label, }) => {
|
|
49
52
|
const { resolvedMode, toggle } = (0, useThemeMode_1.useThemeMode)();
|
|
50
|
-
const { mutedColor, hoverBg } = useSwitcherColors();
|
|
53
|
+
const { mutedColor, hoverBg, focusRing } = useSwitcherColors();
|
|
51
54
|
const isDark = resolvedMode === "dark";
|
|
52
55
|
const Icon = isDark ? lucide_react_1.Moon : lucide_react_1.Sun;
|
|
53
56
|
const accessibleLabel = label !== null && label !== void 0 ? label : `Switch to ${isDark ? "light" : "dark"} mode`;
|
|
54
|
-
return ((0, jsx_runtime_1.jsx)(react_2.Tooltip, { label: accessibleLabel, openDelay: 400, children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": accessibleLabel, "aria-pressed": isDark, icon: (0, jsx_runtime_1.jsx)(Icon, { size: SIZES[size].icon, "aria-hidden": true }), onClick: toggle, size: SIZES[size].control, variant: "ghost", color: mutedColor, borderRadius: "full", _hover: { bg: hoverBg }, _focusVisible:
|
|
57
|
+
return ((0, jsx_runtime_1.jsx)(react_2.Tooltip, { label: accessibleLabel, openDelay: 400, children: (0, jsx_runtime_1.jsx)(react_2.IconButton, { "aria-label": accessibleLabel, "aria-pressed": isDark, icon: (0, jsx_runtime_1.jsx)(Icon, { size: SIZES[size].icon, "aria-hidden": true }), onClick: toggle, size: SIZES[size].control, variant: "ghost", color: mutedColor, borderRadius: "full", _hover: { bg: hoverBg }, _focusVisible: focusRing }) }));
|
|
55
58
|
};
|
|
56
59
|
const SegmentedVariant = ({ size, label, showBrandPicker, }) => {
|
|
57
60
|
const { mode, setMode } = (0, useThemeMode_1.useThemeMode)();
|
|
58
61
|
const { trackBg, activeBg, activeColor, mutedColor, borderColor } = useSwitcherColors();
|
|
62
|
+
const { colors } = (0, useCustomTheme_1.useCustomTheme)();
|
|
63
|
+
// One tab stop, so the group wears the indicator: brand border plus the field bloom.
|
|
64
|
+
const focusBorder = (0, outlineRung_1.liftToContrast)(colors.primary[500], trackBg, outlineRung_1.AA_NON_TEXT);
|
|
65
|
+
const [showFocus, setShowFocus] = (0, react_1.useState)(false);
|
|
59
66
|
const optionRefs = (0, react_1.useRef)([]);
|
|
60
67
|
// APG radiogroup behavior: arrows move focus and selection together.
|
|
61
68
|
const handleKeyDown = (event, index) => {
|
|
@@ -69,20 +76,20 @@ const SegmentedVariant = ({ size, label, showBrandPicker, }) => {
|
|
|
69
76
|
setMode(MODE_OPTIONS[next].value);
|
|
70
77
|
(_a = optionRefs.current[next]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
71
78
|
};
|
|
72
|
-
return ((0, jsx_runtime_1.jsxs)(react_2.HStack, { role: "radiogroup", "aria-label": label !== null && label !== void 0 ? label : "Color mode", display: "inline-flex", spacing: 1, p: "0.25rem", bg: trackBg, border: "0.063rem solid", borderColor: borderColor, borderRadius: "full", children: [MODE_OPTIONS.map(({ value, label: optionLabel, Icon }, index) => {
|
|
79
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.HStack, { role: "radiogroup", "aria-label": label !== null && label !== void 0 ? label : "Color mode", display: "inline-flex", spacing: 1, p: "0.25rem", bg: trackBg, border: "0.063rem solid", borderColor: showFocus ? focusBorder : borderColor, boxShadow: showFocus ? (0, focusRing_styles_1.focusGlowShadow)(colors) : undefined, borderRadius: "full", onFocus: (event) => setShowFocus(event.target.matches(":focus-visible")), onBlur: () => setShowFocus(false), children: [MODE_OPTIONS.map(({ value, label: optionLabel, Icon }, index) => {
|
|
73
80
|
const isSelected = mode === value;
|
|
74
81
|
return ((0, jsx_runtime_1.jsx)(react_2.Button, { ref: (node) => {
|
|
75
82
|
optionRefs.current[index] = node;
|
|
76
|
-
}, role: "radio", "aria-checked": isSelected, "aria-label": optionLabel, onClick: () => setMode(value), onKeyDown: (event) => handleKeyDown(event, index), size: SIZES[size].control, variant: "ghost", borderRadius: "full", bg: isSelected ? activeBg : "transparent", color: isSelected ? activeColor : mutedColor, boxShadow: isSelected ? "sm" : "none", _hover: { color: activeColor }, _focusVisible: {
|
|
83
|
+
}, role: "radio", "aria-checked": isSelected, "aria-label": optionLabel, onClick: () => setMode(value), onKeyDown: (event) => handleKeyDown(event, index), size: SIZES[size].control, variant: "ghost", borderRadius: "full", bg: isSelected ? activeBg : "transparent", color: isSelected ? activeColor : mutedColor, boxShadow: isSelected ? "sm" : "none", _hover: { color: activeColor }, _focusVisible: { outline: "2px solid transparent", outlineOffset: "2px" }, children: (0, jsx_runtime_1.jsx)(Icon, { size: SIZES[size].icon, "aria-hidden": true }) }, value));
|
|
77
84
|
}), showBrandPicker && (0, jsx_runtime_1.jsx)(BrandMenu, { size: size })] }));
|
|
78
85
|
};
|
|
79
86
|
const MenuVariant = ({ size, label, showBrandPicker, }) => {
|
|
80
87
|
var _a;
|
|
81
88
|
const { mode, brand, setMode, setBrand } = (0, useThemeMode_1.useThemeMode)();
|
|
82
|
-
const { mutedColor, hoverBg, menuColor } = useSwitcherColors();
|
|
89
|
+
const { mutedColor, hoverBg, menuColor, focusRing } = useSwitcherColors();
|
|
83
90
|
const active = (_a = MODE_OPTIONS.find((option) => option.value === mode)) !== null && _a !== void 0 ? _a : MODE_OPTIONS[0];
|
|
84
91
|
const brands = Object.keys(index_1.brandThemes);
|
|
85
|
-
return ((0, jsx_runtime_1.jsxs)(react_2.Menu, { children: [(0, jsx_runtime_1.jsx)(react_2.MenuButton, { as: react_2.IconButton, "aria-label": label !== null && label !== void 0 ? label : `Color mode, current ${active.label}`, icon: (0, jsx_runtime_1.jsx)(active.Icon, { size: SIZES[size].icon, "aria-hidden": true }), size: SIZES[size].control, variant: "ghost", color: mutedColor, borderRadius: "full", _hover: { bg: hoverBg }, _focusVisible:
|
|
92
|
+
return ((0, jsx_runtime_1.jsxs)(react_2.Menu, { children: [(0, jsx_runtime_1.jsx)(react_2.MenuButton, { as: react_2.IconButton, "aria-label": label !== null && label !== void 0 ? label : `Color mode, current ${active.label}`, icon: (0, jsx_runtime_1.jsx)(active.Icon, { size: SIZES[size].icon, "aria-hidden": true }), size: SIZES[size].control, variant: "ghost", color: mutedColor, borderRadius: "full", _hover: { bg: hoverBg }, _focusVisible: focusRing }), (0, jsx_runtime_1.jsxs)(react_2.MenuList, { minW: "10rem", color: menuColor, children: [(0, jsx_runtime_1.jsx)(react_2.MenuOptionGroup, { title: "Appearance", type: "radio", value: mode, onChange: (value) => setMode(value), children: MODE_OPTIONS.map(({ value, label: optionLabel, Icon }) => ((0, jsx_runtime_1.jsx)(react_2.MenuItemOption, { value: value, children: (0, jsx_runtime_1.jsxs)(react_2.HStack, { spacing: 2, children: [(0, jsx_runtime_1.jsx)(Icon, { size: SIZES[size].icon, "aria-hidden": true }), (0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", children: optionLabel })] }) }, value))) }), showBrandPicker && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(react_2.MenuDivider, {}), (0, jsx_runtime_1.jsx)(react_2.MenuOptionGroup, { title: "Brand", type: "radio", value: brand, onChange: (value) => setBrand(value), children: brands.map((option) => ((0, jsx_runtime_1.jsx)(react_2.MenuItemOption, { value: option, children: (0, jsx_runtime_1.jsxs)(react_2.HStack, { spacing: 2, children: [(0, jsx_runtime_1.jsx)(BrandSwatch, { brand: option }), (0, jsx_runtime_1.jsx)(react_2.Text, { as: "span", children: toBrandLabel(option) })] }) }, option))) })] }))] })] }));
|
|
86
93
|
};
|
|
87
94
|
const ThemeSwitcher = ({ variant = "icon", showBrandPicker = false, size = "md", "aria-label": ariaLabel, }) => {
|
|
88
95
|
if (variant === "segmented") {
|
|
@@ -2,7 +2,7 @@ import { CONTROL_SIZES } from "../../Theme/tokens/primitives/controlSizes.js";
|
|
|
2
2
|
import { transitionFor } from "../../Theme/tokens/primitives/motion.js";
|
|
3
3
|
import { placeholderInk } from "../../Theme/tokens/builders/placeholderInk.js";
|
|
4
4
|
import { AA_NON_TEXT, liftToContrast } from "../../Theme/tokens/builders/outlineRung.js";
|
|
5
|
-
import {
|
|
5
|
+
import { fieldFocusVisible, focusGlowShadow } from "../../Theme/chakra/focusRing.styles.js";
|
|
6
6
|
export const FIELD_RADIUS = "lg";
|
|
7
7
|
export const FIELD_BORDER_WIDTH = "1px";
|
|
8
8
|
export const FIELD_TRANSITION = transitionFor(["border-color", "box-shadow", "background-color"]);
|
|
@@ -43,7 +43,7 @@ export const fieldControlStyles = (colors) => {
|
|
|
43
43
|
...fieldTextStyles(colors),
|
|
44
44
|
_placeholder: { color: placeholderInk(colors), opacity: 1 },
|
|
45
45
|
_hover: { borderColor: fieldHoverBorder(colors) },
|
|
46
|
-
_focusVisible: { borderColor: colors.primary[500], ...
|
|
46
|
+
_focusVisible: { borderColor: colors.primary[500], ...fieldFocusVisible(colors) },
|
|
47
47
|
_invalid: {
|
|
48
48
|
borderColor: colors.semanticText.error,
|
|
49
49
|
_hover: { borderColor: colors.semanticText.error },
|
|
@@ -60,11 +60,11 @@ export const getFieldStateStyles = (theme, { error = false, focused = false, dis
|
|
|
60
60
|
: focused
|
|
61
61
|
? colors.primary[500]
|
|
62
62
|
: colors.boxborder[500];
|
|
63
|
-
const box = { ...fieldBoxStyles(colors), borderColor, boxShadow: focused ?
|
|
63
|
+
const box = { ...fieldBoxStyles(colors), borderColor, boxShadow: focused ? focusGlowShadow(colors) : "none" };
|
|
64
64
|
if (!disabled)
|
|
65
65
|
return box;
|
|
66
66
|
const { bg, borderColor: disabledBorder, cursor } = disabledStyles(colors);
|
|
67
67
|
return { ...box, bg, borderColor: disabledBorder, cursor };
|
|
68
68
|
};
|
|
69
|
-
/**
|
|
70
|
-
export const fieldFocusRing = (theme) =>
|
|
69
|
+
/** Glow for `_focusWithin` on composite fields. `error` is accepted but ignored: invalid is the border's job. */
|
|
70
|
+
export const fieldFocusRing = (theme) => focusGlowShadow(theme.colors);
|
|
@@ -5,6 +5,7 @@ import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
|
|
|
5
5
|
import Button from "../Button/Button.js";
|
|
6
6
|
import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
7
7
|
import { resolveFilledSurface } from "../../Theme/tokens/builders/filledSurface.js";
|
|
8
|
+
import { fieldFocusVisible } from "../../Theme/chakra/focusRing.styles.js";
|
|
8
9
|
import { DAY_CLASS, dayAccessibleName, dayStateClassName, resolveDayStateVisual, } from "./dayStates.js";
|
|
9
10
|
/** Internal month grid shared by Single/RangeDatePicker; not published from index.ts, so only reachable via a deep import. */
|
|
10
11
|
export const CalendarPanel = ({ currentMonth, setCurrentMonth, today, isRange, tempDate, tempRangeStart, tempRangeEnd, isSameDay, isBefore, isAfter, minDate, maxDate, disablePastDates, disableFutureDates, disableToday, onDaySelect, hoveredDate, onDayHover, renderWeekdays, dayStates, renderDayContent, }) => {
|
|
@@ -35,11 +36,7 @@ export const CalendarPanel = ({ currentMonth, setCurrentMonth, today, isRange, t
|
|
|
35
36
|
bg: theme.colors.background[50],
|
|
36
37
|
outline: "none",
|
|
37
38
|
_hover: { borderColor: theme.colors.primary[300] },
|
|
38
|
-
_focus: {
|
|
39
|
-
outline: "none",
|
|
40
|
-
borderColor: theme.colors.primary[500],
|
|
41
|
-
boxShadow: `0 0 0 1px ${theme.colors.primary[500]}`,
|
|
42
|
-
},
|
|
39
|
+
_focus: { borderColor: theme.colors.primary[500], ...fieldFocusVisible(theme.colors) },
|
|
43
40
|
style: {
|
|
44
41
|
WebkitAppearance: "menulist",
|
|
45
42
|
MozAppearance: "menulist",
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { HStack, PinInput, PinInputField, Box, Text, Button, Flex, } from "@chakra-ui/react";
|
|
3
3
|
import { useCustomTheme } from "../../../Theme/useCustomTheme.js";
|
|
4
|
+
import { fieldFocusVisible } from "../../../Theme/chakra/focusRing.styles.js";
|
|
4
5
|
import { MailCheck } from "lucide-react";
|
|
5
6
|
/** Full verification card (icon, title, description, resend link, digits-only PinInput) — for a bare OTP field in your own layout, use PinInput instead. */
|
|
6
7
|
export default function VerifyEmailOtp({ resendMail, onChange, onComplete, placeholder = "", pins = 5, description, title, isDisabled = false, isInvalid = false, styles, }) {
|
|
7
8
|
const theme = useCustomTheme();
|
|
8
|
-
return (_jsxs(Box, { style: styles, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", p: 6, w: "100%", maxW: "25rem", mx: "auto", bg: theme.colors.background[50], border: "1px solid", borderColor: theme.colors.boxborder[200], borderRadius: "xl", children: [_jsx(Box, { mb: 4, children: _jsx(MailCheck, { size: 80, color: theme.colors.accentText }) }), _jsx(Text, { fontSize: "2xl", fontWeight: "bold", mb: 2, textAlign: "center", children: title }), _jsxs(Text, { fontSize: "md", textAlign: "center", color: theme.colors.textMuted, mb: 6, children: [description, _jsx("br", {}), "your new Pixel Account"] }), _jsx(HStack, { spacing: 3, mb: 6, role: "group", "aria-label": title || "Verification code", children: _jsx(PinInput, { placeholder: placeholder, onChange: onChange, onComplete: onComplete, isDisabled: isDisabled, isInvalid: isInvalid, size: "lg", focusBorderColor: theme.colors.primary[500], children: Array.from({ length: pins }).map((_, index) => (_jsx(PinInputField, { "aria-label": `${title || "Verification code"}, digit ${index + 1} of ${pins}`, borderRadius: "lg", border: "0.063rem solid", borderColor: theme.colors.boxborder[500], backgroundColor: theme.colors.background[200], _focus: {
|
|
9
|
-
borderColor: theme.colors.primary[500],
|
|
10
|
-
boxShadow: `0 0 0 0.063rem ${theme.colors.primary[500]}`,
|
|
11
|
-
} }, index))) }) }), _jsx(Flex, { justify: "center", children: _jsxs(Text, { fontSize: "sm", color: theme.colors.textMuted, children: ["Didn\u2019t receive the code?", " ", _jsx(Button, { variant: "link", color: theme.colors.accentText, fontWeight: "semibold", onClick: resendMail, children: "Resend Code" })] }) })] }));
|
|
9
|
+
return (_jsxs(Box, { style: styles, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", p: 6, w: "100%", maxW: "25rem", mx: "auto", bg: theme.colors.background[50], border: "1px solid", borderColor: theme.colors.boxborder[200], borderRadius: "xl", children: [_jsx(Box, { mb: 4, children: _jsx(MailCheck, { size: 80, color: theme.colors.accentText }) }), _jsx(Text, { fontSize: "2xl", fontWeight: "bold", mb: 2, textAlign: "center", children: title }), _jsxs(Text, { fontSize: "md", textAlign: "center", color: theme.colors.textMuted, mb: 6, children: [description, _jsx("br", {}), "your new Pixel Account"] }), _jsx(HStack, { spacing: 3, mb: 6, role: "group", "aria-label": title || "Verification code", children: _jsx(PinInput, { placeholder: placeholder, onChange: onChange, onComplete: onComplete, isDisabled: isDisabled, isInvalid: isInvalid, size: "lg", focusBorderColor: theme.colors.primary[500], children: Array.from({ length: pins }).map((_, index) => (_jsx(PinInputField, { "aria-label": `${title || "Verification code"}, digit ${index + 1} of ${pins}`, borderRadius: "lg", border: "0.063rem solid", borderColor: theme.colors.boxborder[500], backgroundColor: theme.colors.background[200], _focus: { borderColor: theme.colors.primary[500], ...fieldFocusVisible(theme.colors) } }, index))) }) }), _jsx(Flex, { justify: "center", children: _jsxs(Text, { fontSize: "sm", color: theme.colors.textMuted, children: ["Didn\u2019t receive the code?", " ", _jsx(Button, { variant: "link", color: theme.colors.accentText, fontWeight: "semibold", onClick: resendMail, children: "Resend Code" })] }) })] }));
|
|
12
10
|
}
|
|
@@ -8,6 +8,7 @@ import ToolTip from "../ToolTip/ToolTip.js";
|
|
|
8
8
|
import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
9
9
|
import { accentTextOnCanvas, onFilled } from "../../Theme/tokens/builders/accentText.js";
|
|
10
10
|
import { getFilterHoverBg } from "./filterHoverStyle.js";
|
|
11
|
+
import { fieldFocusVisible } from "../../Theme/chakra/focusRing.styles.js";
|
|
11
12
|
const FilterSidebar = ({ sidebarOptions, selected, onChange, maxVisible = 10, width = 280, variant = "minimal", containerPadding, containerHeight,
|
|
12
13
|
// headerPadding = 2,
|
|
13
14
|
panelPadding = 3, clearAllButton = true, onClearAllHandler,
|
|
@@ -168,7 +169,7 @@ panelPadding = 3, clearAllButton = true, onClearAllHandler,
|
|
|
168
169
|
return Array.from({ length: 5 }, (_, i) => (_jsx(Box, { children: _jsx(Star, { size: 16, color: starColor, fill: i < r ? starColor : "none" }) }, `star-${r}-${i}`)));
|
|
169
170
|
})() }), _jsx(Text, { fontSize: "sm", color: theme.colors.text[500], children: "& Up" })] }) }, `rating-${r}`))) })) : null, section.searchable && (_jsx(Input, { size: "xs", h: "26px", fontSize: "xs", "aria-label": `Search ${section.label}`, placeholder: `Search ${section.label}...`, borderRadius: "md", bg: theme.colors.background[50], border: "1px solid",
|
|
170
171
|
// NOTE: boxborder[500] not gray[200] — WCAG 1.4.11 needs >=3:1 for a control boundary; gray[200] fails in dark.
|
|
171
|
-
borderColor: theme.colors.boxborder[500], _focus: { borderColor: theme.colors.primary[
|
|
172
|
+
borderColor: theme.colors.boxborder[500], _focus: { borderColor: theme.colors.primary[500], ...fieldFocusVisible(theme.colors) }, value: searchTerms[section.id] || "", onChange: (e) => {
|
|
172
173
|
const v = e.target.value;
|
|
173
174
|
setSearchTerms((prev) => ({ ...prev, [section.id]: v }));
|
|
174
175
|
if (v)
|
|
@@ -8,14 +8,14 @@ import { AA_NON_TEXT, liftToContrast } from "../../Theme/tokens/builders/outline
|
|
|
8
8
|
import Select from "../Select/Select.js";
|
|
9
9
|
import VeritcalDivider from "../Divider/Divider.js";
|
|
10
10
|
const HeaderActions = ({ select, edit, create, surface, }) => {
|
|
11
|
-
var _a, _b, _c
|
|
11
|
+
var _a, _b, _c;
|
|
12
12
|
const { colors } = useCustomTheme();
|
|
13
13
|
const canvas = surface !== null && surface !== void 0 ? surface : colors.backgroundColor.main;
|
|
14
14
|
const ink = liftToContrast(colors.secondary[500], canvas, AA_NORMAL_TEXT);
|
|
15
15
|
const iconInk = liftToContrast(colors.secondary[500], canvas, AA_NON_TEXT);
|
|
16
16
|
const elements = [];
|
|
17
17
|
if (select === null || select === void 0 ? void 0 : select.isSelect) {
|
|
18
|
-
elements.push(_jsx(Box, { width: (_a = select.width) !== null && _a !== void 0 ? _a : "12.5rem", children: _jsx(Select, { options: (_b = select.options) !== null && _b !== void 0 ? _b : [], placeholder: select.selectPlaceholderText, "aria-label":
|
|
18
|
+
elements.push(_jsx(Box, { width: (_a = select.width) !== null && _a !== void 0 ? _a : "12.5rem", children: _jsx(Select, { options: (_b = select.options) !== null && _b !== void 0 ? _b : [], placeholder: select.selectPlaceholderText, "aria-label": select.ariaLabel || select.selectPlaceholderText || "Select", native: (_c = select.native) !== null && _c !== void 0 ? _c : false, onChange: (option) => { var _a; return (_a = select.onSelectChange) === null || _a === void 0 ? void 0 : _a.call(select, option); }, value: select.value }, "select") }, "select"));
|
|
19
19
|
}
|
|
20
20
|
if (edit === null || edit === void 0 ? void 0 : edit.isEditable) {
|
|
21
21
|
elements.push(_jsxs(Box, { as: "button", type: "button", bg: "transparent", borderRadius: "lg", _focusVisible: { boxShadow: `0 0 0 2px ${iconInk}`, outline: "none" }, display: "flex", alignItems: "center", gap: "0.375rem", cursor: "pointer", fontSize: 14, onClick: () => { var _a; return (_a = edit.onEdit) === null || _a === void 0 ? void 0 : _a.call(edit); }, children: [_jsx(SquarePen, { size: 16, color: iconInk }), _jsx(Text, { color: ink, children: edit.label ? edit.label : "Edit Layout" })] }, "edit"));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { controlSizeStyles, fieldControlStyles, FIELD_BORDER_WIDTH } from "../Common/fieldStyles.js";
|
|
2
2
|
import { CONTROL_SIZE_NAMES, DEFAULT_CONTROL_SIZE } from "../../Theme/tokens/primitives/controlSizes.js";
|
|
3
|
-
import {
|
|
3
|
+
import { fieldFocusVisible } from "../../Theme/chakra/focusRing.styles.js";
|
|
4
4
|
/** Field look shared by Input, Textarea and NumberInput; `_invalid` also clears Chakra's stock invalid shadow. */
|
|
5
5
|
export const fieldPartStyles = (colors) => {
|
|
6
6
|
const error = colors.semanticText.error;
|
|
@@ -10,7 +10,7 @@ export const fieldPartStyles = (colors) => {
|
|
|
10
10
|
borderColor: error,
|
|
11
11
|
boxShadow: "none",
|
|
12
12
|
_hover: { borderColor: error },
|
|
13
|
-
_focusVisible: { borderColor: error, ...
|
|
13
|
+
_focusVisible: { borderColor: error, ...fieldFocusVisible(colors) },
|
|
14
14
|
},
|
|
15
15
|
};
|
|
16
16
|
};
|
|
@@ -8,6 +8,6 @@ import Button from "../../Button/Button.js";
|
|
|
8
8
|
/** Standalone filter+Edit+Create action bar; NOT rendered by KanbanBoard (which uses HeaderActions instead) and not exported from the package. */
|
|
9
9
|
const KanbanActions = ({ options, onSelectChange, onEdit, onCreate, }) => {
|
|
10
10
|
const { colors } = useCustomTheme();
|
|
11
|
-
return (_jsxs(Box, { display: "flex", alignItems: "center", gap: "0.625rem", children: [_jsx(Select, { options: options, placeholder: "Filter by Status", width: "12.5rem", onChange: (option) => onSelectChange && onSelectChange(option) }), _jsxs(Box, { display: "flex", alignItems: "center", gap: "0.5rem", children: [_jsx(Button, { size: "sm", variant: "ghost", leftIcon: _jsx(SquarePen, { size: 20, color: colors.text[500] }), onClick: () => onEdit === null || onEdit === void 0 ? void 0 : onEdit(), children: "Edit Layout" }), _jsx(VeritcalDivider, {}), _jsx(Button, { size: "sm", variant: "solid", leftIcon: _jsx(CirclePlus, { size: 20 }), onClick: () => onCreate === null || onCreate === void 0 ? void 0 : onCreate(), children: "Create New" })] })] }));
|
|
11
|
+
return (_jsxs(Box, { display: "flex", alignItems: "center", gap: "0.625rem", children: [_jsx(Select, { native: false, options: options, placeholder: "Filter by Status", width: "12.5rem", onChange: (option) => onSelectChange && onSelectChange(option) }), _jsxs(Box, { display: "flex", alignItems: "center", gap: "0.5rem", children: [_jsx(Button, { size: "sm", variant: "ghost", leftIcon: _jsx(SquarePen, { size: 20, color: colors.text[500] }), onClick: () => onEdit === null || onEdit === void 0 ? void 0 : onEdit(), children: "Edit Layout" }), _jsx(VeritcalDivider, {}), _jsx(Button, { size: "sm", variant: "solid", leftIcon: _jsx(CirclePlus, { size: 20 }), onClick: () => onCreate === null || onCreate === void 0 ? void 0 : onCreate(), children: "Create New" })] })] }));
|
|
12
12
|
};
|
|
13
13
|
export default KanbanActions;
|
|
@@ -19,7 +19,7 @@ const generateUniqueId = (() => {
|
|
|
19
19
|
return `${Date.now()}-${counter}`;
|
|
20
20
|
};
|
|
21
21
|
})();
|
|
22
|
-
export default function MultiSelect({ value, onValueChange, width = "100%", label = "label", isRequired = true, isInformation = false, informationMessage = "", name, id, placeholderText = "Type valid email and press enter", isDisabled, isReadOnly, size = DEFAULT_CONTROL_SIZE, inputStyle, helperText, error, errorMessage, }) {
|
|
22
|
+
export default function MultiSelect({ value, onValueChange, width = "100%", label = "label", isRequired = true, isInformation = false, informationMessage = "", name, id, placeholderText = "Type valid email and press enter", isDisabled, isReadOnly, addOnBlur = false, size = DEFAULT_CONTROL_SIZE, inputStyle, helperText, error, errorMessage, }) {
|
|
23
23
|
const theme = useCustomTheme();
|
|
24
24
|
const s = getSearchSelectSizeStyles((size || DEFAULT_CONTROL_SIZE));
|
|
25
25
|
const options = value;
|
|
@@ -37,23 +37,34 @@ export default function MultiSelect({ value, onValueChange, width = "100%", labe
|
|
|
37
37
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
38
38
|
return emailRegex.test(email);
|
|
39
39
|
};
|
|
40
|
+
const commitInput = useCallback(() => {
|
|
41
|
+
const entry = inputValue.trim();
|
|
42
|
+
if (entry === "")
|
|
43
|
+
return;
|
|
44
|
+
if (!validateEmail(entry)) {
|
|
45
|
+
setLocalError("Invalid email address");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (!options.some((option) => option.label === entry)) {
|
|
49
|
+
onValueChange([...options, { id: generateUniqueId(), label: entry }]);
|
|
50
|
+
}
|
|
51
|
+
setInputValue("");
|
|
52
|
+
}, [inputValue, options, onValueChange]);
|
|
40
53
|
const handleKeyDown = (e) => {
|
|
41
|
-
if (e.key === "Enter"
|
|
42
|
-
if (
|
|
43
|
-
setLocalError("Invalid email address");
|
|
54
|
+
if (e.key === "Enter") {
|
|
55
|
+
if (inputValue.trim() === "")
|
|
44
56
|
return;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (!existingOption) {
|
|
48
|
-
const newOption = { id: generateUniqueId(), label: inputValue };
|
|
49
|
-
onValueChange([...options, newOption]);
|
|
50
|
-
setInputValue("");
|
|
51
|
-
}
|
|
57
|
+
e.preventDefault();
|
|
58
|
+
commitInput();
|
|
52
59
|
}
|
|
53
60
|
else if (e.key === "Backspace" && inputValue === "") {
|
|
54
61
|
onValueChange(options.slice(0, -1));
|
|
55
62
|
}
|
|
56
63
|
};
|
|
64
|
+
const handleBlur = useCallback(() => {
|
|
65
|
+
if (addOnBlur && !isReadOnly && !isDisabled)
|
|
66
|
+
commitInput();
|
|
67
|
+
}, [addOnBlur, isReadOnly, isDisabled, commitInput]);
|
|
57
68
|
const handleRemove = useCallback((optionToRemove) => {
|
|
58
69
|
onValueChange(options.filter((option) => option.id !== optionToRemove.id));
|
|
59
70
|
}, [options, onValueChange]);
|
|
@@ -66,5 +77,5 @@ export default function MultiSelect({ value, onValueChange, width = "100%", labe
|
|
|
66
77
|
}, children: [options.map((option) => (_jsx(Tag, { size: s.tagSize, colorScheme: "primary", label: option.label, onIconClick: () => handleRemove(option), icon: X }, option.id))), _jsx(Input, { ref: inputRef, type: "text", value: inputValue, isDisabled: isDisabled, isReadOnly: isReadOnly, isRequired: isRequired, isInvalid: isInvalid, ...ids.controlProps, name: name, size: size, variant: "unstyled", h: s.fieldHeight, minH: s.fieldHeight, fontSize: s.fieldFontSize, fontWeight: 400, color: theme.colors.text[900], flex: "1", minW: 0, _placeholder: { color: placeholderInk(theme.colors), opacity: 1 }, style: {
|
|
67
78
|
backgroundColor: "transparent",
|
|
68
79
|
...inputStyle,
|
|
69
|
-
}, onChange: handleInputChange, onKeyDown: handleKeyDown, placeholder: options.length === 0 ? placeholderText : "" })] }), _jsx(FieldMessage, { error: isInvalid, errorMessage: shownErrorMessage, helperText: helperText, helperId: ids.helperId, errorId: ids.errorId })] }));
|
|
80
|
+
}, onChange: handleInputChange, onKeyDown: handleKeyDown, onBlur: handleBlur, placeholder: options.length === 0 ? placeholderText : "" })] }), _jsx(FieldMessage, { error: isInvalid, errorMessage: shownErrorMessage, helperText: helperText, helperId: ids.helperId, errorId: ids.errorId })] }));
|
|
70
81
|
}
|
|
@@ -13,10 +13,19 @@ const toDate = (value) => {
|
|
|
13
13
|
return new Date(/^-?\d+$/.test(value) ? Number(value) : value);
|
|
14
14
|
};
|
|
15
15
|
const startOfDay = (date) => new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime();
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
16
|
+
// NOTE: calendar arithmetic, not -24h — a DST shift makes the day shorter or longer.
|
|
17
|
+
const startOfPrevDay = (dayStart) => {
|
|
18
|
+
const d = new Date(dayStart);
|
|
19
|
+
d.setDate(d.getDate() - 1);
|
|
20
|
+
return startOfDay(d);
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Buckets rows into Today/Yesterday/Earlier, input order preserved within each bucket.
|
|
24
|
+
* `now` defaults to the wall clock; pass it to pin "today" in tests or a fixed-date view.
|
|
25
|
+
*/
|
|
26
|
+
export function sectionizeByDay(rows, getTime, labels = DEFAULT_DAY_LABELS, now = Date.now()) {
|
|
27
|
+
const todayStart = startOfDay(toDate(now));
|
|
28
|
+
const yesterdayStart = startOfPrevDay(todayStart);
|
|
20
29
|
const today = [];
|
|
21
30
|
const yesterday = [];
|
|
22
31
|
const earlier = [];
|
|
@@ -4,6 +4,7 @@ import { useCustomTheme } from "../../Theme/useCustomTheme.js";
|
|
|
4
4
|
import { TextLabel } from "../Common/FormLabel.js";
|
|
5
5
|
import { DEFAULT_CONTROL_SIZE } from "../../Theme/tokens/primitives/controlSizes.js";
|
|
6
6
|
import { pinInputCellSize } from "./pinInputCellSize.js";
|
|
7
|
+
import { fieldFocusVisible } from "../../Theme/chakra/focusRing.styles.js";
|
|
7
8
|
/** The real, published OTP input (exported as `PinInput` from index.ts) — Chakra-native boxes, paste support, `type: "alphanumeric" | "number"`. */
|
|
8
9
|
export default function PinInputs({ otp, mask, defaultValue, placeholder, manageFocus, errorBorderColor, focusBorderColor, onChange, onComplete, type, color = "primary", variant, pins = 3, label, id, isRequired, isInformation, informationMessage, size = DEFAULT_CONTROL_SIZE, }) {
|
|
9
10
|
var _a;
|
|
@@ -12,8 +13,5 @@ export default function PinInputs({ otp, mask, defaultValue, placeholder, manage
|
|
|
12
13
|
// Square cells at the same heights every other field uses — Chakra's own PinInput size
|
|
13
14
|
// scale doesn't line up with the library's, so cells are sized directly.
|
|
14
15
|
const cell = pinInputCellSize(size);
|
|
15
|
-
return (_jsxs(_Fragment, { children: [label && (_jsx(TextLabel, { label: label, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), _jsx(HStack, { role: "group", "aria-label": fieldName, children: _jsx(PinInput, { otp: otp, mask: mask, defaultValue: defaultValue, placeholder: placeholder, manageFocus: manageFocus, errorBorderColor: errorBorderColor, focusBorderColor: focusBorderColor, onChange: onChange, onComplete: onComplete, type: type, colorScheme: color, variant: variant, children: Array.from({ length: pins }).map((_, index) => (_jsx(PinInputField, { "aria-label": `${fieldName}, digit ${index + 1} of ${pins}`, boxSize: cell.boxSize, fontSize: cell.fontSize, borderRadius: "lg", backgroundColor: theme.colors.background[100], borderColor: theme.colors.boxborder[500], _focus: {
|
|
16
|
-
borderColor: theme.colors.primary[500],
|
|
17
|
-
boxShadow: `0 0 0 0.063rem ${theme.colors.primary[500]}`,
|
|
18
|
-
} }, index))) }) })] }));
|
|
16
|
+
return (_jsxs(_Fragment, { children: [label && (_jsx(TextLabel, { label: label, isRequired: isRequired, isInformation: isInformation, informationMessage: informationMessage })), _jsx(HStack, { role: "group", "aria-label": fieldName, children: _jsx(PinInput, { otp: otp, mask: mask, defaultValue: defaultValue, placeholder: placeholder, manageFocus: manageFocus, errorBorderColor: errorBorderColor, focusBorderColor: focusBorderColor, onChange: onChange, onComplete: onComplete, type: type, colorScheme: color, variant: variant, children: Array.from({ length: pins }).map((_, index) => (_jsx(PinInputField, { "aria-label": `${fieldName}, digit ${index + 1} of ${pins}`, boxSize: cell.boxSize, fontSize: cell.fontSize, borderRadius: "lg", backgroundColor: theme.colors.background[100], borderColor: theme.colors.boxborder[500], _focus: { borderColor: theme.colors.primary[500], ...fieldFocusVisible(theme.colors) } }, index))) }) })] }));
|
|
19
17
|
}
|
|
@@ -483,7 +483,7 @@ const SearchSelect = ({ id, label, options, onChange, onSelect, onSearch, isOpti
|
|
|
483
483
|
}, onBlur: () => {
|
|
484
484
|
setFocused(false);
|
|
485
485
|
setFocusedTrigger((prev) => (prev === "input" ? null : prev));
|
|
486
|
-
}, placeholder: selectedValues.length
|
|
486
|
+
}, placeholder: selectedValues.length ? "" : placeholder })), _jsxs(Box, { position: "absolute", right: s.rightOffset, top: "50%", transform: "translateY(-50%)", display: "flex", alignItems: "center", gap: 1, children: [isRemoveAllIcon && selectedValues.length > 0 && !isDisabled && (_jsx(ToolTip, { placement: "top", label: "Remove All", hasArrow: true, fontSize: "0.75rem", children: _jsx(IconButton, { icon: _jsx(X, { size: s.clearIconSize, color: theme.colors.text[900] }), "aria-label": "Clear all", variant: "ghost", size: s.iconButtonSize, onClick: handleClearAll, sx: {
|
|
487
487
|
bg: "transparent",
|
|
488
488
|
_hover: { bg: "transparent" },
|
|
489
489
|
_active: { bg: "transparent" },
|