@noya-app/noya-designsystem 0.1.31 → 0.1.32

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 (61) hide show
  1. package/.turbo/turbo-build.log +20 -12
  2. package/.turbo/turbo-lint.log +2 -1
  3. package/CHANGELOG.md +7 -0
  4. package/README.md +13 -1
  5. package/dist/index.css +1 -0
  6. package/dist/index.d.ts +132 -509
  7. package/dist/index.js +4167 -2716
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +4097 -2643
  10. package/dist/index.mjs.map +1 -1
  11. package/package.json +14 -5
  12. package/src/components/ActivityIndicator.tsx +4 -36
  13. package/src/components/Avatar.tsx +63 -62
  14. package/src/components/Button.tsx +53 -172
  15. package/src/components/Chip.tsx +117 -150
  16. package/src/components/ContextMenu.tsx +13 -35
  17. package/src/components/Dialog.tsx +66 -54
  18. package/src/components/Divider.tsx +31 -41
  19. package/src/components/DraggableMenuButton.tsx +29 -30
  20. package/src/components/DropdownMenu.tsx +30 -40
  21. package/src/components/FillInputField.tsx +16 -26
  22. package/src/components/FillPreviewBackground.tsx +18 -22
  23. package/src/components/FloatingWindow.tsx +4 -7
  24. package/src/components/GridView.tsx +70 -200
  25. package/src/components/IconButton.tsx +1 -5
  26. package/src/components/InputField.tsx +191 -194
  27. package/src/components/InputFieldWithCompletions.tsx +20 -27
  28. package/src/components/InspectorContainer.tsx +4 -9
  29. package/src/components/InspectorPrimitives.tsx +135 -109
  30. package/src/components/Label.tsx +5 -36
  31. package/src/components/LabeledElementView.tsx +5 -26
  32. package/src/components/ListView.tsx +239 -167
  33. package/src/components/Popover.tsx +15 -39
  34. package/src/components/Progress.tsx +21 -44
  35. package/src/components/RadioGroup.tsx +6 -71
  36. package/src/components/ScrollArea.tsx +11 -39
  37. package/src/components/SelectMenu.tsx +31 -48
  38. package/src/components/Slider.tsx +7 -43
  39. package/src/components/Spacer.tsx +6 -18
  40. package/src/components/Switch.tsx +4 -42
  41. package/src/components/Text.tsx +31 -66
  42. package/src/components/TextArea.tsx +5 -31
  43. package/src/components/Toast.tsx +15 -57
  44. package/src/components/Tooltip.tsx +4 -13
  45. package/src/components/WorkspaceLayout.tsx +4 -14
  46. package/src/components/internal/Menu.tsx +37 -83
  47. package/src/contexts/DesignSystemConfiguration.tsx +1 -47
  48. package/src/contexts/DialogContext.tsx +2 -10
  49. package/src/hooks/useDarkMode.ts +14 -0
  50. package/src/index.css +108 -0
  51. package/src/index.tsx +3 -4
  52. package/src/theme/index.ts +4 -16
  53. package/src/utils/tailwind.ts +17 -0
  54. package/tailwind.config.ts +106 -166
  55. package/tsup.config.ts +16 -0
  56. package/dist/index.d.mts +0 -1443
  57. package/src/components/Grid.tsx +0 -54
  58. package/src/components/Stack.tsx +0 -164
  59. package/src/theme/dark.ts +0 -45
  60. package/src/theme/light.ts +0 -226
  61. package/src/utils/breakpoints.ts +0 -45
@@ -17,14 +17,12 @@ import React, {
17
17
  useRef,
18
18
  useState,
19
19
  } from "react";
20
- import styled from "styled-components";
21
20
  import handleNudge from "../utils/handleNudge";
22
21
  import { Button } from "./Button";
23
22
  import { DropdownMenu } from "./DropdownMenu";
24
23
  import { MenuItem } from "./internal/Menu";
25
24
  import TextInput, { TextInputProps } from "./internal/TextInput";
26
25
  import { Popover } from "./Popover";
27
- import { Stack } from "./Stack";
28
26
 
29
27
  type LabelPosition = "start" | "end";
30
28
 
