@osdk/react-components 0.3.0 → 0.4.0-main-90a01d202dfa1e497125bd6cfcdc8175278fb7ec

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 (99) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/build/browser/action-form/ActionFormApi.js.map +1 -1
  3. package/build/browser/action-form/BaseForm.js +100 -12
  4. package/build/browser/action-form/BaseForm.js.map +1 -1
  5. package/build/browser/action-form/BaseForm.module.css +21 -1
  6. package/build/browser/action-form/BaseForm.module.css.js +4 -1
  7. package/build/browser/action-form/FormField.js +3 -1
  8. package/build/browser/action-form/FormField.js.map +1 -1
  9. package/build/browser/action-form/FormFieldApi.js.map +1 -1
  10. package/build/browser/action-form/fields/BaseInput.module.css +4 -0
  11. package/build/browser/action-form/fields/DatetimePickerField.js +3 -1
  12. package/build/browser/action-form/fields/DatetimePickerField.js.map +1 -1
  13. package/build/browser/action-form/fields/DatetimePickerField.module.css +4 -0
  14. package/build/browser/action-form/fields/FieldBridge.js +31 -4
  15. package/build/browser/action-form/fields/FieldBridge.js.map +1 -1
  16. package/build/browser/action-form/fields/FilePickerField.js +6 -2
  17. package/build/browser/action-form/fields/FilePickerField.js.map +1 -1
  18. package/build/browser/action-form/fields/FilePickerField.module.css +4 -0
  19. package/build/browser/action-form/fields/FormFieldRenderer.js +24 -12
  20. package/build/browser/action-form/fields/FormFieldRenderer.js.map +1 -1
  21. package/build/browser/action-form/fields/NumberInputField.js +12 -8
  22. package/build/browser/action-form/fields/NumberInputField.js.map +1 -1
  23. package/build/browser/action-form/fields/NumberInputField.module.css +4 -0
  24. package/build/browser/action-form/fields/TextAreaField.js +3 -1
  25. package/build/browser/action-form/fields/TextAreaField.js.map +1 -1
  26. package/build/browser/action-form/fields/TextInputField.js +3 -1
  27. package/build/browser/action-form/fields/TextInputField.js.map +1 -1
  28. package/build/browser/action-form/utils/extractValidationRules.js +186 -0
  29. package/build/browser/action-form/utils/extractValidationRules.js.map +1 -0
  30. package/build/browser/public/experimental.js.map +1 -1
  31. package/build/browser/shared/hooks/useAsyncAction.js +56 -0
  32. package/build/browser/shared/hooks/useAsyncAction.js.map +1 -0
  33. package/build/browser/shared/hooks/useIsMounted.js +32 -0
  34. package/build/browser/shared/hooks/useIsMounted.js.map +1 -0
  35. package/build/browser/styles.css +37 -1
  36. package/build/cjs/public/experimental.cjs +361 -37
  37. package/build/cjs/public/experimental.cjs.map +1 -1
  38. package/build/cjs/public/experimental.css +30 -1
  39. package/build/cjs/public/experimental.css.map +1 -1
  40. package/build/cjs/public/experimental.d.cts +40 -13
  41. package/build/esm/action-form/ActionFormApi.js.map +1 -1
  42. package/build/esm/action-form/BaseForm.js +100 -12
  43. package/build/esm/action-form/BaseForm.js.map +1 -1
  44. package/build/esm/action-form/BaseForm.module.css +21 -1
  45. package/build/esm/action-form/FormField.js +3 -1
  46. package/build/esm/action-form/FormField.js.map +1 -1
  47. package/build/esm/action-form/FormFieldApi.js.map +1 -1
  48. package/build/esm/action-form/fields/BaseInput.module.css +4 -0
  49. package/build/esm/action-form/fields/DatetimePickerField.js +3 -1
  50. package/build/esm/action-form/fields/DatetimePickerField.js.map +1 -1
  51. package/build/esm/action-form/fields/DatetimePickerField.module.css +4 -0
  52. package/build/esm/action-form/fields/FieldBridge.js +31 -4
  53. package/build/esm/action-form/fields/FieldBridge.js.map +1 -1
  54. package/build/esm/action-form/fields/FilePickerField.js +6 -2
  55. package/build/esm/action-form/fields/FilePickerField.js.map +1 -1
  56. package/build/esm/action-form/fields/FilePickerField.module.css +4 -0
  57. package/build/esm/action-form/fields/FormFieldRenderer.js +24 -12
  58. package/build/esm/action-form/fields/FormFieldRenderer.js.map +1 -1
  59. package/build/esm/action-form/fields/NumberInputField.js +12 -8
  60. package/build/esm/action-form/fields/NumberInputField.js.map +1 -1
  61. package/build/esm/action-form/fields/NumberInputField.module.css +4 -0
  62. package/build/esm/action-form/fields/TextAreaField.js +3 -1
  63. package/build/esm/action-form/fields/TextAreaField.js.map +1 -1
  64. package/build/esm/action-form/fields/TextInputField.js +3 -1
  65. package/build/esm/action-form/fields/TextInputField.js.map +1 -1
  66. package/build/esm/action-form/utils/extractValidationRules.js +186 -0
  67. package/build/esm/action-form/utils/extractValidationRules.js.map +1 -0
  68. package/build/esm/public/experimental.js.map +1 -1
  69. package/build/esm/shared/hooks/useAsyncAction.js +56 -0
  70. package/build/esm/shared/hooks/useAsyncAction.js.map +1 -0
  71. package/build/esm/shared/hooks/useIsMounted.js +32 -0
  72. package/build/esm/shared/hooks/useIsMounted.js.map +1 -0
  73. package/build/types/action-form/ActionFormApi.d.ts +1 -1
  74. package/build/types/action-form/ActionFormApi.d.ts.map +1 -1
  75. package/build/types/action-form/BaseForm.d.ts.map +1 -1
  76. package/build/types/action-form/FormField.d.ts +1 -0
  77. package/build/types/action-form/FormField.d.ts.map +1 -1
  78. package/build/types/action-form/FormFieldApi.d.ts +39 -12
  79. package/build/types/action-form/FormFieldApi.d.ts.map +1 -1
  80. package/build/types/action-form/fields/DatetimePickerField.d.ts +1 -1
  81. package/build/types/action-form/fields/DatetimePickerField.d.ts.map +1 -1
  82. package/build/types/action-form/fields/FieldBridge.d.ts.map +1 -1
  83. package/build/types/action-form/fields/FormFieldRenderer.d.ts +2 -0
  84. package/build/types/action-form/fields/FormFieldRenderer.d.ts.map +1 -1
  85. package/build/types/action-form/fields/NumberInputField.d.ts +1 -1
  86. package/build/types/action-form/fields/NumberInputField.d.ts.map +1 -1
  87. package/build/types/action-form/fields/TextAreaField.d.ts +1 -1
  88. package/build/types/action-form/fields/TextAreaField.d.ts.map +1 -1
  89. package/build/types/action-form/fields/TextInputField.d.ts +1 -1
  90. package/build/types/action-form/fields/TextInputField.d.ts.map +1 -1
  91. package/build/types/action-form/utils/extractValidationRules.d.ts +13 -0
  92. package/build/types/action-form/utils/extractValidationRules.d.ts.map +1 -0
  93. package/build/types/public/experimental.d.ts +1 -1
  94. package/build/types/public/experimental.d.ts.map +1 -1
  95. package/build/types/shared/hooks/useAsyncAction.d.ts +16 -0
  96. package/build/types/shared/hooks/useAsyncAction.d.ts.map +1 -0
  97. package/build/types/shared/hooks/useIsMounted.d.ts +5 -0
  98. package/build/types/shared/hooks/useIsMounted.d.ts.map +1 -0
  99. package/package.json +8 -8
@@ -14,31 +14,58 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import React, { memo, useCallback } from "react";
17
+ import React, { memo, useCallback, useMemo } from "react";
18
18
  import { useController } from "react-hook-form";
19
+ import { extractValidationRules } from "../utils/extractValidationRules.js";
19
20
  import { FormFieldRenderer } from "./FormFieldRenderer.js";
21
+ const SELECT_LIKE_FIELDS = new Set(["RADIO_BUTTONS", "DROPDOWN"]);
20
22
  export const FieldBridge = /*#__PURE__*/memo(function ({
21
23
  fieldDef,
22
24
  control,
23
25
  onExternalChange
24
26
  }) {
27
+ const rules = useMemo(() => extractValidationRules(fieldDef), [fieldDef]);
25
28
  const {
26
29
  field: {
27
30
  onChange,
31
+ onBlur,
28
32
  value
33
+ },
34
+ fieldState: {
35
+ error: fieldError
29
36
  }
30
37
  } = useController({
31
38
  name: fieldDef.fieldKey,
32
- control
39
+ control,
40
+ rules
33
41
  });
42
+ const isSelectLike = SELECT_LIKE_FIELDS.has(fieldDef.fieldComponent);
34
43
  const handleChange = useCallback(newValue => {
35
44
  onChange(newValue);
36
45
  onExternalChange?.(fieldDef.fieldKey, newValue);
37
- }, [onChange, onExternalChange, fieldDef.fieldKey]);
46
+ // Select-like fields are "pick once" interactions — mark as touched
47
+ // immediately so RHF revalidates (clears errors) on selection rather
48
+ // than waiting for focus to leave the container.
49
+ if (isSelectLike) {
50
+ onBlur();
51
+ }
52
+ }, [onChange, onBlur, onExternalChange, fieldDef.fieldKey, isSelectLike]);
53
+
54
+ // Ignore blur events where focus stays within the field container
55
+ // (e.g. moving between radio buttons in a group). Only fire RHF's
56
+ // onBlur when focus truly leaves the field.
57
+ const handleBlur = useCallback(e => {
58
+ if (e.currentTarget.contains(e.relatedTarget)) {
59
+ return;
60
+ }
61
+ onBlur();
62
+ }, [onBlur]);
38
63
  return /*#__PURE__*/React.createElement(FormFieldRenderer, {
39
64
  value: value,
40
65
  fieldDefinition: fieldDef,
41
- onFieldValueChange: handleChange
66
+ onFieldValueChange: handleChange,
67
+ onBlur: handleBlur,
68
+ error: fieldError?.message
42
69
  });
