@noya-app/noya-designsystem 0.1.41 → 0.1.43

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 (53) hide show
  1. package/.turbo/turbo-build.log +10 -10
  2. package/CHANGELOG.md +16 -0
  3. package/dist/index.css +1 -1
  4. package/dist/index.d.mts +268 -147
  5. package/dist/index.d.ts +268 -147
  6. package/dist/index.js +7618 -6908
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +6161 -5487
  9. package/dist/index.mjs.map +1 -1
  10. package/package.json +4 -5
  11. package/src/__tests__/combobox.test.ts +578 -0
  12. package/src/components/ActivityIndicator.tsx +4 -4
  13. package/src/components/AnimatePresence.tsx +5 -5
  14. package/src/components/Avatar.tsx +5 -2
  15. package/src/components/BaseToolbar.tsx +61 -0
  16. package/src/components/Button.tsx +1 -1
  17. package/src/components/Checkbox.tsx +6 -5
  18. package/src/components/Combobox.tsx +327 -337
  19. package/src/components/ComboboxMenu.tsx +88 -0
  20. package/src/components/Dialog.tsx +10 -6
  21. package/src/components/DimensionInput.tsx +4 -4
  22. package/src/components/FillPreviewBackground.tsx +51 -44
  23. package/src/components/FloatingWindow.tsx +5 -2
  24. package/src/components/GradientPicker.tsx +14 -14
  25. package/src/components/IconButton.tsx +6 -12
  26. package/src/components/Icons.tsx +3 -3
  27. package/src/components/InputField.tsx +145 -160
  28. package/src/components/Label.tsx +4 -4
  29. package/src/components/LabeledElementView.tsx +35 -41
  30. package/src/components/ListView.tsx +49 -39
  31. package/src/components/Message.tsx +75 -0
  32. package/src/components/Progress.tsx +2 -2
  33. package/src/components/ScrollArea.tsx +7 -5
  34. package/src/components/SegmentedControl.tsx +171 -0
  35. package/src/components/SelectMenu.tsx +61 -10
  36. package/src/components/Slider.tsx +5 -2
  37. package/src/components/Sortable.tsx +17 -27
  38. package/src/components/Spacer.tsx +28 -9
  39. package/src/components/Switch.tsx +8 -8
  40. package/src/components/TextArea.tsx +59 -12
  41. package/src/components/Toolbar.tsx +129 -0
  42. package/src/components/Tooltip.tsx +10 -7
  43. package/src/components/WorkspaceLayout.tsx +145 -152
  44. package/src/components/internal/Menu.tsx +5 -4
  45. package/src/contexts/DesignSystemConfiguration.tsx +15 -24
  46. package/src/contexts/DialogContext.tsx +137 -49
  47. package/src/contexts/ImageDataContext.tsx +6 -12
  48. package/src/index.css +1 -3
  49. package/src/index.tsx +12 -3
  50. package/src/utils/combobox.ts +369 -0
  51. package/tailwind.config.ts +1 -2
  52. package/src/components/RadioGroup.tsx +0 -100
  53. package/src/utils/completions.ts +0 -21
@@ -1,13 +1,11 @@
1
- import { CaretDownIcon } from "@noya-app/noya-icons";
1
+ import { DropdownChevronIcon } from "@noya-app/noya-icons";
2
2
  import { assignRef, memoGeneric } from "@noya-app/react-utils";
3
3
  import { Property } from "csstype";
