{"version":3,"file":"index.mjs","names":["Ref","useImperativeHandle","useRef","useState","SelectChangeEvent","SelectHandle","SelectOption","autoUpdate","offset","Placement","useFloating","size","floatingUiSize","flip","useClick","useDismiss","useRole","useListNavigation","useTypeahead","useInteractions","FloatingPortal","FloatingFocusManager","ThemeColor","clsx","sizeVariant","Dialog","Button","SelectProps","id","className","name","variant","color","placeholder","disabled","options","V","value","onChange","event","placement","floatingMinWidth","zIndex","dialogClassName","ref","onFocus","onBlur","Select","isOpen","setIsOpen","activeIndex","setActiveIndex","selectedIndex","findIndex","option","selectedOption","refs","floatingStyles","context","open","onOpenChange","whileElementsMounted","middleware","padding","apply","rects","elements","availableHeight","Object","assign","floating","style","width","Math","max","reference","firstChild","firstElementChild","HTMLElement","maxHeight","min","listRef","listContentRef","map","label","current","isTypingRef","click","enabled","dismiss","role","listNav","onNavigate","loop","typeahead","onMatch","index","handleSelect","onTypingChange","isTyping","focus","domReference","getReferenceProps","getFloatingProps","getItemProps","type","setReference","icon","setFloating","i","isActive","isSelected","node","onClick","onKeyDown","key","preventDefault","FieldName","Field","FieldProps","SelectHandle","SelectOption","useField","useControl","Select","useRef","Props","Omit","name","placeholder","options","SelectField","id","forcedId","rest","controlInputRef","field","control","defaultValue","onFocus","current","focus","register","errors","blur","value","event","change"],"sources":["../../../../src/components/fields/select/Select.tsx","../../../../src/components/fields/select/SelectField.tsx"],"sourcesContent":["import { Ref, useImperativeHandle, useRef, useState } from \"react\";\nimport { SelectChangeEvent, SelectHandle, SelectOption } from \"./types\";\nimport {\n  autoUpdate,\n  offset,\n  Placement,\n  useFloating,\n  size as floatingUiSize,\n  flip,\n  useClick,\n  useDismiss,\n  useRole,\n  useListNavigation,\n  useTypeahead,\n  useInteractions,\n  FloatingPortal,\n  FloatingFocusManager,\n} from \"@floating-ui/react\";\nimport { ThemeColor } from \"../../../types\";\nimport clsx from \"clsx\";\nimport { sizeVariant } from \"../text/Input\";\nimport { Dialog } from \"../../dialog\";\nimport { Button } from \"../../button\";\n\ninterface SelectProps<V extends string | number = string> {\n  id?: string;\n  className?: string;\n  name: string;\n  variant?: \"normal\" | \"ghost\";\n  color?: ThemeColor;\n  size?: \"small\" | \"medium\" | \"large\" | \"custom\";\n  placeholder?: string;\n  disabled?: boolean;\n  options: SelectOption<V>[];\n  value: V | null;\n  onChange: (event: SelectChangeEvent<V>) => void;\n  placement?: Placement;\n  floatingMinWidth?: number;\n  zIndex?: number;\n\n  dialogClassName?: string;\n  ref?: Ref<SelectHandle>;\n\n  onFocus?: () => void;\n  onBlur?: () => void;\n}\n\nexport function Select<V extends string | number = string>({\n  id,\n  className,\n  name,\n  variant = \"normal\",\n  zIndex,\n  color = \"yellow\",\n  size = \"medium\",\n  placeholder = \"Select ...\",\n  disabled = false,\n  options,\n  value,\n  onChange,\n  floatingMinWidth = 130,\n  placement = \"bottom\",\n  onFocus,\n  onBlur,\n  dialogClassName,\n  ref,\n}: SelectProps<V>) {\n  const [isOpen, setIsOpen] = useState(false);\n  const [activeIndex, setActiveIndex] = useState<number | null>(null);\n\n  const selectedIndex = options.findIndex((option) => option.value === value);\n  const selectedOption = selectedIndex !== -1 ? options[selectedIndex] : null;\n\n  const { refs, floatingStyles, context } = useFloating({\n    placement,\n    open: isOpen,\n    onOpenChange: setIsOpen,\n    whileElementsMounted: autoUpdate,\n    middleware: [\n      offset(5),\n      flip({ padding: 10 }),\n      floatingUiSize({\n        apply({ rects, elements, availableHeight }) {\n          Object.assign(elements.floating.style, {\n            width: `${Math.max(floatingMinWidth, rects.reference.width)}px`,\n          });\n          const firstChild = elements.floating.firstElementChild as HTMLElement;\n          if (firstChild) {\n            firstChild.style.maxHeight = `${Math.min(availableHeight, 320)}px`;\n          }\n        },\n        padding: 10,\n      }),\n    ],\n  });\n\n  const listRef = useRef<(HTMLElement | null)[]>([]);\n  const listContentRef = useRef(options.map((option) => option.label));\n  listContentRef.current = options.map((option) => option.label);\n\n  const isTypingRef = useRef(false);\n\n  const click = useClick(context, { event: \"mousedown\", enabled: !disabled });\n  const dismiss = useDismiss(context);\n  const role = useRole(context, { role: \"select\" });\n  const listNav = useListNavigation(context, {\n    listRef,\n    activeIndex,\n    selectedIndex,\n    onNavigate: setActiveIndex,\n    loop: true,\n    enabled: !disabled,\n  });\n\n  const typeahead = useTypeahead(context, {\n    listRef: listContentRef,\n    activeIndex,\n    selectedIndex: selectedIndex === -1 ? null : selectedIndex,\n    onMatch: isOpen ? setActiveIndex : (index) => handleSelect(index ?? -1),\n    onTypingChange(isTyping) {\n      isTypingRef.current = isTyping;\n    },\n    enabled: !disabled,\n  });\n\n  useImperativeHandle(\n    ref,\n    () => ({\n      focus: () => {\n        (refs.domReference.current as HTMLElement | null)?.focus();\n      },\n    }),\n    [refs.domReference],\n  );\n\n  const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions([\n    dismiss,\n    role,\n    listNav,\n    typeahead,\n    click,\n  ]);\n\n  function handleSelect(index: number) {\n    const option = options[index];\n    onChange({\n      type: \"select-one\",\n      name,\n      value: option ? option.value : null,\n    });\n    setIsOpen(false);\n  }\n\n  return (\n    <>\n      <div\n        data-color={color}\n        aria-disabled={disabled}\n        className={clsx(\n          \"p8n-input-text box-border flex cursor-pointer rounded-[calc(var(--h-input)/2)] -outline-offset-1\",\n          className,\n          sizeVariant[size],\n          isOpen && \"focus\",\n        )}\n        data-variant={variant}\n        ref={refs.setReference}\n        tabIndex={disabled ? -1 : 0}\n        {...getReferenceProps({ onFocus, onBlur })}\n      >\n        <span className=\"flex flex-1 items-center truncate px-2\">\n          {selectedOption ? (\n            <>\n              {selectedOption.icon && <i className={selectedOption.icon}></i>}\n              {selectedOption.label}\n            </>\n          ) : (\n            <>{placeholder}</>\n          )}\n        </span>\n        <Button\n          id={id}\n          color=\"gray\"\n          withRipple={false}\n          icon\n          variant=\"text\"\n          focusable={false}\n          type=\"button\"\n          size=\"input\"\n        >\n          <i className={isOpen ? \"fe-angle-up\" : \"fe-angle-down\"}></i>\n        </Button>\n      </div>\n      {isOpen && (\n        <FloatingPortal preserveTabOrder={true}>\n          <FloatingFocusManager context={context} modal={false}>\n            <div\n              className=\"z-dialog outline-hidden\"\n              data-testid=\"select-list\"\n              ref={refs.setFloating}\n              style={{ ...floatingStyles, zIndex }}\n              {...getFloatingProps()}\n            >\n              <Dialog\n                placement={context.placement}\n                className={clsx(\"motion-safe:animate-fade-in-list overflow-auto\", dialogClassName)}\n                rounded={!dialogClassName}\n              >\n                {options.map((option, i) => {\n                  const isActive = i === activeIndex;\n                  const isSelected = i === selectedIndex;\n                  return (\n                    <button\n                      type=\"button\"\n                      key={option.value}\n                      className={clsx(\"option\", isSelected ? \"bg-gray-2\" : isActive && \"bg-gray-1\")}\n                      data-presentation=\"compact\"\n                      role=\"option\"\n                      aria-selected={isSelected}\n                      ref={(node) => {\n                        listRef.current[i] = node;\n                      }}\n                      {...getItemProps({\n                        onClick() {\n                          handleSelect(i);\n                        },\n                        onKeyDown(event) {\n                          if (event.key === \"Enter\") {\n                            event.preventDefault();\n                            handleSelect(i);\n                          }\n                          if (event.key === \" \" && !isTypingRef.current) {\n                            event.preventDefault();\n                            handleSelect(i);\n                          }\n                        },\n                      })}\n                    >\n                      {option.icon && <i className={option.icon}></i>}\n                      {option.label}\n                    </button>\n                  );\n                })}\n              </Dialog>\n            </div>\n          </FloatingFocusManager>\n        </FloatingPortal>\n      )}\n    </>\n  );\n}\n","import { FieldName } from \"@conform-to/react/future\";\nimport { Field, FieldProps } from \"../field/Field\";\nimport { SelectHandle, SelectOption } from \"./types\";\nimport { useField, useControl } from \"@conform-to/react/future\";\nimport { Select } from \"./Select\";\nimport { useRef } from \"react\";\n\ninterface Props extends Omit<FieldProps, \"children\" | \"group\"> {\n  name: FieldName<string | number | null | undefined>;\n  placeholder?: string;\n  options: SelectOption[];\n}\n\nexport function SelectField({ name, placeholder, options, id: forcedId, ...rest }: Props) {\n  const controlInputRef = useRef<SelectHandle>(null);\n  const field = useField(name);\n  const id = forcedId ?? field.id;\n  const control = useControl({\n    defaultValue: field.defaultValue,\n    onFocus() {\n      controlInputRef.current?.focus();\n    },\n  });\n\n  return (\n    <>\n      <input\n        type=\"text\"\n        name={field.name}\n        autoComplete=\"off\"\n        defaultValue={field.defaultValue}\n        ref={control.register}\n        hidden\n      />\n      <Field id={id} errors={field.errors} data-testid={field.name} {...rest}>\n        <Select\n          name={field.name}\n          ref={controlInputRef}\n          placeholder={placeholder}\n          options={options}\n          onFocus={control.focus}\n          onBlur={control.blur}\n          value={control.value ?? null}\n          onChange={(event) => control.change(event.value)}\n        ></Select>\n      </Field>\n    </>\n  );\n}\n"],"mappings":"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"}