@andrilla/mado-ui 1.0.11 → 1.1.1

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,9 +1,9 @@
1
1
  "use client";
2
2
  import { extendTailwindMerge, twJoin } from "tailwind-merge";
3
3
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
- import { Button as Button$1, Checkbox as Checkbox$1, Description, Dialog, DialogBackdrop, DialogPanel, DialogTitle, Disclosure, DisclosureButton, DisclosurePanel, Field, Fieldset as Fieldset$1, Input as Input$1, Label, Legend, Listbox, ListboxButton, ListboxOption, ListboxOptions, ListboxSelectedOption, Menu, MenuButton, MenuHeading, MenuItem, MenuItems, MenuSection, MenuSeparator, Textarea as Textarea$1 } from "@headlessui/react";
4
+ import { Button as Button$1, Checkbox as Checkbox$1, Combobox, ComboboxButton, ComboboxInput, ComboboxOption, ComboboxOptions, Description, Dialog, DialogBackdrop, DialogPanel, DialogTitle, Disclosure, DisclosureButton, DisclosurePanel, Field, Fieldset as Fieldset$1, Input as Input$1, Label, Legend, Listbox, ListboxButton, ListboxOption, ListboxOptions, ListboxSelectedOption, Menu, MenuButton, MenuHeading, MenuItem, MenuItems, MenuSection, MenuSeparator, Textarea as Textarea$1 } from "@headlessui/react";
5
5
  import * as React from "react";
