colibri-ui 0.8.92 → 0.8.94
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/Datepicker/components/DatePicker/index.js +18 -8
- package/Datepicker/components/DatePicker/index.props.d.ts +1 -0
- package/Datepicker/index.d.ts +1 -1
- package/Datepicker/index.js +3 -1
- package/Datepicker/index.props.d.ts +1 -0
- package/MultiSelect/index.js +14 -2
- package/MultiSelect/index.props.d.ts +3 -1
- package/Pagination/Pagination.d.ts +3 -0
- package/Pagination/Pagination.js +162 -0
- package/Pagination/Pagination.module.css +118 -0
- package/Pagination/helpers.d.ts +5 -0
- package/Pagination/helpers.js +36 -0
- package/Pagination/index.d.ts +3 -0
- package/Pagination/index.js +9 -0
- package/Pagination/index.props.d.ts +31 -0
- package/Pagination/package.json +9 -0
- package/README.md +51 -0
- package/Select/index.d.ts +1 -1
- package/Select/index.js +14 -2
- package/Select/index.props.d.ts +3 -1
- package/Theme/index.d.ts +10 -0
- package/Theme/themes/buenos_aires.d.ts +5 -0
- package/Theme/themes/buenos_aires.js +5 -0
- package/Theme/themes/jaipur.d.ts +5 -0
- package/Theme/themes/jaipur.js +5 -0
- package/TimeSelect/index.js +3 -1
- package/base/FormField/index.d.ts +1 -1
- package/base/FormField/index.js +3 -1
- package/base/FormField/index.props.d.ts +2 -0
- package/esm/Datepicker/components/DatePicker/index.js +18 -8
- package/esm/Datepicker/components/DatePicker/index.props.d.ts +1 -0
- package/esm/Datepicker/index.d.ts +1 -1
- package/esm/Datepicker/index.js +3 -1
- package/esm/Datepicker/index.props.d.ts +1 -0
- package/esm/MultiSelect/index.js +15 -3
- package/esm/MultiSelect/index.props.d.ts +3 -1
- package/esm/Pagination/Pagination.d.ts +3 -0
- package/esm/Pagination/Pagination.js +154 -0
- package/esm/Pagination/Pagination.module.css +118 -0
- package/esm/Pagination/helpers.d.ts +5 -0
- package/esm/Pagination/helpers.js +31 -0
- package/esm/Pagination/index.d.ts +3 -0
- package/esm/Pagination/index.js +2 -0
- package/esm/Pagination/index.props.d.ts +31 -0
- package/esm/Select/index.d.ts +1 -1
- package/esm/Select/index.js +15 -3
- package/esm/Select/index.props.d.ts +3 -1
- package/esm/Theme/index.d.ts +10 -0
- package/esm/Theme/themes/buenos_aires.d.ts +5 -0
- package/esm/Theme/themes/buenos_aires.js +5 -0
- package/esm/Theme/themes/jaipur.d.ts +5 -0
- package/esm/Theme/themes/jaipur.js +5 -0
- package/esm/TimeSelect/index.js +3 -1
- package/esm/base/FormField/index.d.ts +1 -1
- package/esm/base/FormField/index.js +3 -1
- package/esm/base/FormField/index.props.d.ts +2 -0
- package/esm/index.d.ts +2 -0
- package/esm/index.js +2 -0
- package/esm/theme_ba_variables.css +5 -0
- package/esm/theme_jaipur_variables.css +5 -0
- package/index.d.ts +2 -0
- package/index.js +5 -0
- package/package.json +1 -1
- package/theme_ba_variables.css +5 -0
- package/theme_jaipur_variables.css +5 -0
|
@@ -39,6 +39,7 @@ const DatePicker = _a => {
|
|
|
39
39
|
var _b;
|
|
40
40
|
var {
|
|
41
41
|
className,
|
|
42
|
+
disabled = false,
|
|
42
43
|
endPlaceholder,
|
|
43
44
|
hasError,
|
|
44
45
|
hint,
|
|
@@ -55,7 +56,7 @@ const DatePicker = _a => {
|
|
|
55
56
|
onChangeDate,
|
|
56
57
|
onChangeRange
|
|
57
58
|
} = _a,
|
|
58
|
-
calendarProps = tslib.__rest(_a, ["className", "endPlaceholder", "hasError", "hint", "label", "placeholder", "required", "selectedDate", "selectedRange", "selectionMode", "size", "defaultVisibleMonth", "monthsToShow", "startPlaceholder", "onChangeDate", "onChangeRange"]);
|
|
59
|
+
calendarProps = tslib.__rest(_a, ["className", "disabled", "endPlaceholder", "hasError", "hint", "label", "placeholder", "required", "selectedDate", "selectedRange", "selectionMode", "size", "defaultVisibleMonth", "monthsToShow", "startPlaceholder", "onChangeDate", "onChangeRange"]);
|
|
59
60
|
const [date, setDate] = React.useState(selectedDate);
|
|
60
61
|
const [range, setRange] = React.useState(selectedRange);
|
|
61
62
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
@@ -64,6 +65,7 @@ const DatePicker = _a => {
|
|
|
64
65
|
const calendarSize = calendarSizeByDatepickerSize[size];
|
|
65
66
|
const visibleMonth = (_b = calendarValue !== null && calendarValue !== void 0 ? calendarValue : calendarRangeValue[0]) !== null && _b !== void 0 ? _b : new Date();
|
|
66
67
|
const isRangeMode = selectionMode === "range";
|
|
68
|
+
const isCalendarOpen = isOpen && !disabled;
|
|
67
69
|
React.useEffect(() => {
|
|
68
70
|
setDate(selectedDate);
|
|
69
71
|
}, [selectedDate]);
|
|
@@ -73,12 +75,14 @@ const DatePicker = _a => {
|
|
|
73
75
|
setRange([selectedRangeStart, selectedRangeEnd]);
|
|
74
76
|
}, [isRangeMode, selectedRangeStart, selectedRangeEnd]);
|
|
75
77
|
const handleDateChange = nextDate => {
|
|
78
|
+
if (disabled) return;
|
|
76
79
|
const nextValue = index.toISODate(nextDate);
|
|
77
80
|
setDate(nextValue);
|
|
78
81
|
setIsOpen(false);
|
|
79
82
|
onChangeDate === null || onChangeDate === void 0 ? void 0 : onChangeDate(nextValue);
|
|
80
83
|
};
|
|
81
84
|
const handleRangeChange = nextRange => {
|
|
85
|
+
if (disabled) return;
|
|
82
86
|
const nextValue = [nextRange[0] ? index.toISODate(nextRange[0]) : "", nextRange[1] ? index.toISODate(nextRange[1]) : ""];
|
|
83
87
|
setRange(nextValue);
|
|
84
88
|
if (nextValue[0] && nextValue[1]) setIsOpen(false);
|
|
@@ -110,14 +114,15 @@ const DatePicker = _a => {
|
|
|
110
114
|
className: styles__default.default["range-input"]
|
|
111
115
|
}, /*#__PURE__*/React__default.default.createElement(index$1.InputRoot, {
|
|
112
116
|
className: styles__default.default["range-control-start"],
|
|
113
|
-
disabled:
|
|
117
|
+
disabled: disabled,
|
|
114
118
|
hasError: hasError,
|
|
115
119
|
size: size
|
|
116
120
|
}, /*#__PURE__*/React__default.default.createElement(index$2.BaseInput, {
|
|
117
|
-
"aria-expanded":
|
|
121
|
+
"aria-expanded": isCalendarOpen,
|
|
118
122
|
"aria-haspopup": "true",
|
|
119
123
|
"aria-invalid": hasError,
|
|
120
124
|
autoComplete: "off",
|
|
125
|
+
disabled: disabled,
|
|
121
126
|
maxLength: 10,
|
|
122
127
|
placeholder: startPlaceholder !== null && startPlaceholder !== void 0 ? startPlaceholder : placeholder,
|
|
123
128
|
readOnly: true,
|
|
@@ -125,15 +130,16 @@ const DatePicker = _a => {
|
|
|
125
130
|
value: index.toDMYDate(range[0])
|
|
126
131
|
})), /*#__PURE__*/React__default.default.createElement(index$1.InputRoot, {
|
|
127
132
|
className: styles__default.default["range-control-end"],
|
|
128
|
-
disabled:
|
|
133
|
+
disabled: disabled,
|
|
129
134
|
endIcon: /*#__PURE__*/React__default.default.createElement(CalendarIcon, null),
|
|
130
135
|
hasError: hasError,
|
|
131
136
|
size: size
|
|
132
137
|
}, /*#__PURE__*/React__default.default.createElement(index$2.BaseInput, {
|
|
133
|
-
"aria-expanded":
|
|
138
|
+
"aria-expanded": isCalendarOpen,
|
|
134
139
|
"aria-haspopup": "true",
|
|
135
140
|
"aria-invalid": hasError,
|
|
136
141
|
autoComplete: "off",
|
|
142
|
+
disabled: disabled,
|
|
137
143
|
maxLength: 10,
|
|
138
144
|
placeholder: endPlaceholder !== null && endPlaceholder !== void 0 ? endPlaceholder : placeholder,
|
|
139
145
|
readOnly: true,
|
|
@@ -146,7 +152,8 @@ const DatePicker = _a => {
|
|
|
146
152
|
hint: hint,
|
|
147
153
|
hasError: hasError
|
|
148
154
|
}, /*#__PURE__*/React__default.default.createElement(index$4.Dropdown, {
|
|
149
|
-
|
|
155
|
+
disabled: disabled,
|
|
156
|
+
visible: isCalendarOpen,
|
|
150
157
|
onVisibleChange: setIsOpen,
|
|
151
158
|
placement: "bottom",
|
|
152
159
|
preventAutoClose: true,
|
|
@@ -155,13 +162,16 @@ const DatePicker = _a => {
|
|
|
155
162
|
className: styles__default.default["calendar-popup"]
|
|
156
163
|
}, renderCalendar())
|
|
157
164
|
}, /*#__PURE__*/React__default.default.createElement("div", {
|
|
158
|
-
|
|
165
|
+
"aria-disabled": disabled || undefined,
|
|
166
|
+
className: styles__default.default.trigger,
|
|
167
|
+
tabIndex: disabled ? -1 : 0
|
|
159
168
|
}, isRangeMode ? renderRangeInput() : (/*#__PURE__*/React__default.default.createElement(index$5.Input, {
|
|
160
169
|
className: styles__default.default.input,
|
|
161
|
-
"aria-expanded":
|
|
170
|
+
"aria-expanded": isCalendarOpen,
|
|
162
171
|
"aria-haspopup": "true",
|
|
163
172
|
"aria-invalid": hasError,
|
|
164
173
|
autoComplete: "off",
|
|
174
|
+
disabled: disabled,
|
|
165
175
|
endIcon: /*#__PURE__*/React__default.default.createElement(CalendarIcon, null),
|
|
166
176
|
hasError: hasError,
|
|
167
177
|
maxLength: 10,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { DatepickerSize, DatepickerCalendarProps, Props as DatepickerProps } from "../../index.props";
|
|
2
2
|
export type DatePickerProps = DatepickerCalendarProps & {
|
|
3
3
|
className?: string;
|
|
4
|
+
disabled?: boolean;
|
|
4
5
|
endPlaceholder?: string;
|
|
5
6
|
hasError?: boolean;
|
|
6
7
|
hint?: DatepickerProps["hint"];
|
package/Datepicker/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { Props } from "./index.props";
|
|
3
|
-
export declare const Datepicker: ({ className, endPlaceholder, hasError, hint, label, placeholder, required, selectedDate, selectedRange, selectionMode, size, startPlaceholder, onChangeDate, onChangeRange, ...calendarProps }: Props) => React.JSX.Element;
|
|
3
|
+
export declare const Datepicker: ({ className, disabled, endPlaceholder, hasError, hint, label, placeholder, required, selectedDate, selectedRange, selectionMode, size, startPlaceholder, onChangeDate, onChangeRange, ...calendarProps }: Props) => React.JSX.Element;
|
package/Datepicker/index.js
CHANGED
|
@@ -15,6 +15,7 @@ var styles__default = /*#__PURE__*/_interopDefault(styles);
|
|
|
15
15
|
const Datepicker = _a => {
|
|
16
16
|
var {
|
|
17
17
|
className,
|
|
18
|
+
disabled,
|
|
18
19
|
endPlaceholder,
|
|
19
20
|
hasError,
|
|
20
21
|
hint,
|
|
@@ -29,10 +30,11 @@ const Datepicker = _a => {
|
|
|
29
30
|
onChangeDate,
|
|
30
31
|
onChangeRange
|
|
31
32
|
} = _a,
|
|
32
|
-
calendarProps = tslib.__rest(_a, ["className", "endPlaceholder", "hasError", "hint", "label", "placeholder", "required", "selectedDate", "selectedRange", "selectionMode", "size", "startPlaceholder", "onChangeDate", "onChangeRange"]);
|
|
33
|
+
calendarProps = tslib.__rest(_a, ["className", "disabled", "endPlaceholder", "hasError", "hint", "label", "placeholder", "required", "selectedDate", "selectedRange", "selectionMode", "size", "startPlaceholder", "onChangeDate", "onChangeRange"]);
|
|
33
34
|
return /*#__PURE__*/React__default.default.createElement("div", {
|
|
34
35
|
className: clsx__default.default(styles__default.default.root, className)
|
|
35
36
|
}, /*#__PURE__*/React__default.default.createElement(index.DatePicker, Object.assign({}, calendarProps, {
|
|
37
|
+
disabled: disabled,
|
|
36
38
|
endPlaceholder: endPlaceholder,
|
|
37
39
|
hasError: hasError,
|
|
38
40
|
hint: hint,
|
|
@@ -6,6 +6,7 @@ export type DatepickerRangeValue = [string, string];
|
|
|
6
6
|
export type DatepickerCalendarProps = Omit<CalendarCommonProps, "className" | "size">;
|
|
7
7
|
export type Props = DatepickerCalendarProps & {
|
|
8
8
|
className?: string;
|
|
9
|
+
disabled?: boolean;
|
|
9
10
|
endPlaceholder?: string;
|
|
10
11
|
hasError?: boolean;
|
|
11
12
|
hint?: ReactNode;
|
package/MultiSelect/index.js
CHANGED
|
@@ -39,9 +39,14 @@ const MultiSelect = ({
|
|
|
39
39
|
name,
|
|
40
40
|
value = [],
|
|
41
41
|
type,
|
|
42
|
-
onChange
|
|
42
|
+
onChange,
|
|
43
|
+
"aria-label": ariaLabel
|
|
43
44
|
}) => {
|
|
44
45
|
const [isOpen, setIsOpen] = React.useState(false);
|
|
46
|
+
const id = React.useId();
|
|
47
|
+
const labelId = label ? `${id}-label` : undefined;
|
|
48
|
+
const valueId = `${id}-value`;
|
|
49
|
+
const hintId = hint ? `${id}-hint` : undefined;
|
|
45
50
|
const internalSelectedKeys = React.useMemo(() => value.map(index.toKey), [value]);
|
|
46
51
|
const preparedGroups = React.useMemo(() => groups.map(group => Object.assign(Object.assign({}, group), {
|
|
47
52
|
options: group.options.map(option => Object.assign(Object.assign({}, option), {
|
|
@@ -80,7 +85,9 @@ const MultiSelect = ({
|
|
|
80
85
|
}, className),
|
|
81
86
|
required: required,
|
|
82
87
|
label: label,
|
|
88
|
+
labelId: labelId,
|
|
83
89
|
hint: hint,
|
|
90
|
+
hintId: hintId,
|
|
84
91
|
hasError: hasError
|
|
85
92
|
}, /*#__PURE__*/React__default.default.createElement(index$2.Dropdown, {
|
|
86
93
|
placement: "bottom-start",
|
|
@@ -96,7 +103,11 @@ const MultiSelect = ({
|
|
|
96
103
|
}),
|
|
97
104
|
samewidth: true
|
|
98
105
|
}, /*#__PURE__*/React__default.default.createElement("div", {
|
|
99
|
-
|
|
106
|
+
"aria-describedby": hintId,
|
|
107
|
+
"aria-disabled": disabled || undefined,
|
|
108
|
+
"aria-label": labelId ? undefined : ariaLabel,
|
|
109
|
+
"aria-labelledby": labelId ? `${labelId} ${valueId}` : undefined,
|
|
110
|
+
tabIndex: disabled ? -1 : 0,
|
|
100
111
|
role: "button",
|
|
101
112
|
style: {
|
|
102
113
|
width: fullWidth ? "100%" : "fit-content"
|
|
@@ -118,6 +129,7 @@ const MultiSelect = ({
|
|
|
118
129
|
}),
|
|
119
130
|
disabled: Boolean(disabled)
|
|
120
131
|
}, /*#__PURE__*/React__default.default.createElement("div", {
|
|
132
|
+
id: valueId,
|
|
121
133
|
className: clsx__default.default(styles__default.default["base-input"], styles__default.default[type === "chip" ? "base-input-flex" : "base-input-text"])
|
|
122
134
|
}, preparedLabel.length ? type === "chip" ?
|
|
123
135
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
@@ -20,7 +20,9 @@ export type SelectedItem = {
|
|
|
20
20
|
group: string;
|
|
21
21
|
option: string;
|
|
22
22
|
};
|
|
23
|
-
export interface MultiSelectProps extends Omit<FormFieldProps, "children"> {
|
|
23
|
+
export interface MultiSelectProps extends Omit<FormFieldProps, "children" | "labelId"> {
|
|
24
|
+
/** Accessible name of the trigger when no visible `label` is passed. */
|
|
25
|
+
"aria-label"?: string;
|
|
24
26
|
groups: GroupProps[];
|
|
25
27
|
className?: string;
|
|
26
28
|
zIndex?: number;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { PaginationProps } from "./index.props";
|
|
3
|
+
export declare const Pagination: ({ totalPages, page, defaultPage, onPageChange, siblingCount, boundaryCount, disabledPages, disabled, mode, size, pageSize, defaultPageSize, pageSizeOptions, onPageSizeChange, showPageSize, showQuickJump, helperText, previousLabel, nextLabel, pageLabel, quickJumpLabel, pageSizeLabel, className, ref, "aria-label": ariaLabel, ...props }: PaginationProps) => React.JSX.Element;
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var tslib = require('tslib');
|
|
4
|
+
var React = require('react');
|
|
5
|
+
var clsx = require('clsx');
|
|
6
|
+
var Chevron = require('../Icons/Chevron.js');
|
|
7
|
+
var index = require('../Input/index.js');
|
|
8
|
+
var index$1 = require('../Select/index.js');
|
|
9
|
+
var helpers = require('./helpers.js');
|
|
10
|
+
var styles = require('./Pagination.module.css');
|
|
11
|
+
|
|
12
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
|
+
|
|
14
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
15
|
+
var clsx__default = /*#__PURE__*/_interopDefault(clsx);
|
|
16
|
+
var styles__default = /*#__PURE__*/_interopDefault(styles);
|
|
17
|
+
|
|
18
|
+
const NO_PAGES = [];
|
|
19
|
+
const DEFAULT_PAGE_SIZE_OPTIONS = [20, 50, 100];
|
|
20
|
+
const defaultPageLabel = page => `Page ${page}`;
|
|
21
|
+
const Pagination = _a => {
|
|
22
|
+
var {
|
|
23
|
+
totalPages,
|
|
24
|
+
page,
|
|
25
|
+
defaultPage = 1,
|
|
26
|
+
onPageChange,
|
|
27
|
+
siblingCount = 1,
|
|
28
|
+
boundaryCount = 1,
|
|
29
|
+
disabledPages = NO_PAGES,
|
|
30
|
+
disabled = false,
|
|
31
|
+
mode = "default",
|
|
32
|
+
size = "m",
|
|
33
|
+
pageSize,
|
|
34
|
+
defaultPageSize = 20,
|
|
35
|
+
pageSizeOptions = DEFAULT_PAGE_SIZE_OPTIONS,
|
|
36
|
+
onPageSizeChange,
|
|
37
|
+
showPageSize = false,
|
|
38
|
+
showQuickJump = false,
|
|
39
|
+
helperText,
|
|
40
|
+
previousLabel = "Previous page",
|
|
41
|
+
nextLabel = "Next page",
|
|
42
|
+
pageLabel = defaultPageLabel,
|
|
43
|
+
quickJumpLabel = "Go to page",
|
|
44
|
+
pageSizeLabel = "Per page",
|
|
45
|
+
className,
|
|
46
|
+
ref,
|
|
47
|
+
"aria-label": ariaLabel = "Pagination"
|
|
48
|
+
} = _a,
|
|
49
|
+
props = tslib.__rest(_a, ["totalPages", "page", "defaultPage", "onPageChange", "siblingCount", "boundaryCount", "disabledPages", "disabled", "mode", "size", "pageSize", "defaultPageSize", "pageSizeOptions", "onPageSizeChange", "showPageSize", "showQuickJump", "helperText", "previousLabel", "nextLabel", "pageLabel", "quickJumpLabel", "pageSizeLabel", "className", "ref", "aria-label"]);
|
|
50
|
+
const total = helpers.toTotalPages(totalPages);
|
|
51
|
+
const [internalPage, setInternalPage] = React.useState(() => helpers.clamp(defaultPage, 1, total));
|
|
52
|
+
const currentPage = helpers.clamp(page !== null && page !== void 0 ? page : internalPage, 1, total);
|
|
53
|
+
const [internalPageSize, setInternalPageSize] = React.useState(defaultPageSize);
|
|
54
|
+
const currentPageSize = pageSize !== null && pageSize !== void 0 ? pageSize : internalPageSize;
|
|
55
|
+
const [quickJumpDraft, setQuickJumpDraft] = React.useState(null);
|
|
56
|
+
const disabledSet = React.useMemo(() => new Set(disabledPages), [disabledPages]);
|
|
57
|
+
const items = React.useMemo(() => helpers.getPaginationItems(total, currentPage, siblingCount, boundaryCount), [total, currentPage, siblingCount, boundaryCount]);
|
|
58
|
+
const pageSizeSelectOptions = React.useMemo(() => pageSizeOptions.map(option => ({
|
|
59
|
+
value: String(option),
|
|
60
|
+
label: option
|
|
61
|
+
})), [pageSizeOptions]);
|
|
62
|
+
const previousPage = helpers.findEnabledPage(currentPage, -1, total, disabledSet);
|
|
63
|
+
const nextPage = helpers.findEnabledPage(currentPage, 1, total, disabledSet);
|
|
64
|
+
const changePage = nextValue => {
|
|
65
|
+
const next = helpers.clamp(Math.floor(nextValue), 1, total);
|
|
66
|
+
if (disabled || disabledSet.has(next) || next === currentPage) return;
|
|
67
|
+
if (page === undefined) setInternalPage(next);
|
|
68
|
+
onPageChange === null || onPageChange === void 0 ? void 0 : onPageChange(next);
|
|
69
|
+
};
|
|
70
|
+
const commitQuickJump = () => {
|
|
71
|
+
if (quickJumpDraft === null) return;
|
|
72
|
+
const parsed = Number(quickJumpDraft);
|
|
73
|
+
if (quickJumpDraft.trim() !== "" && Number.isInteger(parsed)) {
|
|
74
|
+
changePage(parsed);
|
|
75
|
+
}
|
|
76
|
+
setQuickJumpDraft(null);
|
|
77
|
+
};
|
|
78
|
+
const changePageSize = next => {
|
|
79
|
+
if (pageSize === undefined) setInternalPageSize(next);
|
|
80
|
+
onPageSizeChange === null || onPageSizeChange === void 0 ? void 0 : onPageSizeChange(next);
|
|
81
|
+
};
|
|
82
|
+
const hasActions = showQuickJump || showPageSize || Boolean(helperText);
|
|
83
|
+
return /*#__PURE__*/React__default.default.createElement("nav", Object.assign({}, props, {
|
|
84
|
+
ref: ref,
|
|
85
|
+
"aria-label": ariaLabel,
|
|
86
|
+
className: clsx__default.default(styles__default.default.root, styles__default.default[`size_${size}`], {
|
|
87
|
+
[styles__default.default.root_disabled]: disabled
|
|
88
|
+
}, className)
|
|
89
|
+
}), /*#__PURE__*/React__default.default.createElement("div", {
|
|
90
|
+
className: styles__default.default.main
|
|
91
|
+
}, /*#__PURE__*/React__default.default.createElement("button", {
|
|
92
|
+
type: "button",
|
|
93
|
+
className: styles__default.default.arrow,
|
|
94
|
+
"aria-label": previousLabel,
|
|
95
|
+
disabled: disabled || previousPage === undefined,
|
|
96
|
+
onClick: () => {
|
|
97
|
+
if (previousPage !== undefined) changePage(previousPage);
|
|
98
|
+
}
|
|
99
|
+
}, /*#__PURE__*/React__default.default.createElement(Chevron.Chevron, {
|
|
100
|
+
className: styles__default.default.arrow_previous,
|
|
101
|
+
width: 16,
|
|
102
|
+
height: 16,
|
|
103
|
+
"aria-hidden": "true"
|
|
104
|
+
})), mode === "compact" ? (/*#__PURE__*/React__default.default.createElement("span", {
|
|
105
|
+
className: styles__default.default.counter,
|
|
106
|
+
"aria-live": "polite"
|
|
107
|
+
}, /*#__PURE__*/React__default.default.createElement("strong", null, currentPage), /*#__PURE__*/React__default.default.createElement("span", null, "/"), total)) : (/*#__PURE__*/React__default.default.createElement("div", {
|
|
108
|
+
className: styles__default.default.pages
|
|
109
|
+
}, items.map(item => typeof item === "number" ? (/*#__PURE__*/React__default.default.createElement("button", {
|
|
110
|
+
type: "button",
|
|
111
|
+
key: item,
|
|
112
|
+
className: clsx__default.default(styles__default.default.page, {
|
|
113
|
+
[styles__default.default.page_current]: item === currentPage
|
|
114
|
+
}),
|
|
115
|
+
"aria-label": pageLabel(item),
|
|
116
|
+
"aria-current": item === currentPage ? "page" : undefined,
|
|
117
|
+
disabled: disabled || disabledSet.has(item),
|
|
118
|
+
onClick: () => changePage(item)
|
|
119
|
+
}, item)) : (/*#__PURE__*/React__default.default.createElement("span", {
|
|
120
|
+
key: item,
|
|
121
|
+
className: styles__default.default.ellipsis,
|
|
122
|
+
"aria-hidden": "true"
|
|
123
|
+
}, "\u2026"))))), /*#__PURE__*/React__default.default.createElement("button", {
|
|
124
|
+
type: "button",
|
|
125
|
+
className: styles__default.default.arrow,
|
|
126
|
+
"aria-label": nextLabel,
|
|
127
|
+
disabled: disabled || nextPage === undefined,
|
|
128
|
+
onClick: () => {
|
|
129
|
+
if (nextPage !== undefined) changePage(nextPage);
|
|
130
|
+
}
|
|
131
|
+
}, /*#__PURE__*/React__default.default.createElement(Chevron.Chevron, {
|
|
132
|
+
className: styles__default.default.arrow_next,
|
|
133
|
+
width: 16,
|
|
134
|
+
height: 16,
|
|
135
|
+
"aria-hidden": "true"
|
|
136
|
+
}))), hasActions && (/*#__PURE__*/React__default.default.createElement("div", {
|
|
137
|
+
className: styles__default.default.actions
|
|
138
|
+
}, showQuickJump && (/*#__PURE__*/React__default.default.createElement(index.Input, {
|
|
139
|
+
className: styles__default.default.jump,
|
|
140
|
+
size: size,
|
|
141
|
+
label: quickJumpLabel,
|
|
142
|
+
inputMode: "numeric",
|
|
143
|
+
value: quickJumpDraft !== null && quickJumpDraft !== void 0 ? quickJumpDraft : String(currentPage),
|
|
144
|
+
disabled: disabled,
|
|
145
|
+
onChange: (_, value) => setQuickJumpDraft(value),
|
|
146
|
+
onBlur: commitQuickJump,
|
|
147
|
+
onKeyDown: event => {
|
|
148
|
+
if (event.key === "Enter") commitQuickJump();
|
|
149
|
+
}
|
|
150
|
+
})), showPageSize && (/*#__PURE__*/React__default.default.createElement(index$1.Select, {
|
|
151
|
+
size: size,
|
|
152
|
+
label: pageSizeLabel,
|
|
153
|
+
options: pageSizeSelectOptions,
|
|
154
|
+
value: String(currentPageSize),
|
|
155
|
+
disabled: disabled,
|
|
156
|
+
onChange: value => changePageSize(Number(value))
|
|
157
|
+
})), helperText && /*#__PURE__*/React__default.default.createElement("div", {
|
|
158
|
+
className: styles__default.default.helper
|
|
159
|
+
}, helperText))));
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
exports.Pagination = Pagination;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
--pagination-item-size: var(--component-input-height-m);
|
|
3
|
+
--pagination-font-size: var(--font-size-text-md);
|
|
4
|
+
color: var(--component-pagination-text);
|
|
5
|
+
display: inline-flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
font-family: var(--font-family-ui);
|
|
8
|
+
gap: var(--space-3);
|
|
9
|
+
max-inline-size: 100%;
|
|
10
|
+
}
|
|
11
|
+
.root_disabled {
|
|
12
|
+
opacity: 0.55;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.size_s {
|
|
16
|
+
--pagination-item-size: var(--component-input-height-s);
|
|
17
|
+
--pagination-font-size: var(--font-size-text-sm);
|
|
18
|
+
}
|
|
19
|
+
.size_l {
|
|
20
|
+
--pagination-item-size: var(--component-input-height-l);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.main,
|
|
24
|
+
.pages {
|
|
25
|
+
align-items: center;
|
|
26
|
+
display: flex;
|
|
27
|
+
gap: var(--space-1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.page,
|
|
31
|
+
.arrow {
|
|
32
|
+
align-items: center;
|
|
33
|
+
background: transparent;
|
|
34
|
+
block-size: var(--pagination-item-size);
|
|
35
|
+
border: none;
|
|
36
|
+
border-radius: var(--radius-sm);
|
|
37
|
+
box-sizing: border-box;
|
|
38
|
+
color: inherit;
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
display: inline-flex;
|
|
41
|
+
font: inherit;
|
|
42
|
+
font-size: var(--pagination-font-size);
|
|
43
|
+
justify-content: center;
|
|
44
|
+
min-inline-size: var(--pagination-item-size);
|
|
45
|
+
padding: 0 var(--space-2);
|
|
46
|
+
}
|
|
47
|
+
.page:disabled,
|
|
48
|
+
.arrow:disabled {
|
|
49
|
+
color: var(--color-text-disabled);
|
|
50
|
+
cursor: not-allowed;
|
|
51
|
+
}
|
|
52
|
+
.page:focus-visible,
|
|
53
|
+
.arrow:focus-visible {
|
|
54
|
+
outline: var(--focus-ring-width) solid var(--component-pagination-focus-ring);
|
|
55
|
+
outline-offset: var(--focus-ring-width);
|
|
56
|
+
}
|
|
57
|
+
.page:hover:not(:disabled),
|
|
58
|
+
.arrow:hover:not(:disabled) {
|
|
59
|
+
background: var(--component-pagination-bg-hover);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.page_current,
|
|
63
|
+
.page_current:hover:not(:disabled) {
|
|
64
|
+
background: var(--component-pagination-bg-current);
|
|
65
|
+
color: var(--component-pagination-text-current);
|
|
66
|
+
cursor: default;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.arrow_previous {
|
|
70
|
+
transform: rotate(90deg);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.arrow_next {
|
|
74
|
+
transform: rotate(-90deg);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.ellipsis {
|
|
78
|
+
align-items: center;
|
|
79
|
+
block-size: var(--pagination-item-size);
|
|
80
|
+
color: var(--color-text-secondary);
|
|
81
|
+
display: inline-flex;
|
|
82
|
+
font-size: var(--pagination-font-size);
|
|
83
|
+
justify-content: center;
|
|
84
|
+
min-inline-size: var(--space-6);
|
|
85
|
+
-webkit-user-select: none;
|
|
86
|
+
user-select: none;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.counter {
|
|
90
|
+
align-items: center;
|
|
91
|
+
display: flex;
|
|
92
|
+
font-size: var(--pagination-font-size);
|
|
93
|
+
gap: var(--space-1);
|
|
94
|
+
justify-content: center;
|
|
95
|
+
min-inline-size: var(--space-20);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.actions {
|
|
99
|
+
align-items: flex-end;
|
|
100
|
+
display: flex;
|
|
101
|
+
flex-wrap: wrap;
|
|
102
|
+
gap: var(--space-4);
|
|
103
|
+
min-inline-size: 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.jump {
|
|
107
|
+
inline-size: var(--space-20);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.helper {
|
|
111
|
+
color: var(--color-text-secondary);
|
|
112
|
+
font-size: var(--font-size-text-sm);
|
|
113
|
+
line-height: var(--pagination-item-size);
|
|
114
|
+
min-inline-size: 0;
|
|
115
|
+
overflow: hidden;
|
|
116
|
+
text-overflow: ellipsis;
|
|
117
|
+
white-space: nowrap;
|
|
118
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { PaginationItem } from "./index.props";
|
|
2
|
+
export declare const clamp: (value: number, min: number, max: number) => number;
|
|
3
|
+
export declare const toTotalPages: (totalPages: number) => number;
|
|
4
|
+
export declare const getPaginationItems: (totalPages: number, page: number, siblingCount?: number, boundaryCount?: number) => PaginationItem[];
|
|
5
|
+
export declare const findEnabledPage: (from: number, direction: -1 | 1, total: number, disabledPages: ReadonlySet<number>) => number | undefined;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const range = (start, end) => Array.from({
|
|
4
|
+
length: Math.max(0, end - start + 1)
|
|
5
|
+
}, (_, index) => start + index);
|
|
6
|
+
const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
7
|
+
const toTotalPages = totalPages => Math.max(1, Math.floor(totalPages) || 1);
|
|
8
|
+
const getPaginationItems = (totalPages, page, siblingCount = 1, boundaryCount = 1) => {
|
|
9
|
+
const total = toTotalPages(totalPages);
|
|
10
|
+
const current = clamp(Math.floor(page) || 1, 1, total);
|
|
11
|
+
const siblings = Math.max(0, Math.floor(siblingCount));
|
|
12
|
+
const boundaries = Math.max(0, Math.floor(boundaryCount));
|
|
13
|
+
const pages = [...new Set([...range(1, Math.min(boundaries, total)), ...range(Math.max(1, current - siblings), Math.min(total, current + siblings)), ...range(Math.max(1, total - boundaries + 1), total)])].sort((left, right) => left - right);
|
|
14
|
+
return pages.flatMap((visiblePage, index) => {
|
|
15
|
+
const previous = pages[index - 1];
|
|
16
|
+
if (previous === undefined) return [visiblePage];
|
|
17
|
+
if (visiblePage - previous === 2) return [previous + 1, visiblePage];
|
|
18
|
+
if (visiblePage - previous > 2) {
|
|
19
|
+
const ellipsis = visiblePage > current ? "end-ellipsis" : "start-ellipsis";
|
|
20
|
+
return [ellipsis, visiblePage];
|
|
21
|
+
}
|
|
22
|
+
return [visiblePage];
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
const findEnabledPage = (from, direction, total, disabledPages) => {
|
|
26
|
+
let candidate = from + direction;
|
|
27
|
+
while (candidate >= 1 && candidate <= total && disabledPages.has(candidate)) {
|
|
28
|
+
candidate += direction;
|
|
29
|
+
}
|
|
30
|
+
return candidate >= 1 && candidate <= total ? candidate : undefined;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
exports.clamp = clamp;
|
|
34
|
+
exports.findEnabledPage = findEnabledPage;
|
|
35
|
+
exports.getPaginationItems = getPaginationItems;
|
|
36
|
+
exports.toTotalPages = toTotalPages;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { HTMLAttributes, ReactNode, Ref } from "react";
|
|
2
|
+
export type PaginationSize = "s" | "m" | "l";
|
|
3
|
+
export type PaginationMode = "default" | "compact";
|
|
4
|
+
export type PaginationItem = number | "start-ellipsis" | "end-ellipsis";
|
|
5
|
+
export interface PaginationProps extends Omit<HTMLAttributes<HTMLElement>, "onChange" | "defaultValue"> {
|
|
6
|
+
totalPages: number;
|
|
7
|
+
page?: number;
|
|
8
|
+
defaultPage?: number;
|
|
9
|
+
onPageChange?: (page: number) => void;
|
|
10
|
+
/** Pages shown on each side of the current page. */
|
|
11
|
+
siblingCount?: number;
|
|
12
|
+
/** Pages always shown at the start and at the end. */
|
|
13
|
+
boundaryCount?: number;
|
|
14
|
+
disabledPages?: readonly number[];
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
mode?: PaginationMode;
|
|
17
|
+
size?: PaginationSize;
|
|
18
|
+
pageSize?: number;
|
|
19
|
+
defaultPageSize?: number;
|
|
20
|
+
pageSizeOptions?: readonly number[];
|
|
21
|
+
onPageSizeChange?: (pageSize: number) => void;
|
|
22
|
+
showPageSize?: boolean;
|
|
23
|
+
showQuickJump?: boolean;
|
|
24
|
+
helperText?: ReactNode;
|
|
25
|
+
previousLabel?: string;
|
|
26
|
+
nextLabel?: string;
|
|
27
|
+
pageLabel?: (page: number) => string;
|
|
28
|
+
quickJumpLabel?: ReactNode;
|
|
29
|
+
pageSizeLabel?: ReactNode;
|
|
30
|
+
ref?: Ref<HTMLElement>;
|
|
31
|
+
}
|
package/README.md
CHANGED
|
@@ -196,6 +196,57 @@ const css = `@media ${media.down("sm")} { … }`;
|
|
|
196
196
|
|
|
197
197
|
Returns `false` on the server and during hydration. Use it to decide whether to mount a heavy component; to show/hide markup use CSS media queries, otherwise the wrong variant renders until hydration.
|
|
198
198
|
|
|
199
|
+
## Development Commands
|
|
200
|
+
|
|
201
|
+
Run these commands from the repository root after installing dependencies with `yarn install`.
|
|
202
|
+
|
|
203
|
+
### Checks and Fixes
|
|
204
|
+
|
|
205
|
+
| Command | Purpose |
|
|
206
|
+
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
207
|
+
| `yarn lint` | Run both ESLint and Stylelint. |
|
|
208
|
+
| `yarn lint:ts` | Check JavaScript and TypeScript with ESLint. |
|
|
209
|
+
| `yarn lint:ts:fix` | Apply automatic ESLint fixes. |
|
|
210
|
+
| `yarn lint:css` | Check SCSS with Stylelint. |
|
|
211
|
+
| `yarn lint:css:fix` | Apply automatic Stylelint fixes. |
|
|
212
|
+
| `yarn lint:deps` | Check component dependency boundaries. |
|
|
213
|
+
| `yarn test` | Run Jest tests and collect coverage in `.coverage/`. |
|
|
214
|
+
| `yarn test:coverage` | Explicitly enable coverage; currently equivalent to `yarn test` because coverage is enabled in the Jest configuration. |
|
|
215
|
+
| `yarn audit:dead-code` | Check for unused files, exports and dependencies with Knip. |
|
|
216
|
+
|
|
217
|
+
`./verify.sh` runs lint, dependency boundary checks, tests and the dead code audit in sequence, stopping at the first failure.
|
|
218
|
+
|
|
219
|
+
### Storybook
|
|
220
|
+
|
|
221
|
+
| Command | Purpose |
|
|
222
|
+
| ---------------------- | ------------------------------------------------------- |
|
|
223
|
+
| `yarn storybook` | Start the Storybook development server on port 6006. |
|
|
224
|
+
| `yarn build-storybook` | Build the static Storybook site in `storybook-static/`. |
|
|
225
|
+
|
|
226
|
+
### Package Build
|
|
227
|
+
|
|
228
|
+
| Command | Purpose |
|
|
229
|
+
| -------------------------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
230
|
+
| `yarn build` | Clean `dist/`, build CommonJS and ESM output with Rollup, run all build stages below and check the resulting exports. |
|
|
231
|
+
| `yarn clean` | Delete `dist/`. |
|
|
232
|
+
| `yarn build:sass` | Compile SCSS to CSS and apply Autoprefixer for both package formats. |
|
|
233
|
+
| `yarn build:updateImports` | Replace SCSS import paths with CSS paths in the built JavaScript. |
|
|
234
|
+
| `yarn build:variables` | Generate CSS variables files for Buenos Aires and Jaipur. |
|
|
235
|
+
| `yarn build:postbuild` | Copy package metadata and README, and generate component package manifests. |
|
|
236
|
+
| `yarn build:check` | Check that built CommonJS and ESM entry points provide the runtime exports declared in their types. |
|
|
237
|
+
|
|
238
|
+
Use `yarn build` for a complete build. Individual build stages operate on existing output and are mainly useful when diagnosing the build pipeline.
|
|
239
|
+
|
|
240
|
+
### Audits
|
|
241
|
+
|
|
242
|
+
| Command | Purpose |
|
|
243
|
+
| -------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
244
|
+
| `yarn run audit` | Check production and development dependencies for known vulnerabilities using Yarn's audit command. |
|
|
245
|
+
| `yarn audit:snyk` | Check dependencies with Snyk; requires Snyk authentication. |
|
|
246
|
+
| `yarn audit:package` | Check the built package with Publint and Are the Types Wrong using the `node16` profile. Run after `yarn build`. |
|
|
247
|
+
|
|
248
|
+
Dependency security audits require network access. To check for available dependency updates, run `yarn outdated` directly.
|
|
249
|
+
|
|
199
250
|
## License
|
|
200
251
|
|
|
201
252
|
MIT
|
package/Select/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { JSX } from "react";
|
|
2
2
|
import type { SelectProps } from "./index.props";
|
|
3
|
-
export declare const Select: <T extends string>({ options, value, name, zIndex, fontSize, label, hint, hasError, required, placeholder, disabled, size, fullWidth, customInputRoot, className, onChange, }: SelectProps<T>) => JSX.Element;
|
|
3
|
+
export declare const Select: <T extends string>({ options, value, name, zIndex, fontSize, label, hint, hasError, required, placeholder, disabled, size, fullWidth, customInputRoot, className, onChange, "aria-label": ariaLabel, }: SelectProps<T>) => JSX.Element;
|