@fluentui/react-spinbutton 9.0.8 → 9.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. package/CHANGELOG.json +81 -1
  2. package/CHANGELOG.md +27 -2
  3. package/lib/SpinButton.js.map +1 -1
  4. package/lib/SpinButtonField.js.map +1 -1
  5. package/lib/components/SpinButton/SpinButton.js.map +1 -1
  6. package/lib/components/SpinButton/SpinButton.types.js.map +1 -1
  7. package/lib/components/SpinButton/index.js.map +1 -1
  8. package/lib/components/SpinButton/renderSpinButton.js.map +1 -1
  9. package/lib/components/SpinButton/useSpinButton.js.map +1 -1
  10. package/lib/components/SpinButton/useSpinButtonStyles.js.map +1 -1
  11. package/lib/components/SpinButtonField/SpinButtonField.js.map +1 -1
  12. package/lib/components/SpinButtonField/index.js.map +1 -1
  13. package/lib/index.js.map +1 -1
  14. package/lib/utils/clamp.js.map +1 -1
  15. package/lib/utils/getBound.js.map +1 -1
  16. package/lib/utils/index.js.map +1 -1
  17. package/lib/utils/precision.js.map +1 -1
  18. package/lib-amd/SpinButton.js +6 -0
  19. package/lib-amd/SpinButton.js.map +1 -0
  20. package/lib-amd/SpinButtonField.js +6 -0
  21. package/lib-amd/SpinButtonField.js.map +1 -0
  22. package/lib-amd/components/SpinButton/SpinButton.js +15 -0
  23. package/lib-amd/components/SpinButton/SpinButton.js.map +1 -0
  24. package/lib-amd/components/SpinButton/SpinButton.types.js +5 -0
  25. package/lib-amd/components/SpinButton/SpinButton.types.js.map +1 -0
  26. package/lib-amd/components/SpinButton/index.js +10 -0
  27. package/lib-amd/components/SpinButton/index.js.map +1 -0
  28. package/lib-amd/components/SpinButton/renderSpinButton.js +36 -0
  29. package/lib-amd/components/SpinButton/renderSpinButton.js.map +1 -0
  30. package/lib-amd/components/SpinButton/useSpinButton.js +252 -0
  31. package/lib-amd/components/SpinButton/useSpinButton.js.map +1 -0
  32. package/lib-amd/components/SpinButton/useSpinButtonStyles.js +312 -0
  33. package/lib-amd/components/SpinButton/useSpinButtonStyles.js.map +1 -0
  34. package/lib-amd/components/SpinButtonField/SpinButtonField.js +13 -0
  35. package/lib-amd/components/SpinButtonField/SpinButtonField.js.map +1 -0
  36. package/lib-amd/components/SpinButtonField/index.js +6 -0
  37. package/lib-amd/components/SpinButtonField/index.js.map +1 -0
  38. package/lib-amd/index.js +13 -0
  39. package/lib-amd/index.js.map +1 -0
  40. package/lib-amd/utils/clamp.js +30 -0
  41. package/lib-amd/utils/clamp.js.map +1 -0
  42. package/lib-amd/utils/getBound.js +19 -0
  43. package/lib-amd/utils/getBound.js.map +1 -0
  44. package/lib-amd/utils/index.js +8 -0
  45. package/lib-amd/utils/index.js.map +1 -0
  46. package/lib-amd/utils/precision.js +44 -0
  47. package/lib-amd/utils/precision.js.map +1 -0
  48. package/lib-commonjs/SpinButton.js.map +1 -1
  49. package/lib-commonjs/SpinButtonField.js.map +1 -1
  50. package/lib-commonjs/components/SpinButton/SpinButton.js.map +1 -1
  51. package/lib-commonjs/components/SpinButton/index.js.map +1 -1
  52. package/lib-commonjs/components/SpinButton/renderSpinButton.js.map +1 -1
  53. package/lib-commonjs/components/SpinButton/useSpinButton.js.map +1 -1
  54. package/lib-commonjs/components/SpinButton/useSpinButtonStyles.js.map +1 -1
  55. package/lib-commonjs/components/SpinButtonField/SpinButtonField.js.map +1 -1
  56. package/lib-commonjs/components/SpinButtonField/index.js.map +1 -1
  57. package/lib-commonjs/index.js.map +1 -1
  58. package/lib-commonjs/utils/clamp.js.map +1 -1
  59. package/lib-commonjs/utils/getBound.js.map +1 -1
  60. package/lib-commonjs/utils/index.js.map +1 -1
  61. package/lib-commonjs/utils/precision.js.map +1 -1
  62. package/package.json +8 -9
  63. package/Spec.md +0 -370
  64. package/spec-assets/spec-spinbutton-anatomy-alt-optional.png +0 -0
  65. package/spec-assets/spec-spinbutton-anatomy.png +0 -0
  66. package/spec-assets/spec-spinbutton-rtl.png +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderSpinButton.js","sourceRoot":"","sources":["../../../../../../../../../packages/react-components/react-spinbutton/src/components/SpinButton/renderSpinButton.tsx"],"names":[],"mappings":";;;;IAIA;;OAEG;IACI,IAAM,yBAAyB,GAAG,UAAC,KAAsB;QAC9D,6BAA6B;QAC7B,4DAA4D;QAC5D,mDAAmD;QACnD,iEAAiE;QAEjE,gGAAgG;QAChG,8BAA8B;QAC9B,qBAAqB;QACrB,gBAAgB;QAChB,SAAS;QACT,iEAAiE;QACjE,iEAAiE;QACjE,UAAU;QACV,OAAO;QACP,KAAK;QAEL,WAAW;QACX,qCAAqC;QACrC,+EAA+E;QAC/E,kBAAkB;QAClB,KAAK;QAEC,IAAA,KAAuB,0BAAQ,CAAkB,KAAK,CAAC,EAArD,KAAK,WAAA,EAAE,SAAS,eAAqC,CAAC;QAE9D,OAAO,CACL,oBAAC,KAAK,CAAC,IAAI,uBAAK,SAAS,CAAC,IAAI;YAC5B,oBAAC,KAAK,CAAC,KAAK,uBAAK,SAAS,CAAC,KAAK,EAAI;YACpC,oBAAC,KAAK,CAAC,eAAe,uBAAK,SAAS,CAAC,eAAe,EAAI;YACxD,oBAAC,KAAK,CAAC,eAAe,uBAAK,SAAS,CAAC,eAAe,EAAI,CAC7C,CACd,CAAC;IACJ,CAAC,CAAC;IAhCW,QAAA,yBAAyB,6BAgCpC","sourcesContent":["import * as React from 'react';\nimport { getSlots } from '@fluentui/react-utilities';\nimport type { SpinButtonState, SpinButtonSlots } from './SpinButton.types';\n\n/**\n * Render the final JSX of SpinButton\n */\nexport const renderSpinButton_unstable = (state: SpinButtonState) => {\n // Leaving this here for now.\n // This is the approach using react-input's Input component.\n // It has some Typescript problems and feels hacky.\n // const { slots, slotProps } = getSlots<SpinButtonSlots>(state);\n\n // const { contentAfter, ...otherInputSlotProps } = slotProps.input as SpinButtonSlots['input'];\n // const inputContentAfter = {\n // ...contentAfter,\n // children: (\n // <>\n // <slots.incrementButton {...slotProps.incrementButton} />\n // <slots.decrementButton {...slotProps.decrementButton} />\n // </>\n // ),\n // };\n\n // return (\n // <slots.root {...slotProps.root}>\n // <slots.input {...otherInputSlotProps} contentAfter={inputContentAfter}/>\n // </slots.root>\n // );\n\n const { slots, slotProps } = getSlots<SpinButtonSlots>(state);\n\n return (\n <slots.root {...slotProps.root}>\n <slots.input {...slotProps.input} />\n <slots.incrementButton {...slotProps.incrementButton} />\n <slots.decrementButton {...slotProps.decrementButton} />\n </slots.root>\n );\n};\n"]}
@@ -0,0 +1,252 @@
1
+ define(["require", "exports", "tslib", "react", "@fluentui/react-utilities", "@fluentui/keyboard-keys", "../../utils/index", "@fluentui/react-icons"], function (require, exports, tslib_1, React, react_utilities_1, Keys, index_1, react_icons_1) {
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.useSpinButton_unstable = void 0;
5
+ var DEFAULT_SPIN_DELAY_MS = 150;
6
+ var MIN_SPIN_DELAY_MS = 80;
7
+ var MAX_SPIN_TIME_MS = 1000;
8
+ // This is here to give an ease the mouse held down case.
9
+ // Exact easing it to be defined. Once it is we'll likely
10
+ // pull this out into a util function in the SpinButton package.
11
+ var lerp = function (start, end, percent) { return start + (end - start) * percent; };
12
+ /**
13
+ * Create the state required to render SpinButton.
14
+ *
15
+ * The returned state can be modified with hooks such as useSpinButtonStyles_unstable,
16
+ * before being passed to renderSpinButton_unstable.
17
+ *
18
+ * @param props - props from this instance of SpinButton
19
+ * @param ref - reference to root HTMLElement of SpinButton
20
+ */
21
+ var useSpinButton_unstable = function (props, ref) {
22
+ var _a;
23
+ var nativeProps = react_utilities_1.getPartitionedNativeProps({
24
+ props: props,
25
+ primarySlotTagName: 'input',
26
+ excludedPropNames: ['defaultValue', 'max', 'min', 'onChange', 'size', 'value'],
27
+ });
28
+ var value = props.value, displayValue = props.displayValue, defaultValue = props.defaultValue, min = props.min, max = props.max, _b = props.step, step = _b === void 0 ? 1 : _b, _c = props.stepPage, stepPage = _c === void 0 ? 1 : _c, precisionFromProps = props.precision, onChange = props.onChange, _d = props.size, size = _d === void 0 ? 'medium' : _d, _e = props.appearance, appearance = _e === void 0 ? 'outline' : _e, root = props.root, input = props.input, incrementButton = props.incrementButton, decrementButton = props.decrementButton;
29
+ var precision = React.useMemo(function () {
30
+ return precisionFromProps !== null && precisionFromProps !== void 0 ? precisionFromProps : Math.max(index_1.calculatePrecision(step), 0);
31
+ }, [precisionFromProps, step]);
32
+ var _f = react_utilities_1.useControllableState({
33
+ state: value,
34
+ defaultState: defaultValue,
35
+ initialState: 0,
36
+ }), currentValue = _f[0], setCurrentValue = _f[1];
37
+ var isControlled = value !== undefined;
38
+ var _g = React.useState(undefined), textValue = _g[0], setTextValue = _g[1];
39
+ var _h = React.useState('rest'), keyboardSpinState = _h[0], setKeyboardSpinState = _h[1];
40
+ var internalState = React.useRef({
41
+ value: currentValue,
42
+ spinState: 'rest',
43
+ spinTime: 0,
44
+ spinDelay: DEFAULT_SPIN_DELAY_MS,
45
+ atBound: currentValue !== null ? index_1.getBound(index_1.precisionRound(currentValue, precision), min, max) : 'none',
46
+ });
47
+ var _j = react_utilities_1.useTimeout(), setStepTimeout = _j[0], clearStepTimeout = _j[1];
48
+ var stepValue = function (e, direction, startFrom) {
49
+ var startValue = internalState.current.value;
50
+ if (startFrom) {
51
+ var num = parseFloat(startFrom);
52
+ if (!isNaN(num)) {
53
+ startValue = num;
54
+ }
55
+ }
56
+ var val = startValue;
57
+ var dir = direction === 'up' || direction === 'upPage' ? 1 : -1;
58
+ var stepSize = direction === 'upPage' || direction === 'downPage' ? stepPage : step;
59
+ if (val === null) {
60
+ var stepStart = min === undefined ? 0 : min;
61
+ var nullStep = index_1.clamp(stepStart + stepSize * dir, min, max);
62
+ commit(e, nullStep);
63
+ return;
64
+ }
65
+ var newValue = val + stepSize * dir;
66
+ if (!Number.isNaN(newValue)) {
67
+ newValue = index_1.clamp(newValue, min, max);
68
+ }
69
+ commit(e, newValue);
70
+ if (internalState.current.spinState !== 'rest') {
71
+ setStepTimeout(function () {
72
+ // Ease the step speed a bit
73
+ internalState.current.spinTime += internalState.current.spinDelay;
74
+ internalState.current.spinDelay = lerp(DEFAULT_SPIN_DELAY_MS, MIN_SPIN_DELAY_MS, internalState.current.spinTime / MAX_SPIN_TIME_MS);
75
+ stepValue(e, direction);
76
+ }, internalState.current.spinDelay);
77
+ }
78
+ };
79
+ var handleInputChange = function (e) {
80
+ if (!internalState.current.previousTextValue) {
81
+ internalState.current.previousTextValue = textValue;
82
+ }
83
+ var newValue = e.target.value;
84
+ setTextValue(newValue);
85
+ };
86
+ var handleIncrementMouseDown = function (e) {
87
+ internalState.current.spinState = 'up';
88
+ stepValue(e, 'up');
89
+ };
90
+ var handleDecrementMouseDown = function (e) {
91
+ internalState.current.spinState = 'down';
92
+ stepValue(e, 'down');
93
+ };
94
+ var handleStepMouseUpOrLeave = function (e) {
95
+ clearStepTimeout();
96
+ internalState.current.spinState = 'rest';
97
+ internalState.current.spinDelay = DEFAULT_SPIN_DELAY_MS;
98
+ internalState.current.spinTime = 0;
99
+ };
100
+ var handleBlur = function (e) {
101
+ commit(e, currentValue, textValue);
102
+ internalState.current.previousTextValue = undefined;
103
+ };
104
+ var handleKeyDown = function (e) {
105
+ var nextKeyboardSpinState = 'rest';
106
+ if (e.key === Keys.ArrowUp) {
107
+ stepValue(e, 'up', textValue);
108
+ nextKeyboardSpinState = 'up';
109
+ }
110
+ else if (e.key === Keys.ArrowDown) {
111
+ stepValue(e, 'down', textValue);
112
+ nextKeyboardSpinState = 'down';
113
+ }
114
+ else if (e.key === Keys.PageUp) {
115
+ e.preventDefault();
116
+ stepValue(e, 'upPage', textValue);
117
+ nextKeyboardSpinState = 'up';
118
+ }
119
+ else if (e.key === Keys.PageDown) {
120
+ e.preventDefault();
121
+ stepValue(e, 'downPage', textValue);
122
+ nextKeyboardSpinState = 'down';
123
+ }
124
+ else if (!e.shiftKey && e.key === Keys.Home && min !== undefined) {
125
+ commit(e, min);
126
+ nextKeyboardSpinState = 'down';
127
+ }
128
+ else if (!e.shiftKey && e.key === Keys.End && max !== undefined) {
129
+ commit(e, max);
130
+ nextKeyboardSpinState = 'up';
131
+ }
132
+ else if (e.key === Keys.Enter) {
133
+ commit(e, currentValue, textValue);
134
+ internalState.current.previousTextValue = undefined;
135
+ }
136
+ else if (e.key === Keys.Escape) {
137
+ if (internalState.current.previousTextValue) {
138
+ setTextValue(undefined);
139
+ internalState.current.previousTextValue = undefined;
140
+ }
141
+ }
142
+ if (keyboardSpinState !== nextKeyboardSpinState) {
143
+ setKeyboardSpinState(nextKeyboardSpinState);
144
+ }
145
+ };
146
+ var handleKeyUp = function (e) {
147
+ if (keyboardSpinState !== 'rest') {
148
+ setKeyboardSpinState('rest');
149
+ internalState.current.spinState = 'rest';
150
+ }
151
+ };
152
+ var commit = function (e, newValue, newDisplayValue) {
153
+ var valueChanged = newValue !== undefined && currentValue !== newValue;
154
+ var displayValueChanged = newDisplayValue !== undefined &&
155
+ internalState.current.previousTextValue !== undefined &&
156
+ internalState.current.previousTextValue !== newDisplayValue;
157
+ var roundedValue;
158
+ if (valueChanged) {
159
+ roundedValue = index_1.precisionRound(newValue, precision);
160
+ setCurrentValue(roundedValue);
161
+ }
162
+ else if (displayValueChanged && !isControlled) {
163
+ var nextValue = parseFloat(newDisplayValue);
164
+ if (!isNaN(nextValue)) {
165
+ setCurrentValue(index_1.precisionRound(nextValue, precision));
166
+ }
167
+ }
168
+ if (valueChanged || displayValueChanged) {
169
+ onChange === null || onChange === void 0 ? void 0 : onChange(e, { value: roundedValue, displayValue: newDisplayValue });
170
+ }
171
+ setTextValue(undefined);
172
+ };
173
+ var state = {
174
+ size: size,
175
+ appearance: appearance,
176
+ spinState: keyboardSpinState,
177
+ atBound: internalState.current.atBound,
178
+ components: {
179
+ root: 'span',
180
+ input: 'input',
181
+ incrementButton: 'button',
182
+ decrementButton: 'button',
183
+ },
184
+ root: react_utilities_1.resolveShorthand(root, {
185
+ required: true,
186
+ defaultProps: nativeProps.root,
187
+ }),
188
+ input: react_utilities_1.resolveShorthand(input, {
189
+ required: true,
190
+ defaultProps: tslib_1.__assign({ ref: ref, autoComplete: 'off', role: 'spinbutton', appearance: appearance, type: 'text' }, nativeProps.primary),
191
+ }),
192
+ incrementButton: react_utilities_1.resolveShorthand(incrementButton, {
193
+ required: true,
194
+ defaultProps: {
195
+ tabIndex: -1,
196
+ children: React.createElement(react_icons_1.ChevronUp16Regular, null),
197
+ disabled: nativeProps.primary.disabled,
198
+ 'aria-label': 'Increment value',
199
+ type: 'button',
200
+ },
201
+ }),
202
+ decrementButton: react_utilities_1.resolveShorthand(decrementButton, {
203
+ required: true,
204
+ defaultProps: {
205
+ tabIndex: -1,
206
+ children: React.createElement(react_icons_1.ChevronDown16Regular, null),
207
+ disabled: nativeProps.primary.disabled,
208
+ 'aria-label': 'Decrement value',
209
+ type: 'button',
210
+ },
211
+ }),
212
+ };
213
+ var valueToDisplay;
214
+ if (textValue !== undefined) {
215
+ valueToDisplay = textValue;
216
+ }
217
+ else if (value === null || currentValue === null) {
218
+ valueToDisplay = displayValue !== null && displayValue !== void 0 ? displayValue : '';
219
+ internalState.current.value = null;
220
+ internalState.current.atBound = 'none';
221
+ }
222
+ else {
223
+ var roundedValue = index_1.precisionRound(currentValue, precision);
224
+ internalState.current.value = roundedValue;
225
+ internalState.current.atBound = index_1.getBound(roundedValue, min, max);
226
+ if (isControlled) {
227
+ valueToDisplay = displayValue !== null && displayValue !== void 0 ? displayValue : String(roundedValue);
228
+ }
229
+ else {
230
+ valueToDisplay = String(roundedValue);
231
+ }
232
+ }
233
+ state.input.value = valueToDisplay;
234
+ state.input['aria-valuemin'] = min;
235
+ state.input['aria-valuemax'] = max;
236
+ state.input['aria-valuenow'] = currentValue !== null && currentValue !== void 0 ? currentValue : undefined;
237
+ state.input['aria-valuetext'] = (_a = state.input['aria-valuetext']) !== null && _a !== void 0 ? _a : ((value !== undefined && displayValue) || undefined);
238
+ state.input.onChange = react_utilities_1.mergeCallbacks(state.input.onChange, handleInputChange);
239
+ state.input.onBlur = react_utilities_1.mergeCallbacks(state.input.onBlur, handleBlur);
240
+ state.input.onKeyDown = react_utilities_1.mergeCallbacks(state.input.onKeyDown, handleKeyDown);
241
+ state.input.onKeyUp = react_utilities_1.mergeCallbacks(state.input.onKeyUp, handleKeyUp);
242
+ state.incrementButton.onMouseDown = react_utilities_1.mergeCallbacks(handleIncrementMouseDown, state.incrementButton.onMouseDown);
243
+ state.incrementButton.onMouseUp = react_utilities_1.mergeCallbacks(state.incrementButton.onMouseUp, handleStepMouseUpOrLeave);
244
+ state.incrementButton.onMouseLeave = react_utilities_1.mergeCallbacks(state.incrementButton.onMouseLeave, handleStepMouseUpOrLeave);
245
+ state.decrementButton.onMouseDown = react_utilities_1.mergeCallbacks(handleDecrementMouseDown, state.decrementButton.onMouseDown);
246
+ state.decrementButton.onMouseUp = react_utilities_1.mergeCallbacks(state.decrementButton.onMouseUp, handleStepMouseUpOrLeave);
247
+ state.decrementButton.onMouseLeave = react_utilities_1.mergeCallbacks(state.decrementButton.onMouseLeave, handleStepMouseUpOrLeave);
248
+ return state;
249
+ };
250
+ exports.useSpinButton_unstable = useSpinButton_unstable;
251
+ });
252
+ //# sourceMappingURL=useSpinButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSpinButton.js","sourceRoot":"","sources":["../../../../../../../../../packages/react-components/react-spinbutton/src/components/SpinButton/useSpinButton.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react';\nimport {\n getPartitionedNativeProps,\n mergeCallbacks,\n resolveShorthand,\n useControllableState,\n useTimeout,\n} from '@fluentui/react-utilities';\nimport * as Keys from '@fluentui/keyboard-keys';\nimport {\n SpinButtonProps,\n SpinButtonState,\n SpinButtonSpinState,\n SpinButtonChangeEvent,\n SpinButtonBounds,\n} from './SpinButton.types';\nimport { calculatePrecision, precisionRound, getBound, clamp } from '../../utils/index';\nimport { ChevronUp16Regular, ChevronDown16Regular } from '@fluentui/react-icons';\n\ntype InternalState = {\n value: number | null;\n spinState: SpinButtonSpinState;\n spinTime: number;\n spinDelay: number;\n previousTextValue?: string;\n atBound: SpinButtonBounds;\n};\n\nconst DEFAULT_SPIN_DELAY_MS = 150;\nconst MIN_SPIN_DELAY_MS = 80;\nconst MAX_SPIN_TIME_MS = 1000;\n\n// This is here to give an ease the mouse held down case.\n// Exact easing it to be defined. Once it is we'll likely\n// pull this out into a util function in the SpinButton package.\nconst lerp = (start: number, end: number, percent: number): number => start + (end - start) * percent;\n\n/**\n * Create the state required to render SpinButton.\n *\n * The returned state can be modified with hooks such as useSpinButtonStyles_unstable,\n * before being passed to renderSpinButton_unstable.\n *\n * @param props - props from this instance of SpinButton\n * @param ref - reference to root HTMLElement of SpinButton\n */\nexport const useSpinButton_unstable = (props: SpinButtonProps, ref: React.Ref<HTMLInputElement>): SpinButtonState => {\n const nativeProps = getPartitionedNativeProps({\n props,\n primarySlotTagName: 'input',\n excludedPropNames: ['defaultValue', 'max', 'min', 'onChange', 'size', 'value'],\n });\n\n const {\n value,\n displayValue,\n defaultValue,\n min,\n max,\n step = 1,\n stepPage = 1,\n precision: precisionFromProps,\n onChange,\n size = 'medium',\n appearance = 'outline',\n root,\n input,\n incrementButton,\n decrementButton,\n } = props;\n\n const precision = React.useMemo(() => {\n return precisionFromProps ?? Math.max(calculatePrecision(step), 0);\n }, [precisionFromProps, step]);\n\n const [currentValue, setCurrentValue] = useControllableState({\n state: value,\n defaultState: defaultValue,\n initialState: 0,\n });\n\n const isControlled = value !== undefined;\n\n const [textValue, setTextValue] = React.useState<string | undefined>(undefined);\n const [keyboardSpinState, setKeyboardSpinState] = React.useState<SpinButtonSpinState>('rest');\n\n const internalState = React.useRef<InternalState>({\n value: currentValue,\n spinState: 'rest',\n spinTime: 0,\n spinDelay: DEFAULT_SPIN_DELAY_MS,\n atBound: currentValue !== null ? getBound(precisionRound(currentValue, precision), min, max) : 'none',\n });\n\n const [setStepTimeout, clearStepTimeout] = useTimeout();\n\n const stepValue = (\n e: SpinButtonChangeEvent,\n direction: 'up' | 'down' | 'upPage' | 'downPage',\n startFrom?: string,\n ) => {\n let startValue = internalState.current.value;\n if (startFrom) {\n const num = parseFloat(startFrom);\n if (!isNaN(num)) {\n startValue = num;\n }\n }\n const val = startValue;\n const dir = direction === 'up' || direction === 'upPage' ? 1 : -1;\n const stepSize = direction === 'upPage' || direction === 'downPage' ? stepPage : step;\n\n if (val === null) {\n const stepStart = min === undefined ? 0 : min;\n const nullStep = clamp(stepStart + stepSize * dir, min, max);\n commit(e, nullStep);\n return;\n }\n\n let newValue = val + stepSize * dir;\n if (!Number.isNaN(newValue)) {\n newValue = clamp(newValue, min, max);\n }\n\n commit(e, newValue);\n\n if (internalState.current.spinState !== 'rest') {\n setStepTimeout(() => {\n // Ease the step speed a bit\n internalState.current.spinTime += internalState.current.spinDelay;\n internalState.current.spinDelay = lerp(\n DEFAULT_SPIN_DELAY_MS,\n MIN_SPIN_DELAY_MS,\n internalState.current.spinTime / MAX_SPIN_TIME_MS,\n );\n stepValue(e, direction);\n }, internalState.current.spinDelay);\n }\n };\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (!internalState.current.previousTextValue) {\n internalState.current.previousTextValue = textValue;\n }\n const newValue = e.target.value;\n setTextValue(newValue);\n };\n\n const handleIncrementMouseDown = (e: React.MouseEvent<HTMLButtonElement>) => {\n internalState.current.spinState = 'up';\n stepValue(e, 'up');\n };\n\n const handleDecrementMouseDown = (e: React.MouseEvent<HTMLButtonElement>) => {\n internalState.current.spinState = 'down';\n stepValue(e, 'down');\n };\n\n const handleStepMouseUpOrLeave = (e: React.MouseEvent<HTMLButtonElement>) => {\n clearStepTimeout();\n internalState.current.spinState = 'rest';\n internalState.current.spinDelay = DEFAULT_SPIN_DELAY_MS;\n internalState.current.spinTime = 0;\n };\n\n const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n commit(e, currentValue, textValue);\n internalState.current.previousTextValue = undefined;\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n let nextKeyboardSpinState: SpinButtonSpinState = 'rest';\n\n if (e.key === Keys.ArrowUp) {\n stepValue(e, 'up', textValue);\n nextKeyboardSpinState = 'up';\n } else if (e.key === Keys.ArrowDown) {\n stepValue(e, 'down', textValue);\n nextKeyboardSpinState = 'down';\n } else if (e.key === Keys.PageUp) {\n e.preventDefault();\n stepValue(e, 'upPage', textValue);\n nextKeyboardSpinState = 'up';\n } else if (e.key === Keys.PageDown) {\n e.preventDefault();\n stepValue(e, 'downPage', textValue);\n nextKeyboardSpinState = 'down';\n } else if (!e.shiftKey && e.key === Keys.Home && min !== undefined) {\n commit(e, min);\n nextKeyboardSpinState = 'down';\n } else if (!e.shiftKey && e.key === Keys.End && max !== undefined) {\n commit(e, max);\n nextKeyboardSpinState = 'up';\n } else if (e.key === Keys.Enter) {\n commit(e, currentValue, textValue);\n internalState.current.previousTextValue = undefined;\n } else if (e.key === Keys.Escape) {\n if (internalState.current.previousTextValue) {\n setTextValue(undefined);\n internalState.current.previousTextValue = undefined;\n }\n }\n\n if (keyboardSpinState !== nextKeyboardSpinState) {\n setKeyboardSpinState(nextKeyboardSpinState);\n }\n };\n\n const handleKeyUp = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (keyboardSpinState !== 'rest') {\n setKeyboardSpinState('rest');\n internalState.current.spinState = 'rest';\n }\n };\n\n const commit = (e: SpinButtonChangeEvent, newValue?: number | null, newDisplayValue?: string) => {\n const valueChanged = newValue !== undefined && currentValue !== newValue;\n const displayValueChanged =\n newDisplayValue !== undefined &&\n internalState.current.previousTextValue !== undefined &&\n internalState.current.previousTextValue !== newDisplayValue;\n\n let roundedValue;\n if (valueChanged) {\n roundedValue = precisionRound(newValue!, precision);\n setCurrentValue(roundedValue);\n } else if (displayValueChanged && !isControlled) {\n const nextValue = parseFloat(newDisplayValue as string);\n if (!isNaN(nextValue)) {\n setCurrentValue(precisionRound(nextValue, precision));\n }\n }\n\n if (valueChanged || displayValueChanged) {\n onChange?.(e, { value: roundedValue, displayValue: newDisplayValue });\n }\n\n setTextValue(undefined);\n };\n\n const state: SpinButtonState = {\n size,\n appearance,\n spinState: keyboardSpinState,\n atBound: internalState.current.atBound,\n\n components: {\n root: 'span',\n input: 'input',\n incrementButton: 'button',\n decrementButton: 'button',\n },\n root: resolveShorthand(root, {\n required: true,\n defaultProps: nativeProps.root,\n }),\n input: resolveShorthand(input, {\n required: true,\n defaultProps: {\n ref,\n autoComplete: 'off',\n role: 'spinbutton',\n appearance,\n type: 'text',\n ...nativeProps.primary,\n },\n }),\n incrementButton: resolveShorthand(incrementButton, {\n required: true,\n defaultProps: {\n tabIndex: -1,\n children: <ChevronUp16Regular />,\n disabled: nativeProps.primary.disabled,\n 'aria-label': 'Increment value',\n type: 'button',\n },\n }),\n decrementButton: resolveShorthand(decrementButton, {\n required: true,\n defaultProps: {\n tabIndex: -1,\n children: <ChevronDown16Regular />,\n disabled: nativeProps.primary.disabled,\n 'aria-label': 'Decrement value',\n type: 'button',\n },\n }),\n };\n\n let valueToDisplay;\n if (textValue !== undefined) {\n valueToDisplay = textValue;\n } else if (value === null || currentValue === null) {\n valueToDisplay = displayValue ?? '';\n internalState.current.value = null;\n internalState.current.atBound = 'none';\n } else {\n const roundedValue = precisionRound(currentValue, precision);\n internalState.current.value = roundedValue;\n internalState.current.atBound = getBound(roundedValue, min, max);\n if (isControlled) {\n valueToDisplay = displayValue ?? String(roundedValue);\n } else {\n valueToDisplay = String(roundedValue);\n }\n }\n\n state.input.value = valueToDisplay;\n state.input['aria-valuemin'] = min;\n state.input['aria-valuemax'] = max;\n state.input['aria-valuenow'] = currentValue ?? undefined;\n state.input['aria-valuetext'] = state.input['aria-valuetext'] ?? ((value !== undefined && displayValue) || undefined);\n state.input.onChange = mergeCallbacks(state.input.onChange, handleInputChange);\n state.input.onBlur = mergeCallbacks(state.input.onBlur, handleBlur);\n state.input.onKeyDown = mergeCallbacks(state.input.onKeyDown, handleKeyDown);\n state.input.onKeyUp = mergeCallbacks(state.input.onKeyUp, handleKeyUp);\n\n state.incrementButton.onMouseDown = mergeCallbacks(handleIncrementMouseDown, state.incrementButton.onMouseDown);\n state.incrementButton.onMouseUp = mergeCallbacks(state.incrementButton.onMouseUp, handleStepMouseUpOrLeave);\n state.incrementButton.onMouseLeave = mergeCallbacks(state.incrementButton.onMouseLeave, handleStepMouseUpOrLeave);\n\n state.decrementButton.onMouseDown = mergeCallbacks(handleDecrementMouseDown, state.decrementButton.onMouseDown);\n state.decrementButton.onMouseUp = mergeCallbacks(state.decrementButton.onMouseUp, handleStepMouseUpOrLeave);\n state.decrementButton.onMouseLeave = mergeCallbacks(state.decrementButton.onMouseLeave, handleStepMouseUpOrLeave);\n\n return state;\n};\n"]}
@@ -0,0 +1,312 @@
1
+ define(["require", "exports", "tslib", "@griffel/react", "@fluentui/react-theme", "@fluentui/react-input"], function (require, exports, tslib_1, react_1, react_theme_1, react_input_1) {
2
+ "use strict";
3
+ var _a, _b, _c, _d, _e, _f, _g, _h;
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.useSpinButtonStyles_unstable = exports.spinButtonClassNames = void 0;
6
+ exports.spinButtonClassNames = {
7
+ root: 'fui-SpinButton',
8
+ input: 'fui-SpinButton__input',
9
+ incrementButton: 'fui-SpinButton__incrementButton',
10
+ decrementButton: 'fui-SpinButton__decrementButton',
11
+ };
12
+ var spinButtonExtraClassNames = {
13
+ buttonActive: 'fui-SpinButton__button_active',
14
+ };
15
+ var useRootStyles = react_1.makeStyles({
16
+ base: tslib_1.__assign(tslib_1.__assign({ display: 'inline-grid', gridTemplateColumns: "1fr 24px", gridTemplateRows: '1fr 1fr', columnGap: react_theme_1.tokens.spacingHorizontalXS, rowGap: 0, paddingRight: 0, position: 'relative' }, react_1.shorthands.border('0')), { isolation: 'isolate',
17
+ // Apply border styles on the ::before pseudo element.
18
+ // We cannot use ::after since react-input uses that
19
+ // for the selector styles.
20
+ // Using the pseudo element allows us to place the border
21
+ // above content in the component which ensures the buttons
22
+ // line up visually with the border as expected. Without this
23
+ // there is a bit of a gap which can become very noticeable
24
+ // at high zoom or when OS zoom levels are not divisible by 2
25
+ // (e.g., 150% on Windows in Firefox)
26
+ // This is most noticeable on the "outline" appearance which is
27
+ // also the default so it feels worth the extra ceremony to get right.
28
+ '::before': tslib_1.__assign(tslib_1.__assign({ content: '""', boxSizing: 'border-box', position: 'absolute', top: 0, right: 0, bottom: 0, left: 0 }, react_1.shorthands.borderRadius(react_theme_1.tokens.borderRadiusMedium)), { pointerEvents: 'none', zIndex: 10 }), '::after': {
29
+ right: 0,
30
+ bottom: 0,
31
+ left: 0,
32
+ zIndex: 20,
33
+ } }),
34
+ small: {
35
+ paddingLeft: react_theme_1.tokens.spacingHorizontalS,
36
+ },
37
+ // intentionally empty
38
+ medium: {},
39
+ outline: {
40
+ '::before': tslib_1.__assign(tslib_1.__assign({}, react_1.shorthands.border('1px', 'solid', react_theme_1.tokens.colorNeutralStroke1)), { borderBottomColor: react_theme_1.tokens.colorNeutralStrokeAccessible }),
41
+ },
42
+ outlineInteractive: {
43
+ ':hover': {
44
+ '::before': tslib_1.__assign(tslib_1.__assign({}, react_1.shorthands.borderColor(react_theme_1.tokens.colorNeutralStroke1Hover)), { borderBottomColor: react_theme_1.tokens.colorNeutralStrokeAccessibleHover }),
45
+ },
46
+ // DO NOT add a space between the selectors! It changes the behavior of make-styles.
47
+ ':active,:focus-within': {
48
+ '::before': tslib_1.__assign(tslib_1.__assign({}, react_1.shorthands.borderColor(react_theme_1.tokens.colorNeutralStroke1Pressed)), { borderBottomColor: react_theme_1.tokens.colorNeutralStrokeAccessiblePressed }),
49
+ },
50
+ },
51
+ underline: {
52
+ '::before': tslib_1.__assign(tslib_1.__assign({}, react_1.shorthands.borderRadius(0)), react_1.shorthands.borderBottom('1px', 'solid', react_theme_1.tokens.colorNeutralStrokeAccessible)),
53
+ },
54
+ underlineInteractive: {
55
+ ':hover': {
56
+ '::before': {
57
+ borderBottomColor: react_theme_1.tokens.colorNeutralStrokeAccessibleHover,
58
+ },
59
+ },
60
+ // DO NOT add a space between the selectors! It changes the behavior of make-styles.
61
+ ':active,:focus-within': {
62
+ '::before': {
63
+ borderBottomColor: react_theme_1.tokens.colorNeutralStrokeAccessiblePressed,
64
+ },
65
+ },
66
+ },
67
+ filled: {
68
+ '::before': tslib_1.__assign({}, react_1.shorthands.border('1px', 'solid', react_theme_1.tokens.colorTransparentStroke)),
69
+ },
70
+ filledInteractive: {
71
+ // DO NOT add a space between the selectors! It changes the behavior of make-styles.
72
+ ':hover,:focus-within': {
73
+ '::before': tslib_1.__assign({}, react_1.shorthands.borderColor(react_theme_1.tokens.colorTransparentStrokeInteractive)),
74
+ },
75
+ },
76
+ invalid: {
77
+ ':not(:focus-within),:hover:not(:focus-within)': {
78
+ '::before': tslib_1.__assign({}, react_1.shorthands.borderColor(react_theme_1.tokens.colorPaletteRedBorder2)),
79
+ },
80
+ },
81
+ disabled: {
82
+ '::before': tslib_1.__assign(tslib_1.__assign({}, react_1.shorthands.borderColor(react_theme_1.tokens.colorNeutralStrokeDisabled)), { '@media (forced-colors: active)': tslib_1.__assign({}, react_1.shorthands.borderColor('GrayText')) }),
83
+ },
84
+ });
85
+ var useInputStyles = react_1.makeStyles({
86
+ base: tslib_1.__assign({ gridColumnStart: '1', gridColumnEnd: '2', gridRowStart: '1', gridRowEnd: '3', outlineStyle: 'none' }, react_1.shorthands.padding(0)),
87
+ });
88
+ var useButtonStyles = react_1.makeStyles({
89
+ base: tslib_1.__assign(tslib_1.__assign({ display: 'inline-flex', width: '24px', alignItems: 'center', justifyContent: 'center' }, react_1.shorthands.border(0)), { position: 'absolute', outlineStyle: 'none', height: '100%', ':enabled:hover': {
90
+ cursor: 'pointer',
91
+ }, ':active': {
92
+ outlineStyle: 'none',
93
+ }, ':disabled': {
94
+ cursor: 'not-allowed',
95
+ } }),
96
+ incrementButton: tslib_1.__assign({ gridColumnStart: '2', gridColumnEnd: '3', gridRowStart: '1', gridRowEnd: '2' }, react_1.shorthands.borderRadius(0, react_theme_1.tokens.borderRadiusMedium, 0, 0)),
97
+ // Padding values numbers don't align with design specs
98
+ // but visually the padding aligns.
99
+ // The icons are set in a 16x16px square but the artwork is inset from that
100
+ // so these padding values are computed by hand.
101
+ // Additionally the design uses fractional values so these are
102
+ // rounded to the nearest integer.
103
+ incrementButtonSmall: tslib_1.__assign({}, react_1.shorthands.padding('3px', '6px', '0px', '4px')),
104
+ incrementButtonMedium: tslib_1.__assign({}, react_1.shorthands.padding('4px', '5px', '1px', '5px')),
105
+ decrementButton: tslib_1.__assign({ gridColumnStart: '2', gridColumnEnd: '3', gridRowStart: '2', gridRowEnd: '3' }, react_1.shorthands.borderRadius(0, 0, react_theme_1.tokens.borderRadiusMedium, 0)),
106
+ decrementButtonSmall: tslib_1.__assign({}, react_1.shorthands.padding('0px', '6px', '3px', '4px')),
107
+ decrementButtonMedium: tslib_1.__assign({}, react_1.shorthands.padding('1px', '5px', '4px', '5px')),
108
+ outline: {
109
+ backgroundColor: 'transparent',
110
+ color: react_theme_1.tokens.colorNeutralForeground3,
111
+ ':enabled': (_a = {
112
+ ':hover': {
113
+ color: react_theme_1.tokens.colorNeutralForeground3Hover,
114
+ backgroundColor: react_theme_1.tokens.colorSubtleBackgroundHover,
115
+ },
116
+ ':active': {
117
+ color: react_theme_1.tokens.colorNeutralForeground3Pressed,
118
+ backgroundColor: react_theme_1.tokens.colorSubtleBackgroundPressed,
119
+ }
120
+ },
121
+ _a["&." + spinButtonExtraClassNames.buttonActive] = {
122
+ color: react_theme_1.tokens.colorNeutralForeground3Pressed,
123
+ backgroundColor: react_theme_1.tokens.colorSubtleBackgroundPressed,
124
+ },
125
+ _a),
126
+ ':disabled': {
127
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
128
+ },
129
+ },
130
+ underline: {
131
+ backgroundColor: 'transparent',
132
+ color: react_theme_1.tokens.colorNeutralForeground3,
133
+ ':enabled': (_b = {
134
+ ':hover': {
135
+ color: react_theme_1.tokens.colorNeutralForeground3Hover,
136
+ backgroundColor: react_theme_1.tokens.colorSubtleBackgroundHover,
137
+ },
138
+ ':active': {
139
+ color: react_theme_1.tokens.colorNeutralForeground3Pressed,
140
+ backgroundColor: react_theme_1.tokens.colorSubtleBackgroundPressed,
141
+ }
142
+ },
143
+ _b["&." + spinButtonExtraClassNames.buttonActive] = {
144
+ color: react_theme_1.tokens.colorNeutralForeground3Pressed,
145
+ backgroundColor: react_theme_1.tokens.colorSubtleBackgroundPressed,
146
+ },
147
+ _b),
148
+ ':disabled': {
149
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
150
+ },
151
+ },
152
+ 'filled-darker': {
153
+ backgroundColor: 'transparent',
154
+ color: react_theme_1.tokens.colorNeutralForeground3,
155
+ ':enabled': (_c = {
156
+ ':hover': {
157
+ color: react_theme_1.tokens.colorNeutralForeground3Hover,
158
+ backgroundColor: react_theme_1.tokens.colorNeutralBackground3Hover,
159
+ },
160
+ ':active': {
161
+ color: react_theme_1.tokens.colorNeutralForeground3Pressed,
162
+ backgroundColor: react_theme_1.tokens.colorNeutralBackground3Pressed,
163
+ }
164
+ },
165
+ _c["&." + spinButtonExtraClassNames.buttonActive] = {
166
+ color: react_theme_1.tokens.colorNeutralForeground3Pressed,
167
+ backgroundColor: react_theme_1.tokens.colorNeutralBackground3Pressed,
168
+ },
169
+ _c),
170
+ ':disabled': {
171
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
172
+ },
173
+ },
174
+ 'filled-lighter': {
175
+ backgroundColor: 'transparent',
176
+ color: react_theme_1.tokens.colorNeutralForeground3,
177
+ ':enabled': (_d = {
178
+ ':hover': {
179
+ color: react_theme_1.tokens.colorNeutralForeground3Hover,
180
+ backgroundColor: react_theme_1.tokens.colorNeutralBackground1Hover,
181
+ }
182
+ },
183
+ _d[":active,&." + spinButtonExtraClassNames.buttonActive] = {
184
+ color: react_theme_1.tokens.colorNeutralForeground3Pressed,
185
+ backgroundColor: react_theme_1.tokens.colorNeutralBackground1Pressed,
186
+ },
187
+ _d),
188
+ ':disabled': {
189
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
190
+ },
191
+ },
192
+ });
193
+ // Cannot just disable button as they need to remain
194
+ // exposed to ATs like screen readers.
195
+ var useButtonDisabledStyles = react_1.makeStyles({
196
+ base: {
197
+ cursor: 'not-allowed',
198
+ ':hover': {
199
+ cursor: 'not-allowed',
200
+ },
201
+ },
202
+ outline: {
203
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
204
+ ':enabled': (_e = {
205
+ ':hover': {
206
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
207
+ backgroundColor: 'transparent',
208
+ },
209
+ ':active': {
210
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
211
+ backgroundColor: 'transparent',
212
+ }
213
+ },
214
+ _e["&." + spinButtonExtraClassNames.buttonActive] = {
215
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
216
+ backgroundColor: 'transparent',
217
+ },
218
+ _e),
219
+ },
220
+ underline: {
221
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
222
+ ':enabled': (_f = {
223
+ ':hover': {
224
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
225
+ backgroundColor: 'transparent',
226
+ },
227
+ ':active': {
228
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
229
+ backgroundColor: 'transparent',
230
+ }
231
+ },
232
+ _f["&." + spinButtonExtraClassNames.buttonActive] = {
233
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
234
+ backgroundColor: 'transparent',
235
+ },
236
+ _f),
237
+ },
238
+ 'filled-darker': {
239
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
240
+ ':enabled': (_g = {
241
+ ':hover': {
242
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
243
+ backgroundColor: 'transparent',
244
+ },
245
+ ':active': {
246
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
247
+ backgroundColor: 'transparent',
248
+ }
249
+ },
250
+ _g["&." + spinButtonExtraClassNames.buttonActive] = {
251
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
252
+ backgroundColor: 'transparent',
253
+ },
254
+ _g),
255
+ },
256
+ 'filled-lighter': {
257
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
258
+ ':enabled': (_h = {
259
+ ':hover': {
260
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
261
+ backgroundColor: 'transparent',
262
+ },
263
+ ':active': {
264
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
265
+ backgroundColor: 'transparent',
266
+ }
267
+ },
268
+ _h["&." + spinButtonExtraClassNames.buttonActive] = {
269
+ color: react_theme_1.tokens.colorNeutralForegroundDisabled,
270
+ backgroundColor: 'transparent',
271
+ },
272
+ _h),
273
+ },
274
+ });
275
+ /**
276
+ * Apply styling to the SpinButton slots based on the state
277
+ */
278
+ var useSpinButtonStyles_unstable = function (state) {
279
+ var appearance = state.appearance, atBound = state.atBound, spinState = state.spinState, size = state.size;
280
+ var disabled = state.input.disabled;
281
+ var invalid = "" + state.input['aria-invalid'] === 'true';
282
+ var filled = appearance.startsWith('filled');
283
+ var rootStyles = useRootStyles();
284
+ var buttonStyles = useButtonStyles();
285
+ var buttonDisabledStyles = useButtonDisabledStyles();
286
+ var inputStyles = useInputStyles();
287
+ // Grab the root className here so we can be sure to merge is last
288
+ var rootClassName = state.root.className;
289
+ state.root.className = undefined;
290
+ // Reuse react-input's styles without re-using the Input component.
291
+ react_input_1.useInputStyles_unstable({
292
+ size: size,
293
+ appearance: appearance,
294
+ input: state.input,
295
+ root: state.root,
296
+ components: {
297
+ root: 'span',
298
+ input: 'input',
299
+ contentBefore: 'span',
300
+ contentAfter: 'span',
301
+ },
302
+ });
303
+ state.root.className = react_1.mergeClasses(state.root.className, // Get the classes from useInputStyles_unstable
304
+ exports.spinButtonClassNames.root, rootStyles.base, rootStyles[size], appearance === 'outline' && rootStyles.outline, appearance === 'underline' && rootStyles.underline, filled && rootStyles.filled, !disabled && appearance === 'outline' && rootStyles.outlineInteractive, !disabled && appearance === 'underline' && rootStyles.underlineInteractive, !disabled && filled && rootStyles.filledInteractive, !disabled && invalid && rootStyles.invalid, disabled && rootStyles.disabled, rootClassName);
305
+ state.incrementButton.className = react_1.mergeClasses(exports.spinButtonClassNames.incrementButton, spinState === 'up' && "" + spinButtonExtraClassNames.buttonActive, buttonStyles.base, buttonStyles.incrementButton, buttonStyles[appearance], size === 'small' ? buttonStyles.incrementButtonSmall : buttonStyles.incrementButtonMedium, (atBound === 'max' || atBound === 'both') && buttonDisabledStyles.base, (atBound === 'max' || atBound === 'both') && buttonDisabledStyles[appearance], state.incrementButton.className);
306
+ state.decrementButton.className = react_1.mergeClasses(exports.spinButtonClassNames.decrementButton, spinState === 'down' && "" + spinButtonExtraClassNames.buttonActive, buttonStyles.base, buttonStyles.decrementButton, buttonStyles[appearance], size === 'small' ? buttonStyles.decrementButtonSmall : buttonStyles.decrementButtonMedium, (atBound === 'min' || atBound === 'both') && buttonDisabledStyles.base, (atBound === 'min' || atBound === 'both') && buttonDisabledStyles[appearance], state.decrementButton.className);
307
+ state.input.className = react_1.mergeClasses(exports.spinButtonClassNames.input, state.input.className, inputStyles.base);
308
+ return state;
309
+ };
310
+ exports.useSpinButtonStyles_unstable = useSpinButtonStyles_unstable;
311
+ });
312
+ //# sourceMappingURL=useSpinButtonStyles.js.map