@servicetitan/form 16.1.0 → 17.1.1

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.
Files changed (59) hide show
  1. package/dist/color-picker/color-palette.js +1 -1
  2. package/dist/color-picker/color-palette.js.map +1 -1
  3. package/dist/color-picker/color-picker.js +5 -5
  4. package/dist/color-picker/color-picker.js.map +1 -1
  5. package/dist/date-range-picker/date-range-picker.js +5 -5
  6. package/dist/date-range-picker/date-range-picker.js.map +1 -1
  7. package/dist/date-range-picker/date-range-picker.module.css +2 -2
  8. package/dist/demo/color-picker.js +5 -5
  9. package/dist/demo/color-picker.js.map +1 -1
  10. package/dist/demo/date-range-picker.js +3 -3
  11. package/dist/demo/date-range-picker.js.map +1 -1
  12. package/dist/demo/dropdown-state.js +7 -7
  13. package/dist/demo/dropdown-state.js.map +1 -1
  14. package/dist/demo/file-uploader.js +4 -4
  15. package/dist/demo/file-uploader.js.map +1 -1
  16. package/dist/demo/input-date-mask.js +3 -3
  17. package/dist/demo/input-date-mask.js.map +1 -1
  18. package/dist/demo/number-input.js +3 -3
  19. package/dist/demo/number-input.js.map +1 -1
  20. package/dist/demo/original-number-input.js +3 -3
  21. package/dist/demo/original-number-input.js.map +1 -1
  22. package/dist/demo/phone-number-input.js +1 -1
  23. package/dist/demo/phone-number-input.js.map +1 -1
  24. package/dist/dropdown-state.d.ts.map +1 -1
  25. package/dist/dropdown-state.js +6 -5
  26. package/dist/dropdown-state.js.map +1 -1
  27. package/dist/file-uploader/config.js +2 -2
  28. package/dist/file-uploader/config.js.map +1 -1
  29. package/dist/file-uploader/file-uploader.js +6 -6
  30. package/dist/file-uploader/file-uploader.js.map +1 -1
  31. package/dist/file-uploader/uploader.js +1 -1
  32. package/dist/file-uploader/uploader.js.map +1 -1
  33. package/dist/form-helpers.js +9 -9
  34. package/dist/form-helpers.js.map +1 -1
  35. package/dist/form-state-error-banner/form-state-error-banner.js +4 -4
  36. package/dist/form-state-error-banner/form-state-error-banner.js.map +1 -1
  37. package/dist/form-validators.js +1 -1
  38. package/dist/form-validators.js.map +1 -1
  39. package/dist/input-date-mask/input-date-mask.js +10 -10
  40. package/dist/input-date-mask/input-date-mask.js.map +1 -1
  41. package/dist/label/label.js +1 -1
  42. package/dist/label/label.js.map +1 -1
  43. package/dist/masked-input.js +1 -1
  44. package/dist/masked-input.js.map +1 -1
  45. package/dist/number-input/number-input.d.ts.map +1 -1
  46. package/dist/number-input/number-input.js +58 -12
  47. package/dist/number-input/number-input.js.map +1 -1
  48. package/dist/original-number-input/ordinal-number-input.js +2 -2
  49. package/dist/original-number-input/ordinal-number-input.js.map +1 -1
  50. package/dist/persistent-form-state/persistent-form-state.js +3 -3
  51. package/dist/persistent-form-state/persistent-form-state.js.map +1 -1
  52. package/dist/phone-number-input/phone-number-input.d.ts +1 -1
  53. package/dist/phone-number-input/phone-number-input.d.ts.map +1 -1
  54. package/dist/phone-number-input/phone-number-input.js +2 -2
  55. package/dist/phone-number-input/phone-number-input.js.map +1 -1
  56. package/package.json +11 -11
  57. package/src/date-range-picker/date-range-picker.module.css +2 -2
  58. package/src/dropdown-state.ts +3 -1
  59. package/src/number-input/number-input.tsx +69 -6
@@ -3,5 +3,5 @@ import { FormInputProps } from '@servicetitan/design-system';
3
3
  export interface PhoneNumberInputProps extends FormInputProps {
4
4
  sip?: boolean;
5
5
  }