4
4
  import React, {
5
- Children,
6
5
  createContext,
7
6
  FocusEventHandler,
8
7
  ForwardedRef,
9
8
  forwardRef,
10
- isValidElement,
11
9
  LabelHTMLAttributes,
12
10
  memo,
13
11
  ReactNode,
@@ -36,7 +34,6 @@ type InputFieldContextValue = {
36
34
  labelPosition: LabelPosition;
37
35
  labelSize?: number;
38
36
  buttonSize?: number;
39
- hasDropdown: boolean;
40
37
  /** @default medium */
41
38
  size: InputFieldSize;
42
39
  isFocused: boolean;
@@ -48,23 +45,64 @@ type InputFieldContextValue = {
48
45
  id?: string;
49
46
  };
50
47
 
48
+ const getLabelPosition = ({
49
+ labelPosition,
50
+ size,
51
+ buttonSize,
52
+ }: {
53
+ labelPosition: LabelPosition;
54
+ size: InputFieldSize;
55
+ buttonSize?: number;
56
+ }) => ({
57
+ left:
58
+ labelPosition === "start"
59
+ ? size === "large"
60
+ ? "6px"
61
+ : size === "medium"
62
+ ? "2px"
63
+ : "0px"
64
+ : "",
65
+ right:
66
+ labelPosition === "end"
67
+ ? size === "large"
68
+ ? `${6 + (buttonSize ?? 0)}px`
69
+ : size === "medium"
70
+ ? `${2 + (buttonSize ?? 0)}px`
71
+ : `${buttonSize ?? 0}px`
72
+ : "",
73
+ });
74
+
75
+ const getInputFieldSpacing = ({
76
+ labelPosition,
77
+ buttonSize,
78
+ labelSize,
79
+ }: {
80
+ labelPosition: LabelPosition;
81
+ size?: InputFieldSize;
82
+ buttonSize?: number;
83
+ labelSize?: number;
84
+ }) => ({
85
+ paddingLeft: `${labelSize && labelPosition === "start" ? 6 + labelSize : 6}px`,
86
+ paddingRight: `${labelPosition === "end" ? 6 + (labelSize ?? 0) + (buttonSize ? buttonSize + 6 : 0) : 6}px`,
87
+ });
88
+
51
89
  const InputFieldContext = createContext<InputFieldContextValue>({
52
90
  labelPosition: "end",
53
91
  labelSize: undefined,
54
92
  buttonSize: undefined,
55
- hasDropdown: false,
56
93
  size: "medium",
57
94
  isFocused: false,
58
95
  onFocusChange: () => {},
59
96
  });
60
97
 
98
+ const noop = () => {};
99
+
61
100
  /* ----------------------------------------------------------------------------
62
101
  * Label
63
102
  * ------------------------------------------------------------------------- */
64
103
 
65
104
  interface LabelContainerProps {
66
105
  labelPosition: LabelPosition;
67
- hasDropdown: boolean;
68
106
  size: InputFieldSize;
69
107
  className?: string;
70
108
  children?: React.ReactNode;
@@ -75,7 +113,6 @@ interface LabelContainerProps {
75
113
  const LabelContainer = forwardRef(function LabelContainer(
76
114
  {
77
115
  labelPosition: $labelPosition,
78
- hasDropdown: $hasDropdown,
79
116
  size: $size,
80
117
  className,
81
118
  style,
@@ -84,27 +121,15 @@ const LabelContainer = forwardRef(function LabelContainer(
84
121
  ref: ForwardedRef<HTMLLabelElement>
85
122
  ) {
86
123
  const { buttonSize } = useContext(InputFieldContext);
124
+ const spacingStyles = getLabelPosition({
125
+ labelPosition: $labelPosition,
126
+ size: $size,
127
+ buttonSize,
128
+ });
129
+
87
130
  const memoizedStyles = useMemo(
88
- () => ({
89
- left:
90
- $labelPosition === "start"
91
- ? $size === "large"
92
- ? "6px"
93
- : $size === "medium"
94
- ? "2px"
95
- : "0px"
96
- : "",
97
- right:
98
- $labelPosition === "end"
99
- ? $size === "large"
100
- ? `${6 + (buttonSize ?? 0)}px`
101
- : $size === "medium"
102
- ? `${2 + (buttonSize ?? 0)}px`
103
- : `${buttonSize ?? 0}px`
104
- : "",
105
- ...style,
106
- }),
107
- [$labelPosition, $size, buttonSize, style]
131
+ () => ({ ...spacingStyles, ...style }),
132
+ [spacingStyles, style]
108
133
  );
109
134
 
110
135
  return (
@@ -114,8 +139,7 @@ const LabelContainer = forwardRef(function LabelContainer(
114
139
  "absolute top-0 bottom-0 flex items-center font-sans text-label font-bold uppercase text-text-disabled select-none z-label pointer-events-none",
115
140
  $labelPosition === "start"
116
141
  ? `justify-start pl-1.5`
117
- : $labelPosition === "end" &&
118
- `justify-end ${$hasDropdown ? "pr-4" : "pr-1.5"}`,
142
+ : $labelPosition === "end" && "justify-end pr-1.5",
119
143
  className
120
144
  )}
121
145
  style={memoizedStyles}
@@ -132,7 +156,7 @@ const InputFieldLabel = memo(
132
156
  props: LabelHTMLAttributes<HTMLLabelElement>,
133
157
  forwardedRef: ForwardedRef<HTMLLabelElement>
134
158
  ) {
135
- const { labelPosition, hasDropdown, setLabelWidth, size, id } =
159
+ const { labelPosition, setLabelWidth, size, id } =
136
160
  useContext(InputFieldContext);
137
161
 
138
162
  const ref = useRef<HTMLLabelElement | null>(null);
@@ -155,7 +179,6 @@ const InputFieldLabel = memo(
155
179
  }}
156
180
  size={size}
157
181
  labelPosition={labelPosition}
158
- hasDropdown={hasDropdown}
159
182
  htmlFor={id}
160
183
  {...props}
161
184
  />
@@ -188,28 +211,18 @@ interface InputFieldDropdownProps<T extends string> {
188
211
  const InputFieldDropdownMenu = memoGeneric(function InputFieldDropdownMenu<
189
212
  T extends string,
190
213
  >({ id, items, onSelect, children }: InputFieldDropdownProps<T>) {
191
- const { size } = useContext(InputFieldContext);
192
-
193
- const contentStyle = useMemo(
194
- () => ({
195
- margin: "-4px 0",
196
- minHeight: size === "small" ? "15px" : undefined,
197
- }),
198
- [size]
199
- );
200
-
201
214
  return (
202
215
  <DropdownContainer>
203
- <DropdownMenu<T> items={items} onSelect={onSelect}>
216
+ <DropdownMenu<T>
217
+ items={items}
218
+ onSelect={onSelect}
219
+ align="end"
220
+ sideOffset={8}
221
+ >
204
222
  {children || (
205
- <Button
206
- id={id}
207
- variant="thin"
208
- className="flex flex-1"
209
- contentStyle={contentStyle}
210
- >
211
- <CaretDownIcon />
212
- </Button>
223
+ <InputFieldButton variant="floating" id={id}>
224
+ <DropdownChevronIcon />
225
+ </InputFieldButton>
213
226
  )}
214
227
  </DropdownMenu>
215
228
  </DropdownContainer>
@@ -220,35 +233,23 @@ const InputFieldDropdownMenu = memoGeneric(function InputFieldDropdownMenu<
220
233
  * Button
221
234
  * ------------------------------------------------------------------------- */
222
235
 
223
- const ButtonContainer = forwardRef<
224
- HTMLSpanElement,
225
- { $size: InputFieldSize; className?: string; children?: React.ReactNode }
226
- >(({ $size, className, ...props }, ref) => (
227
- <span
228
- ref={ref}
229
- className={cx(
230
- "absolute",
231
- $size === "large"
232
- ? "right-[9px] top-2.5"
233
- : $size === "medium"
234
- ? "right-1 top-1"
235
- : $size === "small"
236
- ? "right-0.5 top-0.5"
237
- : "",
238
- "z-label",
239
- className
240
- )}
241
- {...props}
242
- />
243
- ));
244
-
245
236
  /** Inserts a Button at the end of the input. Should not be used with an InputField.Label */
246
237
  const InputFieldButton = memo(
247
238
  forwardRef(function InputFieldButton(
248
- props: React.ButtonHTMLAttributes<HTMLButtonElement>,
239
+ props: React.ButtonHTMLAttributes<HTMLButtonElement> & {
240
+ buttonClassName?: string;
241
+ variant?: "floating" | "normal";
242
+ },
249
243
  forwardedRef: ForwardedRef<HTMLButtonElement>
250
244
  ) {
251
- const { children, onClick, ...rest } = props;
245
+ const {
246
+ children,
247
+ onClick,
248
+ className,
249
+ buttonClassName,
250
+ variant = "normal",
251
+ ...rest
252
+ } = props;
252
253
  const { size, inputRef, setButtonWidth } = useContext(InputFieldContext);
253
254
 
254
255
  const ref = useRef<HTMLButtonElement | null>(null);
@@ -286,7 +287,21 @@ const InputFieldButton = memo(
286
287
  );
287
288
 
288
289
  return (
289
- <ButtonContainer $size={size}>
290
+ <span
291
+ className={cx(
292
+ "absolute",
293
+ size === "large"
294
+ ? "right-[9px] top-2.5"
295
+ : size === "medium"
296
+ ? "right-1 top-1"
297
+ : size === "small"
298
+ ? "right-0.5 top-0.5"
299
+ : "",
300
+ "z-label",
301
+ variant === "floating" && "right-0",
302
+ className
303
+ )}
304
+ >
290
305
  <Button
291
306
  ref={(element) => {
292
307
  ref.current = element;
@@ -297,11 +312,15 @@ const InputFieldButton = memo(
297
312
  onPointerDown={handlePointerDown}
298
313
  tabIndex={-1}
299
314
  size={size === "medium" ? "normal" : size}
315
+ className={cx(
316
+ buttonClassName,
317
+ variant === "floating" && "bg-transparent shadow-none !px-0.5"
318
+ )}
300
319
  {...rest}
301
320
  >
302
321
  {children}
303
322
  </Button>
304
- </ButtonContainer>
323
+ </span>
305
324
  );
306
325
  })
307
326
  );
@@ -322,12 +341,8 @@ type InputFieldVariant = "normal" | "bare";
322
341
  type InputElementProps = {
323
342
  disabled?: boolean;
324
343
  readOnly?: boolean;
325
- $labelPosition: LabelPosition;
326
- $labelSize?: number;
327
- $hasDropdown: boolean;
328
344
  $textAlign?: Property.TextAlign;
329
345
  $variant?: InputFieldVariant;
330
- $size: InputFieldSize;
331
346
  children?: React.ReactNode;
332
347
  className?: string;
333
348
  style?: React.CSSProperties;
@@ -341,45 +356,30 @@ const InputElement = forwardRef(
341
356
  {
342
357
  disabled,
343
358
  readOnly,
344
- $labelPosition,
345
- $labelSize,
346
- $hasDropdown,
347
359
  $textAlign,
348
360
  $variant = "normal",
349
- $size,
350
361
  className,
351
362
  children,
352
363
  value,
353
364
  onSubmit,
354
365
  as = "input",
366
+ style,
355
367
  ...props
356
368
  }: InputElementProps,
357
369
  ref: ForwardedRef<any>
358
370
  ) => {
359
- const paddingLeft =
360
- $variant === "bare"
361
- ? 0
362
- : ($size === "large" ? 10 : $size === "medium" ? 6 : 4) +
363
- ($labelSize && $labelPosition === "start" ? 6 + $labelSize : 0);
364
-
365
- const paddingRight =
366
- $variant === "bare"
367
- ? 0
368
- : ($size === "large" ? 10 : $size === "medium" ? 6 : 1) +
369
- ($labelSize && $labelPosition === "end" ? 6 + $labelSize : 0) +
370
- ($hasDropdown ? 11 : 0);
371
-
372
- const memoizedStyles = useMemo(
373
- () => ({
374
- paddingLeft: `${paddingLeft}px`,
375
- paddingRight: `${paddingRight}px`,
376
- ...props.style,
377
- }),
378
- [paddingLeft, paddingRight, props.style]
379
- );
371
+ const { buttonSize, labelSize, labelPosition, size } =
372
+ useContext(InputFieldContext);
373
+
374
+ const spacingStyles = getInputFieldSpacing({
375
+ labelPosition,
376
+ size,
377
+ buttonSize,
378
+ labelSize,
379
+ });
380
380
 
381
381
  const inputClassName = cx(
382
- "flex w-0 flex-1 relative border-0 outline-none min-w-0 self-stretch rounded bg-input-background focus:ring-2 focus:ring-primary placeholder:text-text-disabled",
382
+ "flex w-0 flex-1 relative border-0 outline-none min-w-0 self-stretch rounded bg-input-background focus:ring-2 focus:ring-primary placeholder:text-text-disabled transition-all",
383
383
  readOnly
384
384
  ? "text-text-muted"
385
385
  : disabled
@@ -387,11 +387,11 @@ const InputElement = forwardRef(
387
387
  : "text-text",
388
388
  "font-sans font-normal",
389
389
  $textAlign && `text-${$textAlign}`,
390
- $size === "small"
390
+ size === "small"
391
391
  ? "text-[11px] leading-[19px] py-[1px]"
392
- : $size === "large"
392
+ : size === "large"
393
393
  ? "py-2.5 text-heading5"
394
- : $size === "medium"
394
+ : size === "medium"
395
395
  ? "py-1 text-heading5"
396
396
  : $variant === "bare" && "py-1 -m-1",
397
397
  className
@@ -403,7 +403,7 @@ const InputElement = forwardRef(
403
403
  ref={ref}
404
404
  {...props}
405
405
  className={inputClassName}
406
- style={memoizedStyles}
406
+ style={{ ...spacingStyles, ...style }}
407
407
  >
408
408
  {children}
409
409
  </span>
@@ -417,7 +417,7 @@ const InputElement = forwardRef(
417
417
  onSubmit={onSubmit ?? (() => {})}
418
418
  {...props}
419
419
  className={inputClassName}
420
- style={memoizedStyles}
420
+ style={{ ...spacingStyles, ...style }}
421
421
  />
422
422
  );
423
423
  }
@@ -434,16 +434,7 @@ const InputFieldInput = forwardRef(function InputFieldInput(
434
434
  { textAlign, variant, ...rest }: InputFieldInputProps,
435
435
  forwardedRef: ForwardedRef<HTMLInputElement>
436
436
  ) {
437
- const {
438
- labelPosition,
439
- labelSize,
440
- hasDropdown,
441
- buttonSize,
442
- size,
443
- onFocusChange,
444
- setInputRef,
445
- id,
446
- } = useContext(InputFieldContext);
437
+ const { onFocusChange, setInputRef, id } = useContext(InputFieldContext);
447
438
 
448
439
  const handleFocusChange = useCallback(
449
440
  (isFocused: boolean) => {
@@ -459,10 +450,6 @@ const InputFieldInput = forwardRef(function InputFieldInput(
459
450
  return (
460
451
  <InputElement
461
452
  ref={forwardedRef}
462
- $labelPosition={labelPosition}
463
- $labelSize={labelSize || buttonSize}
464
- $hasDropdown={hasDropdown}
465
- $size={size}
466
453
  $variant={variant}
467
454
  $textAlign={textAlign}
468
455
  onFocusChange={handleFocusChange}
@@ -472,17 +459,14 @@ const InputFieldInput = forwardRef(function InputFieldInput(
472
459
  );
473
460
  });
474
461
 
475
- const InputFieldTypeahead = (props: { prefix: string; value: string }) => {
476
- const { labelPosition, labelSize, hasDropdown, size } =
477
- useContext(InputFieldContext);
478
-
462
+ const InputFieldTypeahead = (props: {
463
+ prefix: string;
464
+ value: string;
465
+ isFocused: boolean;
466
+ }) => {
479
467
  return (
480
468
  <InputElement
481
469
  as="span"
482
- $labelPosition={labelPosition}
483
- $labelSize={labelSize}
484
- $hasDropdown={hasDropdown}
485
- $size={size}
486
470
  style={useMemo(
487
471
  () => ({
488
472
  position: "absolute",
@@ -498,9 +482,11 @@ const InputFieldTypeahead = (props: { prefix: string; value: string }) => {
498
482
  )}
499
483
  >
500
484
  <span style={{ opacity: 0 }}>{props.prefix}</span>
501
- <span style={{ opacity: 0.5 }}>
502
- {props.value.slice(props.prefix.length)}
503
- </span>
485
+ {props.isFocused && (
486
+ <span style={{ opacity: 0.5 }}>
487
+ {props.value.slice(props.prefix.length)}
488
+ </span>
489
+ )}
504
490
  </InputElement>
505
491
  );
506
492
  };
@@ -511,13 +497,14 @@ const InputFieldTypeahead = (props: { prefix: string; value: string }) => {
511
497
 
512
498
  type InputFieldNumberInputProps = Omit<
513
499
  TextInputProps,
514
- "value" | "onChange" | "onKeyDown" | "onSubmit"
500
+ "value" | "onChange" | "onKeyDown" | "onSubmit" | "readOnly"
515
501
  > & {
516
502
  value: number | undefined;
517
503
  onNudge?: (value: number) => void;
518
504
  variant?: "bare";
519
505
  onFocus?: FocusEventHandler;
520
506
  onBlur?: FocusEventHandler;
507
+ readOnly?: boolean;
521
508
  } & (
522
509
  | {
523
510
  onChange: (value: number) => void;
@@ -532,7 +519,7 @@ function parseNumber(value: string) {
532
519
  }
533
520
 
534
521
  function InputFieldNumberInput(props: InputFieldNumberInputProps) {
535
- const { value, placeholder, onNudge, onBlur, ...rest } = props;
522
+ const { value, placeholder, onNudge, onBlur, readOnly, ...rest } = props;
536
523
  const onSubmit = "onSubmit" in props ? props.onSubmit : undefined;
537
524
  const onChange = "onChange" in props ? props.onChange : undefined;
538
525
 
@@ -609,11 +596,12 @@ function InputFieldNumberInput(props: InputFieldNumberInputProps) {
609
596
  : String(value)
610
597
  }
611
598
  placeholder={placeholder}
612
- onKeyDown={handleKeyDown}
599
+ onKeyDown={!readOnly ? handleKeyDown : undefined}
613
600
  onBlur={handleBlur}
601
+ {...(readOnly ? { readOnly: true } : {})}
614
602
  {...("onChange" in props
615
- ? { onChange: handleChange }
616
- : { onSubmit: handleSubmit })}
603
+ ? { onChange: readOnly ? noop : handleChange }
604
+ : { onSubmit: readOnly ? noop : handleSubmit })}
617
605
  />
618
606
  );
619
607
  }
@@ -644,16 +632,19 @@ const RootContainer = forwardRef<
644
632
 
645
633
  interface InputFieldRootProps {
646
634
  id?: string;
647
- flex?: string;
648
635
  children?: ReactNode;
649
636
  width?: number;
650
637
  /** @default end */
651
638
  labelPosition?: LabelPosition;
652
639
  labelSize?: number;
653
- hasDropdown?: boolean;
654
640
  /** @default medium */
655
641
  size?: InputFieldSize;
656
642
  renderPopoverContent?: (options: { width: number }) => ReactNode;
643
+ /**
644
+ * if there is a popover, this is the offset from the trigger
645
+ * @default 3
646
+ */
647
+ sideOffset?: number;
657
648
  onFocusChange?: (isFocused: boolean) => void;
658
649
  style?: React.CSSProperties;
659
650
  className?: string;
@@ -661,10 +652,10 @@ interface InputFieldRootProps {
661
652
 
662
653
  function InputFieldRoot({
663
654
  id,
664
- flex,
665
655
  children,
666
656
  width,
667
657
  labelPosition = "end",
658
+ sideOffset = 3,
668
659
  labelSize,
669
660
  size = "medium",
670
661
  renderPopoverContent,
@@ -672,13 +663,8 @@ function InputFieldRoot({
672
663
  style,
673
664
  className,
674
665
  }: InputFieldRootProps) {
675
- const childrenArray = Children.toArray(children);
676
666
  const randomId = useId();
677
667
 
678
- const hasDropdown = childrenArray.some(
679
- (child) => isValidElement(child) && child.type === InputFieldDropdownMenu
680
- );
681
-
682
668
  const [isFocused, setIsFocused] = React.useState(false);
683
669
 
684
670
  const [measuredLabelSize, setMeasuredLabelSize] = React.useState<number>();
@@ -710,7 +696,6 @@ function InputFieldRoot({
710
696
  labelPosition,
711
697
  labelSize: measuredLabelSize ?? labelSize,
712
698
  buttonSize: measuredButtonSize,
713
- hasDropdown,
714
699
  size,
715
700
  isFocused,
716
701
  onFocusChange: handleFocusChange,
@@ -725,7 +710,6 @@ function InputFieldRoot({
725
710
  measuredLabelSize,
726
711
  labelSize,
727
712
  measuredButtonSize,
728
- hasDropdown,
729
713
  size,
730
714
  isFocused,
731
715
  handleFocusChange,
@@ -742,7 +726,7 @@ function InputFieldRoot({
742
726
  );
743
727
 
744
728
  const measuredWidthObject = useMemo(
745
- () => (measuredWidth ? { width: measuredWidth + 12 } : undefined),
729
+ () => (measuredWidth ? { width: measuredWidth + 4 } : undefined),
746
730
  [measuredWidth]
747
731
  );
748
732
 
@@ -752,7 +736,7 @@ function InputFieldRoot({
752
736
  <Popover
753
737
  open={true}
754
738
  trigger={rootElement}
755
- sideOffset={3}
739
+ sideOffset={sideOffset}
756
740
  showArrow={false}
757
741
  onOpenAutoFocus={(event) => {
758
742
  event.preventDefault();
@@ -795,19 +779,20 @@ const PrimitiveInputField = ({
795
779
  const { labelSize, labelPosition, buttonSize } =
796
780
  useContext(InputFieldContext);
797
781
 
782
+ const spacingStyles = getInputFieldSpacing({
783
+ labelPosition,
784
+ buttonSize,
785
+ labelSize,
786
+ });
798
787
  const memoizedStyles = useMemo(
799
- () => ({
800
- paddingLeft: `${labelSize && labelPosition === "start" ? 6 + labelSize : 6}px`,
801
- paddingRight: `${labelPosition === "end" ? 6 + (labelSize ?? 0) + (buttonSize ?? 0) : 6}px`,
802
- ...style,
803
- }),
804
- [labelSize, labelPosition, buttonSize, style]
788
+ () => ({ ...spacingStyles, ...style }),
789
+ [spacingStyles, style]
805
790
  );
806
791
  return (
807
792
  <input
808
793
  style={memoizedStyles}
809
794
  className={cx(
810
- "flex w-0 flex-1 relative border-none outline-none min-w-0 self-stretch rounded py-1 bg-input-background select-all pointer-events-[all] focus:ring-2 focus:ring-primary font-sans font-normal text-heading5 placeholder:text-text-disabled focus:z-interactable",
795
+ "flex w-0 flex-1 relative border-none outline-none min-w-0 self-stretch rounded py-1 bg-input-background select-all pointer-events-[all] focus:ring-2 focus:ring-primary font-sans font-normal text-heading5 placeholder:text-text-disabled focus:z-interactable transition-all",
811
796
  readOnly
812
797
  ? "text-text-muted"
813
798
  : disabled
@@ -1,10 +1,10 @@
1
- import React, { forwardRef, LabelHTMLAttributes, memo } from "react";
1
+ import * as React from "react";
2
2
  import { cx } from "../utils/classNames";
3
3
 
4
- interface LabelProps extends LabelHTMLAttributes<HTMLLabelElement> {}
4
+ interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {}
5
5
 
6
- export const Label = memo(
7
- forwardRef<HTMLLabelElement, LabelProps>(function Label(
6
+ export const Label = React.memo(
7
+ React.forwardRef<HTMLLabelElement, LabelProps>(function Label(
8
8
  { className, ...props },
9
9
  ref
10
10
  ) {