@fluentui/react-spinbutton 0.0.0-nightly-20220421-0418.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. package/CHANGELOG.json +173 -0
  2. package/CHANGELOG.md +71 -0
  3. package/LICENSE +15 -0
  4. package/MIGRATION.md +67 -0
  5. package/README.md +37 -0
  6. package/Spec.md +370 -0
  7. package/dist/react-spinbutton.d.ts +192 -0
  8. package/lib/SpinButton.d.ts +1 -0
  9. package/lib/SpinButton.js +2 -0
  10. package/lib/SpinButton.js.map +1 -0
  11. package/lib/components/SpinButton/SpinButton.d.ts +6 -0
  12. package/lib/components/SpinButton/SpinButton.js +15 -0
  13. package/lib/components/SpinButton/SpinButton.js.map +1 -0
  14. package/lib/components/SpinButton/SpinButton.strings.d.ts +2 -0
  15. package/lib/components/SpinButton/SpinButton.strings.js +5 -0
  16. package/lib/components/SpinButton/SpinButton.strings.js.map +1 -0
  17. package/lib/components/SpinButton/SpinButton.types.d.ts +149 -0
  18. package/lib/components/SpinButton/SpinButton.types.js +2 -0
  19. package/lib/components/SpinButton/SpinButton.types.js.map +1 -0
  20. package/lib/components/SpinButton/index.d.ts +5 -0
  21. package/lib/components/SpinButton/index.js +6 -0
  22. package/lib/components/SpinButton/index.js.map +1 -0
  23. package/lib/components/SpinButton/renderSpinButton.d.ts +5 -0
  24. package/lib/components/SpinButton/renderSpinButton.js +37 -0
  25. package/lib/components/SpinButton/renderSpinButton.js.map +1 -0
  26. package/lib/components/SpinButton/useSpinButton.d.ts +12 -0
  27. package/lib/components/SpinButton/useSpinButton.js +263 -0
  28. package/lib/components/SpinButton/useSpinButton.js.map +1 -0
  29. package/lib/components/SpinButton/useSpinButtonStyles.d.ts +7 -0
  30. package/lib/components/SpinButton/useSpinButtonStyles.js +367 -0
  31. package/lib/components/SpinButton/useSpinButtonStyles.js.map +1 -0
  32. package/lib/index.d.ts +2 -0
  33. package/lib/index.js +2 -0
  34. package/lib/index.js.map +1 -0
  35. package/lib/tsdoc-metadata.json +11 -0
  36. package/lib/utils/clamp.d.ts +1 -0
  37. package/lib/utils/clamp.js +31 -0
  38. package/lib/utils/clamp.js.map +1 -0
  39. package/lib/utils/getBound.d.ts +2 -0
  40. package/lib/utils/getBound.js +14 -0
  41. package/lib/utils/getBound.js.map +1 -0
  42. package/lib/utils/index.d.ts +3 -0
  43. package/lib/utils/index.js +4 -0
  44. package/lib/utils/index.js.map +1 -0
  45. package/lib/utils/precision.d.ts +14 -0
  46. package/lib/utils/precision.js +41 -0
  47. package/lib/utils/precision.js.map +1 -0
  48. package/lib-commonjs/SpinButton.d.ts +1 -0
  49. package/lib-commonjs/SpinButton.js +10 -0
  50. package/lib-commonjs/SpinButton.js.map +1 -0
  51. package/lib-commonjs/components/SpinButton/SpinButton.d.ts +6 -0
  52. package/lib-commonjs/components/SpinButton/SpinButton.js +26 -0
  53. package/lib-commonjs/components/SpinButton/SpinButton.js.map +1 -0
  54. package/lib-commonjs/components/SpinButton/SpinButton.strings.d.ts +2 -0
  55. package/lib-commonjs/components/SpinButton/SpinButton.strings.js +11 -0
  56. package/lib-commonjs/components/SpinButton/SpinButton.strings.js.map +1 -0
  57. package/lib-commonjs/components/SpinButton/SpinButton.types.d.ts +149 -0
  58. package/lib-commonjs/components/SpinButton/SpinButton.types.js +6 -0
  59. package/lib-commonjs/components/SpinButton/SpinButton.types.js.map +1 -0
  60. package/lib-commonjs/components/SpinButton/index.d.ts +5 -0
  61. package/lib-commonjs/components/SpinButton/index.js +18 -0
  62. package/lib-commonjs/components/SpinButton/index.js.map +1 -0
  63. package/lib-commonjs/components/SpinButton/renderSpinButton.d.ts +5 -0
  64. package/lib-commonjs/components/SpinButton/renderSpinButton.js +48 -0
  65. package/lib-commonjs/components/SpinButton/renderSpinButton.js.map +1 -0
  66. package/lib-commonjs/components/SpinButton/useSpinButton.d.ts +12 -0
  67. package/lib-commonjs/components/SpinButton/useSpinButton.js +278 -0
  68. package/lib-commonjs/components/SpinButton/useSpinButton.js.map +1 -0
  69. package/lib-commonjs/components/SpinButton/useSpinButtonStyles.d.ts +7 -0
  70. package/lib-commonjs/components/SpinButton/useSpinButtonStyles.js +379 -0
  71. package/lib-commonjs/components/SpinButton/useSpinButtonStyles.js.map +1 -0
  72. package/lib-commonjs/index.d.ts +2 -0
  73. package/lib-commonjs/index.js +40 -0
  74. package/lib-commonjs/index.js.map +1 -0
  75. package/lib-commonjs/utils/clamp.d.ts +1 -0
  76. package/lib-commonjs/utils/clamp.js +40 -0
  77. package/lib-commonjs/utils/clamp.js.map +1 -0
  78. package/lib-commonjs/utils/getBound.d.ts +2 -0
  79. package/lib-commonjs/utils/getBound.js +23 -0
  80. package/lib-commonjs/utils/getBound.js.map +1 -0
  81. package/lib-commonjs/utils/index.d.ts +3 -0
  82. package/lib-commonjs/utils/index.js +14 -0
  83. package/lib-commonjs/utils/index.js.map +1 -0
  84. package/lib-commonjs/utils/precision.d.ts +14 -0
  85. package/lib-commonjs/utils/precision.js +52 -0
  86. package/lib-commonjs/utils/precision.js.map +1 -0
  87. package/package.json +64 -0
  88. package/spec-assets/spec-spinbutton-anatomy-alt-optional.png +0 -0
  89. package/spec-assets/spec-spinbutton-anatomy.png +0 -0
  90. package/spec-assets/spec-spinbutton-rtl.png +0 -0
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.SpinButton = void 0;
7
+
8
+ const React = /*#__PURE__*/require("react");
9
+
10
+ const useSpinButton_1 = /*#__PURE__*/require("./useSpinButton");
11
+
12
+ const renderSpinButton_1 = /*#__PURE__*/require("./renderSpinButton");
13
+
14
+ const useSpinButtonStyles_1 = /*#__PURE__*/require("./useSpinButtonStyles");
15
+ /**
16
+ * A SpinButton allows someone to incrementally adjust a value in small steps.
17
+ */
18
+
19
+
20
+ exports.SpinButton = /*#__PURE__*/React.forwardRef((props, ref) => {
21
+ const state = useSpinButton_1.useSpinButton_unstable(props, ref);
22
+ useSpinButtonStyles_1.useSpinButtonStyles_unstable(state);
23
+ return renderSpinButton_1.renderSpinButton_unstable(state);
24
+ });
25
+ exports.SpinButton.displayName = 'SpinButton';
26
+ //# sourceMappingURL=SpinButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["components/SpinButton/SpinButton.tsx"],"names":[],"mappings":";;;;;;;AAAA,MAAA,KAAA,gBAAA,OAAA,CAAA,OAAA,CAAA;;AACA,MAAA,eAAA,gBAAA,OAAA,CAAA,iBAAA,CAAA;;AACA,MAAA,kBAAA,gBAAA,OAAA,CAAA,oBAAA,CAAA;;AACA,MAAA,qBAAA,gBAAA,OAAA,CAAA,uBAAA,CAAA;AAIA;;AAEG;;;AACU,OAAA,CAAA,UAAA,gBAAmD,KAAK,CAAC,UAAN,CAAiB,CAAC,KAAD,EAAQ,GAAR,KAAe;AAC9F,QAAM,KAAK,GAAG,eAAA,CAAA,sBAAA,CAAuB,KAAvB,EAA8B,GAA9B,CAAd;AAEA,EAAA,qBAAA,CAAA,4BAAA,CAA6B,KAA7B;AACA,SAAO,kBAAA,CAAA,yBAAA,CAA0B,KAA1B,CAAP;AACD,CAL+D,CAAnD;AAOb,OAAA,CAAA,UAAA,CAAW,WAAX,GAAyB,YAAzB","sourcesContent":["import * as React from 'react';\nimport { useSpinButton_unstable } from './useSpinButton';\nimport { renderSpinButton_unstable } from './renderSpinButton';\nimport { useSpinButtonStyles_unstable } from './useSpinButtonStyles';\nimport type { SpinButtonProps } from './SpinButton.types';\nimport type { ForwardRefComponent } from '@fluentui/react-utilities';\n\n/**\n * A SpinButton allows someone to incrementally adjust a value in small steps.\n */\nexport const SpinButton: ForwardRefComponent<SpinButtonProps> = React.forwardRef((props, ref) => {\n const state = useSpinButton_unstable(props, ref);\n\n useSpinButtonStyles_unstable(state);\n return renderSpinButton_unstable(state);\n});\n\nSpinButton.displayName = 'SpinButton';\n"],"sourceRoot":"../src/"}
@@ -0,0 +1,2 @@
1
+ import type { SpinButtonStrings } from './SpinButton.types';
2
+ export declare const spinButtonDefaultStrings: SpinButtonStrings;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.spinButtonDefaultStrings = void 0;
7
+ exports.spinButtonDefaultStrings = {
8
+ incrementButtonLabel: 'Increment by {step}',
9
+ decrementButtonLabel: 'Decrement by {step}'
10
+ };
11
+ //# sourceMappingURL=SpinButton.strings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["components/SpinButton/SpinButton.strings.ts"],"names":[],"mappings":";;;;;;AAEa,OAAA,CAAA,wBAAA,GAA8C;AACzD,EAAA,oBAAoB,EAAE,qBADmC;AAEzD,EAAA,oBAAoB,EAAE;AAFmC,CAA9C","sourcesContent":["import type { SpinButtonStrings } from './SpinButton.types';\n\nexport const spinButtonDefaultStrings: SpinButtonStrings = {\n incrementButtonLabel: 'Increment by {step}',\n decrementButtonLabel: 'Decrement by {step}',\n};\n"],"sourceRoot":"../src/"}
@@ -0,0 +1,149 @@
1
+ import type { ComponentProps, ComponentState, Slot } from '@fluentui/react-utilities';
2
+ import * as React from 'react';
3
+ export declare type SpinButtonSlots = {
4
+ /**
5
+ * The root element of SpinButton is a container `<div>`.
6
+ * The root slot receives the `className` and `style` specified on the `<SpinButton>`.
7
+ * All other native props are applied to the primary slot: `input`.
8
+ */
9
+ root: NonNullable<Slot<'span'>>;
10
+ /**
11
+ * Input that displays the current value and accepts direct input from the user.
12
+ * Displayed value is formatted.
13
+ *
14
+ * This is the primary slot.
15
+ */
16
+ input: NonNullable<Slot<'input'>>;
17
+ /**
18
+ * Renders the increment control.
19
+ */
20
+ incrementButton: NonNullable<Slot<'button'>>;
21
+ /**
22
+ * Renders the decrement control.
23
+ */
24
+ decrementButton: NonNullable<Slot<'button'>>;
25
+ };
26
+ export declare type SpinButtonCommons = {
27
+ /**
28
+ * Initial value of the control (assumed to be valid). Updates to this prop will not be respected.
29
+ *
30
+ * Use this if you intend for the SpinButton to be an uncontrolled component which maintains its
31
+ * own value. For a controlled component, use `value` instead. (Mutually exclusive with `value`.)
32
+ */
33
+ defaultValue: number;
34
+ /**
35
+ * Current value of the control (assumed to be valid).
36
+ *
37
+ * Only provide this if the SpinButton is a controlled component where you are maintaining its
38
+ * current state and passing updates based on change events; otherwise, use the `defaultValue`
39
+ * property. (Mutually exclusive with `defaultValue`.)
40
+ */
41
+ value: number;
42
+ /**
43
+ * String representation of `value`.
44
+ *
45
+ * Use this when displaying the value to users as something other than a plain number.
46
+ * For example, when displaying currency values this might be "$1.00" when value is `1`.
47
+ *
48
+ * Only provide this if the SpinButton is a controlled component where you are maintaining its
49
+ * current state and passing updates based on change events. When SpinButton is used as an
50
+ * uncontrolled component this prop is ignored.
51
+ */
52
+ displayValue: string;
53
+ /**
54
+ * Min value of the control. If not provided, the control has no minimum value.
55
+ */
56
+ min: number;
57
+ /**
58
+ * Max value of the control. If not provided, the control has no maximum value.
59
+ */
60
+ max: number;
61
+ /**
62
+ * Difference between two adjacent values of the control.
63
+ * This value is used to calculate the precision of the input if no `precision` is given.
64
+ * The precision calculated this way will always be greater than or equal 0.
65
+ * @default 1
66
+ */
67
+ step: number;
68
+ /**
69
+ * Large difference between two values. This should be greater than `step` and is used
70
+ * when users hit the Page Up or Page Down keys.
71
+ * @default 1
72
+ */
73
+ stepPage: number;
74
+ /**
75
+ * Callback for when the committed value changes.
76
+ * - User presses the up/down buttons (on single press or every spin)
77
+ * - User presses the up/down arrow keys (on single press or every spin)
78
+ * - User *commits* edits to the input text by focusing away (blurring) or pressing enter.
79
+ * Note that this is NOT called for every key press while the user is editing.
80
+ */
81
+ onChange: (event: SpinButtonChangeEvent, data: SpinButtonOnChangeData) => void;
82
+ /**
83
+ * How many decimal places the value should be rounded to.
84
+ *
85
+ * The default is calculated based on the precision of `step`: i.e. if step = 1, precision = 0.
86
+ * step = 0.0089, precision = 4. step = 300, precision = 2. step = 23.00, precision = 2.
87
+ */
88
+ precision: number;
89
+ /**
90
+ * Controls the colors and borders of the input.
91
+ * @default 'outline'
92
+ */
93
+ appearance: 'outline' | 'underline' | 'filledDarker' | 'filledLighter';
94
+ /**
95
+ * Size of the input.
96
+ * @default 'medium'
97
+ */
98
+ size: 'small' | 'medium';
99
+ /**
100
+ * Controls which input types update the value.
101
+ *
102
+ * - 'all': both the spinner buttons and input field are enabled.
103
+ * - 'spinners-only': only the spinner buttons are enabled.
104
+ * @default all
105
+ */
106
+ inputType: 'all' | 'spinners-only';
107
+ /**
108
+ * Strings for localizing text in the control.
109
+ */
110
+ strings?: SpinButtonStrings;
111
+ };
112
+ /**
113
+ * SpinButton Props
114
+ */
115
+ export declare type SpinButtonProps = Omit<ComponentProps<Partial<SpinButtonSlots>, 'input'>, 'onChange' | 'size'> & Partial<SpinButtonCommons>;
116
+ /**
117
+ * State used in rendering SpinButton
118
+ */
119
+ export declare type SpinButtonState = ComponentState<SpinButtonSlots> & Partial<SpinButtonCommons> & Pick<SpinButtonCommons, 'appearance' | 'size'> & {
120
+ /**
121
+ * State used to track which direction, if any, SpinButton is currently spinning.
122
+ * @default 'rest'
123
+ */
124
+ spinState: SpinButtonSpinState;
125
+ /**
126
+ * State used to track if the value is at the range bounds of [min-max].
127
+ * @default 'none'
128
+ */
129
+ atBound: SpinButtonBounds;
130
+ };
131
+ export declare type SpinButtonChangeEvent = React.MouseEvent<HTMLButtonElement> | React.ChangeEvent<HTMLElement> | React.FocusEvent<HTMLInputElement> | React.KeyboardEvent<HTMLInputElement>;
132
+ export declare type SpinButtonOnChangeData = {
133
+ value?: number;
134
+ displayValue?: string;
135
+ };
136
+ export declare type SpinButtonSpinState = 'rest' | 'up' | 'down';
137
+ export declare type SpinButtonBounds = 'none' | 'min' | 'max' | 'both';
138
+ export declare type SpinButtonStrings = {
139
+ /**
140
+ * Label applied to the increment button.
141
+ * Can include the token "\{step\}" which will be replaced with the value of the `step` prop.
142
+ */
143
+ incrementButtonLabel: string;
144
+ /**
145
+ * Label applied to the decrement button.
146
+ * Can include the token "\{step\}" which will be replaced with the value of the `step` prop.
147
+ */
148
+ decrementButtonLabel: string;
149
+ };
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ //# sourceMappingURL=SpinButton.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","sourceRoot":"../src/"}
@@ -0,0 +1,5 @@
1
+ export * from './SpinButton';
2
+ export * from './SpinButton.types';
3
+ export * from './renderSpinButton';
4
+ export * from './useSpinButton';
5
+ export * from './useSpinButtonStyles';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+
7
+ const tslib_1 = /*#__PURE__*/require("tslib");
8
+
9
+ tslib_1.__exportStar(require("./SpinButton"), exports);
10
+
11
+ tslib_1.__exportStar(require("./SpinButton.types"), exports);
12
+
13
+ tslib_1.__exportStar(require("./renderSpinButton"), exports);
14
+
15
+ tslib_1.__exportStar(require("./useSpinButton"), exports);
16
+
17
+ tslib_1.__exportStar(require("./useSpinButtonStyles"), exports);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["components/SpinButton/index.ts"],"names":[],"mappings":";;;;;;;;AAAA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,cAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,oBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,oBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,iBAAA,CAAA,EAAA,OAAA;;AACA,OAAA,CAAA,YAAA,CAAA,OAAA,CAAA,uBAAA,CAAA,EAAA,OAAA","sourcesContent":["export * from './SpinButton';\nexport * from './SpinButton.types';\nexport * from './renderSpinButton';\nexport * from './useSpinButton';\nexport * from './useSpinButtonStyles';\n"],"sourceRoot":"../src/"}
@@ -0,0 +1,5 @@
1
+ import type { SpinButtonState } from './SpinButton.types';
2
+ /**
3
+ * Render the final JSX of SpinButton
4
+ */
5
+ export declare const renderSpinButton_unstable: (state: SpinButtonState) => JSX.Element;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.renderSpinButton_unstable = void 0;
7
+
8
+ const React = /*#__PURE__*/require("react");
9
+
10
+ const react_utilities_1 = /*#__PURE__*/require("@fluentui/react-utilities");
11
+ /**
12
+ * Render the final JSX of SpinButton
13
+ */
14
+
15
+
16
+ const renderSpinButton_unstable = state => {
17
+ // Leaving this here for now.
18
+ // This is the approach using react-input's Input component.
19
+ // It has some Typescript problems and feels hacky.
20
+ // const { slots, slotProps } = getSlots<SpinButtonSlots>(state);
21
+ // const { contentAfter, ...otherInputSlotProps } = slotProps.input as SpinButtonSlots['input'];
22
+ // const inputContentAfter = {
23
+ // ...contentAfter,
24
+ // children: (
25
+ // <>
26
+ // <slots.incrementButton {...slotProps.incrementButton} />
27
+ // <slots.decrementButton {...slotProps.decrementButton} />
28
+ // </>
29
+ // ),
30
+ // };
31
+ // return (
32
+ // <slots.root {...slotProps.root}>
33
+ // <slots.input {...otherInputSlotProps} contentAfter={inputContentAfter}/>
34
+ // </slots.root>
35
+ // );
36
+ const {
37
+ slots,
38
+ slotProps
39
+ } = react_utilities_1.getSlots(state);
40
+ return React.createElement(slots.root, { ...slotProps.root
41
+ }, React.createElement(slots.input, { ...slotProps.input
42
+ }), React.createElement(slots.incrementButton, { ...slotProps.incrementButton
43
+ }), React.createElement(slots.decrementButton, { ...slotProps.decrementButton
44
+ }));
45
+ };
46
+
47
+ exports.renderSpinButton_unstable = renderSpinButton_unstable;
48
+ //# sourceMappingURL=renderSpinButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["components/SpinButton/renderSpinButton.tsx"],"names":[],"mappings":";;;;;;;AAAA,MAAA,KAAA,gBAAA,OAAA,CAAA,OAAA,CAAA;;AACA,MAAA,iBAAA,gBAAA,OAAA,CAAA,2BAAA,CAAA;AAGA;;AAEG;;;AACI,MAAM,yBAAyB,GAAI,KAAD,IAA2B;AAClE;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AAEA,QAAM;AAAE,IAAA,KAAF;AAAS,IAAA;AAAT,MAAuB,iBAAA,CAAA,QAAA,CAA0B,KAA1B,CAA7B;AAEA,SACE,KAAA,CAAA,aAAA,CAAC,KAAK,CAAC,IAAP,EAAW,EAAA,GAAK,SAAS,CAAC;AAAf,GAAX,EACE,KAAA,CAAA,aAAA,CAAC,KAAK,CAAC,KAAP,EAAY,EAAA,GAAK,SAAS,CAAC;AAAf,GAAZ,CADF,EAEE,KAAA,CAAA,aAAA,CAAC,KAAK,CAAC,eAAP,EAAsB,EAAA,GAAK,SAAS,CAAC;AAAf,GAAtB,CAFF,EAGE,KAAA,CAAA,aAAA,CAAC,KAAK,CAAC,eAAP,EAAsB,EAAA,GAAK,SAAS,CAAC;AAAf,GAAtB,CAHF,CADF;AAOD,CAhCM;;AAAM,OAAA,CAAA,yBAAA,GAAyB,yBAAzB","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"],"sourceRoot":"../src/"}
@@ -0,0 +1,12 @@
1
+ import * as React from 'react';
2
+ import { SpinButtonProps, SpinButtonState } from './SpinButton.types';
3
+ /**
4
+ * Create the state required to render SpinButton.
5
+ *
6
+ * The returned state can be modified with hooks such as useSpinButtonStyles_unstable,
7
+ * before being passed to renderSpinButton_unstable.
8
+ *
9
+ * @param props - props from this instance of SpinButton
10
+ * @param ref - reference to root HTMLElement of SpinButton
11
+ */
12
+ export declare const useSpinButton_unstable: (props: SpinButtonProps, ref: React.Ref<HTMLInputElement>) => SpinButtonState;
@@ -0,0 +1,278 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useSpinButton_unstable = void 0;
7
+
8
+ const React = /*#__PURE__*/require("react");
9
+
10
+ const react_utilities_1 = /*#__PURE__*/require("@fluentui/react-utilities");
11
+
12
+ const Keys = /*#__PURE__*/require("@fluentui/keyboard-keys");
13
+
14
+ const SpinButton_strings_1 = /*#__PURE__*/require("./SpinButton.strings");
15
+
16
+ const index_1 = /*#__PURE__*/require("../../utils/index");
17
+
18
+ const react_icons_1 = /*#__PURE__*/require("@fluentui/react-icons");
19
+
20
+ const DEFAULT_SPIN_DELAY_MS = 150;
21
+ const MIN_SPIN_DELAY_MS = 80;
22
+ const MAX_SPIN_TIME_MS = 1000; // This is here to give an ease the mouse held down case.
23
+ // Exact easing it to be defined. Once it is we'll likely
24
+ // pull this out into a util function in the SpinButton package.
25
+
26
+ const lerp = (start, end, percent) => start + (end - start) * percent;
27
+ /**
28
+ * Create the state required to render SpinButton.
29
+ *
30
+ * The returned state can be modified with hooks such as useSpinButtonStyles_unstable,
31
+ * before being passed to renderSpinButton_unstable.
32
+ *
33
+ * @param props - props from this instance of SpinButton
34
+ * @param ref - reference to root HTMLElement of SpinButton
35
+ */
36
+
37
+
38
+ const useSpinButton_unstable = (props, ref) => {
39
+ const nativeProps = react_utilities_1.getPartitionedNativeProps({
40
+ props,
41
+ primarySlotTagName: 'input',
42
+ excludedPropNames: ['onChange', 'size', 'min', 'max']
43
+ });
44
+ const {
45
+ value,
46
+ displayValue,
47
+ defaultValue,
48
+ min,
49
+ max,
50
+ step = 1,
51
+ stepPage = 1,
52
+ precision: precisionFromProps,
53
+ onChange,
54
+ size = 'medium',
55
+ appearance = 'outline',
56
+ root,
57
+ input,
58
+ incrementButton,
59
+ decrementButton,
60
+ inputType = 'all',
61
+ strings = SpinButton_strings_1.spinButtonDefaultStrings
62
+ } = props;
63
+ const precision = React.useMemo(() => {
64
+ return precisionFromProps !== null && precisionFromProps !== void 0 ? precisionFromProps : Math.max(index_1.calculatePrecision(step), 0);
65
+ }, [precisionFromProps, step]);
66
+ const [currentValue, setCurrentValue] = react_utilities_1.useControllableState({
67
+ state: value,
68
+ defaultState: defaultValue,
69
+ initialState: 0
70
+ });
71
+ const [textValue, setTextValue] = React.useState(value !== undefined && displayValue !== undefined ? displayValue : String(currentValue));
72
+ const [spinState, setSpinState] = React.useState('rest');
73
+ const [atBound, setAtBound] = React.useState('none');
74
+ const internalState = React.useRef({
75
+ value: currentValue,
76
+ spinState,
77
+ spinTime: 0,
78
+ spinDelay: DEFAULT_SPIN_DELAY_MS
79
+ });
80
+ const state = {
81
+ size,
82
+ appearance,
83
+ spinState,
84
+ atBound,
85
+ components: {
86
+ root: 'span',
87
+ input: 'input',
88
+ incrementButton: 'button',
89
+ decrementButton: 'button'
90
+ },
91
+ root: react_utilities_1.resolveShorthand(root, {
92
+ required: true,
93
+ defaultProps: nativeProps.root
94
+ }),
95
+ input: react_utilities_1.resolveShorthand(input, {
96
+ required: true,
97
+ defaultProps: {
98
+ ref,
99
+ autoComplete: 'off',
100
+ role: 'spinbutton',
101
+ appearance: appearance,
102
+ type: 'text',
103
+ ...nativeProps.primary
104
+ }
105
+ }),
106
+ incrementButton: react_utilities_1.resolveShorthand(incrementButton, {
107
+ required: true,
108
+ defaultProps: {
109
+ tabIndex: -1,
110
+ children: React.createElement(react_icons_1.ChevronUp16Regular, null),
111
+ disabled: nativeProps.primary.disabled,
112
+ 'aria-label': strings.incrementButtonLabel.replace('{step}', step.toString())
113
+ }
114
+ }),
115
+ decrementButton: react_utilities_1.resolveShorthand(decrementButton, {
116
+ required: true,
117
+ defaultProps: {
118
+ tabIndex: -1,
119
+ children: React.createElement(react_icons_1.ChevronDown16Regular, null),
120
+ disabled: nativeProps.primary.disabled,
121
+ 'aria-label': strings.decrementButtonLabel.replace('{step}', step.toString())
122
+ }
123
+ })
124
+ };
125
+ const [setStepTimeout, clearStepTimeout] = react_utilities_1.useTimeout();
126
+ React.useEffect(() => {
127
+ let newTextValue;
128
+
129
+ if (value !== undefined) {
130
+ const roundedValue = index_1.precisionRound(value, precision);
131
+ newTextValue = displayValue !== null && displayValue !== void 0 ? displayValue : String(roundedValue);
132
+ internalState.current.value = roundedValue;
133
+ setAtBound(index_1.getBound(roundedValue, min, max));
134
+ } else {
135
+ newTextValue = String(index_1.precisionRound(currentValue, precision));
136
+ internalState.current.value = currentValue;
137
+ }
138
+
139
+ setTextValue(newTextValue);
140
+ }, [value, displayValue, currentValue, precision, setAtBound, min, max]);
141
+
142
+ const handleInputChange = e => {
143
+ if (inputType === 'spinners-only') {
144
+ return;
145
+ }
146
+
147
+ if (!internalState.current.previousTextValue) {
148
+ internalState.current.previousTextValue = textValue;
149
+ }
150
+
151
+ const newValue = e.target.value;
152
+ setTextValue(newValue);
153
+ };
154
+
155
+ const stepValue = (e, direction) => {
156
+ const dir = direction === 'up' || direction === 'upPage' ? 1 : -1;
157
+ const stepSize = direction === 'upPage' || direction === 'downPage' ? stepPage : step;
158
+ const val = internalState.current.value;
159
+ let newValue = val + stepSize * dir;
160
+
161
+ if (!Number.isNaN(newValue)) {
162
+ newValue = index_1.clampWhenInRange(val, newValue, min, max);
163
+ }
164
+
165
+ commit(e, newValue);
166
+
167
+ if (internalState.current.spinState !== 'rest') {
168
+ setStepTimeout(() => {
169
+ // Ease the step speed a bit
170
+ internalState.current.spinTime += internalState.current.spinDelay;
171
+ internalState.current.spinDelay = lerp(DEFAULT_SPIN_DELAY_MS, MIN_SPIN_DELAY_MS, internalState.current.spinTime / MAX_SPIN_TIME_MS);
172
+ stepValue(e, direction);
173
+ }, internalState.current.spinDelay);
174
+ }
175
+ };
176
+
177
+ const handleIncrementMouseDown = e => {
178
+ internalState.current.spinState = 'up';
179
+ stepValue(e, 'up');
180
+ };
181
+
182
+ const handleDecrementMouseDown = e => {
183
+ internalState.current.spinState = 'down';
184
+ stepValue(e, 'down');
185
+ };
186
+
187
+ const handleStepMouseUpOrLeave = e => {
188
+ clearStepTimeout();
189
+ internalState.current.spinState = 'rest';
190
+ internalState.current.spinDelay = DEFAULT_SPIN_DELAY_MS;
191
+ internalState.current.spinTime = 0;
192
+ };
193
+
194
+ const handleBlur = e => {
195
+ commit(e, currentValue, textValue);
196
+ internalState.current.previousTextValue = undefined;
197
+ };
198
+
199
+ const handleKeyDown = e => {
200
+ if (e.key === Keys.ArrowUp) {
201
+ stepValue(e, 'up');
202
+ setSpinState('up');
203
+ } else if (e.key === Keys.ArrowDown) {
204
+ stepValue(e, 'down');
205
+ setSpinState('down');
206
+ } else if (e.key === Keys.PageUp) {
207
+ e.preventDefault();
208
+ stepValue(e, 'upPage');
209
+ setSpinState('up');
210
+ } else if (e.key === Keys.PageDown) {
211
+ e.preventDefault();
212
+ stepValue(e, 'downPage');
213
+ setSpinState('down');
214
+ } else if (!e.shiftKey && e.key === Keys.Home && min !== undefined) {
215
+ commit(e, min);
216
+ setSpinState('down');
217
+ } else if (!e.shiftKey && e.key === Keys.End && max !== undefined) {
218
+ commit(e, max);
219
+ setSpinState('up');
220
+ } else if (e.key === Keys.Enter) {
221
+ commit(e, currentValue, textValue);
222
+ setSpinState('rest');
223
+ } else if (e.key === Keys.Escape) {
224
+ if (internalState.current.previousTextValue) {
225
+ setTextValue(internalState.current.previousTextValue);
226
+ internalState.current.previousTextValue = undefined;
227
+ }
228
+
229
+ setSpinState('rest');
230
+ } else {
231
+ setSpinState('rest');
232
+ }
233
+ };
234
+
235
+ const handleKeyUp = e => {
236
+ setSpinState('rest');
237
+ };
238
+
239
+ const commit = (e, newValue, newDisplayValue) => {
240
+ const valueChanged = newValue !== undefined && currentValue !== newValue;
241
+ const displayValueChanged = newDisplayValue !== undefined && internalState.current.previousTextValue !== undefined && internalState.current.previousTextValue !== newDisplayValue;
242
+ let roundedValue;
243
+
244
+ if (valueChanged) {
245
+ roundedValue = index_1.precisionRound(newValue, precision);
246
+ setCurrentValue(roundedValue);
247
+ internalState.current.value = roundedValue;
248
+ setAtBound(index_1.getBound(roundedValue, min, max));
249
+ }
250
+
251
+ if (valueChanged || displayValueChanged) {
252
+ onChange === null || onChange === void 0 ? void 0 : onChange(e, {
253
+ value: roundedValue,
254
+ displayValue: newDisplayValue
255
+ });
256
+ }
257
+ };
258
+
259
+ state.input.value = textValue;
260
+ state.input['aria-valuemin'] = min;
261
+ state.input['aria-valuemax'] = max;
262
+ state.input['aria-valuenow'] = currentValue;
263
+ state.input['aria-valuetext'] = value !== undefined && displayValue || undefined;
264
+ state.input.onChange = react_utilities_1.useMergedEventCallbacks(state.input.onChange, handleInputChange);
265
+ state.input.onBlur = react_utilities_1.useMergedEventCallbacks(state.input.onBlur, handleBlur);
266
+ state.input.onKeyDown = react_utilities_1.useMergedEventCallbacks(state.input.onKeyDown, handleKeyDown);
267
+ state.input.onKeyUp = react_utilities_1.useMergedEventCallbacks(state.input.onKeyUp, handleKeyUp);
268
+ state.incrementButton.onMouseDown = react_utilities_1.useMergedEventCallbacks(handleIncrementMouseDown, state.incrementButton.onMouseDown);
269
+ state.incrementButton.onMouseUp = react_utilities_1.useMergedEventCallbacks(state.incrementButton.onMouseUp, handleStepMouseUpOrLeave);
270
+ state.incrementButton.onMouseLeave = react_utilities_1.useMergedEventCallbacks(state.incrementButton.onMouseLeave, handleStepMouseUpOrLeave);
271
+ state.decrementButton.onMouseDown = react_utilities_1.useMergedEventCallbacks(handleDecrementMouseDown, state.decrementButton.onMouseDown);
272
+ state.decrementButton.onMouseUp = react_utilities_1.useMergedEventCallbacks(state.decrementButton.onMouseUp, handleStepMouseUpOrLeave);
273
+ state.decrementButton.onMouseLeave = react_utilities_1.useMergedEventCallbacks(state.decrementButton.onMouseLeave, handleStepMouseUpOrLeave);
274
+ return state;
275
+ };
276
+
277
+ exports.useSpinButton_unstable = useSpinButton_unstable;
278
+ //# sourceMappingURL=useSpinButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["components/SpinButton/useSpinButton.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react';\nimport {\n getPartitionedNativeProps,\n resolveShorthand,\n useControllableState,\n useMergedEventCallbacks,\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 { spinButtonDefaultStrings } from './SpinButton.strings';\nimport { calculatePrecision, precisionRound, getBound, clampWhenInRange } from '../../utils/index';\nimport { ChevronUp16Regular, ChevronDown16Regular } from '@fluentui/react-icons';\n\ntype InternalState = {\n value: number;\n spinState: SpinButtonSpinState;\n spinTime: number;\n spinDelay: number;\n previousTextValue?: string;\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: ['onChange', 'size', 'min', 'max'],\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 inputType = 'all',\n strings = spinButtonDefaultStrings,\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 const [textValue, setTextValue] = React.useState(\n value !== undefined && displayValue !== undefined ? displayValue : String(currentValue),\n );\n const [spinState, setSpinState] = React.useState<SpinButtonSpinState>('rest');\n const [atBound, setAtBound] = React.useState<SpinButtonBounds>('none');\n\n const internalState = React.useRef<InternalState>({\n value: currentValue,\n spinState,\n spinTime: 0,\n spinDelay: DEFAULT_SPIN_DELAY_MS,\n });\n\n const state: SpinButtonState = {\n size,\n appearance,\n spinState,\n 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: 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': strings.incrementButtonLabel.replace('{step}', step.toString()),\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': strings.decrementButtonLabel.replace('{step}', step.toString()),\n },\n }),\n };\n\n const [setStepTimeout, clearStepTimeout] = useTimeout();\n\n React.useEffect(() => {\n let newTextValue;\n if (value !== undefined) {\n const roundedValue = precisionRound(value, precision);\n newTextValue = displayValue ?? String(roundedValue);\n internalState.current.value = roundedValue;\n setAtBound(getBound(roundedValue, min, max));\n } else {\n newTextValue = String(precisionRound(currentValue, precision));\n internalState.current.value = currentValue;\n }\n setTextValue(newTextValue);\n }, [value, displayValue, currentValue, precision, setAtBound, min, max]);\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n if (inputType === 'spinners-only') {\n return;\n }\n\n if (!internalState.current.previousTextValue) {\n internalState.current.previousTextValue = textValue;\n }\n\n const newValue = e.target.value;\n setTextValue(newValue);\n };\n\n const stepValue = (e: SpinButtonChangeEvent, direction: 'up' | 'down' | 'upPage' | 'downPage') => {\n const dir = direction === 'up' || direction === 'upPage' ? 1 : -1;\n const stepSize = direction === 'upPage' || direction === 'downPage' ? stepPage : step;\n const val = internalState.current.value;\n\n let newValue = val + stepSize * dir;\n if (!Number.isNaN(newValue)) {\n newValue = clampWhenInRange(val, 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 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 if (e.key === Keys.ArrowUp) {\n stepValue(e, 'up');\n setSpinState('up');\n } else if (e.key === Keys.ArrowDown) {\n stepValue(e, 'down');\n setSpinState('down');\n } else if (e.key === Keys.PageUp) {\n e.preventDefault();\n stepValue(e, 'upPage');\n setSpinState('up');\n } else if (e.key === Keys.PageDown) {\n e.preventDefault();\n stepValue(e, 'downPage');\n setSpinState('down');\n } else if (!e.shiftKey && e.key === Keys.Home && min !== undefined) {\n commit(e, min);\n setSpinState('down');\n } else if (!e.shiftKey && e.key === Keys.End && max !== undefined) {\n commit(e, max);\n setSpinState('up');\n } else if (e.key === Keys.Enter) {\n commit(e, currentValue, textValue);\n setSpinState('rest');\n } else if (e.key === Keys.Escape) {\n if (internalState.current.previousTextValue) {\n setTextValue(internalState.current.previousTextValue);\n internalState.current.previousTextValue = undefined;\n }\n setSpinState('rest');\n } else {\n setSpinState('rest');\n }\n };\n\n const handleKeyUp = (e: React.KeyboardEvent<HTMLInputElement>) => {\n setSpinState('rest');\n };\n\n const commit = (e: SpinButtonChangeEvent, newValue?: number, 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 internalState.current.value = roundedValue;\n setAtBound(getBound(roundedValue, min, max));\n }\n\n if (valueChanged || displayValueChanged) {\n onChange?.(e, { value: roundedValue, displayValue: newDisplayValue });\n }\n };\n\n state.input.value = textValue;\n state.input['aria-valuemin'] = min;\n state.input['aria-valuemax'] = max;\n state.input['aria-valuenow'] = currentValue;\n state.input['aria-valuetext'] = (value !== undefined && displayValue) || undefined;\n state.input.onChange = useMergedEventCallbacks(state.input.onChange, handleInputChange);\n state.input.onBlur = useMergedEventCallbacks(state.input.onBlur, handleBlur);\n state.input.onKeyDown = useMergedEventCallbacks(state.input.onKeyDown, handleKeyDown);\n state.input.onKeyUp = useMergedEventCallbacks(state.input.onKeyUp, handleKeyUp);\n\n state.incrementButton.onMouseDown = useMergedEventCallbacks(\n handleIncrementMouseDown,\n state.incrementButton.onMouseDown,\n );\n state.incrementButton.onMouseUp = useMergedEventCallbacks(state.incrementButton.onMouseUp, handleStepMouseUpOrLeave);\n state.incrementButton.onMouseLeave = useMergedEventCallbacks(\n state.incrementButton.onMouseLeave,\n handleStepMouseUpOrLeave,\n );\n\n state.decrementButton.onMouseDown = useMergedEventCallbacks(\n handleDecrementMouseDown,\n state.decrementButton.onMouseDown,\n );\n state.decrementButton.onMouseUp = useMergedEventCallbacks(state.decrementButton.onMouseUp, handleStepMouseUpOrLeave);\n state.decrementButton.onMouseLeave = useMergedEventCallbacks(\n state.decrementButton.onMouseLeave,\n handleStepMouseUpOrLeave,\n );\n\n return state;\n};\n"],"sourceRoot":"../src/"}
@@ -0,0 +1,7 @@
1
+ import { SlotClassNames } from '@fluentui/react-utilities';
2
+ import type { SpinButtonSlots, SpinButtonState } from './SpinButton.types';
3
+ export declare const spinButtonClassNames: SlotClassNames<SpinButtonSlots>;
4
+ /**
5
+ * Apply styling to the SpinButton slots based on the state
6
+ */
7
+ export declare const useSpinButtonStyles_unstable: (state: SpinButtonState) => SpinButtonState;