43
70
  });
44
71
  //# sourceMappingURL=FieldBridge.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FieldBridge.js","names":["React","memo","useCallback","useController","FormFieldRenderer","FieldBridge","fieldDef","control","onExternalChange","field","onChange","value","name","fieldKey","handleChange","newValue","createElement","fieldDefinition","onFieldValueChange"],"sources":["FieldBridge.tsx"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { memo, useCallback } from \"react\";\nimport type { Control } from \"react-hook-form\";\nimport { useController } from \"react-hook-form\";\nimport type { RendererFieldDefinition } from \"../FormFieldApi.js\";\nimport { FormFieldRenderer } from \"./FormFieldRenderer.js\";\n\nexport interface FieldBridgeProps {\n fieldDef: RendererFieldDefinition;\n control: Control<Record<string, unknown>>;\n onExternalChange?: (fieldKey: string, value: unknown) => void;\n}\nexport const FieldBridge: React.FC<FieldBridgeProps> = memo(\n function FieldBridgeFn({\n fieldDef,\n control,\n onExternalChange,\n }: FieldBridgeProps): React.ReactElement {\n const {\n field: { onChange, value },\n } = useController({\n name: fieldDef.fieldKey,\n control,\n });\n\n const handleChange = useCallback(\n (newValue: unknown) => {\n onChange(newValue);\n onExternalChange?.(fieldDef.fieldKey, newValue);\n },\n [onChange, onExternalChange, fieldDef.fieldKey],\n );\n\n return (\n <FormFieldRenderer\n value={value}\n fieldDefinition={fieldDef}\n onFieldValueChange={handleChange}\n />\n );\n },\n);\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,OAAOA,KAAK,IAAIC,IAAI,EAAEC,WAAW,QAAQ,OAAO;AAEhD,SAASC,aAAa,QAAQ,iBAAiB;AAE/C,SAASC,iBAAiB,QAAQ,wBAAwB;AAO1D,OAAO,MAAMC,WAAuC,gBAAGJ,IAAI,CACzD,UAAuB;EACrBK,QAAQ;EACRC,OAAO;EACPC;AACgB,CAAC,EAAsB;EACvC,MAAM;IACJC,KAAK,EAAE;MAAEC,QAAQ;MAAEC;IAAM;EAC3B,CAAC,GAAGR,aAAa,CAAC;IAChBS,IAAI,EAAEN,QAAQ,CAACO,QAAQ;IACvBN;EACF,CAAC,CAAC;EAEF,MAAMO,YAAY,GAAGZ,WAAW,CAC7Ba,QAAiB,IAAK;IACrBL,QAAQ,CAACK,QAAQ,CAAC;IAClBP,gBAAgB,GAAGF,QAAQ,CAACO,QAAQ,EAAEE,QAAQ,CAAC;EACjD,CAAC,EACD,CAACL,QAAQ,EAAEF,gBAAgB,EAAEF,QAAQ,CAACO,QAAQ,CAChD,CAAC;EAED,oBACEb,KAAA,CAAAgB,aAAA,CAACZ,iBAAiB;IAChBO,KAAK,EAAEA,KAAM;IACbM,eAAe,EAAEX,QAAS;IAC1BY,kBAAkB,EAAEJ;EAAa,CAClC,CAAC;AAEN,CACF,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"FieldBridge.js","names":["React","memo","useCallback","useMemo","useController","extractValidationRules","FormFieldRenderer","SELECT_LIKE_FIELDS","Set","FieldBridge","fieldDef","control","onExternalChange","rules","field","onChange","onBlur","value","fieldState","error","fieldError","name","fieldKey","isSelectLike","has","fieldComponent","handleChange","newValue","handleBlur","e","currentTarget","contains","relatedTarget","createElement","fieldDefinition","onFieldValueChange","message"],"sources":["FieldBridge.tsx"],"sourcesContent":["/*\n * Copyright 2025 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { memo, useCallback, useMemo } from \"react\";\nimport type { Control } from \"react-hook-form\";\nimport { useController } from \"react-hook-form\";\nimport type {\n FieldComponent,\n RendererFieldDefinition,\n} from \"../FormFieldApi.js\";\nimport { extractValidationRules } from \"../utils/extractValidationRules.js\";\nimport { FormFieldRenderer } from \"./FormFieldRenderer.js\";\n\nexport interface FieldBridgeProps {\n fieldDef: RendererFieldDefinition;\n control: Control<Record<string, unknown>>;\n onExternalChange?: (fieldKey: string, value: unknown) => void;\n}\nconst SELECT_LIKE_FIELDS: ReadonlySet<FieldComponent> = new Set<FieldComponent>(\n [\n \"RADIO_BUTTONS\",\n \"DROPDOWN\",\n ],\n);\n\nexport const FieldBridge: React.FC<FieldBridgeProps> = memo(\n function FieldBridgeFn({\n fieldDef,\n control,\n onExternalChange,\n }: FieldBridgeProps): React.ReactElement {\n const rules = useMemo(\n () => extractValidationRules(fieldDef),\n [fieldDef],\n );\n\n const {\n field: { onChange, onBlur, value },\n fieldState: { error: fieldError },\n } = useController({\n name: fieldDef.fieldKey,\n control,\n rules,\n });\n\n const isSelectLike = SELECT_LIKE_FIELDS.has(fieldDef.fieldComponent);\n\n const handleChange = useCallback(\n (newValue: unknown) => {\n onChange(newValue);\n onExternalChange?.(fieldDef.fieldKey, newValue);\n // Select-like fields are \"pick once\" interactions — mark as touched\n // immediately so RHF revalidates (clears errors) on selection rather\n // than waiting for focus to leave the container.\n if (isSelectLike) {\n onBlur();\n }\n },\n [onChange, onBlur, onExternalChange, fieldDef.fieldKey, isSelectLike],\n );\n\n // Ignore blur events where focus stays within the field container\n // (e.g. moving between radio buttons in a group). Only fire RHF's\n // onBlur when focus truly leaves the field.\n const handleBlur = useCallback(\n (e: React.FocusEvent<HTMLDivElement>) => {\n if (e.currentTarget.contains(e.relatedTarget)) {\n return;\n }\n onBlur();\n },\n [onBlur],\n );\n\n return (\n <FormFieldRenderer\n value={value}\n fieldDefinition={fieldDef}\n onFieldValueChange={handleChange}\n onBlur={handleBlur}\n error={fieldError?.message}\n />\n );\n },\n);\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,OAAOA,KAAK,IAAIC,IAAI,EAAEC,WAAW,EAAEC,OAAO,QAAQ,OAAO;AAEzD,SAASC,aAAa,QAAQ,iBAAiB;AAK/C,SAASC,sBAAsB,QAAQ,oCAAoC;AAC3E,SAASC,iBAAiB,QAAQ,wBAAwB;AAO1D,MAAMC,kBAA+C,GAAG,IAAIC,GAAG,CAC7D,CACE,eAAe,EACf,UAAU,CAEd,CAAC;AAED,OAAO,MAAMC,WAAuC,gBAAGR,IAAI,CACzD,UAAuB;EACrBS,QAAQ;EACRC,OAAO;EACPC;AACgB,CAAC,EAAsB;EACvC,MAAMC,KAAK,GAAGV,OAAO,CACnB,MAAME,sBAAsB,CAACK,QAAQ,CAAC,EACtC,CAACA,QAAQ,CACX,CAAC;EAED,MAAM;IACJI,KAAK,EAAE;MAAEC,QAAQ;MAAEC,MAAM;MAAEC;IAAM,CAAC;IAClCC,UAAU,EAAE;MAAEC,KAAK,EAAEC;IAAW;EAClC,CAAC,GAAGhB,aAAa,CAAC;IAChBiB,IAAI,EAAEX,QAAQ,CAACY,QAAQ;IACvBX,OAAO;IACPE;EACF,CAAC,CAAC;EAEF,MAAMU,YAAY,GAAGhB,kBAAkB,CAACiB,GAAG,CAACd,QAAQ,CAACe,cAAc,CAAC;EAEpE,MAAMC,YAAY,GAAGxB,WAAW,CAC7ByB,QAAiB,IAAK;IACrBZ,QAAQ,CAACY,QAAQ,CAAC;IAClBf,gBAAgB,GAAGF,QAAQ,CAACY,QAAQ,EAAEK,QAAQ,CAAC;IAC/C;IACA;IACA;IACA,IAAIJ,YAAY,EAAE;MAChBP,MAAM,CAAC,CAAC;IACV;EACF,CAAC,EACD,CAACD,QAAQ,EAAEC,MAAM,EAAEJ,gBAAgB,EAAEF,QAAQ,CAACY,QAAQ,EAAEC,YAAY,CACtE,CAAC;;EAED;EACA;EACA;EACA,MAAMK,UAAU,GAAG1B,WAAW,CAC3B2B,CAAmC,IAAK;IACvC,IAAIA,CAAC,CAACC,aAAa,CAACC,QAAQ,CAACF,CAAC,CAACG,aAAa,CAAC,EAAE;MAC7C;IACF;IACAhB,MAAM,CAAC,CAAC;EACV,CAAC,EACD,CAACA,MAAM,CACT,CAAC;EAED,oBACEhB,KAAA,CAAAiC,aAAA,CAAC3B,iBAAiB;IAChBW,KAAK,EAAEA,KAAM;IACbiB,eAAe,EAAExB,QAAS;IAC1ByB,kBAAkB,EAAET,YAAa;IACjCV,MAAM,EAAEY,UAAW;IACnBT,KAAK,EAAEC,UAAU,EAAEgB;EAAQ,CAC5B,CAAC;AAEN,CACF,CAAC","ignoreList":[]}