@@ -59,46 +57,60 @@ const InputFieldContext = createContext<InputFieldContextValue>({
59
57
  * Label
60
58
  * ------------------------------------------------------------------------- */
61
59
 
62
- const LabelContainer = styled.label<{
63
- pointerEvents: Property.PointerEvents;
64
- $labelPosition: LabelPosition;
65
- $hasDropdown: boolean;
66
- $size: InputFieldSize;
67
- }>(({ theme, $labelPosition, $hasDropdown, pointerEvents, $size }) => {
68
- const offsetRelativeToSize =
69
- $size === "large" ? 6 : $size === "medium" ? 2 : 0;
70
- return {
71
- ...theme.textStyles.label,
72
- fontWeight: "bold",
73
- color: theme.colors.textDisabled,
74
- position: "absolute",
75
- top: 0,
76
- bottom: 0,
77
- right: $labelPosition === "end" ? offsetRelativeToSize : undefined,
78
- left: $labelPosition === "start" ? offsetRelativeToSize : undefined,
79
- display: "flex",
80
- alignItems: "center",
81
- pointerEvents,
82
- userSelect: "none",
83
- ...($labelPosition === "start"
84
- ? { justifyContent: "flex-start", paddingLeft: "6px" }
85
- : {
86
- justifyContent: "flex-end",
87
- paddingRight: $hasDropdown ? "16px" : "6px",
88
- }),
89
- };
90
- });
60
+ const LabelContainer = forwardRef<
61
+ HTMLLabelElement,
62
+ {
63
+ pointerEvents: Property.PointerEvents;
64
+ $labelPosition: LabelPosition;
65
+ $hasDropdown: boolean;
66
+ $size: InputFieldSize;
67
+ className?: string;
68
+ children?: React.ReactNode;
69
+ style?: React.CSSProperties;
70
+ }
71
+ >(
72
+ (
73
+ { pointerEvents, $labelPosition, $hasDropdown, $size, className, style, ...props },
74
+ ref
75
+ ) => {
76
+ const memoizedStyles = useMemo(() => ({
77
+ left: $labelPosition === "start" ? $size === "large" ? "6px" : $size === "medium" ? "2px" : "0px" : "",
78
+ right: $labelPosition === "end" ? $size === "large" ? "6px" : $size === "medium" ? "2px" : "0px" : "",
79
+ }), [$labelPosition, $size])
80
+
81
+ return (
82
+ <label
83
+ ref={ref}
84
+ className={`absolute top-0 bottom-0 flex items-center font-sans text-label font-bold uppercase text-text-disabled select-none ${
85
+ $labelPosition === "start"
86
+ ? `justify-start pl-[6px]`
87
+ : $labelPosition === "end"
88
+ ? `justify-end ${$hasDropdown ? "pr-[16px]" : "pr-[6px]"}`
89
+ : ""
90
+ } ${pointerEvents === "none" ? "pointer-events-none" : ""} ${className ?? ""}`}
91
+ style={{...memoizedStyles, ...style}}
92
+ {...props}
93
+ />
94
+ );
95
+ }
96
+ );
91
97
 
92
98
  interface InputFieldLabelProps {
93
99
  children?: ReactNode;
94
100
  pointerEvents?: Property.PointerEvents;
95
101
  style?: React.CSSProperties;
102
+ className?: string;
96
103
  }
97
104
 
98
105
  /** Inserts a Label at the start or end of the input given a `labelPosition`on InputField.Root. Should not be used with an InputField.Button */
99
106
  const InputFieldLabel = memo(
100
107
  forwardRef(function InputFieldLabel(
101
- { children = false, pointerEvents = "none", style }: InputFieldLabelProps,
108
+ {
109
+ children = false,
110
+ pointerEvents = "none",
111
+ style,
112
+ className,
113
+ }: InputFieldLabelProps,
102
114
  forwardedRef: ForwardedRef<HTMLLabelElement>
103
115
  ) {
104
116
  const { labelPosition, hasDropdown, setLabelWidth, size } =
@@ -127,6 +139,7 @@ const InputFieldLabel = memo(
127
139
  $labelPosition={labelPosition}
128
140
  $hasDropdown={hasDropdown}
129
141
  style={style}
142
+ className={className}
130
143
  >
131
144
  {children}
132
145
  </LabelContainer>
@@ -138,14 +151,16 @@ const InputFieldLabel = memo(
138
151
  * Dropdown
139
152
  * ------------------------------------------------------------------------- */
140
153
 
141
- const DropdownContainer = styled.span(({ theme }) => ({
142
- position: "absolute",
143
- top: 0,
144
- right: 0,
145
- bottom: 0,
146
- display: "flex",
147
- flexDirection: "column",
148
- }));
154
+ const DropdownContainer = forwardRef<
155
+ HTMLSpanElement,
156
+ { className?: string; children?: React.ReactNode }
157
+ >(({ className, ...props }, ref) => (
158
+ <span
159
+ ref={ref}
160
+ className={`absolute inset-y-0 right-0 flex flex-col ${className ?? ""}`}
161
+ {...props}
162
+ />
163
+ ));
149
164
 
150
165
  interface InputFieldDropdownProps<T extends string> {
151
166
  id?: string;
@@ -171,7 +186,12 @@ const InputFieldDropdownMenu = memo(function InputFieldDropdownMenu<
171
186
  <DropdownContainer>
172
187
  <DropdownMenu<T> items={items} onSelect={onSelect}>
173
188
  {children || (
174
- <Button id={id} variant="thin" flex="1" contentStyle={contentStyle}>
189
+ <Button
190
+ id={id}
191
+ variant="thin"
192
+ className="flex flex-1"
193
+ contentStyle={contentStyle}
194
+ >
175
195
  <CaretDownIcon />
176
196
  </Button>
177
197
  )}
@@ -184,26 +204,26 @@ const InputFieldDropdownMenu = memo(function InputFieldDropdownMenu<
184
204
  * Button
185
205
  * ------------------------------------------------------------------------- */
186
206
 
187
- const ButtonContainer = styled.span<{ $size: InputFieldSize }>(
188
- ({ theme, $size }) => ({
189
- position: "absolute",
190
- right: $size === "large" ? "9px" : $size === "medium" ? "4px" : "2px",
191
- top: $size === "large" ? "10px" : $size === "medium" ? "4px" : "2px",
192
- })
193
- );
207
+ const ButtonContainer = forwardRef<
208
+ HTMLSpanElement,
209
+ { $size: InputFieldSize; className?: string; children?: React.ReactNode }
210
+ >(({ $size, className, ...props }, ref) => (
211
+ <span
212
+ ref={ref}
213
+ className={`absolute ${$size === "large" ? "right-[9px] top-[10px]" :
214
+ $size === "medium" ? "right-[4px] top-[4px]" :
215
+ $size === "small" ? "right-[2px] top-[2px]" : ""} ${className ?? ""}`}
216
+ {...props}
217
+ />
218
+ ));
194
219
 
195
220
  /** Inserts a Button at the end of the input. Should not be used with an InputField.Label */
196
221
  const InputFieldButton = memo(
197
222
  forwardRef(function InputFieldButton(
198
- {
199
- children,
200
- onClick,
201
- }: {
202
- children?: ReactNode;
203
- onClick?: () => void;
204
- },
223
+ props: React.ButtonHTMLAttributes<HTMLButtonElement>,
205
224
  forwardedRef: ForwardedRef<HTMLButtonElement>
206
225
  ) {
226
+ const { children, onClick, ...rest } = props;
207
227
  const { size, inputRef, setButtonWidth } = useContext(InputFieldContext);
208
228
 
209
229
  const ref = useRef<HTMLButtonElement | null>(null);
@@ -219,7 +239,7 @@ const InputFieldButton = memo(
219
239
  }, [setButtonWidth]);
220
240
 
221
241
  const defaultHandleClick = useCallback(
222
- (event: React.MouseEvent) => {
242
+ (event: React.MouseEvent<HTMLButtonElement>) => {
223
243
  if (inputRef && typeof inputRef !== "function") {
224
244
  inputRef.current?.focus();
225
245
  // Select all text
@@ -232,10 +252,13 @@ const InputFieldButton = memo(
232
252
  [inputRef]
233
253
  );
234
254
 
235
- const handlePointerDown = useCallback((event: React.PointerEvent) => {
236
- event.preventDefault();
237
- event.stopPropagation();
238
- }, []);
255
+ const handlePointerDown = useCallback(
256
+ (event: React.PointerEvent<HTMLButtonElement>) => {
257
+ event.preventDefault();
258
+ event.stopPropagation();
259
+ },
260
+ []
261
+ );
239
262
 
240
263
  return (
241
264
  <ButtonContainer $size={size}>
@@ -249,6 +272,7 @@ const InputFieldButton = memo(
249
272
  onPointerDown={handlePointerDown}
250
273
  tabIndex={-1}
251
274
  size={size === "medium" ? "normal" : size}
275
+ {...rest}
252
276
  >
253
277
  {children}
254
278
  </Button>
@@ -270,7 +294,7 @@ const InputFieldButton = memo(
270
294
 
271
295
  type InputFieldVariant = "normal" | "bare";
272
296
 
273
- export const InputElement = styled(TextInput)<{
297
+ type InputElementProps = {
274
298
  disabled?: boolean;
275
299
  readOnly?: boolean;
276
300
  $labelPosition: LabelPosition;
@@ -279,89 +303,75 @@ export const InputElement = styled(TextInput)<{
279
303
  $textAlign?: Property.TextAlign;
280
304
  $variant?: InputFieldVariant;
281
305
  $size: InputFieldSize;
282
- }>(({
283
- theme,
284
- $labelPosition,
285
- $labelSize,
286
- $hasDropdown,
287
- $textAlign,
288
- disabled,
289
- readOnly,
290
- $variant = "normal",
291
- $size,
292
- }) => {
293
- return {
294
- // placeholder
295
- "&::placeholder": {
296
- color: theme.colors.textDisabled,
297
- },
298
- ...theme.textStyles.small,
299
- color: readOnly
300
- ? theme.colors.textMuted
301
- : disabled
302
- ? theme.colors.textDisabled
303
- : theme.colors.text,
304
- ...($size === "small" && {
305
- fontSize: "11px",
306
- }),
307
- width: "0px", // Reset intrinsic width
308
- flex: "1 1 0px",
309
- position: "relative",
310
- border: "0",
311
- outline: "none",
312
- minWidth: "0",
313
- textAlign: $textAlign ?? "left",
314
- alignSelf: "stretch",
315
- borderRadius: "4px",
316
- paddingTop: $size === "large" ? "10px" : $size === "medium" ? "4px" : "1px",
317
- paddingBottom:
318
- $size === "large" ? "10px" : $size === "medium" ? "4px" : "1px",
319
- paddingLeft:
320
- ($size === "large" ? 10 : $size === "medium" ? 6 : 4) +
321
- ($labelSize && $labelPosition === "start" ? 6 + $labelSize : 0) +
322
- "px",
323
- paddingRight:
306
+ children?: React.ReactNode;
307
+ className?: string;
308
+ value?: string;
309
+ onSubmit?: (value: string) => void;
310
+ };
311
+
312
+ const InputElement = forwardRef(
313
+ (
314
+ {
315
+ disabled,
316
+ readOnly,
317
+ $labelPosition,
318
+ $labelSize,
319
+ $hasDropdown,
320
+ $textAlign,
321
+ $variant = "normal",
322
+ $size,
323
+ className,
324
+ children,
325
+ value,
326
+ onSubmit,
327
+ ...props
328
+ }: InputElementProps,
329
+ ref: ForwardedRef<any>
330
+ ) => {
331
+ const paddingLeft =
324
332
  ($size === "large" ? 10 : $size === "medium" ? 6 : 4) +
333
+ ($labelSize && $labelPosition === "start" ? 6 + $labelSize : 0);
334
+
335
+ const paddingRight =
336
+ ($size === "large" ? 10 : $size === "medium" ? 6 : 1) +
325
337
  ($labelSize && $labelPosition === "end" ? 6 + $labelSize : 0) +
326
- ($hasDropdown ? 11 : 0) +
327
- "px",
328
- background: theme.colors.inputBackground,
329
- "&:focus": {
330
- boxShadow: `0 0 0 2px ${theme.colors.primary}`,
331
- },
332
- ...($variant === "bare" && {
333
- paddingTop: "4px",
334
- paddingRight: "4px",
335
- paddingBottom: "4px",
336
- paddingLeft: "4px",
337
- marginTop: "-4px",
338
- marginRight: "-4px",
339
- marginBottom: "-4px",
340
- marginLeft: "-4px",
341
- }),
338
+ ($hasDropdown ? 11 : 0);
342
339
 
343
- // '&[type="search"]::-webkit-search-cancel-button': {
344
- // appearance: "none",
345
- // height: "15px",
346
- // width: "15px",
347
- // background: `url("data:image/svg+xml;utf8,${createCrossSVGString(
348
- // theme.colors.icon
349
- // )}") no-repeat`,
350
- // },
351
- };
352
- });
340
+ const memoizedStyles = useMemo(() => ({
341
+ paddingLeft: `${paddingLeft}px`,
342
+ paddingRight: `${paddingRight}px`,
343
+ }), [paddingLeft, paddingRight])
344
+
345
+ return (
346
+ <TextInput
347
+ value={value ?? ""}
348
+ onSubmit={onSubmit ?? (() => {})}
349
+ ref={ref}
350
+ className={`flex w-0 flex-[1_1_0px] relative border-0 outline-none min-w-0 self-stretch rounded bg-input-background focus:ring-2 focus:ring-primary focus:z-10 placeholder:text-text-disabled ${readOnly ? "text-text-muted" : disabled ? "text-text-disabled" : "text-text"} font-sans font-normal ${$textAlign && `text-${$textAlign}`} ${
351
+ $size === "small"
352
+ ? "text-[11px] leading-[19px] py-[1px]"
353
+ : $size === "large"
354
+ ? "py-[10px] text-heading5"
355
+ : $size === "medium"
356
+ ? "py-1 text-heading5"
357
+ : $variant === "bare" && "p-1 -m-1"
358
+ } ${className ?? ""}`}
359
+ style={memoizedStyles}
360
+ {...props}
361
+ />
362
+ );
363
+ }
364
+ );
365
+
366
+ export type InputFieldInputProps = TextInputProps & {
367
+ textAlign?: Property.TextAlign;
368
+ variant?: "bare";
369
+ };
353
370
 
354
371
  /** Should always be wrapped in InputField.Root */
355
372
  const InputFieldInput = forwardRef(function InputFieldInput(
356
373
  // onFocusChange should only be passed from the root, never directly
357
- {
358
- textAlign,
359
- variant,
360
- ...rest
361
- }: TextInputProps & {
362
- textAlign?: Property.TextAlign;
363
- variant?: "bare";
364
- },
374
+ { textAlign, variant, ...rest }: InputFieldInputProps,
365
375
  forwardedRef: ForwardedRef<HTMLInputElement>
366
376
  ) {
367
377
  const {
@@ -411,7 +421,6 @@ const InputFieldTypeahead = (props: { prefix: string; value: string }) => {
411
421
 
412
422
  return (
413
423
  <InputElement
414
- as="span"
415
424
  $labelPosition={labelPosition}
416
425
  $labelSize={labelSize}
417
426
  $hasDropdown={hasDropdown}
@@ -419,19 +428,9 @@ const InputFieldTypeahead = (props: { prefix: string; value: string }) => {
419
428
  // onFocusChange={onFocusChange}
420
429
  // readOnly
421
430
  // placeholder={props.value}
431
+ {...props}
422
432
  value=""
423
- style={{
424
- position: "absolute",
425
- top: 0,
426
- left: 0,
427
- right: 0,
428
- bottom: 0,
429
- width: "100%",
430
- height: "100%",
431
- pointerEvents: "none",
432
- background: "transparent",
433
- boxShadow: "none",
434
- }}
433
+ className="absolute inset-0 w-full h-full pointer-events-none bg-transparent shadow-none"
435
434
  >
436
435
  <span style={{ opacity: 0 }}>{props.prefix}</span>
437
436
  <span style={{ opacity: 0.5 }}>
@@ -556,16 +555,23 @@ function InputFieldNumberInput(props: InputFieldNumberInputProps) {
556
555
  * Root
557
556
  * ------------------------------------------------------------------------- */
558
557
 
559
- const RootContainer = styled.div<{
560
- $width?: number;
561
- $flex?: string;
562
- }>(({ theme, $flex, $width }) => ({
563
- flex: $flex ?? "1",
564
- display: "flex",
565
- flexDirection: "row",
566
- position: "relative",
567
- maxWidth: typeof $width === "number" ? `${$width}px` : undefined,
568
- }));
558
+ const RootContainer = forwardRef<
559
+ HTMLDivElement,
560
+ {
561
+ $width?: number;
562
+ $flex?: string;
563
+ className?: string;
564
+ children?: React.ReactNode;
565
+ id?: string;
566
+ style?: React.CSSProperties;
567
+ }
568
+ >(({ $width, $flex, className, ...props }, ref) => (
569
+ <div
570
+ ref={ref}
571
+ className={`flex flex-row relative ${$flex ? `flex-[${$flex}]` : "flex-1"} ${$width || $width === 0 ? `max-w-[${$width}px]` : ""} ${className ?? ""}`}
572
+ {...props}
573
+ />
574
+ ));
569
575
 
570
576
  interface InputFieldRootProps {
571
577
  id?: string;
@@ -686,9 +692,9 @@ function InputFieldRoot({
686
692
  }}
687
693
  >
688
694
  {measuredWidth && (
689
- <Stack.V width={measuredWidth} overflow="hidden">
695
+ <div className={`flex flex-col w-[${measuredWidth}] hidden`}>
690
696
  {renderPopoverContent({ width: measuredWidth })}
691
- </Stack.V>
697
+ </div>
692
698
  )}
693
699
  </Popover>
694
700
  ) : (
@@ -698,38 +704,29 @@ function InputFieldRoot({
698
704
  );
699
705
  }
700
706
 
701
- const PrimitiveInputField = styled.input(({ theme, readOnly, disabled }) => {
702
- return {
703
- // placeholder
704
- "&::placeholder": {
705
- color: theme.colors.textDisabled,
706
- },
707
- ...theme.textStyles.small,
708
- color: readOnly
709
- ? theme.colors.textMuted
710
- : disabled
711
- ? theme.colors.textDisabled
712
- : theme.colors.text,
713
- width: "0px", // Reset intrinsic width
714
- flex: "1 1 0px",
715
- position: "relative",
716
- border: "0",
717
- outline: "none",
718
- minWidth: "0",
719
- alignSelf: "stretch",
720
- borderRadius: "4px",
721
- paddingTop: "4px",
722
- paddingBottom: "4px",
723
- paddingLeft: "6px",
724
- paddingRight: "6px",
725
- background: theme.colors.inputBackground,
726
- "&:focus": {
727
- boxShadow: `0 0 0 2px ${theme.colors.primary}`,
728
- },
729
- userSelect: "all",
730
- pointerEvents: "all",
731
- };
732
- });
707
+ const PrimitiveInputField = ({
708
+ readOnly,
709
+ disabled,
710
+ className,
711
+ ...props
712
+ }: {
713
+ readOnly?: boolean;
714
+ disabled?: boolean;
715
+ } & React.DetailedHTMLProps<
716
+ React.InputHTMLAttributes<HTMLInputElement>,
717
+ HTMLInputElement
718
+ >) => (
719
+ <input
720
+ className={`flex w-0 flex-1 relative border-none outline-none min-w-0 self-stretch rounded py-1 px-1.5 bg-input-background select-all pointer-events-[all] focus:ring-2 focus:ring-primary focus:z-10 font-sans font-normal text-heading5 placeholder:text-text-disabled ${
721
+ readOnly
722
+ ? "text-text-muted"
723
+ : disabled
724
+ ? "text-text-disabled"
725
+ : "text-text"
726
+ } ${className ?? ""}`}
727
+ {...props}
728
+ />
729
+ );
733
730
 
734
731
  export namespace InputField {
735
732
  export const Root = memo(InputFieldRoot);
@@ -13,18 +13,16 @@ import React, {
13
13
  useRef,
14
14
  useState,
15
15
  } from "react";
16
- import styled from "styled-components";
17
16
  import {
18
17
  CompletionItem,
19
18
  CompletionListItem,
20
19
  CompletionSectionHeader,
21
20
  } from "../utils/completions";
22
- import { IToken, fuzzyFilter, fuzzyTokenize } from "../utils/fuzzyScorer";
21
+ import { fuzzyFilter, fuzzyTokenize } from "../utils/fuzzyScorer";
23
22
  import { ActivityIndicator } from "./ActivityIndicator";
24
23
  import { InputField, InputFieldSize } from "./InputField";
25
24
  import { IVirtualizedList, ListView } from "./ListView";
26
25
  import { Spacer } from "./Spacer";
27
- import { Stack } from "./Stack";
28
26
  import { Small } from "./Text";
29
27
 
30
28
  function filterWithGroupedSections(
@@ -66,13 +64,6 @@ function filterWithGroupedSections(
66
64
  });
67
65
  }
68
66
 
69
- export const CompletionToken = styled.span<{ $type: IToken["type"] }>(
70
- ({ $type }) => ({
71
- fontWeight: $type === "match" ? "bold" : "normal",
72
- whiteSpace: "pre",
73
- })
74
- );
75
-
76
67
  interface CompletionMenuProps {
77
68
  items: CompletionListItem[];
78
69
  selectedIndex: number;
@@ -127,9 +118,12 @@ export const CompletionMenu = memo(
127
118
  }}
128
119
  >
129
120
  {tokens.map((token, j) => (
130
- <CompletionToken key={j} $type={token.type}>
121
+ <span
122
+ key={j}
123
+ className={`${token.type === "match" ? "font-bold" : "font-normal"} whitespace-pre`}
124
+ >
131
125
  {token.text}
132
- </CompletionToken>
126
+ </span>
133
127
  ))}
134
128
  {item.icon && (
135
129
  <>
@@ -145,7 +139,7 @@ export const CompletionMenu = memo(
145
139
  })
146
140
  );
147
141
 
148
- type Props = {
142
+ export type InputFieldWithCompletionsProps = {
149
143
  loading?: boolean;
150
144
  initialValue?: string;
151
145
  placeholder?: string;
@@ -164,7 +158,7 @@ type Props = {
164
158
  hideMenuWhenEmptyValue?: boolean;
165
159
  };
166
160
 
167
- export interface IInputFieldWithCompletions {
161
+ export interface InputFieldWithCompletionsRef {
168
162
  focus(): void;
169
163
  setValue(value: string): void;
170
164
  selectAllInputText(): void;
@@ -189,8 +183,8 @@ export const InputFieldWithCompletions = memo(
189
183
  children,
190
184
  hideChildrenWhenFocused = false,
191
185
  hideMenuWhenEmptyValue = false,
192
- }: Props,
193
- forwardedRef: ForwardedRef<IInputFieldWithCompletions>
186
+ }: InputFieldWithCompletionsProps,
187
+ forwardedRef: ForwardedRef<InputFieldWithCompletionsRef>
194
188
  ) {
195
189
  const ref = useRef<HTMLInputElement>(null);
196
190
 
@@ -416,12 +410,16 @@ export const InputFieldWithCompletions = memo(
416
410
  return (
417
411
  <InputField.Root
418
412
  size={size}
419
- labelSize={16}
420
413
  renderPopoverContent={({ width }) => {
421
414
  const listSize = { width, height };
422
415
 
423
416
  return (
424
- <Stack.V flex={`0 0 ${height}px`} display={display}>
417
+ <div
418
+ className={`flex flex-col ${!filter && hideMenuWhenEmptyValue ? "none" : "flex"}`}
419
+ style={{
420
+ flex: `0 0 ${height}px`
421
+ }}
422
+ >
425
423
  {filteredItems.length > 0 ? (
426
424
  <CompletionMenu
427
425
  ref={listRef}
@@ -432,18 +430,13 @@ export const InputFieldWithCompletions = memo(
432
430
  listSize={listSize}
433
431
  />
434
432
  ) : (
435
- <Stack.V
436
- height="100px"
437
- padding="20px"
438
- alignItems="center"
439
- justifyContent="center"
440
- >
441
- <Small color="textDisabled">
433
+ <div className="flex flex-col h-[100px] p-5 items-center justify-center">
434
+ <Small className="text-text-disabled">
442
435
  {loading ? "Loading" : "No results"}
443
436
  </Small>
444
- </Stack.V>
437
+ </div>
445
438
  )}
446
- </Stack.V>
439
+ </div>
447
440
  );
448
441
  }}
449
442
  >