6
- export declare const PhoneNumberInput: import("react").ForwardRefExoticComponent<Pick<PhoneNumberInputProps, string | number> & import("react").RefAttributes<HTMLInputElement>>;
6
+ export declare const PhoneNumberInput: import("react").ForwardRefExoticComponent<Pick<PhoneNumberInputProps, keyof PhoneNumberInputProps> & import("react").RefAttributes<HTMLInputElement>>;
7
7
  //# sourceMappingURL=phone-number-input.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"phone-number-input.d.ts","sourceRoot":"","sources":["../../src/phone-number-input/phone-number-input.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAQ,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAEnE,MAAM,WAAW,qBAAsB,SAAQ,cAAc;IACzD,GAAG,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,gBAAgB,2IAS5B,CAAC"}
1
+ {"version":3,"file":"phone-number-input.d.ts","sourceRoot":"","sources":["../../src/phone-number-input/phone-number-input.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAQ,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAEnE,MAAM,WAAW,qBAAsB,SAAQ,cAAc;IACzD,GAAG,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,gBAAgB,uJAS5B,CAAC"}
@@ -19,8 +19,8 @@ const jsx_runtime_1 = require("react/jsx-runtime");
19
19
  const react_1 = require("react");
20
20
  const react_input_mask_1 = __importDefault(require("react-input-mask"));
21
21
  const design_system_1 = require("@servicetitan/design-system");
22
- exports.PhoneNumberInput = react_1.forwardRef((_a, ref) => {
22
+ exports.PhoneNumberInput = (0, react_1.forwardRef)((_a, ref) => {
23
23
  var { sip } = _a, props = __rest(_a, ["sip"]);
24
- return sip ? (jsx_runtime_1.jsx(design_system_1.Form.Input, Object.assign({}, props, { ref: ref }), void 0)) : (jsx_runtime_1.jsx(react_input_mask_1.default, Object.assign({ maskChar: null, mask: "(999) 999-9999" }, props, { children: () => jsx_runtime_1.jsx(design_system_1.Form.Input, Object.assign({ ref: ref }, props), void 0) }), void 0));
24
+ return sip ? ((0, jsx_runtime_1.jsx)(design_system_1.Form.Input, Object.assign({}, props, { ref: ref }), void 0)) : ((0, jsx_runtime_1.jsx)(react_input_mask_1.default, Object.assign({ maskChar: null, mask: "(999) 999-9999" }, props, { children: () => (0, jsx_runtime_1.jsx)(design_system_1.Form.Input, Object.assign({ ref: ref }, props), void 0) }), void 0));
25
25
  });
26
26
  //# sourceMappingURL=phone-number-input.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"phone-number-input.js","sourceRoot":"","sources":["../../src/phone-number-input/phone-number-input.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,iCAAmC;AACnC,wEAAyC;AAEzC,+DAAmE;AAMtD,QAAA,gBAAgB,GAAG,kBAAU,CACtC,CAAC,EAAiB,EAAE,GAAG,EAAE,EAAE;QAA1B,EAAE,GAAG,OAAY,EAAP,KAAK,cAAf,OAAiB,CAAF;IACZ,OAAA,GAAG,CAAC,CAAC,CAAC,CACF,kBAAC,oBAAI,CAAC,KAAK,oBAAK,KAAK,IAAE,GAAG,EAAE,GAAG,YAAI,CACtC,CAAC,CAAC,CAAC,CACA,kBAAC,0BAAS,kBAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAC,gBAAgB,IAAK,KAAK,cACrD,GAAG,EAAE,CAAC,kBAAC,oBAAI,CAAC,KAAK,kBAAC,GAAG,EAAE,GAAG,IAAM,KAAK,UAAI,YAClC,CACf,CAAA;CAAA,CACR,CAAC"}
1
+ {"version":3,"file":"phone-number-input.js","sourceRoot":"","sources":["../../src/phone-number-input/phone-number-input.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAAA,iCAAmC;AACnC,wEAAyC;AAEzC,+DAAmE;AAMtD,QAAA,gBAAgB,GAAG,IAAA,kBAAU,EACtC,CAAC,EAAiB,EAAE,GAAG,EAAE,EAAE;QAA1B,EAAE,GAAG,OAAY,EAAP,KAAK,cAAf,OAAiB,CAAF;IACZ,OAAA,GAAG,CAAC,CAAC,CAAC,CACF,uBAAC,oBAAI,CAAC,KAAK,oBAAK,KAAK,IAAE,GAAG,EAAE,GAAG,YAAI,CACtC,CAAC,CAAC,CAAC,CACA,uBAAC,0BAAS,kBAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAC,gBAAgB,IAAK,KAAK,cACrD,GAAG,EAAE,CAAC,uBAAC,oBAAI,CAAC,KAAK,kBAAC,GAAG,EAAE,GAAG,IAAM,KAAK,UAAI,YAClC,CACf,CAAA;CAAA,CACR,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@servicetitan/form",
3
- "version": "16.1.0",
3
+ "version": "17.1.1",
4
4
  "description": "",
5
5
  "homepage": "https://docs.st.dev/docs/frontend/form",
6
6
  "repository": {
@@ -15,14 +15,14 @@
15
15
  "src"
16
16
  ],
17
17
  "devDependencies": {
18
- "@servicetitan/confirm": "^16.1.0",
19
- "@servicetitan/culture": "^16.1.0",
20
- "@servicetitan/data-query": "^16.1.0",
21
- "@servicetitan/design-system": "~10.2.1",
22
- "@servicetitan/react-ioc": "^16.1.0",
23
- "@servicetitan/tokens": "~10.2.1",
18
+ "@servicetitan/confirm": "^17.1.1",
19
+ "@servicetitan/culture": "^17.1.1",
20
+ "@servicetitan/data-query": "^17.1.1",
21
+ "@servicetitan/design-system": "~10.3.3",
22
+ "@servicetitan/react-ioc": "^17.1.1",
23
+ "@servicetitan/tokens": "~10.3.3",
24
24
  "@types/debounce": "~1.2.1",
25
- "@types/react": "~17.0.24",
25
+ "@types/react": "~17.0.27",
26
26
  "@types/react-input-mask": "~2.0.5",
27
27
  "@types/uuid": "~8.3.1",
28
28
  "accounting": "~0.4.1",
@@ -38,9 +38,9 @@
38
38
  "@servicetitan/confirm": "^14.0.0",
39
39
  "@servicetitan/culture": "^14.0.0",
40
40
  "@servicetitan/data-query": "^14.0.0",
41
- "@servicetitan/design-system": "~10.2.1",
41
+ "@servicetitan/design-system": "~10.3.3",
42
42
  "@servicetitan/react-ioc": "^14.0.0",
43
- "@servicetitan/tokens": "~10.2.1",
43
+ "@servicetitan/tokens": "~10.3.3",
44
44
  "accounting": "~0.4.1",
45
45
  "formstate": "~2.0.0",
46
46
  "mobx": "~6.3.3",
@@ -65,5 +65,5 @@
65
65
  "cli": {
66
66
  "webpack": false
67
67
  },
68
- "gitHead": "3790506ef903e0e9bf129dcf4d2ed352f42b007d"
68
+ "gitHead": "01f27439e67c569dd6534738dfba79d6dbbb41a5"
69
69
  }
@@ -10,7 +10,7 @@
10
10
  overflow: hidden;
11
11
  }
12
12
  .date-range-picker .date-range-picker-kendo :global(.k-textbox-container) {
13
- padding-top: 0;
13
+ padding-top: var(--spacing-0);
14
14
  height: var(--spacing-4);
15
15
  }
16
16
 
@@ -30,7 +30,7 @@
30
30
  }
31
31
 
32
32
  .end-label {
33
- margin: 0 var(--spacing-half);
33
+ margin: var(--spacing-0) var(--spacing-half);
34
34
  color: var(--color-neutral-80);
35
35
  font-size: var(--typescale-4);
36
36
  width: var(--spacing-3);
@@ -84,7 +84,9 @@ export class DropdownState<T extends DropdownOption<any>> {
84
84
  }
85
85
 
86
86
  @computed private get searchFilter() {
87
- if (!this.search) return undefined;
87
+ if (!this.search) {
88
+ return undefined;
89
+ }
88
90
 
89
91
  const filter = { operator: 'contains', value: this.search, ignoreCase: true };
90
92
 
@@ -1,4 +1,12 @@
1
- import { useCallback, useState, useEffect, SyntheticEvent, KeyboardEvent, FocusEvent } from 'react';
1
+ import {
2
+ useCallback,
3
+ useState,
4
+ useEffect,
5
+ useRef,
6
+ SyntheticEvent,
7
+ KeyboardEvent,
8
+ FocusEvent,
9
+ } from 'react';
2
10
 
3
11
  import { useOptionalDependencies } from '@servicetitan/react-ioc';
4
12
 
@@ -10,8 +18,11 @@ import { FormatNumber, getFormattedString } from './get-formatted-string';
10
18
  import { EmptyValue, NumberValue } from './common-interfaces';
11
19
  import { formatNumber as formatNumberDefault } from 'accounting';
12
20
 
21
+ import debounce from 'debounce';
22
+
13
23
  const ARROW_UP_KEY = 38;
14
24
  const ARROW_DOWN_KEY = 40;
25
+ const DEBOUNCE_WAIT = 300;
15
26
 
16
27
  export interface NumberInputProps<TEmpty extends EmptyValue>
17
28
  extends Omit<InputProps, 'value' | 'onChange'> {
@@ -104,7 +115,13 @@ export const NumberInput = <TEmpty extends EmptyValue>({
104
115
  }
105
116
  };
106
117
 
107
- const updateValue = (value: string, silent = false) => {
118
+ /*
119
+ ** "updateImmediateValue" updates the value immediately without clamping min/max,
120
+ ** then "updateClampedValueDebounced" updates applying the min/max after debounce delay
121
+ **
122
+ ** Example: User can type "100" if min is "5" without the "1" immediately being clamped
123
+ */
124
+ const updateImmediateValue = (value: string, silent = false) => {
108
125
  const newState = processValue(
109
126
  value,
110
127
  {
@@ -114,10 +131,6 @@ export const NumberInput = <TEmpty extends EmptyValue>({
114
131
  thousand: thousandsSeparator,
115
132
  decimal: decimalSeparator,
116
133
  },
117
- range: {
118
- min,
119
- max,
120
- },
121
134
  },
122
135
  formatNumber
123
136
  );
@@ -129,6 +142,56 @@ export const NumberInput = <TEmpty extends EmptyValue>({
129
142
  }
130
143
  };
131
144
 
145
+ const updateClampedValueDebounced = useRef<(value: string, silent: boolean) => void>();
146
+
147
+ useEffect(() => {
148
+ let isCurrent = true;
149
+
150
+ const updateClampedValue = (value: string, silent = false) => {
151
+ if (isCurrent) {
152
+ const newState = processValue(
153
+ value,
154
+ {
155
+ emptyValue,
156
+ precision: decimalPlaces,
157
+ separators: {
158
+ thousand: thousandsSeparator,
159
+ decimal: decimalSeparator,
160
+ },
161
+ range: { min, max },
162
+ },
163
+ formatNumber
164
+ );
165
+
166
+ setState(newState);
167
+
168
+ if (!silent) {
169
+ onChange(newState.numberValue);
170
+ }
171
+ }
172
+ };
173
+
174
+ updateClampedValueDebounced.current = debounce(updateClampedValue, DEBOUNCE_WAIT);
175
+
176
+ return () => {
177
+ isCurrent = false;
178
+ };
179
+ }, [
180
+ emptyValue,
181
+ decimalPlaces,
182
+ thousandsSeparator,
183
+ decimalSeparator,
184
+ min,
185
+ max,
186
+ formatNumber,
187
+ onChange,
188
+ ]);
189
+
190
+ const updateValue = (value: string, silent = false) => {
191
+ updateImmediateValue(value, silent);
192
+ updateClampedValueDebounced.current?.(value, silent);
193
+ };
194
+
132
195
  const handleFocus = (event: FocusEvent<HTMLInputElement>) => {
133
196
  if (state.numberValue !== undefined) {
134
197
  updateValue(String(state.numberValue), true);