@edux-design/buttons 0.1.0 → 0.1.2
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 +12 -0
- package/dist/index.d.mts +71 -1
- package/dist/index.d.ts +71 -1
- package/dist/index.js +290 -8
- package/dist/index.mjs +303 -15
- package/package.json +1 -1
- package/src/demo/Button.stories.jsx +20 -1
- package/src/demo/ButtonCounter.stories.jsx +101 -0
- package/src/elements/Button.jsx +23 -7
- package/src/elements/Button.test.jsx +41 -0
- package/src/elements/ButtonCounter.jsx +341 -0
- package/src/elements/ButtonCounter.test.jsx +100 -0
- package/src/index.js +1 -0
package/CHANGELOG.md
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -60,6 +60,8 @@ type IconButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
|
60
60
|
*
|
|
61
61
|
* @typedef {React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
62
62
|
* children?: React.ReactNode,
|
|
63
|
+
* startIcon?: React.ReactNode,
|
|
64
|
+
* endIcon?: React.ReactNode,
|
|
63
65
|
* size?: "small"|"medium"|"large",
|
|
64
66
|
* isSecondary?: boolean,
|
|
65
67
|
* isDanger?: boolean,
|
|
@@ -94,6 +96,8 @@ declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAtt
|
|
|
94
96
|
*/
|
|
95
97
|
type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
96
98
|
children?: React.ReactNode;
|
|
99
|
+
startIcon?: React.ReactNode;
|
|
100
|
+
endIcon?: React.ReactNode;
|
|
97
101
|
size?: "small" | "medium" | "large";
|
|
98
102
|
isSecondary?: boolean;
|
|
99
103
|
isDanger?: boolean;
|
|
@@ -157,4 +161,70 @@ declare namespace ButtonGroupItem {
|
|
|
157
161
|
let displayName: string;
|
|
158
162
|
}
|
|
159
163
|
|
|
160
|
-
|
|
164
|
+
/**
|
|
165
|
+
* ButtonCounter (stepper) component.
|
|
166
|
+
*
|
|
167
|
+
* Renders decrement/increment buttons with a central value display.
|
|
168
|
+
* Supports the same size + variant flags as the main Button.
|
|
169
|
+
*
|
|
170
|
+
* @typedef {React.HTMLAttributes<HTMLDivElement> & {
|
|
171
|
+
* value?: number,
|
|
172
|
+
* defaultValue?: number,
|
|
173
|
+
* onChange?: (value: number) => void,
|
|
174
|
+
* min?: number,
|
|
175
|
+
* max?: number,
|
|
176
|
+
* step?: number,
|
|
177
|
+
* children?: React.ReactNode,
|
|
178
|
+
* size?: "small"|"medium"|"large",
|
|
179
|
+
* isSecondary?: boolean,
|
|
180
|
+
* isDanger?: boolean,
|
|
181
|
+
* isBare?: boolean,
|
|
182
|
+
* isStretched?: boolean,
|
|
183
|
+
* disabled?: boolean,
|
|
184
|
+
* isEditable?: boolean,
|
|
185
|
+
* inputProps?: Omit<React.InputHTMLAttributes<HTMLInputElement>, "value"|"defaultValue"|"onChange"|"type">,
|
|
186
|
+
* decrementIcon?: React.ReactNode,
|
|
187
|
+
* incrementIcon?: React.ReactNode,
|
|
188
|
+
* startIcon?: React.ReactNode,
|
|
189
|
+
* endIcon?: React.ReactNode,
|
|
190
|
+
* decrementButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
191
|
+
* incrementButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
192
|
+
* className?: string,
|
|
193
|
+
* }} ButtonCounterProps
|
|
194
|
+
*/
|
|
195
|
+
/**
|
|
196
|
+
* @type {React.ForwardRefExoticComponent<ButtonCounterProps & React.RefAttributes<HTMLDivElement>>}
|
|
197
|
+
*/
|
|
198
|
+
declare const ButtonCounter: React.ForwardRefExoticComponent<ButtonCounterProps & React.RefAttributes<HTMLDivElement>>;
|
|
199
|
+
/**
|
|
200
|
+
* ButtonCounter (stepper) component.
|
|
201
|
+
*
|
|
202
|
+
* Renders decrement/increment buttons with a central value display.
|
|
203
|
+
* Supports the same size + variant flags as the main Button.
|
|
204
|
+
*/
|
|
205
|
+
type ButtonCounterProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
206
|
+
value?: number;
|
|
207
|
+
defaultValue?: number;
|
|
208
|
+
onChange?: (value: number) => void;
|
|
209
|
+
min?: number;
|
|
210
|
+
max?: number;
|
|
211
|
+
step?: number;
|
|
212
|
+
children?: React.ReactNode;
|
|
213
|
+
size?: "small" | "medium" | "large";
|
|
214
|
+
isSecondary?: boolean;
|
|
215
|
+
isDanger?: boolean;
|
|
216
|
+
isBare?: boolean;
|
|
217
|
+
isStretched?: boolean;
|
|
218
|
+
disabled?: boolean;
|
|
219
|
+
isEditable?: boolean;
|
|
220
|
+
inputProps?: Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "defaultValue" | "onChange" | "type">;
|
|
221
|
+
decrementIcon?: React.ReactNode;
|
|
222
|
+
incrementIcon?: React.ReactNode;
|
|
223
|
+
startIcon?: React.ReactNode;
|
|
224
|
+
endIcon?: React.ReactNode;
|
|
225
|
+
decrementButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
|
|
226
|
+
incrementButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
|
|
227
|
+
className?: string;
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
export { Button, ButtonCounter, ButtonGroup, ButtonGroupItem, IconButton, MenuButton };
|
package/dist/index.d.ts
CHANGED
|
@@ -60,6 +60,8 @@ type IconButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
|
60
60
|
*
|
|
61
61
|
* @typedef {React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
62
62
|
* children?: React.ReactNode,
|
|
63
|
+
* startIcon?: React.ReactNode,
|
|
64
|
+
* endIcon?: React.ReactNode,
|
|
63
65
|
* size?: "small"|"medium"|"large",
|
|
64
66
|
* isSecondary?: boolean,
|
|
65
67
|
* isDanger?: boolean,
|
|
@@ -94,6 +96,8 @@ declare const Button: React.ForwardRefExoticComponent<ButtonProps & React.RefAtt
|
|
|
94
96
|
*/
|
|
95
97
|
type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
96
98
|
children?: React.ReactNode;
|
|
99
|
+
startIcon?: React.ReactNode;
|
|
100
|
+
endIcon?: React.ReactNode;
|
|
97
101
|
size?: "small" | "medium" | "large";
|
|
98
102
|
isSecondary?: boolean;
|
|
99
103
|
isDanger?: boolean;
|
|
@@ -157,4 +161,70 @@ declare namespace ButtonGroupItem {
|
|
|
157
161
|
let displayName: string;
|
|
158
162
|
}
|
|
159
163
|
|
|
160
|
-
|
|
164
|
+
/**
|
|
165
|
+
* ButtonCounter (stepper) component.
|
|
166
|
+
*
|
|
167
|
+
* Renders decrement/increment buttons with a central value display.
|
|
168
|
+
* Supports the same size + variant flags as the main Button.
|
|
169
|
+
*
|
|
170
|
+
* @typedef {React.HTMLAttributes<HTMLDivElement> & {
|
|
171
|
+
* value?: number,
|
|
172
|
+
* defaultValue?: number,
|
|
173
|
+
* onChange?: (value: number) => void,
|
|
174
|
+
* min?: number,
|
|
175
|
+
* max?: number,
|
|
176
|
+
* step?: number,
|
|
177
|
+
* children?: React.ReactNode,
|
|
178
|
+
* size?: "small"|"medium"|"large",
|
|
179
|
+
* isSecondary?: boolean,
|
|
180
|
+
* isDanger?: boolean,
|
|
181
|
+
* isBare?: boolean,
|
|
182
|
+
* isStretched?: boolean,
|
|
183
|
+
* disabled?: boolean,
|
|
184
|
+
* isEditable?: boolean,
|
|
185
|
+
* inputProps?: Omit<React.InputHTMLAttributes<HTMLInputElement>, "value"|"defaultValue"|"onChange"|"type">,
|
|
186
|
+
* decrementIcon?: React.ReactNode,
|
|
187
|
+
* incrementIcon?: React.ReactNode,
|
|
188
|
+
* startIcon?: React.ReactNode,
|
|
189
|
+
* endIcon?: React.ReactNode,
|
|
190
|
+
* decrementButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
191
|
+
* incrementButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
192
|
+
* className?: string,
|
|
193
|
+
* }} ButtonCounterProps
|
|
194
|
+
*/
|
|
195
|
+
/**
|
|
196
|
+
* @type {React.ForwardRefExoticComponent<ButtonCounterProps & React.RefAttributes<HTMLDivElement>>}
|
|
197
|
+
*/
|
|
198
|
+
declare const ButtonCounter: React.ForwardRefExoticComponent<ButtonCounterProps & React.RefAttributes<HTMLDivElement>>;
|
|
199
|
+
/**
|
|
200
|
+
* ButtonCounter (stepper) component.
|
|
201
|
+
*
|
|
202
|
+
* Renders decrement/increment buttons with a central value display.
|
|
203
|
+
* Supports the same size + variant flags as the main Button.
|
|
204
|
+
*/
|
|
205
|
+
type ButtonCounterProps = React.HTMLAttributes<HTMLDivElement> & {
|
|
206
|
+
value?: number;
|
|
207
|
+
defaultValue?: number;
|
|
208
|
+
onChange?: (value: number) => void;
|
|
209
|
+
min?: number;
|
|
210
|
+
max?: number;
|
|
211
|
+
step?: number;
|
|
212
|
+
children?: React.ReactNode;
|
|
213
|
+
size?: "small" | "medium" | "large";
|
|
214
|
+
isSecondary?: boolean;
|
|
215
|
+
isDanger?: boolean;
|
|
216
|
+
isBare?: boolean;
|
|
217
|
+
isStretched?: boolean;
|
|
218
|
+
disabled?: boolean;
|
|
219
|
+
isEditable?: boolean;
|
|
220
|
+
inputProps?: Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "defaultValue" | "onChange" | "type">;
|
|
221
|
+
decrementIcon?: React.ReactNode;
|
|
222
|
+
incrementIcon?: React.ReactNode;
|
|
223
|
+
startIcon?: React.ReactNode;
|
|
224
|
+
endIcon?: React.ReactNode;
|
|
225
|
+
decrementButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
|
|
226
|
+
incrementButtonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
|
|
227
|
+
className?: string;
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
export { Button, ButtonCounter, ButtonGroup, ButtonGroupItem, IconButton, MenuButton };
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
var index_exports = {};
|
|
31
31
|
__export(index_exports, {
|
|
32
32
|
Button: () => Button,
|
|
33
|
+
ButtonCounter: () => ButtonCounter,
|
|
33
34
|
ButtonGroup: () => ButtonGroup,
|
|
34
35
|
ButtonGroupItem: () => ButtonGroupItem,
|
|
35
36
|
IconButton: () => IconButton,
|
|
@@ -102,6 +103,8 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
|
102
103
|
var Button = (0, import_react2.forwardRef)(
|
|
103
104
|
({
|
|
104
105
|
children,
|
|
106
|
+
startIcon,
|
|
107
|
+
endIcon,
|
|
105
108
|
size = "medium",
|
|
106
109
|
isSecondary,
|
|
107
110
|
isDanger,
|
|
@@ -112,19 +115,27 @@ var Button = (0, import_react2.forwardRef)(
|
|
|
112
115
|
...props
|
|
113
116
|
}, ref) => {
|
|
114
117
|
let variant = "primary";
|
|
115
|
-
if (
|
|
116
|
-
|
|
117
|
-
if (isDanger
|
|
118
|
-
|
|
118
|
+
if (disabled) {
|
|
119
|
+
variant = "disabled";
|
|
120
|
+
} else if (isDanger && isBare) {
|
|
121
|
+
variant = "dangerBare";
|
|
122
|
+
} else if (isDanger) {
|
|
123
|
+
variant = "danger";
|
|
124
|
+
} else if (isSecondary) {
|
|
125
|
+
variant = "secondary";
|
|
126
|
+
} else if (isBare) {
|
|
127
|
+
variant = "bare";
|
|
128
|
+
}
|
|
119
129
|
if (process.env.NODE_ENV !== "production") {
|
|
120
130
|
const count = [isSecondary, isDanger, isBare].filter(Boolean).length;
|
|
121
|
-
|
|
131
|
+
const hasAllowedCombo = isDanger && isBare && count === 2;
|
|
132
|
+
if (count > 1 && !hasAllowedCombo) {
|
|
122
133
|
console.warn(
|
|
123
134
|
"[Button]: Multiple variant props passed. Using the highest priority only."
|
|
124
135
|
);
|
|
125
136
|
}
|
|
126
137
|
}
|
|
127
|
-
const defaults = "flex justify-center items-center focus:shadow-focus focus-visible:shadow-focus outline-none transition-all duration-300 ease-in-out cursor-pointer";
|
|
138
|
+
const defaults = "flex justify-center items-center gap-8 focus:shadow-focus focus-visible:shadow-focus outline-none transition-all duration-300 ease-in-out cursor-pointer";
|
|
128
139
|
const fonts = "text-bold tracking-normal hover:underline hover:underline-offset-(--underline-offset-btn) active:underline active:underline-offset-(--underline-offset-btn)";
|
|
129
140
|
const sizes = {
|
|
130
141
|
small: "h-[36px] py-8 px-16 rounded-lg text-sm",
|
|
@@ -136,11 +147,12 @@ var Button = (0, import_react2.forwardRef)(
|
|
|
136
147
|
primary: "border-2 border-border-primary-emphasis bg-bg-primary-base text-white hover:bg-border-focus hover:text-fg-base hover:border-border-emphasis hover:shadow-md active:bg-border-focus active:bg-bg-focus-overlay active:text-fg-base",
|
|
137
148
|
secondary: "border-2 border-border-primary-base bg-bg-base text-fg-primary-emphasis hover:shadow-md hover:bg-bg-primary-subtle active:bg-bg-primary-subtle-90",
|
|
138
149
|
bare: "bg-bg-base text-fg-primary-emphasis hover:bg-bg-minimal active:bg-bg-minimal-5",
|
|
150
|
+
dangerBare: "bg-bg-base text-fg-danger-emphasis hover:bg-bg-danger-subtle active:bg-bg-danger-subtle",
|
|
139
151
|
danger: "bg-bg-danger-base border-2 border-border-danger-emphasis text-white hover:bg-bg-danger-base-5 active:bg-bg-danger-base-10",
|
|
140
152
|
disabled: "border-2 border-border-subtle bg-bg-inactive text-fg-inactive hover:no-underline"
|
|
141
153
|
};
|
|
142
154
|
const STYLES = (0, import_utils2.cx)(defaults, sizes[size], width, fonts, variants[variant]);
|
|
143
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.
|
|
155
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
144
156
|
"button",
|
|
145
157
|
{
|
|
146
158
|
role: "button",
|
|
@@ -150,7 +162,11 @@ var Button = (0, import_react2.forwardRef)(
|
|
|
150
162
|
className: STYLES,
|
|
151
163
|
ref,
|
|
152
164
|
...props,
|
|
153
|
-
children
|
|
165
|
+
children: [
|
|
166
|
+
startIcon,
|
|
167
|
+
children ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children }) : null,
|
|
168
|
+
endIcon
|
|
169
|
+
]
|
|
154
170
|
}
|
|
155
171
|
);
|
|
156
172
|
}
|
|
@@ -511,9 +527,275 @@ function ButtonGroupItem(_props) {
|
|
|
511
527
|
return null;
|
|
512
528
|
}
|
|
513
529
|
ButtonGroupItem.displayName = "ButtonGroupItem";
|
|
530
|
+
|
|
531
|
+
// src/elements/ButtonCounter.jsx
|
|
532
|
+
var import_react7 = __toESM(require("react"));
|
|
533
|
+
var import_utils5 = require("@edux-design/utils");
|
|
534
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
535
|
+
var ButtonCounter = (0, import_react7.forwardRef)(function ButtonCounter2({
|
|
536
|
+
value,
|
|
537
|
+
defaultValue = 1,
|
|
538
|
+
onChange,
|
|
539
|
+
min = Number.NEGATIVE_INFINITY,
|
|
540
|
+
max = Number.POSITIVE_INFINITY,
|
|
541
|
+
step = 1,
|
|
542
|
+
children,
|
|
543
|
+
size = "medium",
|
|
544
|
+
isSecondary,
|
|
545
|
+
isDanger,
|
|
546
|
+
isBare,
|
|
547
|
+
isStretched,
|
|
548
|
+
disabled,
|
|
549
|
+
isEditable = false,
|
|
550
|
+
inputProps,
|
|
551
|
+
decrementIcon,
|
|
552
|
+
incrementIcon,
|
|
553
|
+
startIcon,
|
|
554
|
+
endIcon,
|
|
555
|
+
decrementButtonProps,
|
|
556
|
+
incrementButtonProps,
|
|
557
|
+
className,
|
|
558
|
+
...rest
|
|
559
|
+
}, ref) {
|
|
560
|
+
const isControlled = value !== void 0;
|
|
561
|
+
const [internalValue, setInternalValue] = (0, import_react7.useState)(defaultValue);
|
|
562
|
+
const currentValue = isControlled ? value : internalValue;
|
|
563
|
+
const clampedValue = (0, import_react7.useMemo)(() => {
|
|
564
|
+
const safe = Number.isFinite(currentValue) ? currentValue : defaultValue;
|
|
565
|
+
return Math.min(max, Math.max(min, safe));
|
|
566
|
+
}, [currentValue, defaultValue, max, min]);
|
|
567
|
+
const commitValue = (0, import_react7.useCallback)(
|
|
568
|
+
(next) => {
|
|
569
|
+
const clamped = Math.min(max, Math.max(min, next));
|
|
570
|
+
if (!isControlled) setInternalValue(clamped);
|
|
571
|
+
onChange == null ? void 0 : onChange(clamped);
|
|
572
|
+
},
|
|
573
|
+
[isControlled, max, min, onChange]
|
|
574
|
+
);
|
|
575
|
+
const decrementDisabled = !!disabled || !Number.isFinite(clampedValue) || clampedValue - step < min;
|
|
576
|
+
const incrementDisabled = !!disabled || !Number.isFinite(clampedValue) || clampedValue + step > max;
|
|
577
|
+
let variant = "primary";
|
|
578
|
+
if (disabled) {
|
|
579
|
+
variant = "disabled";
|
|
580
|
+
} else if (isDanger && isBare) {
|
|
581
|
+
variant = "dangerBare";
|
|
582
|
+
} else if (isDanger) {
|
|
583
|
+
variant = "danger";
|
|
584
|
+
} else if (isSecondary) {
|
|
585
|
+
variant = "secondary";
|
|
586
|
+
} else if (isBare) {
|
|
587
|
+
variant = "bare";
|
|
588
|
+
}
|
|
589
|
+
if (process.env.NODE_ENV !== "production") {
|
|
590
|
+
const count = [isSecondary, isDanger, isBare].filter(Boolean).length;
|
|
591
|
+
const hasAllowedCombo = isDanger && isBare && count === 2;
|
|
592
|
+
if (count > 1 && !hasAllowedCombo) {
|
|
593
|
+
console.warn(
|
|
594
|
+
"[ButtonCounter]: Multiple variant props passed. Using the highest priority only."
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
if (step <= 0) {
|
|
598
|
+
console.warn("[ButtonCounter]: step should be > 0.");
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
const CONTROL_SIZES = {
|
|
602
|
+
small: {
|
|
603
|
+
button: "h-[36px] w-[36px] text-sm",
|
|
604
|
+
display: "h-[36px] min-w-[48px] px-12 text-sm"
|
|
605
|
+
},
|
|
606
|
+
medium: {
|
|
607
|
+
button: "h-[44px] w-[44px] text-base",
|
|
608
|
+
display: "h-[44px] min-w-[56px] px-12 text-base"
|
|
609
|
+
},
|
|
610
|
+
large: {
|
|
611
|
+
button: "h-[56px] w-[56px] text-lg",
|
|
612
|
+
display: "h-[56px] min-w-[72px] px-16 text-lg"
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
const defaultsButton = "flex justify-center items-center focus:shadow-focus focus-visible:shadow-focus outline-none transition-all duration-300 ease-in-out cursor-pointer";
|
|
616
|
+
const defaultsDisplay = "flex items-center justify-center text-bold tracking-normal";
|
|
617
|
+
const width = isStretched ? "w-full" : "w-fit-content";
|
|
618
|
+
const variants = {
|
|
619
|
+
primary: {
|
|
620
|
+
button: "border-2 border-border-primary-emphasis bg-bg-primary-base text-white hover:bg-border-focus hover:text-fg-base hover:border-border-emphasis hover:shadow-md active:bg-border-focus active:bg-bg-focus-overlay active:text-fg-base",
|
|
621
|
+
display: "border-y-2 border-x-2 border-border-primary-emphasis bg-bg-primary-base text-white"
|
|
622
|
+
},
|
|
623
|
+
secondary: {
|
|
624
|
+
button: "border-2 border-border-primary-base bg-bg-base text-fg-primary-emphasis hover:shadow-md hover:bg-bg-primary-subtle active:bg-bg-primary-subtle-90",
|
|
625
|
+
display: "border-y-2 border-x-2 border-border-primary-base bg-bg-base text-fg-primary-emphasis"
|
|
626
|
+
},
|
|
627
|
+
bare: {
|
|
628
|
+
button: "bg-bg-base text-fg-primary-emphasis hover:bg-bg-minimal active:bg-bg-minimal-5",
|
|
629
|
+
display: "bg-bg-base text-fg-primary-emphasis"
|
|
630
|
+
},
|
|
631
|
+
dangerBare: {
|
|
632
|
+
button: "bg-bg-base text-fg-danger-emphasis hover:bg-bg-danger-subtle active:bg-bg-danger-subtle",
|
|
633
|
+
display: "bg-bg-base text-fg-danger-emphasis"
|
|
634
|
+
},
|
|
635
|
+
danger: {
|
|
636
|
+
button: "bg-bg-danger-base border-2 border-border-danger-emphasis text-white hover:bg-bg-danger-base-5 active:bg-bg-danger-base-10",
|
|
637
|
+
display: "border-y-2 border-x-2 border-border-danger-emphasis bg-bg-danger-base text-white"
|
|
638
|
+
},
|
|
639
|
+
disabled: {
|
|
640
|
+
button: "border-2 border-border-subtle bg-bg-inactive text-fg-inactive hover:no-underline cursor-not-allowed",
|
|
641
|
+
display: "border-y-2 border-x-2 border-border-subtle bg-bg-inactive text-fg-inactive"
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
const sizeStyles = CONTROL_SIZES[size] ?? CONTROL_SIZES.medium;
|
|
645
|
+
const variantStyles = variants[variant] ?? variants.primary;
|
|
646
|
+
const leftButtonStyles = (0, import_utils5.cx)(
|
|
647
|
+
defaultsButton,
|
|
648
|
+
sizeStyles.button,
|
|
649
|
+
"rounded-l-lg",
|
|
650
|
+
"relative z-10",
|
|
651
|
+
variantStyles.button,
|
|
652
|
+
variant !== "bare" && variant !== "dangerBare" ? "border-r-0" : null
|
|
653
|
+
);
|
|
654
|
+
const rightButtonStyles = (0, import_utils5.cx)(
|
|
655
|
+
defaultsButton,
|
|
656
|
+
sizeStyles.button,
|
|
657
|
+
"rounded-r-lg",
|
|
658
|
+
variantStyles.button,
|
|
659
|
+
variant !== "bare" && variant !== "dangerBare" ? "border-l-0" : null
|
|
660
|
+
);
|
|
661
|
+
const displayStyles = (0, import_utils5.cx)(
|
|
662
|
+
defaultsDisplay,
|
|
663
|
+
sizeStyles.display,
|
|
664
|
+
"relative z-0",
|
|
665
|
+
variantStyles.display,
|
|
666
|
+
isStretched ? "flex-1" : null
|
|
667
|
+
);
|
|
668
|
+
const effectiveDecrementIcon = decrementIcon ?? startIcon ?? "-";
|
|
669
|
+
const effectiveIncrementIcon = incrementIcon ?? endIcon ?? "+";
|
|
670
|
+
const [draftValue, setDraftValue] = (0, import_react7.useState)(String(clampedValue));
|
|
671
|
+
const [isEditing, setIsEditing] = (0, import_react7.useState)(false);
|
|
672
|
+
const inputRef = (0, import_react7.useRef)(null);
|
|
673
|
+
(0, import_react7.useEffect)(() => {
|
|
674
|
+
if (isEditing) return;
|
|
675
|
+
setDraftValue(String(clampedValue));
|
|
676
|
+
}, [clampedValue, isEditing]);
|
|
677
|
+
const commitDraft = (0, import_react7.useCallback)(() => {
|
|
678
|
+
const trimmed = String(draftValue).trim();
|
|
679
|
+
if (trimmed === "") {
|
|
680
|
+
setDraftValue(String(clampedValue));
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
const next = Number(trimmed);
|
|
684
|
+
if (!Number.isFinite(next)) {
|
|
685
|
+
setDraftValue(String(clampedValue));
|
|
686
|
+
return;
|
|
687
|
+
}
|
|
688
|
+
commitValue(next);
|
|
689
|
+
}, [clampedValue, commitValue, draftValue]);
|
|
690
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
691
|
+
"div",
|
|
692
|
+
{
|
|
693
|
+
ref,
|
|
694
|
+
className: (0, import_utils5.cx)("inline-flex items-stretch", width, className),
|
|
695
|
+
...rest,
|
|
696
|
+
children: [
|
|
697
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
698
|
+
"button",
|
|
699
|
+
{
|
|
700
|
+
...decrementButtonProps,
|
|
701
|
+
type: "button",
|
|
702
|
+
"aria-label": (decrementButtonProps == null ? void 0 : decrementButtonProps["aria-label"]) ?? "Decrease",
|
|
703
|
+
"aria-disabled": decrementDisabled,
|
|
704
|
+
disabled: decrementDisabled,
|
|
705
|
+
className: (0, import_utils5.cx)(
|
|
706
|
+
leftButtonStyles,
|
|
707
|
+
decrementDisabled && variant !== "disabled" ? variants.disabled.button : null,
|
|
708
|
+
decrementButtonProps == null ? void 0 : decrementButtonProps.className
|
|
709
|
+
),
|
|
710
|
+
onClick: (event) => {
|
|
711
|
+
var _a;
|
|
712
|
+
(_a = decrementButtonProps == null ? void 0 : decrementButtonProps.onClick) == null ? void 0 : _a.call(decrementButtonProps, event);
|
|
713
|
+
if (event.defaultPrevented) return;
|
|
714
|
+
commitValue(clampedValue - step);
|
|
715
|
+
},
|
|
716
|
+
children: effectiveDecrementIcon
|
|
717
|
+
}
|
|
718
|
+
),
|
|
719
|
+
isEditable && children == null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
720
|
+
"input",
|
|
721
|
+
{
|
|
722
|
+
...inputProps,
|
|
723
|
+
ref: inputRef,
|
|
724
|
+
type: "number",
|
|
725
|
+
inputMode: "numeric",
|
|
726
|
+
disabled: !!disabled,
|
|
727
|
+
"aria-label": (inputProps == null ? void 0 : inputProps["aria-label"]) ?? "Value",
|
|
728
|
+
className: (0, import_utils5.cx)(
|
|
729
|
+
displayStyles,
|
|
730
|
+
"w-[44px] text-center outline-none bg-transparent text-fg-base",
|
|
731
|
+
"[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:m-0 [&::-webkit-inner-spin-button]:m-0",
|
|
732
|
+
"focus:shadow-focus focus-visible:shadow-focus focus:z-15 focus-within:z-15",
|
|
733
|
+
inputProps == null ? void 0 : inputProps.className
|
|
734
|
+
),
|
|
735
|
+
value: draftValue,
|
|
736
|
+
onChange: (event) => {
|
|
737
|
+
var _a;
|
|
738
|
+
(_a = inputProps == null ? void 0 : inputProps.onChange) == null ? void 0 : _a.call(inputProps, event);
|
|
739
|
+
if (event.defaultPrevented) return;
|
|
740
|
+
setDraftValue(event.target.value);
|
|
741
|
+
},
|
|
742
|
+
onFocus: (event) => {
|
|
743
|
+
var _a;
|
|
744
|
+
(_a = inputProps == null ? void 0 : inputProps.onFocus) == null ? void 0 : _a.call(inputProps, event);
|
|
745
|
+
if (event.defaultPrevented) return;
|
|
746
|
+
setIsEditing(true);
|
|
747
|
+
},
|
|
748
|
+
onBlur: (event) => {
|
|
749
|
+
var _a;
|
|
750
|
+
(_a = inputProps == null ? void 0 : inputProps.onBlur) == null ? void 0 : _a.call(inputProps, event);
|
|
751
|
+
if (event.defaultPrevented) return;
|
|
752
|
+
setIsEditing(false);
|
|
753
|
+
commitDraft();
|
|
754
|
+
},
|
|
755
|
+
onKeyDown: (event) => {
|
|
756
|
+
var _a;
|
|
757
|
+
(_a = inputProps == null ? void 0 : inputProps.onKeyDown) == null ? void 0 : _a.call(inputProps, event);
|
|
758
|
+
if (event.defaultPrevented) return;
|
|
759
|
+
if (event.key === "Enter") {
|
|
760
|
+
event.currentTarget.blur();
|
|
761
|
+
}
|
|
762
|
+
if (event.key === "Escape") {
|
|
763
|
+
setDraftValue(String(clampedValue));
|
|
764
|
+
event.currentTarget.blur();
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: (0, import_utils5.cx)(displayStyles, "select-none"), children: children ?? clampedValue }),
|
|
769
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
770
|
+
"button",
|
|
771
|
+
{
|
|
772
|
+
...incrementButtonProps,
|
|
773
|
+
type: "button",
|
|
774
|
+
"aria-label": (incrementButtonProps == null ? void 0 : incrementButtonProps["aria-label"]) ?? "Increase",
|
|
775
|
+
"aria-disabled": incrementDisabled,
|
|
776
|
+
disabled: incrementDisabled,
|
|
777
|
+
className: (0, import_utils5.cx)(
|
|
778
|
+
rightButtonStyles,
|
|
779
|
+
incrementDisabled && variant !== "disabled" ? variants.disabled.button : null,
|
|
780
|
+
incrementButtonProps == null ? void 0 : incrementButtonProps.className
|
|
781
|
+
),
|
|
782
|
+
onClick: (event) => {
|
|
783
|
+
var _a;
|
|
784
|
+
(_a = incrementButtonProps == null ? void 0 : incrementButtonProps.onClick) == null ? void 0 : _a.call(incrementButtonProps, event);
|
|
785
|
+
if (event.defaultPrevented) return;
|
|
786
|
+
commitValue(clampedValue + step);
|
|
787
|
+
},
|
|
788
|
+
children: effectiveIncrementIcon
|
|
789
|
+
}
|
|
790
|
+
)
|
|
791
|
+
]
|
|
792
|
+
}
|
|
793
|
+
);
|
|
794
|
+
});
|
|
514
795
|
// Annotate the CommonJS export names for ESM import in node:
|
|
515
796
|
0 && (module.exports = {
|
|
516
797
|
Button,
|
|
798
|
+
ButtonCounter,
|
|
517
799
|
ButtonGroup,
|
|
518
800
|
ButtonGroupItem,
|
|
519
801
|
IconButton,
|