@@ -23,9 +23,12 @@ export const FilePickerField = /*#__PURE__*/memo(function ({
23
23
  id,
24
24
  value,
25
25
  onChange,
26
+ error,
26
27
  isMulti,
27
28
  accept,
28
- // TODO: implement maxSize validation in a follow-up
29
+ // maxSize is enforced by form-level validation (extractValidationRules),
30
+ // not here. Silently dropping oversized files would leave the user with
31
+ // no indication of why their selection disappeared.
29
32
  maxSize: _maxSize,
30
33
  text = "No file chosen",
31
34
  buttonText = "Browse"
@@ -77,7 +80,8 @@ export const FilePickerField = /*#__PURE__*/memo(function ({
77
80
  role: "button",
78
81
  "aria-label": "Choose file",
79
82
  onClick: openFileDialog,
80
- onKeyDown: handleKeyDown
83
+ onKeyDown: handleKeyDown,
84
+ "aria-invalid": error != null || undefined
81
85
  }, /*#__PURE__*/React.createElement("input", {
82
86
  ref: inputRef,
83
87
  type: "file",
@@ -1 +1 @@
1
- {"version":3,"file":"FilePickerField.js","names":["Button","Cross","classnames","React","memo","useCallback","useMemo","useRef","styles","FilePickerField","id","value","onChange","isMulti","accept","maxSize","_maxSize","text","buttonText","inputRef","openFileDialog","current","click","handleInputChange","event","files","target","length","Array","from","handleClear","stopPropagation","preventDefault","handleKeyDown","key","displayText","getDisplayText","hasValue","acceptString","normalizeAccept","createElement","className","osdkFilePickerTrigger","tabIndex","role","onClick","onKeyDown","ref","type","osdkFilePickerHiddenInput","multiple","osdkFilePickerText","osdkFilePickerPlaceholder","osdkFilePickerClear","osdkFilePickerBrowse","undefined","isArray","join","map","f","name"],"sources":["FilePickerField.tsx"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Button } from \"@base-ui/react/button\";\nimport { Cross } from \"@blueprintjs/icons\";\nimport classnames from \"classnames\";\nimport React, { memo, useCallback, useMemo, useRef } from \"react\";\nimport type { FilePickerProps } from \"../FormFieldApi.js\";\nimport styles from \"./FilePickerField.module.css\";\n\nexport const FilePickerField: React.FC<FilePickerProps> = memo(\n function FilePickerFieldFn({\n id,\n value,\n onChange,\n isMulti,\n accept,\n // TODO: implement maxSize validation in a follow-up\n maxSize: _maxSize,\n text = \"No file chosen\",\n buttonText = \"Browse\",\n }): React.ReactElement {\n const inputRef = useRef<HTMLInputElement>(null);\n\n const openFileDialog = useCallback(() => {\n inputRef.current?.click();\n }, []);\n\n const handleInputChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n const files = event.target.files;\n if (files == null || files.length === 0) {\n onChange?.(null);\n return;\n }\n\n if (isMulti) {\n onChange?.(Array.from(files));\n } else {\n onChange?.(files[0] ?? null);\n }\n },\n [onChange, isMulti],\n );\n\n const handleClear = useCallback(\n (event: React.MouseEvent) => {\n event.stopPropagation();\n event.preventDefault();\n onChange?.(null);\n if (inputRef.current != null) {\n inputRef.current.value = \"\";\n }\n },\n [onChange],\n );\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n openFileDialog();\n }\n },\n [openFileDialog],\n );\n\n const displayText = useMemo(() => getDisplayText(value), [value]);\n const hasValue = displayText != null;\n const acceptString = useMemo(\n () => normalizeAccept(accept),\n [accept],\n );\n return (\n // The entire component is a single tab stop (tabIndex={0}).\n // Text and Browse are <span>s (not buttons) so they don't create\n // extra tab stops — clicks on them bubble up to the container's onClick.\n // The clear button is the only inner interactive element and gets its\n // own tab stop so keyboard users can clear the selection.\n <div\n id={id}\n className={styles.osdkFilePickerTrigger}\n tabIndex={0}\n role=\"button\"\n aria-label=\"Choose file\"\n onClick={openFileDialog}\n onKeyDown={handleKeyDown}\n >\n <input\n ref={inputRef}\n type=\"file\"\n className={styles.osdkFilePickerHiddenInput}\n multiple={isMulti}\n accept={acceptString}\n onChange={handleInputChange}\n aria-hidden=\"true\"\n tabIndex={-1}\n />\n <span\n className={classnames(\n styles.osdkFilePickerText,\n !hasValue && styles.osdkFilePickerPlaceholder,\n )}\n >\n {displayText ?? text}\n </span>\n {hasValue && (\n // stopPropagation + preventDefault prevent the click from\n // bubbling to the container's onClick which opens the file dialog.\n <Button\n className={styles.osdkFilePickerClear}\n onClick={handleClear}\n aria-label=\"Clear selection\"\n >\n <Cross />\n </Button>\n )}\n <span className={styles.osdkFilePickerBrowse}>{buttonText}</span>\n </div>\n );\n },\n);\n\nfunction normalizeAccept(\n accept: string | string[] | undefined,\n): string | undefined {\n if (accept == null) {\n return undefined;\n }\n return Array.isArray(accept) ? accept.join(\",\") : accept;\n}\n\nfunction getDisplayText(value: File | File[] | null): string | undefined {\n if (value == null) {\n return undefined;\n }\n if (Array.isArray(value)) {\n return value.map((f) => f.name).join(\", \");\n }\n return value.name;\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"FilePickerField.js","names":["Button","Cross","classnames","React","memo","useCallback","useMemo","useRef","styles","FilePickerField","id","value","onChange","error","isMulti","accept","maxSize","_maxSize","text","buttonText","inputRef","openFileDialog","current","click","handleInputChange","event","files","target","length","Array","from","handleClear","stopPropagation","preventDefault","handleKeyDown","key","displayText","getDisplayText","hasValue","acceptString","normalizeAccept","createElement","className","osdkFilePickerTrigger","tabIndex","role","onClick","onKeyDown","undefined","ref","type","osdkFilePickerHiddenInput","multiple","osdkFilePickerText","osdkFilePickerPlaceholder","osdkFilePickerClear","osdkFilePickerBrowse","isArray","join","map","f","name"],"sources":["FilePickerField.tsx"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Button } from \"@base-ui/react/button\";\nimport { Cross } from \"@blueprintjs/icons\";\nimport classnames from \"classnames\";\nimport React, { memo, useCallback, useMemo, useRef } from \"react\";\nimport type { FilePickerProps } from \"../FormFieldApi.js\";\nimport styles from \"./FilePickerField.module.css\";\n\nexport const FilePickerField: React.FC<FilePickerProps> = memo(\n function FilePickerFieldFn({\n id,\n value,\n onChange,\n error,\n isMulti,\n accept,\n // maxSize is enforced by form-level validation (extractValidationRules),\n // not here. Silently dropping oversized files would leave the user with\n // no indication of why their selection disappeared.\n maxSize: _maxSize,\n text = \"No file chosen\",\n buttonText = \"Browse\",\n }): React.ReactElement {\n const inputRef = useRef<HTMLInputElement>(null);\n\n const openFileDialog = useCallback(() => {\n inputRef.current?.click();\n }, []);\n\n const handleInputChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => {\n const files = event.target.files;\n if (files == null || files.length === 0) {\n onChange?.(null);\n return;\n }\n\n if (isMulti) {\n onChange?.(Array.from(files));\n } else {\n onChange?.(files[0] ?? null);\n }\n },\n [onChange, isMulti],\n );\n\n const handleClear = useCallback(\n (event: React.MouseEvent) => {\n event.stopPropagation();\n event.preventDefault();\n onChange?.(null);\n if (inputRef.current != null) {\n inputRef.current.value = \"\";\n }\n },\n [onChange],\n );\n\n const handleKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n openFileDialog();\n }\n },\n [openFileDialog],\n );\n\n const displayText = useMemo(() => getDisplayText(value), [value]);\n const hasValue = displayText != null;\n const acceptString = useMemo(\n () => normalizeAccept(accept),\n [accept],\n );\n return (\n // The entire component is a single tab stop (tabIndex={0}).\n // Text and Browse are <span>s (not buttons) so they don't create\n // extra tab stops — clicks on them bubble up to the container's onClick.\n // The clear button is the only inner interactive element and gets its\n // own tab stop so keyboard users can clear the selection.\n <div\n id={id}\n className={styles.osdkFilePickerTrigger}\n tabIndex={0}\n role=\"button\"\n aria-label=\"Choose file\"\n onClick={openFileDialog}\n onKeyDown={handleKeyDown}\n aria-invalid={error != null || undefined}\n >\n <input\n ref={inputRef}\n type=\"file\"\n className={styles.osdkFilePickerHiddenInput}\n multiple={isMulti}\n accept={acceptString}\n onChange={handleInputChange}\n aria-hidden=\"true\"\n tabIndex={-1}\n />\n <span\n className={classnames(\n styles.osdkFilePickerText,\n !hasValue && styles.osdkFilePickerPlaceholder,\n )}\n >\n {displayText ?? text}\n </span>\n {hasValue && (\n // stopPropagation + preventDefault prevent the click from\n // bubbling to the container's onClick which opens the file dialog.\n <Button\n className={styles.osdkFilePickerClear}\n onClick={handleClear}\n aria-label=\"Clear selection\"\n >\n <Cross />\n </Button>\n )}\n <span className={styles.osdkFilePickerBrowse}>{buttonText}</span>\n </div>\n );\n },\n);\n\nfunction normalizeAccept(\n accept: string | string[] | undefined,\n): string | undefined {\n if (accept == null) {\n return undefined;\n }\n return Array.isArray(accept) ? accept.join(\",\") : accept;\n}\n\nfunction getDisplayText(value: File | File[] | null): string | undefined {\n if (value == null) {\n return undefined;\n }\n if (Array.isArray(value)) {\n return value.map((f) => f.name).join(\", \");\n }\n return value.name;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -43,6 +43,10 @@
43
43
  var(--osdk-file-picker-trigger-focus-color);
44
44
  outline-offset: var(--osdk-file-picker-trigger-focus-offset);
45
45
  }
46
+
47
+ &[aria-invalid] {
48
+ border-color: var(--osdk-file-picker-trigger-border-color-error);
49
+ }
46
50
  }
47
51
 
48
52
  /* Visually hidden file input */
@@ -29,7 +29,9 @@ import { TextInputField } from "./TextInputField.js";
29
29
  export const FormFieldRenderer = /*#__PURE__*/memo(function ({
30
30
  fieldDefinition,
31
31
  value,
32
- onFieldValueChange
32
+ onFieldValueChange,
33
+ onBlur,
34
+ error
33
35
  }) {
34
36
  const {
35
37
  label,
@@ -41,31 +43,36 @@ export const FormFieldRenderer = /*#__PURE__*/memo(function ({
41
43
  label: label,
42
44
  isRequired: isRequired,
43
45
  fieldKey: fieldDefinition.fieldKey,
44
- helperText: helperTextPlacement !== "tooltip" ? helperText : undefined
45
- }, renderFieldComponent(fieldDefinition, value, onFieldValueChange));
46
+ helperText: helperTextPlacement !== "tooltip" ? helperText : undefined,
47
+ error: error,
48
+ onBlur: onBlur
49
+ }, renderFieldComponent(fieldDefinition, value, onFieldValueChange, error));
46
50
  });
47
- function renderFieldComponent(fieldDefinition, value, onChange) {
51
+ function renderFieldComponent(fieldDefinition, value, onChange, error) {
48
52
  switch (fieldDefinition.fieldComponent) {
49
53
  case "TEXT_INPUT":
50
54
  return /*#__PURE__*/React.createElement(TextInputField, _extends({
51
55
  id: fieldDefinition.fieldKey,
52
56
  value: value != null ? String(value) : "",
53
57
  onChange: onChange,
54
- placeholder: fieldDefinition.placeholder
58
+ placeholder: fieldDefinition.placeholder,
59
+ error: error
55
60
  }, fieldDefinition.fieldComponentProps));
56
61
  case "TEXT_AREA":
57
62
  return /*#__PURE__*/React.createElement(TextAreaField, _extends({
58
63
  id: fieldDefinition.fieldKey,
59
64
  value: value != null ? String(value) : "",
60
65
  onChange: onChange,
61
- placeholder: fieldDefinition.placeholder
66
+ placeholder: fieldDefinition.placeholder,
67
+ error: error
62
68
  }, fieldDefinition.fieldComponentProps));
63
69
  case "DROPDOWN":
64
70
  {
65
71
  return /*#__PURE__*/React.createElement(DropdownField, _extends({
66
72
  value: value,
67
73
  onChange: onChange,
68
- placeholder: fieldDefinition.placeholder
74
+ placeholder: fieldDefinition.placeholder,
75
+ error: error
69
76
  }, fieldDefinition.fieldComponentProps));
70
77
  }
71
78
  case "DATETIME_PICKER":
@@ -75,19 +82,22 @@ function renderFieldComponent(fieldDefinition, value, onChange) {
75
82
  // TODO: Use coerceFieldValue
76
83
  ,
77
84
  value: value instanceof Date ? value : null,
78
- onChange: onChange
85
+ onChange: onChange,
86
+ error: error
79
87
  }, fieldDefinition.fieldComponentProps));
80
88
  case "RADIO_BUTTONS":
81
89
  return /*#__PURE__*/React.createElement(RadioButtonsField, _extends({
82
90
  id: fieldDefinition.fieldKey,
83
91
  value: value,
84
- onChange: onChange
92
+ onChange: onChange,
93
+ error: error
85
94
  }, fieldDefinition.fieldComponentProps));
86
95
  case "CUSTOM":
87
96
  return /*#__PURE__*/React.createElement(CustomField, _extends({
88
97
  id: fieldDefinition.fieldKey,
89
98
  value: value,
90
- onChange: onChange
99
+ onChange: onChange,
100
+ error: error
91
101
  }, fieldDefinition.fieldComponentProps));
92
102
  case "NUMBER_INPUT":
93
103
  // TODO: Use coerceFieldValue
@@ -95,13 +105,15 @@ function renderFieldComponent(fieldDefinition, value, onChange) {
95
105
  id: fieldDefinition.fieldKey,
96
106
  value: typeof value === "number" ? value : null,
97
107
  onChange: onChange,
98
- placeholder: fieldDefinition.placeholder
108
+ placeholder: fieldDefinition.placeholder,
109
+ error: error
99
110
  }, fieldDefinition.fieldComponentProps));
100
111
  case "FILE_PICKER":
101
112
  return /*#__PURE__*/React.createElement(FilePickerField, _extends({
102
113
  id: fieldDefinition.fieldKey,
103
114
  value: coerceToFileValue(value),
104
- onChange: onChange
115
+ onChange: onChange,
116
+ error: error
105
117
  }, fieldDefinition.fieldComponentProps));
106
118
  case "OBJECT_SET":
107
119
  return /*#__PURE__*/React.createElement(ObjectSetField, _extends({
@@ -1 +1 @@
1
- {"version":3,"file":"FormFieldRenderer.js","names":["React","memo","FormField","CustomField","DatetimePickerField","DropdownField","FilePickerField","NumberInputField","ObjectSetField","RadioButtonsField","TextAreaField","TextInputField","FormFieldRenderer","fieldDefinition","value","onFieldValueChange","label","isRequired","helperText","helperTextPlacement","createElement","fieldKey","undefined","renderFieldComponent","onChange","fieldComponent","_extends","id","String","placeholder","fieldComponentProps","Date","coerceToFileValue","assertUnreachableFieldComponent","isFileArray","every","v","File","Array","isArray","Error"],"sources":["FormFieldRenderer.tsx"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { memo } from \"react\";\nimport { FormField } from \"../FormField.js\";\nimport type { RendererFieldDefinition } from \"../FormFieldApi.js\";\nimport { CustomField } from \"./CustomField.js\";\nimport { DatetimePickerField } from \"./DatetimePickerField.js\";\nimport { DropdownField } from \"./DropdownField.js\";\nimport { FilePickerField } from \"./FilePickerField.js\";\nimport { NumberInputField } from \"./NumberInputField.js\";\nimport { ObjectSetField } from \"./ObjectSetField.js\";\nimport { RadioButtonsField } from \"./RadioButtonsField.js\";\nimport { TextAreaField } from \"./TextAreaField.js\";\nimport { TextInputField } from \"./TextInputField.js\";\n\nexport interface FormFieldRendererProps {\n fieldDefinition: RendererFieldDefinition;\n value: unknown;\n onFieldValueChange: (value: unknown) => void;\n}\n\nexport const FormFieldRenderer: React.FC<FormFieldRendererProps> = memo(\n function FormFieldRendererFn({\n fieldDefinition,\n value,\n onFieldValueChange,\n }: FormFieldRendererProps): React.ReactElement {\n const { label, isRequired, helperText, helperTextPlacement } =\n fieldDefinition;\n\n return (\n <FormField\n label={label}\n isRequired={isRequired}\n fieldKey={fieldDefinition.fieldKey}\n helperText={helperTextPlacement !== \"tooltip\" ? helperText : undefined}\n >\n {renderFieldComponent(fieldDefinition, value, onFieldValueChange)}\n </FormField>\n );\n },\n);\n\nfunction renderFieldComponent(\n fieldDefinition: RendererFieldDefinition,\n value: unknown,\n onChange: (value: unknown) => void,\n): React.ReactElement {\n switch (fieldDefinition.fieldComponent) {\n case \"TEXT_INPUT\":\n return (\n <TextInputField\n id={fieldDefinition.fieldKey}\n value={value != null ? String(value) : \"\"}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"TEXT_AREA\":\n return (\n <TextAreaField\n id={fieldDefinition.fieldKey}\n value={value != null ? String(value) : \"\"}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"DROPDOWN\": {\n return (\n <DropdownField\n value={value}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n }\n case \"DATETIME_PICKER\":\n return (\n <DatetimePickerField\n id={fieldDefinition.fieldKey}\n placeholder={fieldDefinition.placeholder}\n // TODO: Use coerceFieldValue\n value={value instanceof Date ? value : null}\n onChange={onChange}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"RADIO_BUTTONS\":\n return (\n <RadioButtonsField\n id={fieldDefinition.fieldKey}\n value={value}\n onChange={onChange}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"CUSTOM\":\n return (\n <CustomField\n id={fieldDefinition.fieldKey}\n value={value}\n onChange={onChange}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"NUMBER_INPUT\":\n // TODO: Use coerceFieldValue\n return (\n <NumberInputField\n id={fieldDefinition.fieldKey}\n value={typeof value === \"number\" ? value : null}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"FILE_PICKER\":\n return (\n <FilePickerField\n id={fieldDefinition.fieldKey}\n value={coerceToFileValue(value)}\n onChange={onChange}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"OBJECT_SET\":\n return (\n <ObjectSetField\n id={fieldDefinition.fieldKey}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n default:\n return assertUnreachableFieldComponent(fieldDefinition);\n }\n}\n\n// TODO: Move and share with `coerceFieldValue`\nfunction isFileArray(value: unknown[]): value is File[] {\n return value.every((v) => v instanceof File);\n}\n\nfunction coerceToFileValue(value: unknown): File | File[] | null {\n if (value instanceof File) {\n return value;\n }\n if (Array.isArray(value) && isFileArray(value)) {\n return value;\n }\n return null;\n}\n\nfunction assertUnreachableFieldComponent(value: never): never {\n throw new Error(`Unhandled field component: ${String(value)}`);\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"FormFieldRenderer.js","names":["React","memo","FormField","CustomField","DatetimePickerField","DropdownField","FilePickerField","NumberInputField","ObjectSetField","RadioButtonsField","TextAreaField","TextInputField","FormFieldRenderer","fieldDefinition","value","onFieldValueChange","onBlur","error","label","isRequired","helperText","helperTextPlacement","createElement","fieldKey","undefined","renderFieldComponent","onChange","fieldComponent","_extends","id","String","placeholder","fieldComponentProps","Date","coerceToFileValue","assertUnreachableFieldComponent","isFileArray","every","v","File","Array","isArray","Error"],"sources":["FormFieldRenderer.tsx"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { memo } from \"react\";\nimport { FormField } from \"../FormField.js\";\nimport type { RendererFieldDefinition } from \"../FormFieldApi.js\";\nimport { CustomField } from \"./CustomField.js\";\nimport { DatetimePickerField } from \"./DatetimePickerField.js\";\nimport { DropdownField } from \"./DropdownField.js\";\nimport { FilePickerField } from \"./FilePickerField.js\";\nimport { NumberInputField } from \"./NumberInputField.js\";\nimport { ObjectSetField } from \"./ObjectSetField.js\";\nimport { RadioButtonsField } from \"./RadioButtonsField.js\";\nimport { TextAreaField } from \"./TextAreaField.js\";\nimport { TextInputField } from \"./TextInputField.js\";\n\nexport interface FormFieldRendererProps {\n fieldDefinition: RendererFieldDefinition;\n value: unknown;\n onFieldValueChange: (value: unknown) => void;\n onBlur: (e: React.FocusEvent<HTMLDivElement>) => void;\n error: string | undefined;\n}\n\nexport const FormFieldRenderer: React.FC<FormFieldRendererProps> = memo(\n function FormFieldRendererFn({\n fieldDefinition,\n value,\n onFieldValueChange,\n onBlur,\n error,\n }: FormFieldRendererProps): React.ReactElement {\n const { label, isRequired, helperText, helperTextPlacement } =\n fieldDefinition;\n\n return (\n <FormField\n label={label}\n isRequired={isRequired}\n fieldKey={fieldDefinition.fieldKey}\n helperText={helperTextPlacement !== \"tooltip\" ? helperText : undefined}\n error={error}\n onBlur={onBlur}\n >\n {renderFieldComponent(\n fieldDefinition,\n value,\n onFieldValueChange,\n error,\n )}\n </FormField>\n );\n },\n);\n\nfunction renderFieldComponent(\n fieldDefinition: RendererFieldDefinition,\n value: unknown,\n onChange: (value: unknown) => void,\n error: string | undefined,\n): React.ReactElement {\n switch (fieldDefinition.fieldComponent) {\n case \"TEXT_INPUT\":\n return (\n <TextInputField\n id={fieldDefinition.fieldKey}\n value={value != null ? String(value) : \"\"}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"TEXT_AREA\":\n return (\n <TextAreaField\n id={fieldDefinition.fieldKey}\n value={value != null ? String(value) : \"\"}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"DROPDOWN\": {\n return (\n <DropdownField\n value={value}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n }\n case \"DATETIME_PICKER\":\n return (\n <DatetimePickerField\n id={fieldDefinition.fieldKey}\n placeholder={fieldDefinition.placeholder}\n // TODO: Use coerceFieldValue\n value={value instanceof Date ? value : null}\n onChange={onChange}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"RADIO_BUTTONS\":\n return (\n <RadioButtonsField\n id={fieldDefinition.fieldKey}\n value={value}\n onChange={onChange}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"CUSTOM\":\n return (\n <CustomField\n id={fieldDefinition.fieldKey}\n value={value}\n onChange={onChange}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"NUMBER_INPUT\":\n // TODO: Use coerceFieldValue\n return (\n <NumberInputField\n id={fieldDefinition.fieldKey}\n value={typeof value === \"number\" ? value : null}\n onChange={onChange}\n placeholder={fieldDefinition.placeholder}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"FILE_PICKER\":\n return (\n <FilePickerField\n id={fieldDefinition.fieldKey}\n value={coerceToFileValue(value)}\n onChange={onChange}\n error={error}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n case \"OBJECT_SET\":\n return (\n <ObjectSetField\n id={fieldDefinition.fieldKey}\n {...fieldDefinition.fieldComponentProps}\n />\n );\n default:\n return assertUnreachableFieldComponent(fieldDefinition);\n }\n}\n\n// TODO: Move and share with `coerceFieldValue`\nfunction isFileArray(value: unknown[]): value is File[] {\n return value.every((v) => v instanceof File);\n}\n\nfunction coerceToFileValue(value: unknown): File | File[] | null {\n if (value instanceof File) {\n return value;\n }\n if (Array.isArray(value) && isFileArray(value)) {\n return value;\n }\n return null;\n}\n\nfunction assertUnreachableFieldComponent(value: never): never {\n throw new Error(`Unhandled field component: ${String(value)}`);\n}\n"],"mappings":"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","ignoreList":[]}
@@ -35,16 +35,14 @@ import styles from "./NumberInputField.module.css";
35
35
  const VALID_NUMERIC_REGEX = /^[+-.]?(\d+\.?\d*|\d*\.?\d+)?([eE][+-]?\d*)?$/;
36
36
  const DEFAULT_STEP = 1;
37
37
  const CHEVRON_SIZE = 12;
38
-
39
- // TODO: Add min/max validation so the field can surface
40
- // out-of-range errors through the form validation system.
41
38
  export function NumberInputField({
42
39
  id,
43
40
  value,
44
41
  onChange,
42
+ error,
45
43
  placeholder,
46
- min: _min,
47
- max: _max,
44
+ min,
45
+ max,
48
46
  step
49
47
  }) {
50
48
  const [displayValue, setDisplayValue] = useState(() => formatNumberForDisplay(value));
@@ -67,11 +65,11 @@ export function NumberInputField({
67
65
  }, [onChange]);
68
66
  const applyStep = useCallback(direction => {
69
67
  const current = parseNumericValue(displayValue) ?? 0;
70
- const next = current + direction * (step ?? DEFAULT_STEP);
68
+ const next = clamp(current + direction * (step ?? DEFAULT_STEP), min, max);
71
69
  const formatted = formatNumberForDisplay(next);
72
70
  setDisplayValue(formatted);
73
71
  onChange?.(next);
74
- }, [displayValue, onChange, step]);
72
+ }, [displayValue, onChange, step, min, max]);
75
73
  const handleKeyDown = useCallback(e => {
76
74
  if (e.key !== "ArrowUp" && e.key !== "ArrowDown") {
77
75
  return;
@@ -86,7 +84,8 @@ export function NumberInputField({
86
84
  applyStep(-1);
87
85
  }, [applyStep]);
88
86
  return /*#__PURE__*/React.createElement("div", {
89
- className: styles.osdkNumberInputWrapper
87
+ className: styles.osdkNumberInputWrapper,
88
+ "aria-invalid": error != null || undefined
90
89
  }, /*#__PURE__*/React.createElement(Input, {
91
90
  id: id,
92
91
  className: styles.osdkNumberInputField,
@@ -127,4 +126,9 @@ function parseNumericValue(text) {
127
126
  function formatNumberForDisplay(value) {
128
127
  return value != null ? String(value) : "";
129
128
  }
129
+ function clamp(value, min, max) {
130
+ if (min != null && value < min) return min;
131
+ if (max != null && value > max) return max;
132
+ return value;
133
+ }
130
134
  //# sourceMappingURL=NumberInputField.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"NumberInputField.js","names":["Button","Input","ChevronDown","ChevronUp","React","useCallback","useRef","useState","styles","VALID_NUMERIC_REGEX","DEFAULT_STEP","CHEVRON_SIZE","NumberInputField","id","value","onChange","placeholder","min","_min","max","_max","step","displayValue","setDisplayValue","formatNumberForDisplay","prevValueRef","current","currentParsed","parseNumericValue","handleValueChange","newValue","isValidInput","applyStep","direction","next","formatted","handleKeyDown","e","key","preventDefault","handleStepUp","handleStepDown","createElement","className","osdkNumberInputWrapper","osdkNumberInputField","type","inputMode","onValueChange","onKeyDown","osdkNumberInputStepper","osdkNumberInputStepButton","tabIndex","onClick","size","text","test","parsed","Number","isNaN","String"],"sources":["NumberInputField.tsx"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Button } from \"@base-ui/react/button\";\nimport { Input } from \"@base-ui/react/input\";\nimport { ChevronDown, ChevronUp } from \"@blueprintjs/icons\";\nimport React, { useCallback, useRef, useState } from \"react\";\nimport type { NumberInputFieldProps } from \"../FormFieldApi.js\";\nimport styles from \"./NumberInputField.module.css\";\n\n/**\n * Structural regex for valid numeric input.\n *\n * Allows intermediate typing states that will become valid numbers:\n * \"\" — user cleared the field (all groups are optional)\n * \"-\" — user started typing a negative number\n * \".\" — user started typing a decimal like \".5\"\n * \"+\" — user started typing an explicitly positive number\n * \"1.\", \"1e\", \"1e+\" — partial but structurally valid\n *\n * Rejects obviously invalid strings like \"1.2.3\" or \"+-5\".\n */\nconst VALID_NUMERIC_REGEX = /^[+-.]?(\\d+\\.?\\d*|\\d*\\.?\\d+)?([eE][+-]?\\d*)?$/;\n\nconst DEFAULT_STEP = 1;\nconst CHEVRON_SIZE = 12;\n\n// TODO: Add min/max validation so the field can surface\n// out-of-range errors through the form validation system.\nexport function NumberInputField({\n id,\n value,\n onChange,\n placeholder,\n min: _min,\n max: _max,\n step,\n}: NumberInputFieldProps): React.ReactElement {\n const [displayValue, setDisplayValue] = useState<string>(() =>\n formatNumberForDisplay(value)\n );\n\n const prevValueRef = useRef(value);\n\n // Sync external value → internal display string\n if (prevValueRef.current !== value) {\n prevValueRef.current = value;\n const currentParsed = parseNumericValue(displayValue);\n\n if (value !== currentParsed) {\n setDisplayValue(formatNumberForDisplay(value));\n }\n }\n\n const handleValueChange = useCallback(\n (newValue: string) => {\n if (!isValidInput(newValue)) {\n return;\n }\n\n setDisplayValue(newValue);\n onChange?.(parseNumericValue(newValue));\n },\n [onChange],\n );\n\n const applyStep = useCallback(\n (direction: 1 | -1) => {\n const current = parseNumericValue(displayValue) ?? 0;\n const delta = direction * (step ?? DEFAULT_STEP);\n const next = current + delta;\n const formatted = formatNumberForDisplay(next);\n setDisplayValue(formatted);\n onChange?.(next);\n },\n [displayValue, onChange, step],\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key !== \"ArrowUp\" && e.key !== \"ArrowDown\") {\n return;\n }\n e.preventDefault();\n applyStep(e.key === \"ArrowUp\" ? 1 : -1);\n },\n [applyStep],\n );\n\n const handleStepUp = useCallback(() => {\n applyStep(1);\n }, [applyStep]);\n\n const handleStepDown = useCallback(() => {\n applyStep(-1);\n }, [applyStep]);\n\n return (\n <div className={styles.osdkNumberInputWrapper}>\n <Input\n id={id}\n className={styles.osdkNumberInputField}\n type=\"text\"\n inputMode=\"decimal\"\n value={displayValue}\n onValueChange={handleValueChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n />\n <div className={styles.osdkNumberInputStepper}>\n <Button\n className={styles.osdkNumberInputStepButton}\n aria-label=\"Increment\"\n tabIndex={-1}\n onClick={handleStepUp}\n >\n <ChevronUp size={CHEVRON_SIZE} />\n </Button>\n <Button\n className={styles.osdkNumberInputStepButton}\n aria-label=\"Decrement\"\n tabIndex={-1}\n onClick={handleStepDown}\n >\n <ChevronDown size={CHEVRON_SIZE} />\n </Button>\n </div>\n </div>\n );\n}\n\nfunction isValidInput(text: string): boolean {\n return VALID_NUMERIC_REGEX.test(text);\n}\n\nfunction parseNumericValue(text: string): number | null {\n if (text === \"\") {\n return null;\n }\n const parsed = Number(text);\n return Number.isNaN(parsed) ? null : parsed;\n}\n\nfunction formatNumberForDisplay(value: number | null): string {\n return value != null ? String(value) : \"\";\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"NumberInputField.js","names":["Button","Input","ChevronDown","ChevronUp","React","useCallback","useRef","useState","styles","VALID_NUMERIC_REGEX","DEFAULT_STEP","CHEVRON_SIZE","NumberInputField","id","value","onChange","error","placeholder","min","max","step","displayValue","setDisplayValue","formatNumberForDisplay","prevValueRef","current","currentParsed","parseNumericValue","handleValueChange","newValue","isValidInput","applyStep","direction","next","clamp","formatted","handleKeyDown","e","key","preventDefault","handleStepUp","handleStepDown","createElement","className","osdkNumberInputWrapper","undefined","osdkNumberInputField","type","inputMode","onValueChange","onKeyDown","osdkNumberInputStepper","osdkNumberInputStepButton","tabIndex","onClick","size","text","test","parsed","Number","isNaN","String"],"sources":["NumberInputField.tsx"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Button } from \"@base-ui/react/button\";\nimport { Input } from \"@base-ui/react/input\";\nimport { ChevronDown, ChevronUp } from \"@blueprintjs/icons\";\nimport React, { useCallback, useRef, useState } from \"react\";\nimport type { NumberInputFieldProps } from \"../FormFieldApi.js\";\nimport styles from \"./NumberInputField.module.css\";\n\n/**\n * Structural regex for valid numeric input.\n *\n * Allows intermediate typing states that will become valid numbers:\n * \"\" — user cleared the field (all groups are optional)\n * \"-\" — user started typing a negative number\n * \".\" — user started typing a decimal like \".5\"\n * \"+\" — user started typing an explicitly positive number\n * \"1.\", \"1e\", \"1e+\" — partial but structurally valid\n *\n * Rejects obviously invalid strings like \"1.2.3\" or \"+-5\".\n */\nconst VALID_NUMERIC_REGEX = /^[+-.]?(\\d+\\.?\\d*|\\d*\\.?\\d+)?([eE][+-]?\\d*)?$/;\n\nconst DEFAULT_STEP = 1;\nconst CHEVRON_SIZE = 12;\n\nexport function NumberInputField({\n id,\n value,\n onChange,\n error,\n placeholder,\n min,\n max,\n step,\n}: NumberInputFieldProps): React.ReactElement {\n const [displayValue, setDisplayValue] = useState<string>(() =>\n formatNumberForDisplay(value)\n );\n\n const prevValueRef = useRef(value);\n\n // Sync external value → internal display string\n if (prevValueRef.current !== value) {\n prevValueRef.current = value;\n const currentParsed = parseNumericValue(displayValue);\n\n if (value !== currentParsed) {\n setDisplayValue(formatNumberForDisplay(value));\n }\n }\n\n const handleValueChange = useCallback(\n (newValue: string) => {\n if (!isValidInput(newValue)) {\n return;\n }\n\n setDisplayValue(newValue);\n onChange?.(parseNumericValue(newValue));\n },\n [onChange],\n );\n\n const applyStep = useCallback(\n (direction: 1 | -1) => {\n const current = parseNumericValue(displayValue) ?? 0;\n const delta = direction * (step ?? DEFAULT_STEP);\n const next = clamp(current + delta, min, max);\n const formatted = formatNumberForDisplay(next);\n setDisplayValue(formatted);\n onChange?.(next);\n },\n [displayValue, onChange, step, min, max],\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key !== \"ArrowUp\" && e.key !== \"ArrowDown\") {\n return;\n }\n e.preventDefault();\n applyStep(e.key === \"ArrowUp\" ? 1 : -1);\n },\n [applyStep],\n );\n\n const handleStepUp = useCallback(() => {\n applyStep(1);\n }, [applyStep]);\n\n const handleStepDown = useCallback(() => {\n applyStep(-1);\n }, [applyStep]);\n\n return (\n <div\n className={styles.osdkNumberInputWrapper}\n aria-invalid={error != null || undefined}\n >\n <Input\n id={id}\n className={styles.osdkNumberInputField}\n type=\"text\"\n inputMode=\"decimal\"\n value={displayValue}\n onValueChange={handleValueChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n />\n <div className={styles.osdkNumberInputStepper}>\n <Button\n className={styles.osdkNumberInputStepButton}\n aria-label=\"Increment\"\n tabIndex={-1}\n onClick={handleStepUp}\n >\n <ChevronUp size={CHEVRON_SIZE} />\n </Button>\n <Button\n className={styles.osdkNumberInputStepButton}\n aria-label=\"Decrement\"\n tabIndex={-1}\n onClick={handleStepDown}\n >\n <ChevronDown size={CHEVRON_SIZE} />\n </Button>\n </div>\n </div>\n );\n}\n\nfunction isValidInput(text: string): boolean {\n return VALID_NUMERIC_REGEX.test(text);\n}\n\nfunction parseNumericValue(text: string): number | null {\n if (text === \"\") {\n return null;\n }\n const parsed = Number(text);\n return Number.isNaN(parsed) ? null : parsed;\n}\n\nfunction formatNumberForDisplay(value: number | null): string {\n return value != null ? String(value) : \"\";\n}\n\nfunction clamp(\n value: number,\n min: number | undefined,\n max: number | undefined,\n): number {\n if (min != null && value < min) return min;\n if (max != null && value > max) return max;\n return value;\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,MAAM,QAAQ,uBAAuB;AAC9C,SAASC,KAAK,QAAQ,sBAAsB;AAC5C,SAASC,WAAW,EAAEC,SAAS,QAAQ,oBAAoB;AAC3D,OAAOC,KAAK,IAAIC,WAAW,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,OAAO;AAE5D,OAAOC,MAAM,MAAM,+BAA+B;;AAElD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,MAAMC,mBAAmB,GAAG,+CAA+C;AAE3E,MAAMC,YAAY,GAAG,CAAC;AACtB,MAAMC,YAAY,GAAG,EAAE;AAEvB,OAAO,SAASC,gBAAgBA,CAAC;EAC/BC,EAAE;EACFC,KAAK;EACLC,QAAQ;EACRC,KAAK;EACLC,WAAW;EACXC,GAAG;EACHC,GAAG;EACHC;AACqB,CAAC,EAAsB;EAC5C,MAAM,CAACC,YAAY,EAAEC,eAAe,CAAC,GAAGf,QAAQ,CAAS,MACvDgB,sBAAsB,CAACT,KAAK,CAC9B,CAAC;EAED,MAAMU,YAAY,GAAGlB,MAAM,CAACQ,KAAK,CAAC;;EAElC;EACA,IAAIU,YAAY,CAACC,OAAO,KAAKX,KAAK,EAAE;IAClCU,YAAY,CAACC,OAAO,GAAGX,KAAK;IAC5B,MAAMY,aAAa,GAAGC,iBAAiB,CAACN,YAAY,CAAC;IAErD,IAAIP,KAAK,KAAKY,aAAa,EAAE;MAC3BJ,eAAe,CAACC,sBAAsB,CAACT,KAAK,CAAC,CAAC;IAChD;EACF;EAEA,MAAMc,iBAAiB,GAAGvB,WAAW,CAClCwB,QAAgB,IAAK;IACpB,IAAI,CAACC,YAAY,CAACD,QAAQ,CAAC,EAAE;MAC3B;IACF;IAEAP,eAAe,CAACO,QAAQ,CAAC;IACzBd,QAAQ,GAAGY,iBAAiB,CAACE,QAAQ,CAAC,CAAC;EACzC,CAAC,EACD,CAACd,QAAQ,CACX,CAAC;EAED,MAAMgB,SAAS,GAAG1B,WAAW,CAC1B2B,SAAiB,IAAK;IACrB,MAAMP,OAAO,GAAGE,iBAAiB,CAACN,YAAY,CAAC,IAAI,CAAC;IAEpD,MAAMY,IAAI,GAAGC,KAAK,CAACT,OAAO,GADZO,SAAS,IAAIZ,IAAI,IAAIV,YAAY,CACb,EAAEQ,GAAG,EAAEC,GAAG,CAAC;IAC7C,MAAMgB,SAAS,GAAGZ,sBAAsB,CAACU,IAAI,CAAC;IAC9CX,eAAe,CAACa,SAAS,CAAC;IAC1BpB,QAAQ,GAAGkB,IAAI,CAAC;EAClB,CAAC,EACD,CAACZ,YAAY,EAAEN,QAAQ,EAAEK,IAAI,EAAEF,GAAG,EAAEC,GAAG,CACzC,CAAC;EAED,MAAMiB,aAAa,GAAG/B,WAAW,CAC9BgC,CAAwC,IAAK;IAC5C,IAAIA,CAAC,CAACC,GAAG,KAAK,SAAS,IAAID,CAAC,CAACC,GAAG,KAAK,WAAW,EAAE;MAChD;IACF;IACAD,CAAC,CAACE,cAAc,CAAC,CAAC;IAClBR,SAAS,CAACM,CAAC,CAACC,GAAG,KAAK,SAAS,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;EACzC,CAAC,EACD,CAACP,SAAS,CACZ,CAAC;EAED,MAAMS,YAAY,GAAGnC,WAAW,CAAC,MAAM;IACrC0B,SAAS,CAAC,CAAC,CAAC;EACd,CAAC,EAAE,CAACA,SAAS,CAAC,CAAC;EAEf,MAAMU,cAAc,GAAGpC,WAAW,CAAC,MAAM;IACvC0B,SAAS,CAAC,CAAC,CAAC,CAAC;EACf,CAAC,EAAE,CAACA,SAAS,CAAC,CAAC;EAEf,oBACE3B,KAAA,CAAAsC,aAAA;IACEC,SAAS,EAAEnC,MAAM,CAACoC,sBAAuB;IACzC,gBAAc5B,KAAK,IAAI,IAAI,IAAI6B;EAAU,gBAEzCzC,KAAA,CAAAsC,aAAA,CAACzC,KAAK;IACJY,EAAE,EAAEA,EAAG;IACP8B,SAAS,EAAEnC,MAAM,CAACsC,oBAAqB;IACvCC,IAAI,EAAC,MAAM;IACXC,SAAS,EAAC,SAAS;IACnBlC,KAAK,EAAEO,YAAa;IACpB4B,aAAa,EAAErB,iBAAkB;IACjCsB,SAAS,EAAEd,aAAc;IACzBnB,WAAW,EAAEA;EAAY,CAC1B,CAAC,eACFb,KAAA,CAAAsC,aAAA;IAAKC,SAAS,EAAEnC,MAAM,CAAC2C;EAAuB,gBAC5C/C,KAAA,CAAAsC,aAAA,CAAC1C,MAAM;IACL2C,SAAS,EAAEnC,MAAM,CAAC4C,yBAA0B;IAC5C,cAAW,WAAW;IACtBC,QAAQ,EAAE,CAAC,CAAE;IACbC,OAAO,EAAEd;EAAa,gBAEtBpC,KAAA,CAAAsC,aAAA,CAACvC,SAAS;IAACoD,IAAI,EAAE5C;EAAa,CAAE,CAC1B,CAAC,eACTP,KAAA,CAAAsC,aAAA,CAAC1C,MAAM;IACL2C,SAAS,EAAEnC,MAAM,CAAC4C,yBAA0B;IAC5C,cAAW,WAAW;IACtBC,QAAQ,EAAE,CAAC,CAAE;IACbC,OAAO,EAAEb;EAAe,gBAExBrC,KAAA,CAAAsC,aAAA,CAACxC,WAAW;IAACqD,IAAI,EAAE5C;EAAa,CAAE,CAC5B,CACL,CACF,CAAC;AAEV;AAEA,SAASmB,YAAYA,CAAC0B,IAAY,EAAW;EAC3C,OAAO/C,mBAAmB,CAACgD,IAAI,CAACD,IAAI,CAAC;AACvC;AAEA,SAAS7B,iBAAiBA,CAAC6B,IAAY,EAAiB;EACtD,IAAIA,IAAI,KAAK,EAAE,EAAE;IACf,OAAO,IAAI;EACb;EACA,MAAME,MAAM,GAAGC,MAAM,CAACH,IAAI,CAAC;EAC3B,OAAOG,MAAM,CAACC,KAAK,CAACF,MAAM,CAAC,GAAG,IAAI,GAAGA,MAAM;AAC7C;AAEA,SAASnC,sBAAsBA,CAACT,KAAoB,EAAU;EAC5D,OAAOA,KAAK,IAAI,IAAI,GAAG+C,MAAM,CAAC/C,KAAK,CAAC,GAAG,EAAE;AAC3C;AAEA,SAASoB,KAAKA,CACZpB,KAAa,EACbI,GAAuB,EACvBC,GAAuB,EACf;EACR,IAAID,GAAG,IAAI,IAAI,IAAIJ,KAAK,GAAGI,GAAG,EAAE,OAAOA,GAAG;EAC1C,IAAIC,GAAG,IAAI,IAAI,IAAIL,KAAK,GAAGK,GAAG,EAAE,OAAOA,GAAG;EAC1C,OAAOL,KAAK;AACd","ignoreList":[]}
@@ -34,6 +34,10 @@
34
34
  outline-offset: var(--osdk-input-focus-offset);
35
35
  border-color: var(--osdk-input-border-color-focus);
36
36
  }
37
+
38
+ &[aria-invalid] {
39
+ border-color: var(--osdk-input-border-color-error);
40
+ }
37
41
  }
38
42
 
39
43
  .osdkNumberInputField {
@@ -25,6 +25,7 @@ export function TextAreaField({
25
25
  id,
26
26
  value,
27
27
  onChange,
28
+ error,
28
29
  placeholder,
29
30
  rows,
30
31
  wrap,
@@ -44,7 +45,8 @@ export function TextAreaField({
44
45
  placeholder: placeholder,
45
46
  minLength: minLength,
46
47
  maxLength: maxLength,
47
- render: renderTextarea
48
+ render: renderTextarea,
49
+ "aria-invalid": error != null || undefined
48
50
  });
49
51
  }
50
52
  //# sourceMappingURL=TextAreaField.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TextAreaField.js","names":["Input","React","useCallback","styles","TEXTAREA_STYLE","resize","TextAreaField","id","value","onChange","placeholder","rows","wrap","minLength","maxLength","renderTextarea","props","createElement","_extends","style","className","osdkBaseInput","onValueChange","render"],"sources":["TextAreaField.tsx"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Input } from \"@base-ui/react/input\";\nimport React, { useCallback } from \"react\";\nimport type { TextAreaFieldProps } from \"../FormFieldApi.js\";\nimport styles from \"./BaseInput.module.css\";\n\nconst TEXTAREA_STYLE: React.CSSProperties = { resize: \"vertical\" };\n\nexport function TextAreaField({\n id,\n value,\n onChange,\n placeholder,\n rows,\n wrap,\n minLength,\n maxLength,\n}: TextAreaFieldProps): React.ReactElement {\n const renderTextarea = useCallback(\n (props: React.ComponentPropsWithRef<\"textarea\">) => (\n <textarea {...props} rows={rows} wrap={wrap} style={TEXTAREA_STYLE} />\n ),\n [rows, wrap],\n );\n\n return (\n <Input\n id={id}\n className={styles.osdkBaseInput}\n value={value ?? \"\"}\n onValueChange={onChange}\n placeholder={placeholder}\n minLength={minLength}\n maxLength={maxLength}\n render={renderTextarea}\n />\n );\n}\n"],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,KAAK,QAAQ,sBAAsB;AAC5C,OAAOC,KAAK,IAAIC,WAAW,QAAQ,OAAO;AAE1C,OAAOC,MAAM,MAAM,wBAAwB;AAE3C,MAAMC,cAAmC,GAAG;EAAEC,MAAM,EAAE;AAAW,CAAC;AAElE,OAAO,SAASC,aAAaA,CAAC;EAC5BC,EAAE;EACFC,KAAK;EACLC,QAAQ;EACRC,WAAW;EACXC,IAAI;EACJC,IAAI;EACJC,SAAS;EACTC;AACkB,CAAC,EAAsB;EACzC,MAAMC,cAAc,GAAGb,WAAW,CAC/Bc,KAA8C,iBAC7Cf,KAAA,CAAAgB,aAAA,aAAAC,QAAA,KAAcF,KAAK;IAAEL,IAAI,EAAEA,IAAK;IAACC,IAAI,EAAEA,IAAK;IAACO,KAAK,EAAEf;EAAe,EAAE,CACtE,EACD,CAACO,IAAI,EAAEC,IAAI,CACb,CAAC;EAED,oBACEX,KAAA,CAAAgB,aAAA,CAACjB,KAAK;IACJO,EAAE,EAAEA,EAAG;IACPa,SAAS,EAAEjB,MAAM,CAACkB,aAAc;IAChCb,KAAK,EAAEA,KAAK,IAAI,EAAG;IACnBc,aAAa,EAAEb,QAAS;IACxBC,WAAW,EAAEA,WAAY;IACzBG,SAAS,EAAEA,SAAU;IACrBC,SAAS,EAAEA,SAAU;IACrBS,MAAM,EAAER;EAAe,CACxB,CAAC;AAEN","ignoreList":[]}
1
+ {"version":3,"file":"TextAreaField.js","names":["Input","React","useCallback","styles","TEXTAREA_STYLE","resize","TextAreaField","id","value","onChange","error","placeholder","rows","wrap","minLength","maxLength","renderTextarea","props","createElement","_extends","style","className","osdkBaseInput","onValueChange","render","undefined"],"sources":["TextAreaField.tsx"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Input } from \"@base-ui/react/input\";\nimport React, { useCallback } from \"react\";\nimport type { TextAreaFieldProps } from \"../FormFieldApi.js\";\nimport styles from \"./BaseInput.module.css\";\n\nconst TEXTAREA_STYLE: React.CSSProperties = { resize: \"vertical\" };\n\nexport function TextAreaField({\n id,\n value,\n onChange,\n error,\n placeholder,\n rows,\n wrap,\n minLength,\n maxLength,\n}: TextAreaFieldProps): React.ReactElement {\n const renderTextarea = useCallback(\n (props: React.ComponentPropsWithRef<\"textarea\">) => (\n <textarea {...props} rows={rows} wrap={wrap} style={TEXTAREA_STYLE} />\n ),\n [rows, wrap],\n );\n\n return (\n <Input\n id={id}\n className={styles.osdkBaseInput}\n value={value ?? \"\"}\n onValueChange={onChange}\n placeholder={placeholder}\n minLength={minLength}\n maxLength={maxLength}\n render={renderTextarea}\n aria-invalid={error != null || undefined}\n />\n );\n}\n"],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,KAAK,QAAQ,sBAAsB;AAC5C,OAAOC,KAAK,IAAIC,WAAW,QAAQ,OAAO;AAE1C,OAAOC,MAAM,MAAM,wBAAwB;AAE3C,MAAMC,cAAmC,GAAG;EAAEC,MAAM,EAAE;AAAW,CAAC;AAElE,OAAO,SAASC,aAAaA,CAAC;EAC5BC,EAAE;EACFC,KAAK;EACLC,QAAQ;EACRC,KAAK;EACLC,WAAW;EACXC,IAAI;EACJC,IAAI;EACJC,SAAS;EACTC;AACkB,CAAC,EAAsB;EACzC,MAAMC,cAAc,GAAGd,WAAW,CAC/Be,KAA8C,iBAC7ChB,KAAA,CAAAiB,aAAA,aAAAC,QAAA,KAAcF,KAAK;IAAEL,IAAI,EAAEA,IAAK;IAACC,IAAI,EAAEA,IAAK;IAACO,KAAK,EAAEhB;EAAe,EAAE,CACtE,EACD,CAACQ,IAAI,EAAEC,IAAI,CACb,CAAC;EAED,oBACEZ,KAAA,CAAAiB,aAAA,CAAClB,KAAK;IACJO,EAAE,EAAEA,EAAG;IACPc,SAAS,EAAElB,MAAM,CAACmB,aAAc;IAChCd,KAAK,EAAEA,KAAK,IAAI,EAAG;IACnBe,aAAa,EAAEd,QAAS;IACxBE,WAAW,EAAEA,WAAY;IACzBG,SAAS,EAAEA,SAAU;IACrBC,SAAS,EAAEA,SAAU;IACrBS,MAAM,EAAER,cAAe;IACvB,gBAAcN,KAAK,IAAI,IAAI,IAAIe;EAAU,CAC1C,CAAC;AAEN","ignoreList":[]}
@@ -21,6 +21,7 @@ export function TextInputField({
21
21
  id,
22
22
  value,
23
23
  onChange,
24
+ error,
24
25
  placeholder,
25
26
  minLength,
26
27
  maxLength
@@ -33,7 +34,8 @@ export function TextInputField({
33
34
  onValueChange: onChange,
34
35
  placeholder: placeholder,
35
36
  minLength: minLength,
36
- maxLength: maxLength
37
+ maxLength: maxLength,
38
+ "aria-invalid": error != null || undefined
37
39
  });
38
40
  }
39
41
  //# sourceMappingURL=TextInputField.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TextInputField.js","names":["Input","React","styles","TextInputField","id","value","onChange","placeholder","minLength","maxLength","createElement","className","osdkBaseInput","type","onValueChange"],"sources":["TextInputField.tsx"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Input } from \"@base-ui/react/input\";\nimport React from \"react\";\nimport type { TextInputFieldProps } from \"../FormFieldApi.js\";\nimport styles from \"./BaseInput.module.css\";\n\nexport function TextInputField({\n id,\n value,\n onChange,\n placeholder,\n minLength,\n maxLength,\n}: TextInputFieldProps & { id?: string }): React.ReactElement {\n return (\n <Input\n id={id}\n className={styles.osdkBaseInput}\n type=\"text\"\n value={value ?? \"\"}\n onValueChange={onChange}\n placeholder={placeholder}\n minLength={minLength}\n maxLength={maxLength}\n />\n );\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,KAAK,QAAQ,sBAAsB;AAC5C,OAAOC,KAAK,MAAM,OAAO;AAEzB,OAAOC,MAAM,MAAM,wBAAwB;AAE3C,OAAO,SAASC,cAAcA,CAAC;EAC7BC,EAAE;EACFC,KAAK;EACLC,QAAQ;EACRC,WAAW;EACXC,SAAS;EACTC;AACqC,CAAC,EAAsB;EAC5D,oBACER,KAAA,CAAAS,aAAA,CAACV,KAAK;IACJI,EAAE,EAAEA,EAAG;IACPO,SAAS,EAAET,MAAM,CAACU,aAAc;IAChCC,IAAI,EAAC,MAAM;IACXR,KAAK,EAAEA,KAAK,IAAI,EAAG;IACnBS,aAAa,EAAER,QAAS;IACxBC,WAAW,EAAEA,WAAY;IACzBC,SAAS,EAAEA,SAAU;IACrBC,SAAS,EAAEA;EAAU,CACtB,CAAC;AAEN","ignoreList":[]}
1
+ {"version":3,"file":"TextInputField.js","names":["Input","React","styles","TextInputField","id","value","onChange","error","placeholder","minLength","maxLength","createElement","className","osdkBaseInput","type","onValueChange","undefined"],"sources":["TextInputField.tsx"],"sourcesContent":["/*\n * Copyright 2026 Palantir Technologies, Inc. All rights reserved.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Input } from \"@base-ui/react/input\";\nimport React from \"react\";\nimport type { TextInputFieldProps } from \"../FormFieldApi.js\";\nimport styles from \"./BaseInput.module.css\";\n\nexport function TextInputField({\n id,\n value,\n onChange,\n error,\n placeholder,\n minLength,\n maxLength,\n}: TextInputFieldProps & { id?: string }): React.ReactElement {\n return (\n <Input\n id={id}\n className={styles.osdkBaseInput}\n type=\"text\"\n value={value ?? \"\"}\n onValueChange={onChange}\n placeholder={placeholder}\n minLength={minLength}\n maxLength={maxLength}\n aria-invalid={error != null || undefined}\n />\n );\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,SAASA,KAAK,QAAQ,sBAAsB;AAC5C,OAAOC,KAAK,MAAM,OAAO;AAEzB,OAAOC,MAAM,MAAM,wBAAwB;AAE3C,OAAO,SAASC,cAAcA,CAAC;EAC7BC,EAAE;EACFC,KAAK;EACLC,QAAQ;EACRC,KAAK;EACLC,WAAW;EACXC,SAAS;EACTC;AACqC,CAAC,EAAsB;EAC5D,oBACET,KAAA,CAAAU,aAAA,CAACX,KAAK;IACJI,EAAE,EAAEA,EAAG;IACPQ,SAAS,EAAEV,MAAM,CAACW,aAAc;IAChCC,IAAI,EAAC,MAAM;IACXT,KAAK,EAAEA,KAAK,IAAI,EAAG;IACnBU,aAAa,EAAET,QAAS;IACxBE,WAAW,EAAEA,WAAY;IACzBC,SAAS,EAAEA,SAAU;IACrBC,SAAS,EAAEA,SAAU;IACrB,gBAAcH,KAAK,IAAI,IAAI,IAAIS;EAAU,CAC1C,CAAC;AAEN","ignoreList":[]}