6
- import { Children, cloneElement, createContext, isValidElement, useContext, useEffect, useEffectEvent, useId, useLayoutEffect, useRef, useState, useSyncExternalStore } from "react";
6
+ import { Children, cloneElement, createContext, isValidElement, useCallback, useContext, useEffect, useEffectEvent, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
7
7
  import * as ReactDOM from "react-dom";
8
8
  import { createPortal } from "react-dom";
9
9
  //#region src/utils/custom-tailwind-merge.ts
@@ -1252,7 +1252,7 @@ if (isBrowser) {
1252
1252
  * @param {String} str
1253
1253
  * @return {String}
1254
1254
  */
1255
- const toLowerCase = (str) => str.replace(lowerCaseRgx, "$1-$2").toLowerCase();
1255
+ const toLowerCase$1 = (str) => str.replace(lowerCaseRgx, "$1-$2").toLowerCase();
1256
1256
  /**
1257
1257
  * Prioritize this method instead of regex when possible
1258
1258
  * @param {String} str
@@ -1890,7 +1890,7 @@ const sanitizePropertyName = (propertyName, target, tweenType) => {
1890
1890
  const cachedPropertyName = propertyNamesCache[propertyName];
1891
1891
  if (cachedPropertyName) return cachedPropertyName;
1892
1892
  else {
1893
- const lowerCaseName = propertyName ? toLowerCase(propertyName) : propertyName;
1893
+ const lowerCaseName = propertyName ? toLowerCase$1(propertyName) : propertyName;
1894
1894
  propertyNamesCache[propertyName] = lowerCaseName;
1895
1895
  return lowerCaseName;
1896
1896
  }
@@ -1923,7 +1923,7 @@ const cleanInlineStyles = (renderable) => {
1923
1923
  for (let key in cachedTransforms) str += transformsFragmentStrings[key] + cachedTransforms[key] + ") ";
1924
1924
  targetStyle.transform = str;
1925
1925
  }
1926
- } else if (tweenHadNoInlineValue) targetStyle.removeProperty(toLowerCase(tweenProperty));
1926
+ } else if (tweenHadNoInlineValue) targetStyle.removeProperty(toLowerCase$1(tweenProperty));
1927
1927
  else targetStyle[tweenProperty] = originalInlinedValue;
1928
1928
  if (animation._tail === tween) animation.targets.forEach((t) => {
1929
1929
  if (t.getAttribute && t.getAttribute("style") === "") t.removeAttribute("style");
@@ -3971,6 +3971,20 @@ function getWeekdayName(weekday = d) {
3971
3971
  return weekdayNamesList[weekday.getDay()];
3972
3972
  }
3973
3973
  //#endregion
3974
+ //#region src/utils/string-manipulation.ts
3975
+ /**
3976
+ * # To Lower Case
3977
+ * Converts a string to lowercase, and offers easy string replacements for creating snake case, kebab case, or your own.
3978
+ * @param str - The string to convert to lowercase.
3979
+ * @param options - Configuration options.
3980
+ * @param options[0] - The delimiter to split the string. Defaults to space.
3981
+ * @param options[1] - The string to join the parts back together. Defaults to space.
3982
+ * @returns The lowercase version of the input string, with the replacements, if provided.
3983
+ */
3984
+ function toLowerCase(str, [delimiter, joiner]) {
3985
+ return str.toLowerCase().replaceAll(delimiter || " ", joiner || " ");
3986
+ }
3987
+ //#endregion
3974
3988
  //#region src/components/chevron-up-down-anime.tsx
3975
3989
  function ChevronUpDownAnime({ className, isUp = false }) {
3976
3990
  const firstLoadRef = useRef(true);
@@ -6210,46 +6224,43 @@ function Input({ children, className, description, descriptionProps: { className
6210
6224
  }
6211
6225
  //#endregion
6212
6226
  //#region src/hooks/create-fast-context.tsx
6213
- function createFastContext(defaultInitialState) {
6214
- function useStoreData(initialState = defaultInitialState) {
6215
- const store = useRef(initialState), get = () => store.current, subscribers = useRef(/* @__PURE__ */ new Set());
6216
- const set = (value) => {
6217
- if (typeof value === "function") store.current = value(store.current);
6218
- else store.current = value;
6219
- subscribers.current.forEach((callback) => callback());
6220
- };
6221
- const subscribe = (callback) => {
6222
- subscribers.current.add(callback);
6223
- return () => subscribers.current.delete(callback);
6224
- };
6227
+ function createFastContext(initialState) {
6228
+ function useStoreData() {
6229
+ const store = useRef(initialState);
6230
+ const get = useCallback(() => store.current, []);
6231
+ const subscribers = useRef(/* @__PURE__ */ new Set());
6225
6232
  return {
6226
6233
  get,
6227
- set,
6228
- subscribe
6234
+ set: useCallback((value) => {
6235
+ store.current = {
6236
+ ...store.current,
6237
+ ...value
6238
+ };
6239
+ subscribers.current.forEach((callback) => callback());
6240
+ }, []),
6241
+ subscribe: useCallback((callback) => {
6242
+ subscribers.current.add(callback);
6243
+ return () => subscribers.current.delete(callback);
6244
+ }, [])
6229
6245
  };
6230
6246
  }
6231
6247
  const StoreContext = createContext(null);
6232
- function Provider({ initialValue = defaultInitialState, ...props }) {
6248
+ function Provider({ children }) {
6233
6249
  return /* @__PURE__ */ jsx(StoreContext.Provider, {
6234
- value: useStoreData(initialValue),
6235
- ...props
6250
+ value: useStoreData(),
6251
+ children
6236
6252
  });
6237
6253
  }
6238
- function useStore(selector, initialValue) {
6254
+ function useStore(selector) {
6239
6255
  const store = useContext(StoreContext);
6240
- if (!store) {
6241
- const selectedValue = selector(initialValue !== void 0 ? initialValue : defaultInitialState);
6242
- const noOpSet = () => console.warn("Attempting to set store value outside of Provider");
6243
- return [selectedValue, noOpSet];
6244
- }
6245
- return [useSyncExternalStore(store.subscribe, () => selector(store.get()), () => selector(initialValue !== void 0 ? initialValue : defaultInitialState)), store.set];
6256
+ if (!store) throw new Error("Store not found");
6257
+ return [useSyncExternalStore(store.subscribe, () => selector(store.get()), () => selector(initialState)), store.set];
6246
6258
  }
6247
6259
  return {
6248
6260
  Provider,
6249
6261
  useStore
6250
6262
  };
6251
6263
  }
6252
- const { Provider, useStore } = createFastContext("incomplete");
6253
6264
  //#endregion
6254
6265
  //#region src/hooks/use-mobile-device.ts
6255
6266
  function useMobileDevice() {
@@ -6347,7 +6358,7 @@ function ModalTitle({ as, ref, ...props }) {
6347
6358
  ref
6348
6359
  });
6349
6360
  }
6350
- function ModalDialog(props) {
6361
+ function ModalDialog({ dialogPanelProps: { className: dialogPanelClassName, style: dialogPanelStyle, ...dialogPanelProps } = {}, modalScrollContainerProps: { className: modalScrollContainerClassName, ...modalScrollContainerProps } = {}, ...props }) {
6351
6362
  const [modalControls, setModalControls] = useModalControls((store) => store), isMobileDevice = useMobileDevice();
6352
6363
  const { className, closeModal, dialogPanelRef, isOpen, place, pseudoContainerRef, readyToClose } = modalControls || {};
6353
6364
  const [dialogPanelEl, setDialogPanelEl] = useState(null);
@@ -6383,17 +6394,11 @@ function ModalDialog(props) {
6383
6394
  if (!setModalControls) return;
6384
6395
  if (progressY >= DRAG_TO_CLOSE_PROGRESS && !readyToCloseRef.current) {
6385
6396
  readyToCloseRef.current = true;
6386
- setModalControls((prev) => ({
6387
- ...prev,
6388
- readyToClose: true
6389
- }));
6397
+ setModalControls({ readyToClose: true });
6390
6398
  }
6391
6399
  if (progressY < DRAG_TO_CLOSE_PROGRESS && readyToCloseRef.current) {
6392
6400
  readyToCloseRef.current = false;
6393
- setModalControls((prev) => ({
6394
- ...prev,
6395
- readyToClose: false
6396
- }));
6401
+ setModalControls({ readyToClose: false });
6397
6402
  }
6398
6403
  },
6399
6404
  trigger: draggableTrigger
@@ -6410,7 +6415,6 @@ function ModalDialog(props) {
6410
6415
  pseudoContainer.style.width = `${width}px`;
6411
6416
  pseudoContainer.style.height = `100dvh`;
6412
6417
  pseudoContainer.style.zIndex = "-1";
6413
- pseudoContainer.style.border = "2px solid blue";
6414
6418
  document.body.appendChild(pseudoContainer);
6415
6419
  animate(dialogPanel, {
6416
6420
  ...isMobileDevice ? {
@@ -6478,8 +6482,12 @@ function ModalDialog(props) {
6478
6482
  })
6479
6483
  }), /* @__PURE__ */ jsxs(DialogPanel, {
6480
6484
  ref: setDialogPanelRef,
6481
- className: twMerge("fixed left-1/2 w-screen -translate-x-1/2 bg-neutral-50 px-4 shadow-[0_-15px_50px_-12px] shadow-neutral-950/25 ease-exponential sm:w-[calc(100vw-2rem)] sm:max-w-fit sm:px-6 sm:shadow-2xl lg:px-8 dark:bg-neutral-900", place === "center" ? "top-1/2 -translate-y-1/2 rounded-2xl" : "bottom-0 h-fit max-h-[calc(100dvh-4rem)] translate-y-0 rounded-ss-4xl rounded-se-4xl after:absolute after:inset-x-0 after:-bottom-64 after:h-64 after:bg-inherit sm:top-1/2 sm:bottom-auto sm:-translate-y-1/2 sm:rounded-ee-4xl sm:rounded-es-4xl sm:after:hidden pointer-fine:top-1/2 pointer-fine:bottom-auto pointer-fine:-translate-y-1/2 pointer-fine:rounded-3xl", className),
6482
- style: isMobileDevice ? void 0 : { opacity: 0 },
6485
+ ...dialogPanelProps,
6486
+ className: twMerge("fixed left-1/2 w-screen -translate-x-1/2 bg-neutral-50 shadow-[0_-15px_50px_-12px] shadow-neutral-950/25 ease-exponential sm:w-[calc(100vw-2rem)] sm:max-w-fit sm:shadow-2xl dark:bg-neutral-900", place === "center" ? "top-1/2 -translate-y-1/2 rounded-2xl" : "bottom-0 h-fit max-h-[calc(100dvh-4rem)] translate-y-0 rounded-ss-4xl rounded-se-4xl after:absolute after:inset-x-0 after:-bottom-64 after:h-64 after:bg-inherit sm:top-1/2 sm:bottom-auto sm:-translate-y-1/2 sm:rounded-ee-4xl sm:rounded-es-4xl sm:after:hidden pointer-fine:top-1/2 pointer-fine:bottom-auto pointer-fine:-translate-y-1/2 pointer-fine:rounded-3xl", dialogPanelClassName),
6487
+ style: {
6488
+ ...dialogPanelStyle,
6489
+ ...isMobileDevice ? {} : { opacity: 0 }
6490
+ },
6483
6491
  children: [/* @__PURE__ */ jsx("button", {
6484
6492
  className: "absolute inset-x-0 top-0 z-10 flex h-6 cursor-grab items-center justify-center after:h-1 after:w-8 after:rounded-full after:bg-neutral-500/50 after:transition-[scale,background-color] after:duration-500 after:ease-exponential active:cursor-grabbing active:after:scale-x-150 active:after:scale-y-125 active:after:bg-neutral-500 data-ready:after:scale-x-200 data-ready:after:scale-y-200 data-ready:after:bg-(--base-theme-color) pointer-fine:hover:after:scale-x-125 pointer-fine:hover:after:bg-neutral-500/75 pointer-fine:active:after:scale-x-150 pointer-fine:active:after:bg-neutral-500 data-ready:pointer-fine:hover:after:scale-x-200 data-ready:pointer-fine:hover:after:scale-y-200 data-ready:pointer-fine:hover:after:bg-(--base-theme-color) data-ready:pointer-fine:active:after:scale-x-200 data-ready:pointer-fine:active:after:scale-y-200 data-ready:pointer-fine:active:after:bg-(--base-theme-color)",
6485
6493
  ...readyToClose ? { "data-ready": "" } : {},
@@ -6490,10 +6498,11 @@ function ModalDialog(props) {
6490
6498
  children: "Drag down to close"
6491
6499
  })
6492
6500
  }), /* @__PURE__ */ jsx("div", {
6493
- className: "overflow-y-scroll",
6501
+ ...modalScrollContainerProps,
6502
+ className: twMerge("h-fit max-h-[calc(100dvh-4rem)] overflow-y-scroll px-4 sm:px-6 lg:px-8", modalScrollContainerClassName),
6494
6503
  children: /* @__PURE__ */ jsx("div", {
6495
6504
  ...props,
6496
- className: "py-4 sm:py-6 lg:py-8"
6505
+ className: twMerge("h-full py-3 sm:py-5 lg:py-7", className)
6497
6506
  })
6498
6507
  })]
6499
6508
  })]
@@ -6526,11 +6535,10 @@ function ModalDisplay({ children, className, onClose, onOpen, place = "bottom" }
6526
6535
  const closeFunctions = () => {
6527
6536
  onClose?.();
6528
6537
  modalControls?.pseudoContainerRef?.current?.remove();
6529
- setModalControls?.((previous) => ({
6530
- ...previous,
6538
+ setModalControls?.({
6531
6539
  pseudoContainerRef: { current: null },
6532
6540
  readyToClose: false
6533
- }));
6541
+ });
6534
6542
  };
6535
6543
  const mobileAnimation = {
6536
6544
  y: "100%",
@@ -6559,15 +6567,14 @@ function ModalDisplay({ children, className, onClose, onOpen, place = "bottom" }
6559
6567
  });
6560
6568
  };
6561
6569
  useEffect(() => {
6562
- setModalControls?.((previous) => ({
6563
- ...previous,
6570
+ setModalControls?.({
6564
6571
  isOpen,
6565
6572
  place,
6566
6573
  className,
6567
6574
  openModal,
6568
6575
  closeModal,
6569
6576
  dialogPanelRef: localDialogPanelRef
6570
- }));
6577
+ });
6571
6578
  }, [
6572
6579
  className,
6573
6580
  closeModal,
@@ -6634,6 +6641,10 @@ function ChevronUpChevronDown({ weight = "regular", ...props }) {
6634
6641
  }
6635
6642
  //#endregion
6636
6643
  //#region src/components/select.tsx
6644
+ const { Provider: SelectContextProvider, useStore: useSelectContext } = createFastContext({
6645
+ multiple: false,
6646
+ selectedOptionDisplayProps: {}
6647
+ });
6637
6648
  /**
6638
6649
  * ## Select Section Title
6639
6650
  *
@@ -6648,48 +6659,32 @@ function SelectSectionTitle({ className, ...props }) {
6648
6659
  /**
6649
6660
  * ## SelectOption
6650
6661
  *
6651
- * @prop children - This is what is displayed in the drop down menu
6652
- * @prop name - This is displayed in the trigger button
6653
- * @prop value - This is used for FormData
6654
- */
6655
- function SelectOption({ children, className, name, ...props }) {
6662
+ * @prop children - This is what is displayed in the drop down menu.
6663
+ * @prop name - This is displayed in the trigger button.
6664
+ * @prop value - This is used for FormData.
6665
+ * @prop selectedDisplayProps - This is used to customize the display of the selected option (takes priority over selectedOptionDisplayProps).
6666
+ */
6667
+ function SelectOption({ children, className, name, selectedDisplayProps: { children: selectedDisplayChildren, className: selectedDisplayClassName, ...selectedDisplayProps } = {}, ...props }) {
6668
+ const [selectContext] = useSelectContext((store) => store), { multiple, selectedOptionDisplayProps } = selectContext || {};
6669
+ const { children: selectedOptionDisplayChildren, className: selectedOptionDisplayClassName } = selectedOptionDisplayProps || {};
6656
6670
  return /* @__PURE__ */ jsx(ListboxOption, {
6657
6671
  className: "group/option contents",
6658
6672
  ...props,
6659
6673
  children: (bag) => bag.selectedOption ? /* @__PURE__ */ jsx("span", {
6660
- className: `mr-3 before:absolute before:-left-3 before:content-[',_']`,
6661
- children: name
6674
+ ...selectedOptionDisplayProps,
6675
+ ...selectedDisplayProps,
6676
+ className: twMerge(!selectedDisplayClassName && !selectedOptionDisplayClassName && multiple && `before:content-[',_'] group-first-of-type/option:before:content-['']`, selectedOptionDisplayClassName, selectedDisplayClassName),
6677
+ children: selectedDisplayChildren ? typeof selectedDisplayChildren === "function" ? selectedDisplayChildren(name) : selectedDisplayChildren : selectedOptionDisplayChildren ? typeof selectedOptionDisplayChildren === "function" ? selectedOptionDisplayChildren(name) : selectedOptionDisplayChildren : name
6662
6678
  }) : /* @__PURE__ */ jsxs("div", {
6663
- className: twMerge("flex cursor-pointer items-center gap-2 rounded-lg px-2 py-1 transition-[background-color] duration-200 ease-exponential select-none [--theme-color:var(--base-theme-color)] corner-super-1.5 group-disabled/option:opacity-50 group-data-focus/option:bg-(--theme-color)/15 group-data-selected/option:cursor-default group-data-selected/option:text-(--theme-color) group-data-focus/option:group-data-selected/option:bg-transparent dark:group-data-focus/option:bg-(--theme-color)/15", className),
6664
- children: [/* @__PURE__ */ jsx(Checkmark, { className: "invisible size-3.5 group-data-selected/option:visible" }), typeof children === "function" ? children(bag) : children]
6679
+ className: twMerge("flex cursor-pointer items-center gap-2 rounded-lg px-2 py-1 transition-[background-color,color] duration-200 ease-exponential select-none [--theme-color:var(--base-theme-color)] corner-super-1.5 group-disabled/option:opacity-50 group-data-focus/option:bg-(--theme-color)/15 group-data-selected/option:text-(--theme-color) dark:group-data-focus/option:bg-(--theme-color)/15", !multiple && "group-data-selected/option:cursor-default group-data-focus/option:group-data-selected/option:bg-transparent", className),
6680
+ children: [/* @__PURE__ */ jsx(Checkmark, { className: "size-3.5 scale-70 opacity-0 transition-[opacity,scale] duration-200 ease-exponential group-data-selected/option:scale-100 group-data-selected/option:opacity-100" }), typeof children === "function" ? children(bag) : children]
6665
6681
  })
6666
6682
  });
6667
6683
  }
6668
- /**
6669
- * # Select
6670
- *
6671
- * A customizable select component intended to work very similar to HTML's `<select>` element.
6672
- *
6673
- * Use the `SelectOption` component to define the options.
6674
- *
6675
- * Use the `SelectSectionTitle` component to define titles.
6676
- *
6677
- * @prop label - The label for the select component.
6678
- * @prop description - The description for the select component.
6679
- * @prop placeholder - The placeholder for the select component.
6680
- * @prop required - Whether the select component is required.
6681
- * @prop invalid - Whether the select component is invalid.
6682
- * @prop multiple - Whether the select component allows multiple selections.
6683
- * @prop optionsProps - The props to be passed to each SelectOption component.
6684
- * @prop selectedOptionProps - The props to be passed to the selected option component.
6685
- * @prop fieldProps - The props to be passed to the parent field component.
6686
- * @prop labelProps - The props to be passed to the label component.
6687
- * @prop descriptionProps - The props to be passed to the description component.
6688
- * @prop anchor - The anchor point for the drop down menu.
6689
- */
6690
- function Select({ buttonProps, children, className, description, descriptionProps: { className: descriptionClassName, ...descriptionProps } = {}, fieldProps: { className: fieldClassName, ...fieldProps } = {}, invalid, label, labelProps: { className: labelClassName, ...labelProps } = {}, onChange, optionsProps: { anchor, className: optionsClassName, transition, ...optionsProps } = {}, placeholder, required, selectedOptionProps: { ...selectedOptionProps } = {}, ...props }) {
6684
+ function SelectField({ buttonProps, children, className, description, descriptionProps: { className: descriptionClassName, ...descriptionProps } = {}, fieldProps: { className: fieldClassName, ...fieldProps } = {}, invalid, label, labelProps: { className: labelClassName, ...labelProps } = {}, onChange, optionsProps: { anchor, className: optionsClassName, transition, ...optionsProps } = {}, placeholder, required, selectedOptionProps, selectedOptionDisplayProps, ...props }) {
6691
6685
  const uniqueId = useId();
6692
- const multiple = props.multiple;
6686
+ const multiple = Boolean(props.multiple);
6687
+ const [, setSelectContext] = useSelectContext((store) => store);
6693
6688
  const selectOptionList = Children.toArray(children).filter((child) => isValidElement(child) && child.props && typeof child.props === "object" && "name" in child.props && "value" in child.props && "children" in child.props);
6694
6689
  const listboxButtonRef = useRef(null);
6695
6690
  const [isInvalid, setIsInvalid] = useState(invalid);
@@ -6701,6 +6696,15 @@ function Select({ buttonProps, children, className, description, descriptionProp
6701
6696
  };
6702
6697
  const handleInvalid = () => setIsInvalid(true);
6703
6698
  const refocus = () => listboxButtonRef.current?.focus();
6699
+ const onVisible = useEffectEvent(() => {
6700
+ setSelectContext?.({
6701
+ multiple,
6702
+ selectedOptionDisplayProps
6703
+ });
6704
+ });
6705
+ useEffect(() => {
6706
+ onVisible();
6707
+ }, []);
6704
6708
  return /* @__PURE__ */ jsxs(Field, {
6705
6709
  ...fieldProps,
6706
6710
  className: (bag) => twMerge("grid gap-1", typeof fieldClassName === "function" ? fieldClassName(bag) : fieldClassName),
@@ -6757,6 +6761,382 @@ function Select({ buttonProps, children, className, description, descriptionProp
6757
6761
  ]
6758
6762
  });
6759
6763
  }
6764
+ /**
6765
+ * # Select
6766
+ *
6767
+ * A customizable select component intended to work very similar to HTML's `<select>` element.
6768
+ *
6769
+ * Use the `SelectOption` component to define the options.
6770
+ *
6771
+ * Use the `SelectSectionTitle` component to define titles.
6772
+ *
6773
+ * @prop label - The label for the select component.
6774
+ * @prop description - The description for the select component.
6775
+ * @prop placeholder - The placeholder for the select component.
6776
+ * @prop required - Whether the select component is required.
6777
+ * @prop invalid - Whether the select component is invalid.
6778
+ * @prop multiple - Whether the select component allows multiple selections.
6779
+ * @prop optionsProps - The props to be passed to each SelectOption component.
6780
+ * @prop selectedOptionProps - The props to be passed to the selected option component.
6781
+ * @prop selectedOptionDisplayProps - The props to be passed to each selected option in the selected option component.
6782
+ * @prop fieldProps - The props to be passed to the parent field component.
6783
+ * @prop labelProps - The props to be passed to the label component.
6784
+ * @prop descriptionProps - The props to be passed to the description component.
6785
+ * @prop anchor - The anchor point for the drop down menu.
6786
+ */
6787
+ function Select(props) {
6788
+ return /* @__PURE__ */ jsx(SelectContextProvider, { children: /* @__PURE__ */ jsx(SelectField, { ...props }) });
6789
+ }
6790
+ //#endregion
6791
+ //#region src/symbols/plus.tsx
6792
+ function Plus({ weight = "regular", ...props }) {
6793
+ switch (weight) {
6794
+ case "ultralight": return /* @__PURE__ */ jsx("svg", {
6795
+ viewBox: "9.76562 -65.2349 59.96 59.96",
6796
+ ...props,
6797
+ children: /* @__PURE__ */ jsx("path", { d: "M40.8828-6.4126L40.8828-64.0952C40.8828-64.7417 40.3511-65.2349 39.7466-65.2349C39.1421-65.2349 38.6069-64.7417 38.6069-64.0952L38.6069-6.4126C38.6069-5.76611 39.1421-5.27293 39.7466-5.27293C40.3511-5.27293 40.8828-5.76611 40.8828-6.4126ZM10.9053-34.1142L68.5879-34.1142C69.2344-34.1142 69.7242-34.6494 69.7242-35.2539C69.7242-35.8584 69.2344-36.3936 68.5879-36.3936L10.9053-36.3936C10.2554-36.3936 9.76562-35.8584 9.76562-35.2539C9.76562-34.6494 10.2554-34.1142 10.9053-34.1142Z" })
6798
+ });
6799
+ case "thin": return /* @__PURE__ */ jsx("svg", {
6800
+ viewBox: "9.76562 -65.6758 60.83 60.84",
6801
+ ...props,
6802
+ children: /* @__PURE__ */ jsx("path", { d: "M41.9492-6.60743L41.9492-63.9004C41.9492-64.875 41.1406-65.6758 40.1875-65.6758C39.2344-65.6758 38.4121-64.875 38.4121-63.9004L38.4121-6.60743C38.4121-5.63281 39.2344-4.83202 40.1875-4.83202C41.1406-4.83202 41.9492-5.63281 41.9492-6.60743ZM11.541-33.4785L68.834-33.4785C69.8086-33.4785 70.5957-34.3008 70.5957-35.2539C70.5957-36.207 69.8086-37.0293 68.834-37.0293L11.541-37.0293C10.5527-37.0293 9.76562-36.207 9.76562-35.2539C9.76562-34.3008 10.5527-33.4785 11.541-33.4785Z" })
6803
+ });
6804
+ case "light": return /* @__PURE__ */ jsx("svg", {
6805
+ viewBox: "9.76562 -66.5366 62.53 62.57",
6806
+ ...props,
6807
+ children: /* @__PURE__ */ jsx("path", { d: "M44.0313-6.9878L44.0313-63.52C44.0313-65.1353 42.6821-66.5366 41.0483-66.5366C39.4146-66.5366 38.0317-65.1353 38.0317-63.52L38.0317-6.9878C38.0317-5.37256 39.4146-3.97119 41.0483-3.97119C42.6821-3.97119 44.0313-5.37256 44.0313-6.9878ZM12.7822-32.2373L69.3145-32.2373C70.9297-32.2373 72.2974-33.6201 72.2974-35.2539C72.2974-36.8877 70.9297-38.2705 69.3145-38.2705L12.7822-38.2705C11.1333-38.2705 9.76562-36.8877 9.76562-35.2539C9.76562-33.6201 11.1333-32.2373 12.7822-32.2373Z" })
6808
+ });
6809
+ case "regular": return /* @__PURE__ */ jsx("svg", {
6810
+ viewBox: "9.76562 -67.1875 63.82 63.87",
6811
+ ...props,
6812
+ children: /* @__PURE__ */ jsx("path", { d: "M45.6055-7.27539L45.6055-63.2324C45.6055-65.332 43.8477-67.1875 41.6992-67.1875C39.5508-67.1875 37.7441-65.332 37.7441-63.2324L37.7441-7.27539C37.7441-5.17578 39.5508-3.32031 41.6992-3.32031C43.8477-3.32031 45.6055-5.17578 45.6055-7.27539ZM13.7207-31.2988L69.6777-31.2988C71.7773-31.2988 73.584-33.1055 73.584-35.2539C73.584-37.4023 71.7773-39.209 69.6777-39.209L13.7207-39.209C11.5723-39.209 9.76562-37.4023 9.76562-35.2539C9.76562-33.1055 11.5723-31.2988 13.7207-31.2988Z" })
6813
+ });
6814
+ case "medium": return /* @__PURE__ */ jsx("svg", {
6815
+ viewBox: "9.76562 -67.6006 64.67 64.71",
6816
+ ...props,
6817
+ children: /* @__PURE__ */ jsx("path", { d: "M46.8623-7.6709L46.8623-62.8193C46.8623-65.3936 44.7354-67.6006 42.1211-67.6006C39.5068-67.6006 37.3398-65.3936 37.3398-62.8193L37.3398-7.6709C37.3398-5.09668 39.5068-2.88965 42.1211-2.88965C44.7354-2.88965 46.8623-5.09668 46.8623-7.6709ZM14.5469-30.4639L69.6953-30.4639C72.2695-30.4639 74.4365-32.6309 74.4365-35.2451C74.4365-37.8594 72.2695-40.0264 69.6953-40.0264L14.5469-40.0264C11.9326-40.0264 9.76562-37.8594 9.76562-35.2451C9.76562-32.6309 11.9326-30.4639 14.5469-30.4639Z" })
6818
+ });
6819
+ case "semibold": return /* @__PURE__ */ jsx("svg", {
6820
+ viewBox: "9.76562 -67.9173 65.32 65.36",
6821
+ ...props,
6822
+ children: /* @__PURE__ */ jsx("path", { d: "M47.8259-7.97412L47.8259-62.5026C47.8259-65.4407 45.4159-67.9173 42.4445-67.9173C39.4731-67.9173 37.0299-65.4407 37.0299-62.5026L37.0299-7.97412C37.0299-5.03604 39.4731-2.55947 42.4445-2.55947C45.4159-2.55947 47.8259-5.03604 47.8259-7.97412ZM15.1803-29.8237L69.7088-29.8237C72.6469-29.8237 75.0901-32.267 75.0901-35.2384C75.0901-38.2098 72.6469-40.653 69.7088-40.653L15.1803-40.653C12.2089-40.653 9.76562-38.2098 9.76562-35.2384C9.76562-32.267 12.2089-29.8237 15.1803-29.8237Z" })
6823
+ });
6824
+ case "bold": return /* @__PURE__ */ jsx("svg", {
6825
+ viewBox: "9.76562 -68.335 66.19 66.21",
6826
+ ...props,
6827
+ children: /* @__PURE__ */ jsx("path", { d: "M49.0967-8.37402L49.0967-62.085C49.0967-65.5029 46.3135-68.335 42.8711-68.335C39.4287-68.335 36.6211-65.5029 36.6211-62.085L36.6211-8.37402C36.6211-4.95605 39.4287-2.12402 42.8711-2.12402C46.3135-2.12402 49.0967-4.95605 49.0967-8.37402ZM16.0156-28.9795L69.7266-28.9795C73.1445-28.9795 75.9521-31.7871 75.9521-35.2295C75.9521-38.6719 73.1445-41.4795 69.7266-41.4795L16.0156-41.4795C12.5732-41.4795 9.76562-38.6719 9.76562-35.2295C9.76562-31.7871 12.5732-28.9795 16.0156-28.9795Z" })
6828
+ });
6829
+ case "heavy": return /* @__PURE__ */ jsx("svg", {
6830
+ viewBox: "9.76562 -68.9408 67.44 67.45",
6831
+ ...props,
6832
+ children: /* @__PURE__ */ jsx("path", { d: "M50.9399-8.95406L50.9399-61.4791C50.9399-65.5932 47.6153-68.9408 43.4898-68.9408C39.3643-68.9408 36.0282-65.5932 36.0282-61.4791L36.0282-8.95406C36.0282-4.84005 39.3643-1.49243 43.4898-1.49243C47.6153-1.49243 50.9399-4.84005 50.9399-8.95406ZM17.2272-27.755L69.7523-27.755C73.8663-27.755 77.2024-31.0911 77.2024-35.2166C77.2024-39.3421 73.8663-42.6782 69.7523-42.6782L17.2272-42.6782C13.1017-42.6782 9.76562-39.3421 9.76562-35.2166C9.76562-31.0911 13.1017-27.755 17.2272-27.755Z" })
6833
+ });
6834
+ case "black": return /* @__PURE__ */ jsx("svg", {
6835
+ viewBox: "9.76562 -69.4824 68.55 68.55",
6836
+ ...props,
6837
+ children: /* @__PURE__ */ jsx("path", { d: "M52.5879-9.47266L52.5879-60.9375C52.5879-65.6738 48.7793-69.4824 44.043-69.4824C39.3066-69.4824 35.498-65.6738 35.498-60.9375L35.498-9.47266C35.498-4.73633 39.3066-0.927734 44.043-0.927734C48.7793-0.927734 52.5879-4.73633 52.5879-9.47266ZM18.3105-26.6602L69.7754-26.6602C74.5117-26.6602 78.3203-30.4688 78.3203-35.2051C78.3203-39.9414 74.5117-43.75 69.7754-43.75L18.3105-43.75C13.5742-43.75 9.76562-39.9414 9.76562-35.2051C9.76562-30.4688 13.5742-26.6602 18.3105-26.6602Z" })
6838
+ });
6839
+ }
6840
+ }
6841
+ //#endregion
6842
+ //#region src/components/search.tsx
6843
+ const { Provider: SearchContextProvider, useStore: useSearchContext } = createFastContext({
6844
+ multiple: false,
6845
+ query: "",
6846
+ selectedOptionDisplayProps: {},
6847
+ selectedOptionList: []
6848
+ });
6849
+ /**
6850
+ * ## Search Section Title
6851
+ *
6852
+ * Displays a simple title.
6853
+ */
6854
+ function SearchSectionTitle({ className, ...props }) {
6855
+ return /* @__PURE__ */ jsx("div", {
6856
+ className: twMerge("sticky -top-1 z-10 -mx-1 bg-inherit mask-t-from-transparent mask-t-from-0 mask-t-to-white mask-t-to-1.5 pl-2 font-bold text-neutral-500/50 backdrop-blur-[2px] backdrop-brightness-101", className),
6857
+ ...props
6858
+ });
6859
+ }
6860
+ /**
6861
+ * ## SearchOption
6862
+ *
6863
+ * @prop children - This is what is displayed in the drop down menu
6864
+ * @prop name - This is used for filtering by default
6865
+ * @prop value - This is used as selected value and for FormData
6866
+ */
6867
+ function SearchOption({ children, className, isInDisplay, name, selectedDisplayProps: { children: selectedDisplayChildren, className: selectedDisplayClassName, ...selectedDisplayProps } = {}, value, ...props }) {
6868
+ const [searchContext] = useSearchContext((store) => store);
6869
+ const { multiple, query, selectedOptionDisplayProps } = searchContext || {};
6870
+ if (!((query || "").trim() === "" || name.toLowerCase().includes((query || "").toLowerCase()) || isInDisplay)) return /* @__PURE__ */ jsx(Fragment, {});
6871
+ const { children: selectedOptionDisplayChildren, className: selectedOptionDisplayClassName } = selectedOptionDisplayProps || {};
6872
+ return isInDisplay ? /* @__PURE__ */ jsx("span", {
6873
+ ...selectedOptionDisplayProps,
6874
+ ...selectedDisplayProps,
6875
+ className: twMerge(!selectedDisplayClassName && !selectedOptionDisplayClassName && multiple && `after:content-[',_'] last-of-type:after:content-['']`, selectedOptionDisplayClassName, selectedDisplayClassName),
6876
+ children: selectedDisplayChildren ? typeof selectedDisplayChildren === "function" ? selectedDisplayChildren(name) : selectedDisplayChildren : selectedOptionDisplayChildren ? typeof selectedOptionDisplayChildren === "function" ? selectedOptionDisplayChildren(name) : selectedOptionDisplayChildren : name
6877
+ }) : /* @__PURE__ */ jsx(ComboboxOption, {
6878
+ className: "group/option contents",
6879
+ value: {
6880
+ id: value,
6881
+ name
6882
+ },
6883
+ ...props,
6884
+ children: (bag) => /* @__PURE__ */ jsxs("div", {
6885
+ className: twMerge("flex cursor-pointer items-center gap-2 rounded-lg px-2 py-1 transition-[background-color,color] duration-200 ease-exponential select-none [--theme-color:var(--base-theme-color)] corner-super-1.5 group-disabled/option:opacity-50 group-data-focus/option:bg-(--theme-color)/15 group-data-selected/option:text-(--theme-color) dark:group-data-focus/option:bg-(--theme-color)/15", !multiple && "group-data-selected/option:cursor-default group-data-focus/option:group-data-selected/option:bg-transparent", className),
6886
+ children: [/* @__PURE__ */ jsx(Checkmark, { className: "size-3.5 scale-70 opacity-0 transition-[opacity,scale] duration-200 ease-exponential group-data-selected/option:scale-100 group-data-selected/option:opacity-100" }), typeof children === "function" ? children(bag) : children ?? name]
6887
+ })
6888
+ });
6889
+ }
6890
+ function checkEquality(aOptionList, bOptionList) {
6891
+ if (aOptionList.length !== bOptionList.length) return false;
6892
+ for (let i = 0; i < aOptionList.length; i += 1) {
6893
+ const aOption = aOptionList[i], bOption = bOptionList[i];
6894
+ if (aOption?.id !== bOption?.id || aOption?.name !== bOption?.name) return false;
6895
+ }
6896
+ return true;
6897
+ }
6898
+ function SearchField({ allowCustom, buttonProps, children, className, defaultValue, description, descriptionProps: { className: descriptionClassName, ...descriptionProps } = {}, fieldProps: { className: fieldClassName, ...fieldProps } = {}, inputProps, invalid, label, labelProps: { className: labelClassName, ...labelProps } = {}, multiple, onChange, optionsProps: { anchor, className: optionsClassName, transition, ...optionsProps } = {}, placeholder, required = true, shelfProps: { className: shelfClassName, ...shelfProps } = {}, selectedOptionDisplayProps, singleDisplay, ...props }) {
6899
+ const uniqueId = useId();
6900
+ const [searchContext, setSearchContext] = useSearchContext((store) => store), { query } = searchContext || {};
6901
+ const [isInvalid, setIsInvalid] = useState(invalid);
6902
+ const [selectedOptionSync, setSelectedOptionSync] = useState(() => {
6903
+ if (multiple) return Array.isArray(defaultValue) ? defaultValue : [];
6904
+ return typeof defaultValue === "string" ? defaultValue : null;
6905
+ });
6906
+ const comboboxInputRef = useRef(null);
6907
+ const childOptionList = useMemo(() => Children.toArray(children).filter((child) => isValidElement(child) && !!child.props && "value" in child.props && "name" in child.props), [children]);
6908
+ const staticOptionList = useMemo(() => childOptionList.map((child) => ({
6909
+ id: child.props.value,
6910
+ name: child.props.name,
6911
+ selectedDisplayProps: child.props.selectedDisplayProps
6912
+ })), [childOptionList]);
6913
+ const [addedOptionList, setAddedOptionList] = useState([]);
6914
+ const customOptionFromQuery = useMemo(() => {
6915
+ const trimmedQuery = query.trim();
6916
+ if (!allowCustom || trimmedQuery.length === 0) return null;
6917
+ return {
6918
+ id: props.customOptionParams?.formatID?.(trimmedQuery) ?? toLowerCase(trimmedQuery, [" ", "_"]),
6919
+ name: trimmedQuery
6920
+ };
6921
+ }, [
6922
+ allowCustom,
6923
+ props.customOptionParams,
6924
+ query
6925
+ ]);
6926
+ const optionLookupMap = useMemo(() => {
6927
+ const lookupMap = /* @__PURE__ */ new Map();
6928
+ for (const option of staticOptionList) lookupMap.set(option.id, option.name);
6929
+ for (const option of addedOptionList) lookupMap.set(option.id, option.name);
6930
+ return lookupMap;
6931
+ }, [addedOptionList, staticOptionList]);
6932
+ const saveCustomOption = useEffectEvent((option) => {
6933
+ if (!multiple) return;
6934
+ setAddedOptionList((prevOptionList) => {
6935
+ if (prevOptionList.some((prevOption) => prevOption.id === option.id)) return prevOptionList;
6936
+ return [...prevOptionList, option];
6937
+ });
6938
+ });
6939
+ const handleChange = (selected) => {
6940
+ setIsInvalid(false);
6941
+ if (multiple && Array.isArray(selected)) {
6942
+ const selectedValueList = selected.map((selectedValue) => {
6943
+ if (selectedValue && typeof selectedValue === "object" && "id" in selectedValue && "name" in selectedValue) {
6944
+ const option = {
6945
+ id: String(selectedValue.id),
6946
+ name: String(selectedValue.name)
6947
+ };
6948
+ saveCustomOption(option);
6949
+ return option.id;
6950
+ }
6951
+ return String(selectedValue);
6952
+ });
6953
+ setSelectedOptionSync(selectedValueList);
6954
+ onChange?.(selectedValueList);
6955
+ return;
6956
+ }
6957
+ if (!multiple) {
6958
+ const normalizedSelected = selected && typeof selected === "object" && !Array.isArray(selected) ? String(selected.id) : selected;
6959
+ setSelectedOptionSync(normalizedSelected);
6960
+ onChange?.(normalizedSelected);
6961
+ return;
6962
+ }
6963
+ setSelectedOptionSync(selected);
6964
+ };
6965
+ const formatSelectedDisplay = (name) => {
6966
+ const selectedOptionDisplayChildren = selectedOptionDisplayProps?.children;
6967
+ if (!selectedOptionDisplayChildren) return name;
6968
+ const selectedOptionDisplayValue = typeof selectedOptionDisplayChildren === "function" ? selectedOptionDisplayChildren(name) : selectedOptionDisplayChildren;
6969
+ return typeof selectedOptionDisplayValue === "string" ? selectedOptionDisplayValue : name;
6970
+ };
6971
+ const handleInvalid = () => setIsInvalid(true);
6972
+ const refocus = () => comboboxInputRef.current?.focus();
6973
+ const onVisible = useEffectEvent(() => {
6974
+ setSearchContext?.({
6975
+ multiple,
6976
+ query: "",
6977
+ selectedOptionDisplayProps
6978
+ });
6979
+ });
6980
+ useEffect(() => {
6981
+ onVisible();
6982
+ }, []);
6983
+ useEffect(() => {
6984
+ const selectedOptionList = (Array.isArray(selectedOptionSync) ? selectedOptionSync : typeof selectedOptionSync === "string" ? [selectedOptionSync] : []).map((selectedId) => ({
6985
+ id: selectedId,
6986
+ name: optionLookupMap.get(selectedId) ?? selectedId
6987
+ }));
6988
+ if (!checkEquality(searchContext?.selectedOptionList ?? [], selectedOptionList)) setSearchContext?.({ selectedOptionList });
6989
+ }, [
6990
+ optionLookupMap,
6991
+ searchContext?.selectedOptionList,
6992
+ selectedOptionSync,
6993
+ setSearchContext
6994
+ ]);
6995
+ const queryChange = (e) => {
6996
+ const { currentTarget } = e, { value } = currentTarget;
6997
+ setSearchContext?.({ query: value });
6998
+ };
6999
+ const handleClose = () => {
7000
+ setSearchContext?.({ query: "" });
7001
+ };
7002
+ const updateDisplayValue = (value) => {
7003
+ if (multiple && Array.isArray(value)) {
7004
+ if (singleDisplay) return value.map((v) => formatSelectedDisplay(v.name)).join(", ");
7005
+ }
7006
+ if (!multiple && value) return formatSelectedDisplay(value.name);
7007
+ return "";
7008
+ };
7009
+ return /* @__PURE__ */ jsxs(Field, {
7010
+ ...fieldProps,
7011
+ className: (bag) => twMerge("grid gap-1", typeof fieldClassName === "function" ? fieldClassName(bag) : fieldClassName),
7012
+ children: [
7013
+ label && /* @__PURE__ */ jsx(Label, {
7014
+ ...labelProps,
7015
+ className: (bag) => twMerge("text-sm font-medium", required ? `after:text-red-700 after:content-['_*']` : "", typeof labelClassName === "function" ? labelClassName(bag) : labelClassName),
7016
+ children: label
7017
+ }),
7018
+ /* @__PURE__ */ jsxs(Combobox, {
7019
+ ...props,
7020
+ invalid: isInvalid || invalid,
7021
+ multiple,
7022
+ onChange: handleChange,
7023
+ onClose: handleClose,
7024
+ children: [/* @__PURE__ */ jsxs("div", {
7025
+ ...multiple ? { "data-multiple": "" } : {},
7026
+ className: "isolate contents data-multiple:grid",
7027
+ children: [/* @__PURE__ */ jsxs("div", {
7028
+ className: "relative",
7029
+ children: [
7030
+ /* @__PURE__ */ jsx(ComboboxInput, {
7031
+ ...inputProps,
7032
+ "aria-label": typeof label === "string" ? label : props.name,
7033
+ className: (bag) => twMerge("inline-block w-full overflow-clip rounded-xl border border-neutral-500/50 bg-neutral-100 py-1 pr-8 pl-2 text-left text-neutral-950 outline-offset-1 outline-blue-400/95 transition-[background-color] duration-300 ease-exponential corner-super-1.5 dark:bg-neutral-700 dark:text-neutral-50", "focus:outline-3 focus-visible:bg-neutral-50 focus-visible:outline-3 active:bg-neutral-200 dark:focus-visible:bg-neutral-600 dark:active:bg-neutral-800 pointer-fine:hover:bg-neutral-50 pointer-fine:active:bg-neutral-200 dark:pointer-fine:hover:bg-neutral-600 dark:pointer-fine:active:bg-neutral-800", "data-invalid:border-red-500 data-invalid:bg-[color-mix(in_oklch,var(--color-red-500)_5%,var(--color-neutral-100)_5%)] data-invalid:focus-visible:bg-[color-mix(in_oklch,var(--color-red-500)_1%,var(--color-neutral-100))] data-invalid:active:bg-[color-mix(in_oklch,var(--color-red-500)_5%,var(--color-neutral-100))] dark:data-invalid:bg-[color-mix(in_oklch,var(--color-red-500)_5%,var(--color-neutral-800)_5%)] dark:data-invalid:focus-visible:bg-[color-mix(in_oklch,var(--color-red-500)_1%,var(--color-neutral-800))] dark:data-invalid:active:bg-[color-mix(in_oklch,var(--color-red-500)_5%,var(--color-neutral-800)_5%)] data-invalid:pointer-fine:hover:bg-[color-mix(in_oklch,var(--color-red-500)_10%,var(--color-neutral-500)_5%)] data-invalid:pointer-fine:focus-visible:bg-[color-mix(in_oklch,var(--color-red-500)_1%,var(--color-neutral-100))] data-invalid:pointer-fine:active:bg-[color-mix(in_oklch,var(--color-red-500)_5%,var(--color-neutral-100))] dark:data-invalid:pointer-fine:hover:bg-[color-mix(in_oklch,var(--color-red-500)_10%,var(--color-neutral-800)_5%)] dark:data-invalid:pointer-fine:focus-visible:bg-[color-mix(in_oklch,var(--color-red-500)_1%,var(--color-neutral-800))] dark:data-invalid:pointer-fine:active:bg-[color-mix(in_oklch,var(--color-red-500)_5%,var(--color-neutral-800)_5%)]", typeof className === "function" ? className(bag) : className),
7034
+ displayValue: updateDisplayValue,
7035
+ name: props.name,
7036
+ onChange: queryChange,
7037
+ placeholder: placeholder || `${multiple ? "Choose Any" : "Choose One"}${allowCustom ? " or Create Your Own" : ""}`,
7038
+ ref: comboboxInputRef,
7039
+ required
7040
+ }),
7041
+ /* @__PURE__ */ jsx("input", {
7042
+ "aria-hidden": "true",
7043
+ className: "sr-only top-0 left-1/2",
7044
+ id: props.name + ":input:id" + uniqueId,
7045
+ name: props.name,
7046
+ onChange: () => {},
7047
+ onFocus: refocus,
7048
+ onInvalid: handleInvalid,
7049
+ required,
7050
+ tabIndex: -1,
7051
+ value: Array.isArray(selectedOptionSync) ? selectedOptionSync.join(", ") : selectedOptionSync ?? ""
7052
+ }),
7053
+ /* @__PURE__ */ jsx(ComboboxButton, {
7054
+ ...buttonProps,
7055
+ className: "absolute top-1/2 right-1.5 -translate-y-1/2 rounded p-0.5",
7056
+ children: /* @__PURE__ */ jsx(ChevronUpChevronDown, { className: "size-3 fill-current/50" })
7057
+ })
7058
+ ]
7059
+ }), multiple && !singleDisplay && /* @__PURE__ */ jsx("div", {
7060
+ ...shelfProps,
7061
+ className: twMerge("flex min-h-8 flex-wrap gap-1 p-2 before:absolute before:inset-x-0 before:-top-4 before:bottom-0 before:-z-10 before:rounded-b-xl before:border before:border-t-0 before:border-neutral-500/50", shelfClassName),
7062
+ children: searchContext?.selectedOptionList?.length > 0 && [...staticOptionList, ...addedOptionList].filter((option, optionIndex, optionList) => {
7063
+ return optionList.findIndex((innerOption) => innerOption.id === option.id) === optionIndex;
7064
+ }).map((option) => {
7065
+ if (!searchContext.selectedOptionList.some(({ id }) => id === option.id)) return null;
7066
+ return /* @__PURE__ */ jsx(SearchOption, {
7067
+ name: option.name,
7068
+ value: option.id,
7069
+ selectedDisplayProps: option.selectedDisplayProps,
7070
+ isInDisplay: true,
7071
+ children: option.name
7072
+ }, option.id);
7073
+ }).filter(Boolean)
7074
+ })]
7075
+ }), /* @__PURE__ */ jsxs(ComboboxOptions, {
7076
+ ...optionsProps,
7077
+ anchor: anchor || "bottom start",
7078
+ className: (bag) => twMerge("z-50 w-(--input-width) origin-top rounded-xl border border-neutral-500/50 bg-neutral-50/95 p-1 backdrop-blur-sm backdrop-brightness-110 transition-[opacity,scale,translate] duration-300 ease-exponential corner-super-1.5 empty:invisible focus:outline-none data-closed:-translate-y-0.5 data-closed:scale-y-0 data-closed:opacity-0 data-[anchor*=top]:origin-bottom dark:bg-neutral-800/95", multiple && !singleDisplay ? "[--anchor-gap:--spacing(8)]" : "[--anchor-gap:--spacing(1)]", typeof optionsClassName === "function" ? optionsClassName(bag) : optionsClassName),
7079
+ transition: transition ?? true,
7080
+ children: [
7081
+ allowCustom && query.length > 0 && customOptionFromQuery && !addedOptionList.some((addedOption) => addedOption.id === customOptionFromQuery.id) && /* @__PURE__ */ jsx(ComboboxOption, {
7082
+ value: customOptionFromQuery,
7083
+ className: "group/option contents",
7084
+ children: /* @__PURE__ */ jsxs("div", {
7085
+ className: "flex cursor-pointer items-center gap-2 rounded-lg px-2 py-1 transition-[background-color] duration-200 ease-exponential select-none [--theme-color:var(--base-theme-color)] corner-super-1.5 group-disabled/option:opacity-50 group-data-focus/option:bg-(--theme-color)/15 dark:group-data-focus/option:bg-(--theme-color)/15",
7086
+ children: [
7087
+ /* @__PURE__ */ jsx(Plus, { className: "size-3.5" }),
7088
+ "Use ",
7089
+ /* @__PURE__ */ jsxs("b", { children: [
7090
+ "\"",
7091
+ query,
7092
+ "\""
7093
+ ] })
7094
+ ]
7095
+ })
7096
+ }),
7097
+ children,
7098
+ multiple && addedOptionList.filter((addedOption) => !staticOptionList.some((staticOption) => staticOption.id === addedOption.id)).map((addedOption) => /* @__PURE__ */ jsx(SearchOption, {
7099
+ name: addedOption.name,
7100
+ value: addedOption.id,
7101
+ selectedDisplayProps: addedOption.selectedDisplayProps,
7102
+ children: addedOption.name
7103
+ }, "added:" + addedOption.id))
7104
+ ]
7105
+ })]
7106
+ }),
7107
+ description && /* @__PURE__ */ jsx(Description, {
7108
+ ...descriptionProps,
7109
+ className: (bag) => twMerge("text-xs text-current/60", typeof descriptionClassName === "function" ? descriptionClassName(bag) : descriptionClassName),
7110
+ children: description
7111
+ })
7112
+ ]
7113
+ });
7114
+ }
7115
+ /**
7116
+ * # Search
7117
+ *
7118
+ * A searchable select component built on top of Headless UI's `Combobox`.
7119
+ *
7120
+ * Use the `SearchOption` component to define options.
7121
+ *
7122
+ * Use the `SearchSectionTitle` component to define titles.
7123
+ *
7124
+ * @prop label - The label for the select component.
7125
+ * @prop description - The description for the select component.
7126
+ * @prop placeholder - The placeholder for the select component.
7127
+ * @prop required - Whether the select component is required.
7128
+ * @prop invalid - Whether the select component is invalid.
7129
+ * @prop multiple - Whether the select component allows multiple selections.
7130
+ * @prop optionsProps - The props to be passed to each SearchOption component.
7131
+ * @prop selectedOptionDisplayProps - The props to be passed to each selected option in the selected option component.
7132
+ * @prop fieldProps - The props to be passed to the parent field component.
7133
+ * @prop labelProps - The props to be passed to the label component.
7134
+ * @prop descriptionProps - The props to be passed to the description component.
7135
+ * @prop anchor - The anchor point for the drop down menu.
7136
+ */
7137
+ function Search(props) {
7138
+ return /* @__PURE__ */ jsx(SearchContextProvider, { children: /* @__PURE__ */ jsx(SearchField, { ...props }) });
7139
+ }
6760
7140
  //#endregion
6761
7141
  //#region src/symbols/circle.fill.tsx
6762
7142
  function CircleFill({ weight = "regular", ...props }) {
@@ -8759,25 +9139,21 @@ function TooltipDisplay({ anchor = "top", arrow: arrow$4, arrowClassName, childr
8759
9139
  clearTimeout(timeoutRef.current);
8760
9140
  };
8761
9141
  }, []);
8762
- const [, setTooltipContext] = useTooltipContext(() => void 0, defaultTooltipContext);
9142
+ const [tooltipContext, setTooltipContext] = useTooltipContext(() => defaultTooltipContext);
8763
9143
  useEffect(() => {
8764
- setTooltipContext?.((previous) => {
8765
- const nextArrow = arrow$4 || false, nextArrowClassName = arrowClassName || "";
8766
- if (previous.isOpen === isOpen && previous.openTooltip === openTooltip && previous.closeTooltip === closeTooltip && previous.refs === refs && previous.floatingStyles === floatingStyles && previous.isPositioned === isPositioned && previous.placement === placement && previous.middlewareData === middlewareData && previous.arrowRef === arrowRef && previous.arrow === nextArrow && previous.arrowClassName === nextArrowClassName) return previous;
8767
- return {
8768
- ...previous,
8769
- isOpen,
8770
- openTooltip,
8771
- closeTooltip,
8772
- refs,
8773
- floatingStyles,
8774
- isPositioned,
8775
- placement,
8776
- middlewareData,
8777
- arrowRef,
8778
- arrow: nextArrow,
8779
- arrowClassName: nextArrowClassName
8780
- };
9144
+ const nextArrow = arrow$4 || false, nextArrowClassName = arrowClassName || "";
9145
+ if (tooltipContext && tooltipContext.isOpen !== isOpen || tooltipContext.openTooltip !== openTooltip || tooltipContext.closeTooltip !== closeTooltip || tooltipContext.refs !== refs || tooltipContext.floatingStyles !== floatingStyles || tooltipContext.isPositioned !== isPositioned || tooltipContext.placement !== placement || tooltipContext.middlewareData !== middlewareData || tooltipContext.arrowRef !== arrowRef || tooltipContext.arrow !== nextArrow || tooltipContext.arrowClassName !== nextArrowClassName) setTooltipContext?.({
9146
+ isOpen,
9147
+ openTooltip,
9148
+ closeTooltip,
9149
+ refs,
9150
+ floatingStyles,
9151
+ isPositioned,
9152
+ placement,
9153
+ middlewareData,
9154
+ arrowRef,
9155
+ arrow: nextArrow,
9156
+ arrowClassName: nextArrowClassName
8781
9157
  });
8782
9158
  }, [
8783
9159
  arrow$4,
@@ -8838,4 +9214,4 @@ function ArrowSvg({ className, ...props }) {
8838
9214
  });
8839
9215
  }
8840
9216
  //#endregion
8841
- export { Anchor, Button, Checkbox, Details, DetailsBody, DetailsSummary, DropDown, DropDownButton, DropDownItem, DropDownItems, DropDownSection, DropDownSeparator, Fieldset, Form, Ghost, Heading, HumanVerification, IFrame, Input, Link, Modal, ModalClose, ModalDialog, ModalTitle, ModalTrigger, Select, SelectOption, SelectSectionTitle, SubmitButton, Textarea, Time, Tooltip, TooltipPanel, TooltipTrigger, generateHumanValidationToken, getLinkClasses, validateHuman };
9217
+ export { Anchor, Button, Checkbox, Details, DetailsBody, DetailsSummary, DropDown, DropDownButton, DropDownItem, DropDownItems, DropDownSection, DropDownSeparator, Fieldset, Form, Ghost, Heading, HumanVerification, IFrame, Input, Link, Modal, ModalClose, ModalDialog, ModalTitle, ModalTrigger, Search, SearchOption, SearchSectionTitle, Select, SelectOption, SelectSectionTitle, SubmitButton, Textarea, Time, Tooltip, TooltipPanel, TooltipTrigger, generateHumanValidationToken, getLinkClasses, validateHuman };