@g4rcez/components 2.1.1 → 2.2.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"alert.d.ts","sourceRoot":"","sources":["../../../src/components/display/alert.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAmB,eAAe,EAAU,MAAM,cAAc,CAAC;AAExE,OAAO,KAAK,EAAE,EAAc,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAa,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAahE,KAAK,aAAa,GAAG,eAAe,CAAC,SAAS,CAAC,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEpE,eAAO,MAAM,QAAQ,GAAI,OAAO,iBAAiB,CAAC,aAAa,CAAC,sBAiB/D,CAAC;AAEF,QAAA,MAAM,aAAa;;;;;;;;;;CAUlB,CAAC;AAOF,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,KAAK,CAAC,WAAW,GAAG,KAAK,IAAI,gBAAgB,CAC1E,WAAW,CAAC,OAAO,aAAa,CAAC,GACjC,OAAO,CAAC;IACJ,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC;IACzB,OAAO,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CACzC,CAAC,EACF,CAAC,CACJ,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,CAAC,CAAC,SAAS,KAAK,CAAC,WAAW,GAAG,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,GA6CxE,CAAC"}
1
+ {"version":3,"file":"alert.d.ts","sourceRoot":"","sources":["../../../src/components/display/alert.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAmB,eAAe,EAAU,MAAM,cAAc,CAAC;AAExE,OAAO,KAAK,EAAE,EAAc,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAa,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAahE,KAAK,aAAa,GAAG,eAAe,CAAC,SAAS,CAAC,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEpE,eAAO,MAAM,QAAQ,GAAI,OAAO,iBAAiB,CAAC,aAAa,CAAC,sBAiB/D,CAAC;AAEF,QAAA,MAAM,aAAa;;;;;;;;;;CAUlB,CAAC;AAOF,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,KAAK,CAAC,WAAW,GAAG,KAAK,IAAI,gBAAgB,CAC5E,WAAW,CAAC,OAAO,aAAa,CAAC,GACjC,OAAO,CAAC;IACN,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,KAAK,CAAC,YAAY,CAAC;IACzB,OAAO,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CACvC,CAAC,EACF,CAAC,CACF,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,CAAC,CAAC,SAAS,KAAK,CAAC,WAAW,GAAG,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,GAiDxE,CAAC"}
@@ -15,8 +15,8 @@ const transition = {
15
15
  ease: [0.04, 0.62, 0.23, 0.98],
16
16
  };
17
17
  export const Collapse = (props) => (<motion.div {...props} layout layoutRoot layoutScroll initial={false} variants={variants} exit={variants.false} transition={transition} aria-hidden={!props.open} data-component="collapse" animate={props.open.toString()} className={css("aria-hidden:pointer-events-none", props.className)}>
18
- {props.children}
19
- </motion.div>);
18
+ {props.children}
19
+ </motion.div>);
20
20
  const themeVariants = {
21
21
  theme: {
22
22
  primary: "bg-alert-primary-bg text-alert-primary-text border-alert-primary-border",
@@ -35,22 +35,26 @@ const alertVariants = cva("p-4 w-full block border relative rounded-lg text-sm",
35
35
  export const Alert = forwardRef(function Alert({ className, theme, Icon, onClose, open = true, ...props }, ref) {
36
36
  const close = () => onClose?.(false);
37
37
  return (<AnimatePresence presenceAffectsLayout propagate mode="sync">
38
- {open ? <motion.div data-open={!!open} aria-hidden={!open} data-component="alert" className={css("isolate w-full", open ? "pointer-events-auto" : "pointer-events-none")}>
39
- <Collapse data-open={!!open} open={!!open}>
40
- <Polymorph {...props} ref={ref} role="alert" data-theme={theme} as={props.as ?? "div"} className={css(alertVariants({ theme }), className)}>
41
- <h4 className="flex gap-2 items-center mb-2">
42
- {!Icon && theme === "success" ? <CheckCircleIcon aria-hidden="true" size={20}/> : null}
43
- {!Icon && theme === "info" ? <InfoIcon aria-hidden="true" size={20}/> : null}
44
- {!Icon && theme === "danger" ? <TriangleAlertIcon aria-hidden="true" size={20}/> : null}
45
- {Icon}
46
- <span className="text-lg font-semibold tracking-3 text-balance">{props.title}</span>
47
- </h4>
48
- {props.children}
49
- {onClose !== undefined && open ? (<button type="button" onClick={close} className="absolute top-3 right-3 transition-colors duration-300 ease-in-out text-foreground hover:text-danger">
50
- <XIcon size={20}/>
51
- </button>) : null}
52
- </Polymorph>
53
- </Collapse>
54
- </motion.div> : null}
55
- </AnimatePresence>);
38
+ {open ? <motion.div data-open={!!open} aria-hidden={!open} data-component="alert" className={css("isolate w-full", open ? "pointer-events-auto" : "pointer-events-none")}>
39
+ <Collapse data-open={!!open} open={!!open}>
40
+ <Polymorph {...props} ref={ref} role="alert" data-theme={theme} as={props.as ?? "div"} className={css(alertVariants({ theme }), className)}>
41
+ <div className="grid grid-cols-[auto_1fr] gap-base">
42
+ {onClose !== undefined && open ? (<button type="button" onClick={close} className="absolute top-3 right-3 transition-colors duration-300 ease-in-out text-foreground hover:text-danger">
43
+ <XIcon size={20}/>
44
+ </button>) : null}
45
+ <div className={css("flex gap-2 items-center", props.title ? "" : "w-fit")}>
46
+ {!Icon && theme === "success" ? <CheckCircleIcon aria-hidden="true" size={20}/> : null}
47
+ {!Icon && theme === "info" ? <InfoIcon aria-hidden="true" size={20}/> : null}
48
+ {!Icon && theme === "danger" ? <TriangleAlertIcon aria-hidden="true" size={20}/> : null}
49
+ {Icon}
50
+ </div>
51
+ {props.title ? <h4 className="col-start-2 text-lg font-semibold tracking-3 text-balance">{props.title}</h4> : null}
52
+ <div className="col-start-2 w-full">
53
+ {props.children}
54
+ </div>
55
+ </div>
56
+ </Polymorph>
57
+ </Collapse>
58
+ </motion.div> : null}
59
+ </AnimatePresence>);
56
60
  });
@@ -4,8 +4,8 @@ import { Is } from "sidekicker";
4
4
  import { css } from "../../lib/dom";
5
5
  import { Polymorph } from "../core/polymorph";
6
6
  import { Skeleton } from "./skeleton";
7
- export const Card = ({ title, loading, children, as, header = null, container = "", titleClassName = "", ...props }) => (<Polymorph {...props} as={as || "div"} data-component="card" className={css("flex shadow-shadow-card flex-col gap-4 rounded-card border border-card-border bg-card-background w-full py-4", container)}>
8
- {title ? (<header data-component="card-title" className={css("mb-2 w-full border-b border-card-border px-6 pb-4 text-xl font-medium", titleClassName)}>
7
+ export const Card = ({ title, loading, children, as, header = null, container = "", titleClassName = "", ...props }) => (<Polymorph {...props} as={as || "div"} data-component="card" className={css("flex shadow-shadow-card flex-col gap-4 rounded-card border border-card-border bg-card-background w-full py-3", container)}>
8
+ {title ? (<header data-component="card-title" className={css("mb-2 w-full border-b border-card-border px-6 pb-2 text-xl font-medium", titleClassName)}>
9
9
  {title}
10
10
  </header>) : (header)}
11
11
  <div data-component="card-body" className={css("min-w-full px-6", props.className)}>
@@ -1 +1 @@
1
- {"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../../../src/components/display/step.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAA0D,iBAAiB,EAA2C,MAAM,OAAO,CAAC;AAElJ,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAMpC,KAAK,gBAAgB,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AA+BlH,KAAK,UAAU,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC;AAE/D,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAiCF,eAAO,MAAM,cAAc,+BAAgC,CAAC;AAE5D,eAAO,MAAM,IAAI,GAAI,gEAAgE,SAAS,sBA0F7F,CAAC;AAEF,eAAO,MAAM,KAAK,GAAI,OAAO,iBAAiB,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,sBA0BrF,CAAC"}
1
+ {"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../../../src/components/display/step.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAA2C,iBAAiB,EAA2C,MAAM,OAAO,CAAC;AAEnI,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAMpC,KAAK,gBAAgB,GAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AA+BlH,KAAK,UAAU,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC;AAE/D,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAiCF,eAAO,MAAM,cAAc,+BAAgC,CAAC;AAE5D,eAAO,MAAM,IAAI,GAAI,gEAAgE,SAAS,sBA0F7F,CAAC;AAEF,eAAO,MAAM,KAAK,GAAI,OAAO,iBAAiB,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,sBA0BrF,CAAC"}
@@ -4,12 +4,12 @@ import { Label } from "../../types";
4
4
  type ViewProps = {
5
5
  text: string;
6
6
  };
7
- type CommandItem<T extends string, P extends object> = {
7
+ type CommandItem<T extends string, P extends object> = P & {
8
8
  type: T;
9
9
  hint?: string | string[];
10
10
  Icon?: React.ReactElement;
11
11
  enabled?: ((props: ViewProps) => boolean) | boolean;
12
- } & P;
12
+ };
13
13
  type View = string | ((props: ViewProps) => string);
14
14
  type CommandShortcutItem = CommandItem<"shortcut", {
15
15
  title: View;
@@ -1 +1 @@
1
- {"version":3,"file":"command-palette.d.ts","sourceRoot":"","sources":["../../../src/components/floating/command-palette.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAc,WAAW,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAmE,MAAM,OAAO,CAAC;AAQxF,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAKpC,KAAK,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC,KAAK,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,IAAI;IACrD,IAAI,EAAE,CAAC,CAAC;IACR,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,IAAI,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC;IAC1B,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC,GAAG,OAAO,CAAC;CACrD,GAAG,CAAC,CAAC;AAEN,KAAK,IAAI,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,SAAS,KAAK,MAAM,CAAC,CAAC;AAEpD,KAAK,mBAAmB,GAAG,WAAW,CACpC,UAAU,EACV;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,CAAC,IAAI,EAAE;QACb,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;QAClC,KAAK,EAAE,aAAa,GAAG,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,aAAa,CAAC;KAC/D,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CACF,CAAC;AAEF,KAAK,gBAAgB,GAAG,WAAW,CAAC,OAAO,EAAE;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAAC,CAAC;AAEzF,MAAM,MAAM,gBAAgB,GAAG,gBAAgB,GAAG,mBAAmB,CAAC;AA8CtE,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,MAAM,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC;IAC5B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,kBAAkB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;QAAE,OAAO,EAAE,gBAAgB,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChE,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAAC,CAAA;KAAE,CAAC,CAAC;CACjF,CAAC;AAsBF,eAAO,MAAM,cAAc,GAAI,OAAO,mBAAmB,sBAyKxD,CAAC"}
1
+ {"version":3,"file":"command-palette.d.ts","sourceRoot":"","sources":["../../../src/components/floating/command-palette.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAc,WAAW,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAmE,MAAM,OAAO,CAAC;AAQxF,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAKpC,KAAK,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAElC,KAAK,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IACzD,IAAI,EAAE,CAAC,CAAC;IACR,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,IAAI,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC;IAC1B,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC,GAAG,OAAO,CAAC;CACrD,CAAC;AAEF,KAAK,IAAI,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,SAAS,KAAK,MAAM,CAAC,CAAC;AAEpD,KAAK,mBAAmB,GAAG,WAAW,CACpC,UAAU,EACV;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,CAAC,IAAI,EAAE;QACb,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;QAClC,KAAK,EAAE,aAAa,GAAG,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,aAAa,CAAC;KAC/D,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B,CACF,CAAC;AAEF,KAAK,gBAAgB,GAAG,WAAW,CAAC,OAAO,EAAE;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,gBAAgB,EAAE,CAAA;CAAE,CAAC,CAAC;AAEzF,MAAM,MAAM,gBAAgB,GAAG,gBAAgB,GAAG,mBAAmB,CAAC;AA8CtE,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,MAAM,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC;IAC5B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,kBAAkB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;QAAE,OAAO,EAAE,gBAAgB,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChE,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAAC,CAAA;KAAE,CAAC,CAAC;CACjF,CAAC;AAgCF,eAAO,MAAM,cAAc,GAAI,OAAO,mBAAmB,sBAoLxD,CAAC"}
@@ -53,33 +53,50 @@ const getFuzzyData = (commands, value) => {
53
53
  return Dict.unique(filter.concat(withEnabled), (x) => x.title);
54
54
  };
55
55
  const loadingSkeleton = [0, 0, 0, 0, 0];
56
+ const findFirstClickable = (items) => {
57
+ for (let index = 0; index < items.length; index++) {
58
+ const element = items[index];
59
+ if (element.type === "shortcut")
60
+ return element;
61
+ const recursive = findFirstClickable(element.items);
62
+ if (recursive)
63
+ return recursive;
64
+ }
65
+ return null;
66
+ };
56
67
  export const CommandPalette = (props) => {
57
- const bindKey = props.bind ?? "Mod + k";
68
+ const id = useId();
69
+ const [value, setValue] = useState("");
58
70
  const listRef = useRef([]);
59
71
  const translations = useTranslations();
60
- const [value, setValue] = useState("");
61
72
  const valueRef = useStableRef(value);
62
- const id = useId();
63
- const ref = useRef(null);
64
73
  const [activeIndex, setActiveIndex] = useState(null);
74
+ const bindKey = props.bind ?? "Mod + k";
65
75
  const root = useFloating({
66
76
  open: props.open,
67
77
  strategy: "absolute",
68
78
  whileElementsMounted: autoUpdate,
69
79
  onOpenChange: props.onChangeVisibility,
70
80
  });
81
+ const commands = props.commands.flatMap((x) => (x.type === "group" ? [x, ...x.items] : [x]));
82
+ const fuzzy = getFuzzyData(commands, value);
71
83
  const listNav = useListNavigation(root.context, {
72
- cols: 0,
73
84
  listRef,
74
85
  loop: true,
75
86
  activeIndex,
76
87
  virtual: true,
77
88
  allowEscape: true,
78
- focusItemOnHover: false,
79
- focusItemOnOpen: "auto",
89
+ focusItemOnOpen: true,
90
+ focusItemOnHover: true,
80
91
  openOnArrowKeyDown: true,
81
92
  scrollItemIntoView: false,
82
93
  selectedIndex: activeIndex,
94
+ disabledIndices: n => {
95
+ const item = fuzzy[n];
96
+ if (item)
97
+ return item.type === "group";
98
+ return false;
99
+ },
83
100
  onNavigate: (n) => {
84
101
  if (Is.number(n)) {
85
102
  listRef.current[n]?.scrollIntoView({ block: "start", inline: "start" });
@@ -91,9 +108,7 @@ export const CommandPalette = (props) => {
91
108
  });
92
109
  }
93
110
  });
94
- const { getItemProps, getReferenceProps } = useInteractions([listNav]);
95
- const commands = props.commands.flatMap((x) => (x.type === "group" ? [x, ...x.items] : [x]));
96
- const fuzzy = getFuzzyData(commands, value);
111
+ const { getItemProps, getReferenceProps, getFloatingProps } = useInteractions([listNav]);
97
112
  const displayItems = value === ""
98
113
  ? commands
99
114
  : [
@@ -121,7 +136,7 @@ export const CommandPalette = (props) => {
121
136
  }, [bindKey, commands, props, valueRef]);
122
137
  const Icon = props.Icon ?? FilterIcon;
123
138
  return (<Fragment>
124
- <Modal ref={ref} animated={false} closable={false} open={props.open} overlayClickClose ariaTitle="Command palette" bodyClassName="px-0 py-0 pt-0" data-component="command-palette" onChange={props.onChangeVisibility} className="container relative py-0 md:max-w-screen-sm lg:max-w-screen-md overflow-clip">
139
+ <Modal {...getFloatingProps()} animated={false} closable={false} open={props.open} overlayClickClose ariaTitle="Command palette" bodyClassName="px-0 py-0 pt-0" data-component="command-palette" onChange={props.onChangeVisibility} className="container relative py-0 md:max-w-screen-sm lg:max-w-screen-md overflow-clip">
125
140
  <header className="flex sticky top-0 items-center w-full h-12 border-b overflow-clip isolate z-floating border-floating-border bg-floating-background">
126
141
  <div className="flex justify-center items-center size-10">
127
142
  {props.Icon ? <Icon Default={FilterIcon} text={value} size={16}/> : <FilterIcon size={16}/>}
@@ -129,6 +144,21 @@ export const CommandPalette = (props) => {
129
144
  </div>
130
145
  <input {...getReferenceProps({
131
146
  ref: root.refs.setReference,
147
+ onKeyDown: (e) => {
148
+ const item = Is.number(activeIndex) ? displayItems[activeIndex] : null;
149
+ const key = e.key;
150
+ if (key === "Enter") {
151
+ if (item) {
152
+ if (item.type === "shortcut")
153
+ item.action({ event: e, text: value, setOpen: props.onChangeVisibility, });
154
+ }
155
+ else {
156
+ const item = findFirstClickable(fuzzy);
157
+ if (item?.type === "shortcut")
158
+ item.action({ event: e, text: value, setOpen: props.onChangeVisibility, });
159
+ }
160
+ }
161
+ }
132
162
  })} autoFocus value={value} data-combikeysbypass="true" placeholder="Search for..." onChange={(e) => setValue(e.target.value)} className="items-center py-2 px-2 pb-2 w-full h-12 text-lg text-left bg-transparent outline-none"/>
133
163
  </header>
134
164
  {props.loading ? (<ul role="listbox" data-component="command-palette-list" className="flex overflow-y-auto flex-col gap-1 px-2 my-2 w-full max-h-96 origin-[top_center]">
@@ -146,13 +176,8 @@ export const CommandPalette = (props) => {
146
176
  onClick(e) {
147
177
  e.preventDefault();
148
178
  props.onChangeVisibility(false);
149
- root.refs.domReference.current?.focus();
150
179
  if (item.type === "shortcut")
151
- item.action({
152
- event: e,
153
- setOpen: props.onChangeVisibility,
154
- text: value,
155
- });
180
+ item.action({ event: e, text: value, setOpen: props.onChangeVisibility, });
156
181
  },
157
182
  })} item={item} text={value} active={activeIndex === index} key={`${id}-${item.type}-${index}`}/>))}
158
183
  {displayItems.length === 1 ? (<div className={css("flex items-center justify-between rounded-lg p-2 text-secondary")}>
@@ -161,7 +186,7 @@ export const CommandPalette = (props) => {
161
186
  </ul>
162
187
  {props.Preview && Is.number(activeIndex) ? <props.Preview command={displayItems[activeIndex]} text={value}/> : null}
163
188
  </div>)}
164
- {props.footer ? <footer className="flex items-center p-2 h-8 rounded-b-lg bg-background">{props.footer}</footer> : null}
189
+ {props.footer ? <footer className="flex items-center p-2 h-8 rounded-b-lg border-t border-floating-border">{props.footer}</footer> : null}
165
190
  </Modal>
166
191
  </Fragment>);
167
192
  };
@@ -1 +1 @@
1
- {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../../src/components/floating/modal.tsx"],"names":[],"mappings":"AACA,OAAO,EASL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAmB,eAAe,EAA4F,MAAM,cAAc,CAAC;AAE1J,OAAO,KAA+G,MAAM,OAAO,CAAC;AAGpI,OAAO,EAAE,KAAK,EAAO,QAAQ,EAAE,MAAM,aAAa,CAAC;AAKnD,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEtD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,CAAC;AAuD9C,MAAM,MAAM,UAAU,GAAG,QAAQ,CAC/B,eAAe,CAAC,KAAK,CAAC,EACtB,CAAC;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,GAAG;IAC9E,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC,GAAG,OAAO,CAAC;IACV,MAAM,EAAE,KAAK,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,cAAc,CAAC;IACzB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,OAAO,EAAE,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;CAChC,CAAC,CACH,CAAC;AAgFF,KAAK,QAAQ,GAAG;IAAE,OAAO,EAAE,GAAG,CAAC;IAAC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,CAAC;AAI/D,eAAO,MAAM,KAAK;WA1GN,KAAK;gBAAc,MAAM;;UAC3B,OAAO;cACH,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI;;YAE9B,KAAK;UACP,SAAS;cACL,OAAO;aACR,OAAO;cACN,MAAM;aACP,OAAO;eACL,MAAM;cACP,OAAO;eACN,OAAO;mBACH,MAAM;sBACH,MAAM;cACd,cAAc;uBACL,OAAO;qBACT,OAAO;UAClB,QAAQ;kBACA,YAAY,EAAE;aACnB,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC;;;;eApBqB,MAAM;YAAU,KAAK;;UAClE,OAAO;cACH,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI;;YAE9B,KAAK;UACP,SAAS;cACL,OAAO;aACR,OAAO;cACN,MAAM;aACP,OAAO;eACL,MAAM;cACP,OAAO;eACN,OAAO;mBACH,MAAM;sBACH,MAAM;cACd,cAAc;uBACL,OAAO;qBACT,OAAO;UAClB,QAAQ;kBACA,YAAY,EAAE;aACnB,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC;;;2CA0UjC,CAAC"}
1
+ {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../../src/components/floating/modal.tsx"],"names":[],"mappings":"AACA,OAAO,EASL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAmB,eAAe,EAA4F,MAAM,cAAc,CAAC;AAE1J,OAAO,KAA+G,MAAM,OAAO,CAAC;AAGpI,OAAO,EAAE,KAAK,EAAO,QAAQ,EAAE,MAAM,aAAa,CAAC;AAKnD,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEtD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,CAAC;AAuD9C,MAAM,MAAM,UAAU,GAAG,QAAQ,CAC/B,eAAe,CAAC,KAAK,CAAC,EACtB,CAAC;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,GAAG;IAC9E,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC,GAAG,OAAO,CAAC;IACV,MAAM,EAAE,KAAK,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,cAAc,CAAC;IACzB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,OAAO,EAAE,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;CAChC,CAAC,CACH,CAAC;AAgFF,KAAK,QAAQ,GAAG;IAAE,OAAO,EAAE,GAAG,CAAC;IAAC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,CAAC;AAI/D,eAAO,MAAM,KAAK;WA1GN,KAAK;gBAAc,MAAM;;UAC3B,OAAO;cACH,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI;;YAE9B,KAAK;UACP,SAAS;cACL,OAAO;aACR,OAAO;cACN,MAAM;aACP,OAAO;eACL,MAAM;cACP,OAAO;eACN,OAAO;mBACH,MAAM;sBACH,MAAM;cACd,cAAc;uBACL,OAAO;qBACT,OAAO;UAClB,QAAQ;kBACA,YAAY,EAAE;aACnB,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC;;;;eApBqB,MAAM;YAAU,KAAK;;UAClE,OAAO;cACH,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI;;YAE9B,KAAK;UACP,SAAS;cACL,OAAO;aACR,OAAO;cACN,MAAM;aACP,OAAO;eACL,MAAM;cACP,OAAO;eACN,OAAO;mBACH,MAAM;sBACH,MAAM;cACd,cAAc;uBACL,OAAO;qBACT,OAAO;UAClB,QAAQ;kBACA,YAAY,EAAE;aACnB,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC;;;2CA8UjC,CAAC"}
@@ -2,7 +2,7 @@
2
2
  import { FloatingFocusManager, FloatingOverlay, FloatingPortal, useClick, useDismiss, useFloating, useInteractions, useRole, } from "@floating-ui/react";
3
3
  import { cva } from "class-variance-authority";
4
4
  import { XIcon } from "lucide-react";
5
- import { motion, MotionConfig, useMotionValue, animate } from "motion/react";
5
+ import { AnimatePresence, motion, MotionConfig, useMotionValue, animate } from "motion/react";
6
6
  import { Slot } from "../core/slot";
7
7
  import React, { forwardRef, Fragment, useEffect, useId, useImperativeHandle, useRef } from "react";
8
8
  import { useMediaQuery } from "../../hooks/use-media-query";
@@ -164,11 +164,13 @@ export const Modal = forwardRef(({ open, title, footer, asChild, trigger, childr
164
164
  {trigger ? (<Component ref={floating.refs.setReference} {...interactions.getReferenceProps()} layoutId={layoutId} type="button">
165
165
  {Trigger}
166
166
  </Component>) : null}
167
- <FloatingPortal preserveTabOrder root={root}>
168
- {open ? (<FloatingOverlay lockScroll className={css("inset-0 flex isolate bg-floating-overlay/70 z-overlay h-[100dvh] !overflow-clip", type === "drawer" ? "" : "items-start justify-center lg:p-10 pt-10", overlayClassName)}>
169
- <MotionConfig reducedMotion={animated ? "user" : "always"}>
170
- <FloatingFocusManager guards modal closeOnFocusOut={closeOnFocusOut} context={floating.context}>
171
- <motion.div {...props} {...(title
167
+ <MotionConfig reducedMotion={animated ? "user" : "always"}>
168
+ <FloatingPortal preserveTabOrder root={root}>
169
+ <AnimatePresence mode="wait" propagate>
170
+ {open ? (<FloatingOverlay lockScroll className={css("inset-0 flex isolate bg-floating-overlay/70 z-overlay h-[100dvh] !overflow-clip", type === "drawer" ? "" : "items-start justify-center lg:p-10 pt-10", overlayClassName)}>
171
+ <FloatingFocusManager guards modal closeOnFocusOut={closeOnFocusOut} context={floating.context}>
172
+ <AnimatePresence propagate>
173
+ <motion.div {...props} {...(title
172
174
  ? {
173
175
  "aria-labelledby": headingId,
174
176
  "aria-describedby": descriptionId,
@@ -178,13 +180,13 @@ export const Modal = forwardRef(({ open, title, footer, asChild, trigger, childr
178
180
  ref: mergeRefs(floating.refs.setFloating, removeScrollRef),
179
181
  className: css(variants({ position, type }), className, "isolate overscroll-contain"),
180
182
  })} exit="exit" layout={true} animate="enter" initial="initial" layoutId={layoutId} variants={animation} data-component="modal" style={type === "drawer" ? { width: floatingSize } : { height: floatingSize, y: sheetY }}>
181
- {useResizer && resizer ? (<Draggable onChange={onChange} value={floatingSize} sheet={type === "sheet"} position={position} parent={floating.refs.floating}/>) : null}
182
- {title ? (<motion.header {...draggableMotionProps} className="relative w-full isolate">
183
- {title ? (<h2 id={headingId} className="block px-8 pb-2 text-3xl font-medium leading-relaxed border-b select-text border-floating-border">
184
- {title}
185
- </h2>) : null}
186
- </motion.header>) : null}
187
- <motion.section ref={innerContent} data-component="modal-body" className={css("flex-1 select-text overflow-y-auto px-8 py-1", bodyClassName)} onTouchEnd={async () => {
183
+ {useResizer && resizer ? (<Draggable onChange={onChange} value={floatingSize} sheet={type === "sheet"} position={position} parent={floating.refs.floating}/>) : null}
184
+ {title ? (<motion.header {...draggableMotionProps} className="relative w-full isolate">
185
+ {title ? (<h2 id={headingId} className="block px-8 pb-2 text-3xl font-medium leading-relaxed border-b select-text border-floating-border">
186
+ {title}
187
+ </h2>) : null}
188
+ </motion.header>) : null}
189
+ <motion.section ref={innerContent} data-component="modal-body" className={css("flex-1 select-text overflow-y-auto px-8 py-1", bodyClassName)} onTouchEnd={async () => {
188
190
  scroll.set(undefined);
189
191
  scrollInitial.set(undefined);
190
192
  if (isDragging.current) {
@@ -224,18 +226,20 @@ export const Modal = forwardRef(({ open, title, footer, asChild, trigger, childr
224
226
  }
225
227
  scroll.set(y);
226
228
  }}>
227
- {children}
228
- </motion.section>
229
- {footer ? (<footer className="px-8 pt-4 w-full border-t select-text border-floating-border">{footer}</footer>) : null}
230
- {closable ? (<nav className="absolute top-1 right-4 z-floating">
231
- <button type="button" onClick={onClose} className="p-1 opacity-70 transition-colors hover:opacity-100 hover:text-danger focus:text-danger">
232
- <XIcon />
233
- </button>
234
- </nav>) : null}
235
- </motion.div>
236
- </FloatingFocusManager>
237
- </MotionConfig>
238
- </FloatingOverlay>) : null}
239
- </FloatingPortal>
229
+ {children}
230
+ </motion.section>
231
+ {footer ? (<footer className="px-8 pt-4 w-full border-t select-text border-floating-border">{footer}</footer>) : null}
232
+ {closable ? (<nav className="absolute top-1 right-4 z-floating">
233
+ <button type="button" onClick={onClose} className="p-1 opacity-70 transition-colors hover:opacity-100 hover:text-danger focus:text-danger">
234
+ <XIcon />
235
+ </button>
236
+ </nav>) : null}
237
+ </motion.div>
238
+ </AnimatePresence>
239
+ </FloatingFocusManager>
240
+ </FloatingOverlay>) : null}
241
+ </AnimatePresence>
242
+ </FloatingPortal>
243
+ </MotionConfig>
240
244
  </Fragment>);
241
245
  });
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../../../src/components/form/autocomplete.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAoF,MAAM,OAAO,CAAC;AASzG,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAc,eAAe,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,MAAM,qBAAqB,GAAG,WAAW,GAAG;IAAE,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAAC,CAAA;CAAE,CAAC;AAErF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,qBAAqB,EAAE,CAAC;CAClC,CAAC;AAiCF,eAAO,MAAM,YAAY,yGAsWxB,CAAC"}
1
+ {"version":3,"file":"autocomplete.d.ts","sourceRoot":"","sources":["../../../src/components/form/autocomplete.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAoF,MAAM,OAAO,CAAC;AASzG,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAc,eAAe,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,MAAM,qBAAqB,GAAG,WAAW,GAAG;IAAE,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAAC,CAAA;CAAE,CAAC;AAErF,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,GAAG;IACxE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,EAAE,qBAAqB,EAAE,CAAC;CAClC,CAAC;AAiCF,eAAO,MAAM,YAAY,yGAyWxB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { autoUpdate, FloatingFocusManager, FloatingPortal, offset, size, useDismiss, useFloating, useInteractions, useListNavigation, useRole, useTransitionStyles, } from "@floating-ui/react";
2
+ import { autoPlacement, autoUpdate, FloatingFocusManager, FloatingPortal, offset, size, useDismiss, useFloating, useInteractions, useListNavigation, useRole, useTransitionStyles, } from "@floating-ui/react";
3
3
  import { ChevronDown } from "lucide-react";
4
4
  import { AnimatePresence, motion } from "motion/react";
5
5
  import React, { forwardRef, Fragment, useEffect, useRef, useState } from "react";
@@ -14,14 +14,14 @@ import { fzf } from "../../lib/fzf";
14
14
  import { InputField } from "./input-field";
15
15
  const Frag = (props) => <Fragment>{props.children}</Fragment>;
16
16
  const transitionStyles = {
17
- duration: 300,
17
+ duration: 200,
18
18
  initial: { transform: "scaleY(0)", opacity: 0.2 },
19
19
  open: { transform: "scaleY(1)", opacity: 1 },
20
20
  close: { transform: "scaleY(0)", opacity: 0 },
21
21
  };
22
22
  const emptyRef = [];
23
23
  const List = forwardRef(function VirtualList(props, ref) {
24
- return (<motion.ul {...props} ref={ref} className="overscroll-contain w-full rounded-lg">
24
+ return (<motion.ul {...props} ref={ref} className="overscroll-contain w-full max-h-96 rounded-lg">
25
25
  <AnimatePresence>{props.children}</AnimatePresence>
26
26
  </motion.ul>);
27
27
  });
@@ -66,7 +66,7 @@ export const Autocomplete = forwardRef(({ left, error, right, loading, options,
66
66
  const pattern = dynamicOption
67
67
  ? undefined
68
68
  : `^(${options.map((x) => `${safeRegex(x.value)}${x.label ? "|" + safeRegex(x.label) : ""}`).join("|")})$`;
69
- const { x, y, strategy, refs, context } = useFloating({
69
+ const { x, y, strategy, refs, context, placement } = useFloating({
70
70
  open,
71
71
  transform: true,
72
72
  onOpenChange: setOpen,
@@ -74,6 +74,7 @@ export const Autocomplete = forwardRef(({ left, error, right, loading, options,
74
74
  whileElementsMounted: autoUpdate,
75
75
  middleware: [
76
76
  offset(4),
77
+ autoPlacement({ allowedPlacements: ['top-start', 'bottom-start'], alignment: "start" }),
77
78
  size({
78
79
  padding: 10,
79
80
  elementContext: "reference",
@@ -175,7 +176,8 @@ export const Autocomplete = forwardRef(({ left, error, right, loading, options,
175
176
  const id = props.id || props.name;
176
177
  const shadowId = `${id}-shadow`;
177
178
  const isEmpty = displayList.length === 0;
178
- return (<InputField {...props} left={left} error={error} ref={fieldset} form={props.form} loading={loading} name={props.name} feedback={feedback} hideLeft={hideLeft} required={required} title={props.title} container={container} rightLabel={rightLabel} interactive={interactive} id={shadowId} optionalText={optionalText} componentName="autocomplete" labelClassName={labelClassName} placeholder={props.placeholder} right={<span className="flex gap-0.5 items-center">
179
+ const isTopPlacement = placement === "top" || placement === "top-start";
180
+ return (<InputField {...props} left={left} error={error} ref={fieldset} form={props.form} loading={loading} name={props.name} feedback={open && (isTopPlacement) ? props.title : feedback} hideLeft={hideLeft} required={required} title={props.title} container={container} rightLabel={rightLabel} interactive={interactive} id={shadowId} optionalText={optionalText} componentName="autocomplete" labelClassName={labelClassName} placeholder={props.placeholder} right={<span className="flex gap-0.5 items-center">
179
181
  {right}
180
182
  <button type="button" className="p-2 transition-colors md:p-1 link:text-primary" onClick={onCaretDownClick}>
181
183
  <ChevronDown size={20}/>
@@ -235,22 +237,20 @@ export const Autocomplete = forwardRef(({ left, error, right, loading, options,
235
237
  <motion.div {...getFloatingProps({
236
238
  ref: mergeRefs(removeScrollRef, refs.setFloating),
237
239
  style: { ...transitions.styles, left: x, top: y ?? 0, position: strategy, height: "auto" },
238
- })} initial={false} data-floating="true" animate={{ height: isEmpty ? "auto" : h }} className="overscroll-contain p-0 m-0 max-h-80 list-none rounded-t-lg rounded-b-lg border ease-in-out isolate z-floating origin-[top_center] border-floating-border bg-floating-background text-foreground shadow-floating" onAnimationComplete={() => {
240
+ })} initial={false} data-floating="true" animate={{ height: isEmpty ? "auto" : h }} className={css("overscroll-contain p-0 m-0 max-h-80 list-none rounded-t-lg rounded-b-lg border ease-in-out isolate z-floating origin-[top_center] border-floating-border bg-floating-background text-foreground shadow-floating", isTopPlacement ? "origin-[bottom_center]" : "origin-[top_center]")} onAnimationComplete={() => {
239
241
  if (!open)
240
242
  return setH(0);
241
243
  const ul = refs.floating.current;
242
244
  const li = ul.querySelectorAll("li").item(0);
243
245
  const sum = (li ? li.getBoundingClientRect().height : MIN_SIZE) * displayList.length;
244
- return flushSync(() => setH(sum + 10));
246
+ return flushSync(() => setH(sum + 2));
245
247
  }}>
246
248
  {isEmpty ? (<div role="option" className="w-full border-b border-tooltip-border">
247
249
  <span className="flex justify-between p-2 w-full text-left text-disabled">
248
250
  {emptyMessage || translation.autocompleteEmpty}
249
251
  </span>
250
252
  </div>) : null}
251
- <Virtuoso overscan={40} ref={virtuoso} hidden={isEmpty} data={displayList}
252
- // style={{ height: h - 10 }}
253
- defaultItemHeight={MIN_SIZE} components={components} scrollerRef={(e) => void (scroller.current = e)} className="overscroll-contain p-0 max-h-full rounded-lg border-floating bg-floating-background text-foreground" itemContent={(i, option) => {
253
+ <Virtuoso overscan={40} ref={virtuoso} hidden={isEmpty} data={displayList} style={{ height: h }} defaultItemHeight={MIN_SIZE} components={components} scrollerRef={(e) => void (scroller.current = e)} className="overscroll-contain p-0 max-h-full rounded-lg border-floating bg-floating-background text-foreground" itemContent={(i, option) => {
254
254
  const Label = option.Render ?? Frag;
255
255
  const active = value === option.value || value === option.label;
256
256
  const selected = index === i;