@mendylanda/ui 0.1.2 → 0.1.3

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.
package/README.md CHANGED
@@ -57,3 +57,7 @@ Use `chipLabel: false` when the selected values explain themselves. A string suc
57
57
  `<MendyUIProvider menuLayout="anchored">` positions desktop editors beside the selected row at their own height. The default remains `connected`. Both use the single-panel mobile layout. A standalone `<FilterMenu anchor={searchRef}>` can align to a custom search field. The menu grows to the available viewport height, capped by `--mendy-filter-menu-max-height`, which defaults to `44rem`; large lists remain virtualized.
58
58
 
59
59
  Chips enter with a short, staggered Motion spring. Reduced-motion preferences disable their movement. Theme radius still controls their corners.
60
+
61
+ Filter lists use the search anchor's width by default and shrink when the viewport cannot fit both columns. Override `--mendy-filter-list-width` or `--mendy-filter-menu-width` for a custom layout. In anchored mode, editors touch the list and move upward for lower rows so short editors stay within the list's height.
62
+
63
+ `FilterList` uses the original SimCall Motion variants: a 60ms stagger on initial list entry and the default item transition from y=10/opacity=0 to y=0/opacity=1. New chips enter immediately, without a delay based on their list position. `FilterChipList` provides the same orchestration for custom compositions of `FilterChip`; standalone chips also animate.
@@ -1 +1 @@
1
- export const originalClassNames = {"mui-33228ff7d583":"pointer-events-none","mui-b75af7ef6c4d":"invisible","mui-d42ef1497900":"visible","mui-32fb090591d9":"sr-only","mui-747355bdc2a2":"absolute","mui-d2d9e1f13413":"relative","mui-ce13093ad8c9":"inset-0","mui-3ba24c062d55":"inset-x-0","mui-cced28c6dc3f":"start","mui-207bd0b3f259":"start-2","mui-cea70f23972e":"start-3","mui-96a350bd3168":"start-4","mui-361e48d0308f":"end","mui-13422ddc8d83":"end-1","mui-585f4729f611":"end-9","mui-98599e4ee250":"top-0","mui-4e45f4841abb":"top-1/2","mui-866c339ea145":"left-4","mui-3eef1ce97dba":"z-50","mui-a42d519714d6":"container","mui-a2526bc2efa3":"m-0","mui-abba77319850":"-mx-1","mui-1752f11474a6":"mx-auto","mui-d8747231f142":"my-1","mui-958e2cfcf5b6":"-ms-2","mui-8cc46fa87f41":"-me-1.5","mui-f28fea81a5cd":"mt-2","mui-cc51bda60e7e":"ml-auto","mui-496aca80e4d8":"block","mui-222f930b8752":"flex","mui-0f2a693e93e2":"grid","mui-e564b4081d7a":"hidden","mui-995cf20a9c45":"inline","mui-123306850fe1":"inline-flex","mui-3da89b3ed14b":"field-sizing-content","mui-129d6f9b1e07":"aspect-square","mui-f7d12b41bceb":"size-(--cell-size)","mui-dc797fcc7165":"size-1.5","mui-9e7600197f38":"size-2","mui-61c000c8a98a":"size-3.5","mui-100c22d5776b":"size-4","mui-0712570dcc9f":"size-6","mui-79ede756e761":"size-7","mui-ebd37e04d422":"size-8","mui-3ee10ef4c057":"size-9","mui-d0a383a9c24f":"size-10","mui-4dad94bd15e3":"size-auto","mui-a5960ac1d283":"h-(--cell-size)","mui-ce1945804664":"h-6","mui-1fb07b38c63b":"h-8","mui-539ae144f076":"h-9","mui-fdd2f85cad6b":"h-10","mui-a66e9985b093":"h-auto","mui-57c930dc1c31":"h-full","mui-ae2c4b060bb9":"h-px","mui-571ea69568d3":"max-h-(--filter-menu-height)","mui-1f061e70178e":"max-h-(--radix-dropdown-menu-content-available-height)","mui-80baa5d03af7":"max-h-[calc(var(--filter-menu-height)-2px)]","mui-1326520533f0":"max-h-[min(6rem,calc(var(--filter-menu-height)*0.25))]","mui-fb4a3e97b5bd":"max-h-[min(20rem,var(--radix-dropdown-menu-content-available-height,20rem))]","mui-dcd942c18ddc":"max-h-[var(--radix-dropdown-menu-content-available-height)]","mui-410da8dfa8ac":"min-h-0","mui-9974acedf3f7":"min-h-9","mui-8423dc94ee06":"min-h-10","mui-50312c3ce4a3":"min-h-[60px]","mui-d48fe95d4da8":"w-(--cell-size)","mui-8867d85ed290":"w-8","mui-72b37c1a040d":"w-64","mui-37535002f0f7":"w-72","mui-919182384559":"w-[18.75rem]","mui-8dd3eece40db":"w-[var(--mendy-filter-menu-width,32rem)]","mui-8cfb5a42ef9f":"w-fit","mui-58d0413dd93c":"w-full","mui-91f82aa1df0c":"max-w-[60%]","mui-34055e6f8c1b":"max-w-[calc(100vw-2rem)]","mui-81b198a2db84":"max-w-full","mui-1458e495e3ae":"min-w-(--cell-size)","mui-184ddc11e5f9":"min-w-0","mui-e9ab1547c94d":"min-w-[8rem]","mui-7bd5bab6d7f4":"flex-1","mui-66b490dd6005":"shrink","mui-27ead27a81df":"shrink-0","mui-215061302c50":"border-collapse","mui-3a3774477287":"origin-(--radix-dropdown-menu-content-transform-origin)","mui-5dde0fd996f0":"-translate-y-1/2","mui-aa214ea38326":"transform","mui-393df0d154e0":"animate-none!","mui-7b3cd77eb999":"animate-pulse","mui-d343f41ba73e":"cursor-default","mui-acd532d8913e":"resize","mui-ae112c903ef8":"resize-y","mui-da607d0a2538":"grid-cols-[min(var(--mendy-filter-list-width,13rem),50%)_minmax(0,1fr)]","mui-b5985369ee35":"grid-rows-[minmax(0,1fr)]","mui-302c0d124a94":"flex-col","mui-faa8a23c68f6":"flex-wrap","mui-8fd2e2355cbc":"place-content-center","mui-71556df3b421":"items-center","mui-b9677bd1cb66":"items-start","mui-32c92bb1fde4":"justify-between","mui-a503dd374cca":"justify-center","mui-c62ec162662e":"justify-start","mui-19e97f3f40e6":"gap-1","mui-70007b876865":"gap-1.5","mui-074569488cca":"gap-2","mui-d7db3451d154":"gap-3","mui-90fc3ec35a37":"gap-4","mui-27e6c432192f":"space-y-1","mui-267171770524":"space-y-2","mui-5a3a4ee420c2":"truncate","mui-d5111d0e9f48":"overflow-hidden","mui-0fc84a692dad":"overflow-visible","mui-3b82279f859f":"overflow-x-hidden","mui-2368e909f3a5":"overflow-y-auto","mui-998780cdef87":"overscroll-contain","mui-b005d61d0953":"rounded-full","mui-3fa8c572949b":"rounded-md","mui-52417259a4f5":"rounded-none","mui-02e603944040":"rounded-sm","mui-a22ea0ba562a":"rounded-t-none","mui-10c0bae8cba9":"rounded-l-md","mui-34bbd346e74c":"rounded-r-md","mui-4f1a55de40bc":"border","mui-dad556abfe15":"border-0","mui-55860251be20":"border-s","mui-3b6d5fc7b061":"border-e","mui-894c3815a57f":"border-t","mui-bbe39cfb5cc6":"border-b","mui-8450eb0f1857":"border-dashed","mui-163a623b3716":"border-border/50","mui-1267095cdeb7":"border-input","mui-9b76f456b8c9":"border-muted-foreground/50","mui-292affc1f780":"bg-accent","mui-5b272f3c5076":"bg-background","mui-a943bea85d66":"bg-border","mui-0cf6c2e8fe7e":"bg-current","mui-965cf6587342":"bg-destructive","mui-e593c38256e0":"bg-popover","mui-0c2864fba576":"bg-primary","mui-d191cb569aac":"bg-secondary","mui-8fca9236d191":"bg-transparent","mui-717b342c2d01":"fill-current","mui-04760bcd507f":"p-0","mui-1dee6e3ec67d":"p-1","mui-b97db4a9f432":"p-2","mui-094f5333853b":"p-3","mui-56b8f5e0fb12":"px-(--cell-size)","mui-1da2e8f173c5":"px-1.5","mui-e7e01cc7f4df":"px-2","mui-0f9e6672913a":"px-3","mui-9513b3968002":"px-4","mui-0194c6e46323":"px-8","mui-1fcf28756bb1":"py-1","mui-a8c1dfb1d4ef":"py-1.5","mui-b5edc3ea7c91":"py-2","mui-078d945937da":"ps-8","mui-b2100041c585":"ps-9","mui-05d4103bd67f":"pe-2","mui-0e14c365f9e8":"pe-9","mui-559069d2c2e5":"pe-16","mui-0a702d97ed7d":"pt-3","mui-be02e79e6a27":"pt-3!","mui-1a52da5bc88c":"pr-1","mui-f5d8e661d857":"pl-2","mui-75b27e813dcc":"pl-8","mui-05ab12448317":"text-center","mui-e9347b78185f":"text-start","mui-757071a1d1c4":"text-base","mui-c74ab393b96d":"text-sm","mui-3992de70b033":"text-xs","mui-5f120ad4b50b":"text-[0.8rem]","mui-761cdb81bddb":"leading-none","mui-daaac3fbf55e":"font-medium","mui-52101fc7d8bb":"font-normal","mui-e1683b3c030a":"tracking-widest","mui-393883c1db68":"[overflow-wrap:anywhere]","mui-37cf9655f30a":"break-words","mui-726fca123972":"whitespace-normal","mui-963f6168b7d6":"whitespace-nowrap","mui-cc209238d847":"text-accent-foreground","mui-5eafab9bbefc":"text-current","mui-887b9502d5c7":"text-destructive","mui-8d4bf2704c8d":"text-destructive-foreground","mui-957a109f887f":"text-foreground","mui-35f35c41d134":"text-muted-foreground","mui-5bd2afe89f0b":"text-popover-foreground","mui-249f14ee5b6b":"text-primary","mui-abd1aaa1f5b2":"text-primary-foreground","mui-80df79ec9bb5":"text-secondary-foreground","mui-944969efb294":"underline","mui-d52f902a57e8":"underline-offset-4","mui-94f91922a10e":"opacity-0","mui-0b5a4d1257ab":"opacity-50","mui-65694092f002":"opacity-100","mui-0d4ca75de41c":"shadow-lg","mui-94ea94fde25f":"shadow-md","mui-89c3006b2722":"shadow-none","mui-7de07d413c13":"shadow-xs","mui-59edd3d33673":"outline-hidden","mui-318678825324":"outline","mui-dfc3376b8266":"filter","mui-eae178841c68":"transition-colors","mui-2cdd01663c76":"transition-opacity","mui-2b48746f4314":"transition-shadow","mui-b4b2fd95f324":"transition-none","mui-b30fc56058b6":"outline-none","mui-78905c9e865c":"select-none","mui-d80b6593dae5":"[--cell-size:--spacing(8)]","mui-82c2977beb8e":"[--cell-size:min(2rem,calc((100vw-3.5rem)/7))]","mui-971625533e56":"[--filter-menu-height:min(var(--mendy-filter-menu-max-height,44rem),var(--radix-dropdown-menu-content-available-height,44rem))]","mui-cacb19aa9640":"[scrollbar-width:thin]","mui-14bd99410890":"[unicode-bidi:isolate]","mui-9af9a4182597":"group-data-[disabled=true]:pointer-events-none","mui-ad936fcbed63":"group","mui-272ef88d6a0c":"group-data-[disabled=true]:opacity-50","mui-60052b901494":"group-data-[focused=true]/day:relative","mui-d9c5891363f9":"group/day","mui-3f96bf138f7b":"group-data-[focused=true]/day:z-10","mui-d39eb62b8363":"group-data-[focused=true]/day:border-ring","mui-5892a880410a":"group-data-[focused=true]/day:ring-1","mui-31b75c623c06":"group-data-[focused=true]/day:ring-ring","mui-f0ee83167878":"peer-disabled:cursor-not-allowed","mui-2ffc1d06387e":"peer","mui-25d26df52a1d":"peer-disabled:opacity-50","mui-32713fefe32f":"file:border-0","mui-25a74d576c42":"file:bg-transparent","mui-844abccf1fd0":"file:text-sm","mui-dc43de54f42a":"file:font-medium","mui-20315da78444":"placeholder:text-muted-foreground","mui-a267680f9f49":"before:absolute","mui-e22234c7b474":"before:inset-x-0","mui-4d24300d447b":"before:top-0","mui-37a30b916086":"before:border-t","mui-37ad15a95595":"hover:bg-accent","mui-bb6a4b3e902d":"hover:bg-destructive/90","mui-af9ea085901b":"hover:bg-primary/90","mui-099700a5a311":"hover:bg-secondary/80","mui-71863717995b":"hover:bg-transparent","mui-9f1f77b92dcb":"hover:text-accent-foreground","mui-4d6720d47806":"hover:text-foreground","mui-b56720602554":"hover:underline","mui-8da02faac748":"hover:opacity-100","mui-a8c1861c5d03":"focus:bg-accent","mui-a85c4c5d7465":"focus:text-accent-foreground","mui-b906a32b31ee":"focus-visible:border-ring","mui-39be5a15b766":"focus-visible:ring-1","mui-355efe22aedb":"focus-visible:ring-2","mui-365a4654f7b1":"focus-visible:ring-[3px]","mui-db549d38ff19":"focus-visible:ring-ring","mui-392a26f4c1b0":"focus-visible:ring-ring/50","mui-1df9125eebaf":"focus-visible:outline-1","mui-223daa83ed2d":"focus-visible:outline-ring","mui-2e357972fc10":"focus-visible:outline-none","mui-50aafa8694bb":"focus-visible:ring-inset","mui-8d3c1014b967":"disabled:pointer-events-none","mui-db567af109b7":"disabled:cursor-not-allowed","mui-4600b77303d6":"disabled:opacity-50","mui-7eb7501a2ef0":"has-focus:border-ring","mui-d0449753ba7b":"has-focus:ring-[3px]","mui-fc19c8471f34":"has-focus:ring-ring/50","mui-e288cffc2ef4":"has-[>svg]:px-1.5","mui-3b01ee05b16d":"has-[>svg]:px-2.5","mui-9e08353b774f":"has-[>svg]:px-3","mui-2c0115d1c32a":"aria-disabled:opacity-50","mui-1fac1d7d1df3":"aria-invalid:border-destructive","mui-2d91b4cbc3cb":"aria-invalid:ring-destructive","mui-5491fd0b4dc5":"aria-invalid:ring-destructive/20","mui-7d900a71e5ba":"aria-selected:text-muted-foreground","mui-397f5ba426a0":"data-[disabled]:pointer-events-none","mui-9beb654fcb0d":"data-[disabled]:opacity-50","mui-6fa6a8ade7c4":"data-[inset]:pl-8","mui-bbaaa5969856":"data-[more-below=true]:[mask-image:linear-gradient(#000_calc(100%_-_1rem),transparent)]","mui-dfc89afd7885":"data-[navigation=pointer]:focus-visible:ring-0","mui-96308b55e0d6":"data-[range-end=true]:rounded-md","mui-a55dbe6f3eec":"data-[range-end=true]:rounded-r-md","mui-714051e55e8e":"data-[range-end=true]:bg-primary","mui-c764cebcd540":"data-[range-end=true]:text-primary-foreground","mui-05ec0700cd48":"data-[range-middle=true]:rounded-none","mui-5fb598fb06f4":"data-[range-middle=true]:bg-accent","mui-0813905aa141":"data-[range-middle=true]:text-accent-foreground","mui-8020e31bff67":"data-[range-start=true]:rounded-md","mui-ab65911baf1d":"data-[range-start=true]:rounded-l-md","mui-f5460d79341c":"data-[range-start=true]:bg-primary","mui-421a7d3e6631":"data-[range-start=true]:text-primary-foreground","mui-a39af81d518c":"data-[selected-single=true]:bg-primary","mui-b6991ab170de":"data-[selected-single=true]:text-primary-foreground","mui-3cc0d07ef843":"data-[selected=true]:rounded-none","mui-89f6aab7a3f8":"data-[side=bottom]:slide-in-from-top-2","mui-3550f48d66b9":"data-[side=left]:slide-in-from-right-2","mui-7720fe004f5c":"data-[side=right]:slide-in-from-left-2","mui-66b560f839de":"data-[side=top]:slide-in-from-bottom-2","mui-20553d55d224":"data-[state=checked]:border-primary","mui-57d6d6401a2f":"data-[state=checked]:bg-primary","mui-7ca12016214f":"data-[state=checked]:text-primary-foreground","mui-37d8a3f448ff":"data-[state=closed]:animate-none!","mui-0cb4489c3645":"data-[state=closed]:animate-out","mui-bb5869ef903b":"data-[state=closed]:fade-out-0","mui-f4cf4be63707":"data-[state=closed]:zoom-out-95","mui-bae1e782f277":"data-[state=open]:animate-in","mui-4027d9c589b6":"data-[state=open]:bg-accent","mui-1952cd5b00aa":"data-[state=open]:text-accent-foreground","mui-6f73a280432e":"data-[state=open]:text-foreground","mui-790ed041a953":"data-[state=open]:opacity-100","mui-45464a92c1f6":"data-[state=open]:fade-in-0","mui-9ca352480f25":"data-[state=open]:zoom-in-95","mui-f3f7a9c5e1b3":"data-[variant=destructive]:text-destructive","mui-e2bb4ac97190":"data-[variant=destructive]:focus:bg-destructive/10","mui-353a727facfd":"data-[variant=destructive]:focus:text-destructive","mui-237747164b60":"motion-reduce:animate-none","mui-0cc20f4e20c8":"sm:w-[21.875rem]","mui-56760b222da0":"md:flex-row","mui-c05c9b99939d":"md:text-sm","mui-36b12e8339c7":"rtl:rotate-180","mui-9daa2369a41b":"dark:bg-input/30","mui-b2786f463a62":"dark:hover:text-accent-foreground","mui-c88f65aa011e":"dark:aria-invalid:ring-destructive/40","mui-bd73d819941e":"dark:data-[state=checked]:bg-primary","mui-98a28c2293f7":"dark:data-[variant=destructive]:focus:bg-destructive/20","mui-d78a8526410d":"pointer-coarse:[--cell-size:min(2.5rem,calc((100vw-3.5rem)/7))]","mui-b51243872d85":"sm:pointer-fine:h-8","mui-aa0e3c036805":"sm:pointer-fine:min-h-8","mui-0288c4ea71ea":"sm:pointer-fine:py-0.5","mui-41d1475cf71a":"sm:pointer-fine:py-1.5","mui-548a450e8e53":"[&_*]:transition-none!","mui-a1c8c43d9be2":"[&_[role^=menuitem]]:min-h-9","mui-b43343fe71c0":"sm:pointer-fine:[&_[role^=menuitem]]:min-h-8","mui-cc310a330231":"[&_button]:font-semibold","mui-b7ff49878425":"[&_button]:underline","mui-d9bdd2c94504":"[&_button]:underline-offset-4","mui-bcae9d37090c":"[&_svg]:pointer-events-none","mui-c77732bd3ab4":"[&_svg]:size-3.5","mui-040e748a3fa0":"[&_svg]:shrink-0","mui-be87a4a64d81":"[&_svg:not([class*='size-'])]:size-3","mui-eb5ef2dbc2d4":"[&_svg:not([class*='size-'])]:size-4","mui-8637dfd54fbb":"[&_svg:not([class*='text-'])]:text-muted-foreground","mui-4f05a238500e":"[&::-webkit-search-cancel-button]:appearance-none","mui-74ab31abd804":"[&:first-child[data-selected=true]_button]:rounded-l-md","mui-13858191ca50":"rtl:**:[.rdp-button\\_next>svg]:rotate-180","mui-a324a7f99932":"rtl:**:[.rdp-button\\_previous>svg]:rotate-180","mui-82b114bbff3d":"data-[variant=destructive]:*:[svg]:text-destructive!","mui-6ee0c74de40c":"[&:last-child[data-selected=true]_button]:rounded-r-md","mui-6162ab70efb5":"[&:nth-child(2)[data-selected=true]_button]:rounded-l-md","mui-f157ee6bae99":"[&>div]:w-full","mui-ba417cf466b0":"[&>span]:text-xs","mui-829c8ef4f9c5":"[&>span]:opacity-70","mui-bf95f682e553":"[&>span:first-child]:mt-[calc(0.5lh-0.4375rem)]","mui-eb740dd32318":"[&>svg]:size-3.5","mui-019fd73c95db":"[&>svg]:text-muted-foreground","mui-b8293c91796c":"[[data-slot=card-content]_&]:bg-transparent","mui-8dd7e6b42262":"[[data-slot=popover-content]_&]:bg-transparent"};
1
+ export const originalClassNames = {"mui-33228ff7d583":"pointer-events-none","mui-b75af7ef6c4d":"invisible","mui-d42ef1497900":"visible","mui-32fb090591d9":"sr-only","mui-747355bdc2a2":"absolute","mui-d2d9e1f13413":"relative","mui-ce13093ad8c9":"inset-0","mui-3ba24c062d55":"inset-x-0","mui-cced28c6dc3f":"start","mui-207bd0b3f259":"start-2","mui-cea70f23972e":"start-3","mui-361e48d0308f":"end","mui-13422ddc8d83":"end-1","mui-585f4729f611":"end-9","mui-98599e4ee250":"top-0","mui-4e45f4841abb":"top-1/2","mui-3eef1ce97dba":"z-50","mui-a42d519714d6":"container","mui-a2526bc2efa3":"m-0","mui-abba77319850":"-mx-1","mui-1752f11474a6":"mx-auto","mui-d8747231f142":"my-1","mui-958e2cfcf5b6":"-ms-2","mui-291952c2525a":"-ms-px","mui-8cc46fa87f41":"-me-1.5","mui-f28fea81a5cd":"mt-2","mui-cc51bda60e7e":"ml-auto","mui-496aca80e4d8":"block","mui-d1b2a59fbea7":"contents","mui-222f930b8752":"flex","mui-0f2a693e93e2":"grid","mui-e564b4081d7a":"hidden","mui-995cf20a9c45":"inline","mui-123306850fe1":"inline-flex","mui-3da89b3ed14b":"field-sizing-content","mui-129d6f9b1e07":"aspect-square","mui-f7d12b41bceb":"size-(--cell-size)","mui-dc797fcc7165":"size-1.5","mui-61c000c8a98a":"size-3.5","mui-100c22d5776b":"size-4","mui-0712570dcc9f":"size-6","mui-79ede756e761":"size-7","mui-ebd37e04d422":"size-8","mui-3ee10ef4c057":"size-9","mui-d0a383a9c24f":"size-10","mui-4dad94bd15e3":"size-auto","mui-a5960ac1d283":"h-(--cell-size)","mui-ce1945804664":"h-6","mui-1fb07b38c63b":"h-8","mui-539ae144f076":"h-9","mui-fdd2f85cad6b":"h-10","mui-2bf5d58a824b":"h-12","mui-a66e9985b093":"h-auto","mui-57c930dc1c31":"h-full","mui-ae2c4b060bb9":"h-px","mui-571ea69568d3":"max-h-(--filter-menu-height)","mui-1f061e70178e":"max-h-(--radix-dropdown-menu-content-available-height)","mui-80baa5d03af7":"max-h-[calc(var(--filter-menu-height)-2px)]","mui-1326520533f0":"max-h-[min(6rem,calc(var(--filter-menu-height)*0.25))]","mui-fb4a3e97b5bd":"max-h-[min(20rem,var(--radix-dropdown-menu-content-available-height,20rem))]","mui-dcd942c18ddc":"max-h-[var(--radix-dropdown-menu-content-available-height)]","mui-410da8dfa8ac":"min-h-0","mui-9974acedf3f7":"min-h-9","mui-8423dc94ee06":"min-h-10","mui-50312c3ce4a3":"min-h-[60px]","mui-d48fe95d4da8":"w-(--cell-size)","mui-8867d85ed290":"w-8","mui-72b37c1a040d":"w-64","mui-37535002f0f7":"w-72","mui-0b9c84552e40":"w-[var(--mendy-filter-list-width,var(--mendy-filter-anchor-width,18.75rem))]","mui-bd8a502f98ae":"w-[var(--mendy-filter-menu-width,calc(var(--filter-list-width)_+_19rem))]","mui-8cfb5a42ef9f":"w-fit","mui-58d0413dd93c":"w-full","mui-91f82aa1df0c":"max-w-[60%]","mui-34055e6f8c1b":"max-w-[calc(100vw-2rem)]","mui-81b198a2db84":"max-w-full","mui-1458e495e3ae":"min-w-(--cell-size)","mui-184ddc11e5f9":"min-w-0","mui-e9ab1547c94d":"min-w-[8rem]","mui-7bd5bab6d7f4":"flex-1","mui-66b490dd6005":"shrink","mui-27ead27a81df":"shrink-0","mui-215061302c50":"border-collapse","mui-3a3774477287":"origin-(--radix-dropdown-menu-content-transform-origin)","mui-5dde0fd996f0":"-translate-y-1/2","mui-aa214ea38326":"transform","mui-393df0d154e0":"animate-none!","mui-7b3cd77eb999":"animate-pulse","mui-d343f41ba73e":"cursor-default","mui-acd532d8913e":"resize","mui-ae112c903ef8":"resize-y","mui-a3c6c8c31aed":"grid-cols-[min(var(--filter-list-width),calc(100%_-_min(19rem,50%)))_minmax(0,1fr)]","mui-b5985369ee35":"grid-rows-[minmax(0,1fr)]","mui-302c0d124a94":"flex-col","mui-faa8a23c68f6":"flex-wrap","mui-8fd2e2355cbc":"place-content-center","mui-71556df3b421":"items-center","mui-b9677bd1cb66":"items-start","mui-32c92bb1fde4":"justify-between","mui-a503dd374cca":"justify-center","mui-c62ec162662e":"justify-start","mui-19e97f3f40e6":"gap-1","mui-70007b876865":"gap-1.5","mui-074569488cca":"gap-2","mui-d7db3451d154":"gap-3","mui-90fc3ec35a37":"gap-4","mui-27e6c432192f":"space-y-1","mui-267171770524":"space-y-2","mui-5a3a4ee420c2":"truncate","mui-d5111d0e9f48":"overflow-hidden","mui-0fc84a692dad":"overflow-visible","mui-3b82279f859f":"overflow-x-hidden","mui-2368e909f3a5":"overflow-y-auto","mui-998780cdef87":"overscroll-contain","mui-b005d61d0953":"rounded-full","mui-3fa8c572949b":"rounded-md","mui-52417259a4f5":"rounded-none","mui-02e603944040":"rounded-sm","mui-b31810dbd8a9":"rounded-s-none","mui-a22ea0ba562a":"rounded-t-none","mui-10c0bae8cba9":"rounded-l-md","mui-34bbd346e74c":"rounded-r-md","mui-4f1a55de40bc":"border","mui-dad556abfe15":"border-0","mui-55860251be20":"border-s","mui-3b6d5fc7b061":"border-e","mui-894c3815a57f":"border-t","mui-bbe39cfb5cc6":"border-b","mui-8450eb0f1857":"border-dashed","mui-163a623b3716":"border-border/50","mui-1267095cdeb7":"border-input","mui-9b76f456b8c9":"border-muted-foreground/50","mui-292affc1f780":"bg-accent","mui-5b272f3c5076":"bg-background","mui-a943bea85d66":"bg-border","mui-0cf6c2e8fe7e":"bg-current","mui-965cf6587342":"bg-destructive","mui-e593c38256e0":"bg-popover","mui-0c2864fba576":"bg-primary","mui-d191cb569aac":"bg-secondary","mui-8fca9236d191":"bg-transparent","mui-04760bcd507f":"p-0","mui-1dee6e3ec67d":"p-1","mui-b97db4a9f432":"p-2","mui-094f5333853b":"p-3","mui-56b8f5e0fb12":"px-(--cell-size)","mui-1da2e8f173c5":"px-1.5","mui-e7e01cc7f4df":"px-2","mui-0f9e6672913a":"px-3","mui-9513b3968002":"px-4","mui-0194c6e46323":"px-8","mui-1fcf28756bb1":"py-1","mui-a8c1dfb1d4ef":"py-1.5","mui-b5edc3ea7c91":"py-2","mui-078d945937da":"ps-8","mui-b2100041c585":"ps-9","mui-05d4103bd67f":"pe-2","mui-a202804a1738":"pe-3","mui-0e14c365f9e8":"pe-9","mui-559069d2c2e5":"pe-16","mui-0a702d97ed7d":"pt-3","mui-be02e79e6a27":"pt-3!","mui-1a52da5bc88c":"pr-1","mui-f5d8e661d857":"pl-2","mui-05ab12448317":"text-center","mui-e9347b78185f":"text-start","mui-757071a1d1c4":"text-base","mui-c74ab393b96d":"text-sm","mui-3992de70b033":"text-xs","mui-5f120ad4b50b":"text-[0.8rem]","mui-761cdb81bddb":"leading-none","mui-daaac3fbf55e":"font-medium","mui-52101fc7d8bb":"font-normal","mui-e1683b3c030a":"tracking-widest","mui-393883c1db68":"[overflow-wrap:anywhere]","mui-37cf9655f30a":"break-words","mui-726fca123972":"whitespace-normal","mui-963f6168b7d6":"whitespace-nowrap","mui-cc209238d847":"text-accent-foreground","mui-5eafab9bbefc":"text-current","mui-887b9502d5c7":"text-destructive","mui-8d4bf2704c8d":"text-destructive-foreground","mui-957a109f887f":"text-foreground","mui-35f35c41d134":"text-muted-foreground","mui-5bd2afe89f0b":"text-popover-foreground","mui-249f14ee5b6b":"text-primary","mui-abd1aaa1f5b2":"text-primary-foreground","mui-80df79ec9bb5":"text-secondary-foreground","mui-944969efb294":"underline","mui-d52f902a57e8":"underline-offset-4","mui-94f91922a10e":"opacity-0","mui-0b5a4d1257ab":"opacity-50","mui-65694092f002":"opacity-100","mui-0d4ca75de41c":"shadow-lg","mui-94ea94fde25f":"shadow-md","mui-89c3006b2722":"shadow-none","mui-7de07d413c13":"shadow-xs","mui-59edd3d33673":"outline-hidden","mui-318678825324":"outline","mui-e0122edc668b":"drop-shadow-md","mui-dfc3376b8266":"filter","mui-70dd37c11434":"transition","mui-eae178841c68":"transition-colors","mui-2cdd01663c76":"transition-opacity","mui-2b48746f4314":"transition-shadow","mui-b4b2fd95f324":"transition-none","mui-b30fc56058b6":"outline-none","mui-78905c9e865c":"select-none","mui-d80b6593dae5":"[--cell-size:--spacing(8)]","mui-82c2977beb8e":"[--cell-size:min(2rem,calc((100vw-3.5rem)/7))]","mui-d7d803c609c5":"[--filter-list-width:var(--mendy-filter-list-width,var(--mendy-filter-anchor-width,13rem))]","mui-971625533e56":"[--filter-menu-height:min(var(--mendy-filter-menu-max-height,44rem),var(--radix-dropdown-menu-content-available-height,44rem))]","mui-cacb19aa9640":"[scrollbar-width:thin]","mui-14bd99410890":"[unicode-bidi:isolate]","mui-9af9a4182597":"group-data-[disabled=true]:pointer-events-none","mui-ad936fcbed63":"group","mui-272ef88d6a0c":"group-data-[disabled=true]:opacity-50","mui-60052b901494":"group-data-[focused=true]/day:relative","mui-d9c5891363f9":"group/day","mui-3f96bf138f7b":"group-data-[focused=true]/day:z-10","mui-d39eb62b8363":"group-data-[focused=true]/day:border-ring","mui-5892a880410a":"group-data-[focused=true]/day:ring-1","mui-31b75c623c06":"group-data-[focused=true]/day:ring-ring","mui-f0ee83167878":"peer-disabled:cursor-not-allowed","mui-2ffc1d06387e":"peer","mui-25d26df52a1d":"peer-disabled:opacity-50","mui-32713fefe32f":"file:border-0","mui-25a74d576c42":"file:bg-transparent","mui-844abccf1fd0":"file:text-sm","mui-dc43de54f42a":"file:font-medium","mui-20315da78444":"placeholder:text-muted-foreground","mui-a267680f9f49":"before:absolute","mui-e22234c7b474":"before:inset-x-0","mui-4d24300d447b":"before:top-0","mui-37a30b916086":"before:border-t","mui-37ad15a95595":"hover:bg-accent","mui-bb6a4b3e902d":"hover:bg-destructive/90","mui-af9ea085901b":"hover:bg-primary/90","mui-099700a5a311":"hover:bg-secondary/80","mui-71863717995b":"hover:bg-transparent","mui-9f1f77b92dcb":"hover:text-accent-foreground","mui-4d6720d47806":"hover:text-foreground","mui-b56720602554":"hover:underline","mui-8da02faac748":"hover:opacity-100","mui-a8c1861c5d03":"focus:bg-accent","mui-a85c4c5d7465":"focus:text-accent-foreground","mui-b906a32b31ee":"focus-visible:border-ring","mui-39be5a15b766":"focus-visible:ring-1","mui-355efe22aedb":"focus-visible:ring-2","mui-365a4654f7b1":"focus-visible:ring-[3px]","mui-db549d38ff19":"focus-visible:ring-ring","mui-392a26f4c1b0":"focus-visible:ring-ring/50","mui-1df9125eebaf":"focus-visible:outline-1","mui-223daa83ed2d":"focus-visible:outline-ring","mui-2e357972fc10":"focus-visible:outline-none","mui-50aafa8694bb":"focus-visible:ring-inset","mui-8d3c1014b967":"disabled:pointer-events-none","mui-db567af109b7":"disabled:cursor-not-allowed","mui-4600b77303d6":"disabled:opacity-50","mui-7eb7501a2ef0":"has-focus:border-ring","mui-d0449753ba7b":"has-focus:ring-[3px]","mui-fc19c8471f34":"has-focus:ring-ring/50","mui-e288cffc2ef4":"has-[>svg]:px-1.5","mui-3b01ee05b16d":"has-[>svg]:px-2.5","mui-9e08353b774f":"has-[>svg]:px-3","mui-2c0115d1c32a":"aria-disabled:opacity-50","mui-1fac1d7d1df3":"aria-invalid:border-destructive","mui-2d91b4cbc3cb":"aria-invalid:ring-destructive","mui-5491fd0b4dc5":"aria-invalid:ring-destructive/20","mui-7d900a71e5ba":"aria-selected:text-muted-foreground","mui-397f5ba426a0":"data-[disabled]:pointer-events-none","mui-9beb654fcb0d":"data-[disabled]:opacity-50","mui-6fa6a8ade7c4":"data-[inset]:pl-8","mui-bbaaa5969856":"data-[more-below=true]:[mask-image:linear-gradient(#000_calc(100%_-_1rem),transparent)]","mui-dfc89afd7885":"data-[navigation=pointer]:focus-visible:ring-0","mui-96308b55e0d6":"data-[range-end=true]:rounded-md","mui-a55dbe6f3eec":"data-[range-end=true]:rounded-r-md","mui-714051e55e8e":"data-[range-end=true]:bg-primary","mui-c764cebcd540":"data-[range-end=true]:text-primary-foreground","mui-05ec0700cd48":"data-[range-middle=true]:rounded-none","mui-5fb598fb06f4":"data-[range-middle=true]:bg-accent","mui-0813905aa141":"data-[range-middle=true]:text-accent-foreground","mui-8020e31bff67":"data-[range-start=true]:rounded-md","mui-ab65911baf1d":"data-[range-start=true]:rounded-l-md","mui-f5460d79341c":"data-[range-start=true]:bg-primary","mui-421a7d3e6631":"data-[range-start=true]:text-primary-foreground","mui-a39af81d518c":"data-[selected-single=true]:bg-primary","mui-b6991ab170de":"data-[selected-single=true]:text-primary-foreground","mui-3cc0d07ef843":"data-[selected=true]:rounded-none","mui-89f6aab7a3f8":"data-[side=bottom]:slide-in-from-top-2","mui-3550f48d66b9":"data-[side=left]:slide-in-from-right-2","mui-7720fe004f5c":"data-[side=right]:slide-in-from-left-2","mui-66b560f839de":"data-[side=top]:slide-in-from-bottom-2","mui-20553d55d224":"data-[state=checked]:border-primary","mui-57d6d6401a2f":"data-[state=checked]:bg-primary","mui-7ca12016214f":"data-[state=checked]:text-primary-foreground","mui-37d8a3f448ff":"data-[state=closed]:animate-none!","mui-0cb4489c3645":"data-[state=closed]:animate-out","mui-bb5869ef903b":"data-[state=closed]:fade-out-0","mui-f4cf4be63707":"data-[state=closed]:zoom-out-95","mui-bae1e782f277":"data-[state=open]:animate-in","mui-4027d9c589b6":"data-[state=open]:bg-accent","mui-1952cd5b00aa":"data-[state=open]:text-accent-foreground","mui-6f73a280432e":"data-[state=open]:text-foreground","mui-790ed041a953":"data-[state=open]:opacity-100","mui-45464a92c1f6":"data-[state=open]:fade-in-0","mui-9ca352480f25":"data-[state=open]:zoom-in-95","mui-f3f7a9c5e1b3":"data-[variant=destructive]:text-destructive","mui-e2bb4ac97190":"data-[variant=destructive]:focus:bg-destructive/10","mui-353a727facfd":"data-[variant=destructive]:focus:text-destructive","mui-237747164b60":"motion-reduce:animate-none","mui-0cc20f4e20c8":"sm:w-[21.875rem]","mui-56760b222da0":"md:flex-row","mui-c05c9b99939d":"md:text-sm","mui-36b12e8339c7":"rtl:rotate-180","mui-9daa2369a41b":"dark:bg-input/30","mui-b2786f463a62":"dark:hover:text-accent-foreground","mui-c88f65aa011e":"dark:aria-invalid:ring-destructive/40","mui-bd73d819941e":"dark:data-[state=checked]:bg-primary","mui-98a28c2293f7":"dark:data-[variant=destructive]:focus:bg-destructive/20","mui-d78a8526410d":"pointer-coarse:[--cell-size:min(2.5rem,calc((100vw-3.5rem)/7))]","mui-b51243872d85":"sm:pointer-fine:h-8","mui-aa0e3c036805":"sm:pointer-fine:min-h-8","mui-0288c4ea71ea":"sm:pointer-fine:py-0.5","mui-41d1475cf71a":"sm:pointer-fine:py-1.5","mui-548a450e8e53":"[&_*]:transition-none!","mui-a1c8c43d9be2":"[&_[role^=menuitem]]:min-h-9","mui-b43343fe71c0":"sm:pointer-fine:[&_[role^=menuitem]]:min-h-8","mui-cc310a330231":"[&_button]:font-semibold","mui-b7ff49878425":"[&_button]:underline","mui-d9bdd2c94504":"[&_button]:underline-offset-4","mui-bcae9d37090c":"[&_svg]:pointer-events-none","mui-c77732bd3ab4":"[&_svg]:size-3.5","mui-040e748a3fa0":"[&_svg]:shrink-0","mui-be87a4a64d81":"[&_svg:not([class*='size-'])]:size-3","mui-eb5ef2dbc2d4":"[&_svg:not([class*='size-'])]:size-4","mui-8637dfd54fbb":"[&_svg:not([class*='text-'])]:text-muted-foreground","mui-4f05a238500e":"[&::-webkit-search-cancel-button]:appearance-none","mui-74ab31abd804":"[&:first-child[data-selected=true]_button]:rounded-l-md","mui-13858191ca50":"rtl:**:[.rdp-button\\_next>svg]:rotate-180","mui-a324a7f99932":"rtl:**:[.rdp-button\\_previous>svg]:rotate-180","mui-82b114bbff3d":"data-[variant=destructive]:*:[svg]:text-destructive!","mui-6ee0c74de40c":"[&:last-child[data-selected=true]_button]:rounded-r-md","mui-6162ab70efb5":"[&:nth-child(2)[data-selected=true]_button]:rounded-l-md","mui-f157ee6bae99":"[&>div]:w-full","mui-ba417cf466b0":"[&>span]:text-xs","mui-829c8ef4f9c5":"[&>span]:opacity-70","mui-bf95f682e553":"[&>span:first-child]:mt-[calc(0.5lh-0.4375rem)]","mui-eb740dd32318":"[&>svg]:size-3.5","mui-019fd73c95db":"[&>svg]:text-muted-foreground","mui-b8293c91796c":"[[data-slot=card-content]_&]:bg-transparent","mui-8dd7e6b42262":"[[data-slot=popover-content]_&]:bg-transparent"};
@@ -6,10 +6,11 @@ import { ListFilter, Search, X, Circle, ListChecks, Type, Hash, CalendarDays, Sl
6
6
  import { Button } from "../customization.js";
7
7
  import { Input } from "../customization.js";
8
8
  import { Label } from "../customization.js";
9
+ import { FilterOptionSearch } from "./filter-option-search.js";
9
10
  import { FilterDateEditor } from "./filter-date-editor.js";
10
11
  import { Textarea } from "../customization.js";
11
12
  import { DropdownMenu, DropdownMenuTrigger, DropdownMenuRadioGroup, DropdownMenuRadioItem, } from "../primitives/dropdown-menu.js";
12
- import { AppliedFilter, FilterCheckboxItem } from "./filters.js";
13
+ import { AppliedFilter, FilterCheckboxItem, FilterChipList } from "./filters.js";
13
14
  import { FilterOptionCache, useFilterOptions } from "./use-filter-options.js";
14
15
  import { classifyPaste, resolvePasteAmbiguity } from "./filter-state.js";
15
16
  import { cn } from "../utils.js";
@@ -184,13 +185,10 @@ function FilterMenuContent({ anchor }) {
184
185
  }
185
186
  export function FilterList() {
186
187
  const { filters, suggestions } = useRoot();
187
- let entranceIndex = 0;
188
- return (_jsx(_Fragment, { children: filters.entries.flatMap((entry) => !entry.field.hidden &&
188
+ return (_jsx(FilterChipList, { children: filters.entries.flatMap((entry) => !entry.field.hidden &&
189
189
  (entry.field.isActive(entry.value) ||
190
190
  showSuggestion(entry, suggestions, filters.active.length))
191
- ? [
192
- _jsx(FieldChip, { entry: entry, entranceDelay: Math.min(entranceIndex++ * 0.06, 0.3) }, entry.id),
193
- ]
191
+ ? [_jsx(FieldChip, { entry: entry }, entry.id)]
194
192
  : []) }));
195
193
  }
196
194
  function summarize(field, value, choices) {
@@ -215,7 +213,7 @@ export function FilterFieldEditor({ id, autoFocus = true }) {
215
213
  const entry = filters.entries.find((entry) => entry.id === id);
216
214
  return entry ? (_jsx(FieldEditor, { entry: entry, active: true, autoFocus: autoFocus, disabled: disabled || entry.field.disabled, close: () => filters.edit(null), location: "inline" }, id)) : null;
217
215
  }
218
- function FieldChip({ entry, entranceDelay = 0 }) {
216
+ function FieldChip({ entry }) {
219
217
  const { classNames } = useMendyUI();
220
218
  const { filters, summary, suggestions, disabled, trigger } = useRoot();
221
219
  const { id, field, value } = entry;
@@ -229,7 +227,7 @@ function FieldChip({ entry, entranceDelay = 0 }) {
229
227
  const options = useFilterOptions(id, field, active ? value : field.suggestion?.value, false);
230
228
  if (field.hidden || (!active && !suggestion))
231
229
  return null;
232
- return (_jsxs(AppliedFilter, { entranceDelay: entranceDelay, label: field.label, "data-mendy-ui": "", "data-slot": active ? "filter-chip" : "filter-suggestion", "data-state": active ? "applied" : "suggested", className: cn(!active && "mui-4f1a55de40bc mui-8450eb0f1857 mui-9b76f456b8c9 mui-8fca9236d191", (field.summary ?? summary).mode === "all" && "mui-a66e9985b093 mui-9974acedf3f7", classNames?.chip), disabled: chipDisabled(field, active, disabled), removeProps: { className: classNames?.chipRemove }, contentProps: {
230
+ return (_jsxs(AppliedFilter, { label: field.label, "data-mendy-ui": "", "data-slot": active ? "filter-chip" : "filter-suggestion", "data-state": active ? "applied" : "suggested", className: cn(!active && "mui-4f1a55de40bc mui-8450eb0f1857 mui-9b76f456b8c9 mui-8fca9236d191", (field.summary ?? summary).mode === "all" && "mui-a66e9985b093 mui-9974acedf3f7", classNames?.chip), disabled: chipDisabled(field, active, disabled), removeProps: { className: classNames?.chipRemove }, contentProps: {
233
231
  className: classNames?.editor,
234
232
  onCloseAutoFocus: (event) => {
235
233
  if (!currentlyActive.current) {
@@ -378,15 +376,8 @@ function FieldEditor({ entry, active, disabled, close, location, autoFocus = tru
378
376
  return (_jsx(FilterDateEditor, { draftKey: `${entry.id}:date`, autoFocus: autoFocus, showLabel: showDateLabel, showClear: location !== "menu", field: field, value: value, disabled: disabled, apply: apply, error: error }));
379
377
  return (_jsx(ValueEditor, { location: location, field: field, draft: draft, setDraft: setDraft, text: text, setText: setText, input: input, error: error, id: id, disabled: disabled, apply: apply }));
380
378
  }
381
- function useChoiceSearch(field, count) {
382
- const large = (field.source?.items.length ?? 0) > 100 || count > 100;
383
- const [discovered, setDiscovered] = useState(large);
384
- if (large && !discovered)
385
- setDiscovered(true);
386
- return field.searchable || large || discovered;
387
- }
388
379
  function ChoiceEditor({ field, value, input, options, disabled, apply, location, error, }) {
389
- const searchable = useChoiceSearch(field, options.items.length);
380
+ const searchable = field.searchable !== false;
390
381
  const collection = useRef(null);
391
382
  const selected = Array.isArray(value) ? value : value === null ? [] : [value];
392
383
  const selectedSet = new Set(selected);
@@ -394,16 +385,16 @@ function ChoiceEditor({ field, value, input, options, disabled, apply, location,
394
385
  return (_jsxs("div", { "data-mendy-ui": "", "data-filter-choices": "", className: "mui-72b37c1a040d mui-81b198a2db84", onKeyDown: (event) => {
395
386
  if (event.key === "Tab")
396
387
  event.stopPropagation();
397
- }, children: [searchable && (_jsxs("div", { "data-mendy-ui": "", className: "mui-d2d9e1f13413 mui-bbe39cfb5cc6 mui-b97db4a9f432", children: [_jsx(Search, { className: "mui-33228ff7d583 mui-747355bdc2a2 mui-96a350bd3168 mui-4e45f4841abb mui-5dde0fd996f0 mui-100c22d5776b mui-35f35c41d134", "aria-hidden": "true" }), _jsx(Input, { ref: (node) => {
398
- input.current = node;
399
- }, "aria-label": searchLabel, type: "search", disabled: disabled, placeholder: searchLabel, value: options.query, className: "mui-078d945937da mui-b51243872d85 mui-4f05a238500e", onChange: (event) => options.setQuery(event.target.value), onKeyDown: (event) => {
400
- if (event.key === "ArrowDown") {
401
- event.preventDefault();
402
- collection.current?.focusFirst();
403
- }
404
- if (event.key !== "Escape" && event.key !== "Tab")
405
- event.stopPropagation();
406
- } })] })), _jsx(ChoiceCollection, { field: field, options: options, value: value, selected: selected, selectedSet: selectedSet, disabled: disabled, apply: apply, location: location, collection: collection }), _jsx(OptionFeedback, { options: options, error: error })] }));
388
+ }, children: [searchable && (_jsx(FilterOptionSearch, { ref: (node) => {
389
+ input.current = node;
390
+ }, "aria-label": searchLabel, type: "search", disabled: disabled, placeholder: searchLabel, value: options.query, onChange: (event) => options.setQuery(event.target.value), onKeyDown: (event) => {
391
+ if (event.key === "ArrowDown") {
392
+ event.preventDefault();
393
+ collection.current?.focusFirst();
394
+ }
395
+ if (event.key !== "Escape" && event.key !== "Tab")
396
+ event.stopPropagation();
397
+ } })), _jsx(ChoiceCollection, { field: field, options: options, value: value, selected: selected, selectedSet: selectedSet, disabled: disabled, apply: apply, location: location, collection: collection }), _jsx(OptionFeedback, { options: options, error: error })] }));
407
398
  }
408
399
  function ChoiceCollection({ field, options, value, selected, selectedSet, disabled, apply, location, collection, }) {
409
400
  const { classNames } = useMendyUI();
@@ -154,6 +154,7 @@ export interface RuntimeField {
154
154
  merge(current: unknown, incoming: unknown): unknown;
155
155
  urlKey?: string;
156
156
  source?: RuntimeSource;
157
+ /** Search is enabled by default. False disables it regardless of list size. */
157
158
  searchable?: boolean;
158
159
  /** Hide only the menu entry; recognition and chip editing remain available. */
159
160
  menu?: boolean;
@@ -184,6 +185,7 @@ interface SelectConfig<T, V> extends FieldConfig<V> {
184
185
  options: readonly T[] | ExternalOptions<T> | RemoteOptions<T, unknown>;
185
186
  getValue?: (item: T) => string;
186
187
  getLabel?: (item: T) => string;
188
+ /** Search is enabled by default. False disables it regardless of list size. */
187
189
  searchable?: boolean;
188
190
  loading?: boolean;
189
191
  error?: string | null;
@@ -39,7 +39,7 @@ export function FilterMenuPanel({ sections, selectedId, onSelect, onClose, ancho
39
39
  const editor = useRef(null);
40
40
  const rows = useRef(new Map());
41
41
  const pendingEditorFocus = useRef(false);
42
- const { alignOffset, side } = useMenuPlacement(anchor, trigger, desktop);
42
+ const { alignOffset, side, anchorStyle } = useMenuPlacement(anchor, trigger, desktop);
43
43
  const panelId = useId();
44
44
  const detached = desktop && menuLayout === "anchored";
45
45
  const editorPanel = useRef(null);
@@ -92,7 +92,7 @@ export function FilterMenuPanel({ sections, selectedId, onSelect, onClose, ancho
92
92
  requestAnimationFrame(() => previous && rows.current.get(previous)?.focus());
93
93
  }
94
94
  const showList = desktop || !selected;
95
- return (_jsx(DropdownMenuContent, { ref: content, "data-mendy-ui": "", "data-slot": "filter-menu-panel", role: "dialog", "aria-label": "Filters", "aria-labelledby": undefined, "aria-orientation": undefined, align: desktop ? "start" : "end", alignOffset: alignOffset, side: side, sideOffset: 7, collisionPadding: 16, onEscapeKeyDown: (event) => {
95
+ return (_jsx(DropdownMenuContent, { ref: content, "data-mendy-ui": "", "data-slot": "filter-menu-panel", role: "dialog", "aria-label": "Filters", "aria-labelledby": undefined, "aria-orientation": undefined, align: desktop ? "start" : "end", alignOffset: alignOffset, side: side, style: anchorStyle, sideOffset: 7, collisionPadding: 16, onEscapeKeyDown: (event) => {
96
96
  if (selected && !desktop) {
97
97
  event.preventDefault();
98
98
  back();
@@ -117,8 +117,9 @@ export function FilterMenuPanel({ sections, selectedId, onSelect, onClose, ancho
117
117
  rows.current.get(selected?.id ?? "")?.focus();
118
118
  else
119
119
  back();
120
- }), className: cn("mui-971625533e56 mui-571ea69568d3 mui-34055e6f8c1b mui-d5111d0e9f48 mui-04760bcd507f mui-94ea94fde25f mui-393df0d154e0 mui-548a450e8e53", desktop && selected ? "mui-8dd3eece40db" : "mui-919182384559", detached && "mui-0fc84a692dad mui-dad556abfe15 mui-8fca9236d191 mui-89c3006b2722", classNames?.menu), children: _jsxs("div", { className: cn("mui-80baa5d03af7", desktop && selected
121
- ? "mui-0f2a693e93e2 mui-b5985369ee35 mui-da607d0a2538" : "mui-222f930b8752 mui-302c0d124a94", detached && "mui-b9677bd1cb66 mui-70007b876865"), children: [showList && (_jsx(FilterMenuList, { sections: sections, selectedId: selected?.id, initialKey: selected?.id ?? lastSelection.current, panelId: panelId, desktop: desktop, detached: detached, rows: rows, choose: choose, keyboardNavigation: keyboardNavigation, onPointerMove: (id, event) => {
120
+ }), className: cn("mui-971625533e56 mui-571ea69568d3 mui-34055e6f8c1b mui-d5111d0e9f48 mui-04760bcd507f mui-94ea94fde25f mui-393df0d154e0 mui-548a450e8e53", "mui-d7d803c609c5", desktop && selected
121
+ ? "mui-bd8a502f98ae" : "mui-0b9c84552e40", detached && "mui-0fc84a692dad mui-dad556abfe15 mui-8fca9236d191 mui-89c3006b2722", classNames?.menu), children: _jsxs("div", { className: cn("mui-80baa5d03af7", desktop && selected
122
+ ? "mui-0f2a693e93e2 mui-b5985369ee35 mui-a3c6c8c31aed" : "mui-222f930b8752 mui-302c0d124a94", detached && "mui-b9677bd1cb66 mui-e0122edc668b"), children: [showList && (_jsx(FilterMenuList, { sections: sections, selectedId: selected?.id, initialKey: selected?.id ?? lastSelection.current, panelId: panelId, desktop: desktop, detached: detached, rows: rows, choose: choose, keyboardNavigation: keyboardNavigation, onPointerMove: (id, event) => {
122
123
  if (desktop && event.pointerType === "mouse") {
123
124
  setKeyboardNavigation(false);
124
125
  const focused = document.activeElement;
@@ -130,7 +131,7 @@ export function FilterMenuPanel({ sections, selectedId, onSelect, onClose, ancho
130
131
  }
131
132
  pointer.move(id, event);
132
133
  }
133
- } })), selected && (_jsxs("div", { ref: editorPanel, "data-slot": "filter-menu-editor", onPointerEnter: pointer.cancel, style: detached ? { marginTop: editorOffset } : undefined, className: cn("mui-222f930b8752 mui-410da8dfa8ac mui-184ddc11e5f9 mui-80baa5d03af7 mui-302c0d124a94", detached && "mui-d5111d0e9f48 mui-3fa8c572949b mui-4f1a55de40bc mui-e593c38256e0 mui-5bd2afe89f0b mui-94ea94fde25f"), children: [_jsx(EditorHeading, { section: selected, desktop: desktop, back: back, onCleared: focusEditor }), _jsx("div", { ref: editor, id: `${panelId}-${selected.id}`, role: "group", "aria-label": selected.editorLabel, tabIndex: -1, className: cn("mui-410da8dfa8ac mui-184ddc11e5f9 mui-3b82279f859f mui-2368e909f3a5 mui-998780cdef87 mui-b30fc56058b6 mui-f157ee6bae99 mui-a1c8c43d9be2 mui-b43343fe71c0", classNames?.editor), children: selected.content }, selected.id)] }))] }) }));
134
+ } })), selected && (_jsxs("div", { ref: editorPanel, "data-slot": "filter-menu-editor", onPointerEnter: pointer.cancel, style: detached ? { marginTop: editorOffset } : undefined, className: cn("mui-222f930b8752 mui-410da8dfa8ac mui-184ddc11e5f9 mui-80baa5d03af7 mui-302c0d124a94", detached && "mui-291952c2525a mui-d5111d0e9f48 mui-3fa8c572949b mui-b31810dbd8a9 mui-4f1a55de40bc mui-e593c38256e0 mui-5bd2afe89f0b"), children: [_jsx(EditorHeading, { section: selected, desktop: desktop, back: back, onCleared: focusEditor }), _jsx("div", { ref: editor, id: `${panelId}-${selected.id}`, role: "group", "aria-label": selected.editorLabel, tabIndex: -1, className: cn("mui-410da8dfa8ac mui-184ddc11e5f9 mui-3b82279f859f mui-2368e909f3a5 mui-998780cdef87 mui-b30fc56058b6 mui-f157ee6bae99 mui-a1c8c43d9be2 mui-b43343fe71c0", classNames?.editor), children: selected.content }, selected.id)] }))] }) }));
134
135
  }
135
136
  function EditorHeading({ section, desktop, back, onCleared, }) {
136
137
  const { classNames } = useMendyUI();
@@ -172,7 +173,7 @@ function FilterMenuList({ sections, selectedId, initialKey, panelId, desktop, de
172
173
  if (section.label.toLocaleLowerCase().includes(term))
173
174
  matches.push({ ...section, key: section.id });
174
175
  }
175
- return (_jsxs("div", { className: cn("mui-222f930b8752 mui-410da8dfa8ac mui-302c0d124a94", desktop && selectedId && !detached && "mui-3b6d5fc7b061", detached && "mui-d5111d0e9f48 mui-3fa8c572949b mui-4f1a55de40bc mui-e593c38256e0 mui-5bd2afe89f0b mui-94ea94fde25f"), children: [sections.length > 20 && (_jsx("div", { className: "mui-27ead27a81df mui-bbe39cfb5cc6 mui-b97db4a9f432", children: _jsx(Input, { type: "search", "aria-label": "Find a filter", placeholder: "Find a filter\u2026", value: query, className: "mui-b51243872d85", onChange: (event) => setQuery(event.target.value), onKeyDown: (event) => {
176
+ return (_jsxs("div", { "data-slot": "filter-menu-list", className: cn("mui-222f930b8752 mui-410da8dfa8ac mui-302c0d124a94", desktop && selectedId && !detached && "mui-3b6d5fc7b061", detached && "mui-d5111d0e9f48 mui-3fa8c572949b mui-4f1a55de40bc mui-e593c38256e0 mui-5bd2afe89f0b"), children: [sections.length > 20 && (_jsx("div", { className: "mui-27ead27a81df mui-bbe39cfb5cc6 mui-b97db4a9f432", children: _jsx(Input, { type: "search", "aria-label": "Find a filter", placeholder: "Find a filter\u2026", value: query, className: "mui-b51243872d85", onChange: (event) => setQuery(event.target.value), onKeyDown: (event) => {
176
177
  if (event.key === "ArrowDown") {
177
178
  event.preventDefault();
178
179
  collection.current?.focusFirst();
@@ -0,0 +1,4 @@
1
+ import type { ComponentProps } from "react";
2
+ import { Input } from "../customization.js";
3
+ /** The search row belongs to the option panel, with a visible inset keyboard focus ring. */
4
+ export declare function FilterOptionSearch({ className, ...props }: ComponentProps<typeof Input>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,9 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Search } from "lucide-react";
4
+ import { Input } from "../customization.js";
5
+ import { cn } from "../utils.js";
6
+ /** The search row belongs to the option panel, with a visible inset keyboard focus ring. */
7
+ export function FilterOptionSearch({ className, ...props }) {
8
+ return (_jsxs("div", { "data-mendy-ui": "", "data-slot": "filter-option-search", className: "mui-d2d9e1f13413 mui-bbe39cfb5cc6", children: [_jsx(Search, { className: "mui-33228ff7d583 mui-747355bdc2a2 mui-cea70f23972e mui-4e45f4841abb mui-100c22d5776b mui-5dde0fd996f0 mui-35f35c41d134", "aria-hidden": "true" }), _jsx(Input, { ...props, type: "search", className: cn("mui-2bf5d58a824b mui-52417259a4f5 mui-dad556abfe15 mui-8fca9236d191 mui-b2100041c585 mui-a202804a1738 mui-89c3006b2722 mui-39be5a15b766 mui-50aafa8694bb mui-db549d38ff19 mui-4f05a238500e", className) })] }));
9
+ }
@@ -6,6 +6,7 @@ export interface FilterOption {
6
6
  interface SharedProps {
7
7
  label: string;
8
8
  options: readonly FilterOption[];
9
+ /** Search is enabled by default. Set false for a short list. */
9
10
  searchable?: boolean;
10
11
  searchPlaceholder?: string;
11
12
  emptyMessage?: string;
@@ -1,9 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useEffect, useId, useRef, useState } from "react";
4
- import { Input } from "../customization.js";
5
- import { Label } from "../customization.js";
6
- import { Search } from "lucide-react";
3
+ import { useEffect, useRef, useState } from "react";
4
+ import { FilterOptionSearch } from "./filter-option-search.js";
7
5
  import { DropdownMenuRadioGroup, DropdownMenuRadioItem } from "../primitives/dropdown-menu.js";
8
6
  import { FilterCheckboxItem } from "./filters.js";
9
7
  function handleSearchKey(event) {
@@ -17,7 +15,7 @@ function handleSearchKey(event) {
17
15
  if (event.key !== "Escape" && event.key !== "Tab")
18
16
  event.stopPropagation();
19
17
  }
20
- function SearchableOptions({ label, options, searchable, searchPlaceholder, emptyMessage = "No options found.", children, }) {
18
+ function SearchableOptions({ label, options, searchable = true, searchPlaceholder, emptyMessage = "No options found.", children, }) {
21
19
  const [query, setQuery] = useState("");
22
20
  const inputRef = useRef(null);
23
21
  useEffect(() => {
@@ -26,12 +24,13 @@ function SearchableOptions({ label, options, searchable, searchPlaceholder, empt
26
24
  const frame = requestAnimationFrame(() => inputRef.current?.focus());
27
25
  return () => cancelAnimationFrame(frame);
28
26
  }, [searchable]);
29
- const id = useId();
30
- const filtered = options.filter((option) => option.label.toLocaleLowerCase().includes(query.toLocaleLowerCase()));
27
+ const filtered = !searchable
28
+ ? options
29
+ : options.filter((option) => option.label.toLocaleLowerCase().includes(query.toLocaleLowerCase()));
31
30
  return (_jsxs("div", { className: "mui-72b37c1a040d mui-81b198a2db84", "data-mendy-ui": "", "data-slot": "filter-options", onKeyDown: (event) => {
32
31
  if (event.key === "Tab")
33
32
  event.stopPropagation();
34
- }, children: [searchable && (_jsxs("div", { "data-mendy-ui": "", className: "mui-d2d9e1f13413 mui-bbe39cfb5cc6 mui-b97db4a9f432", children: [_jsx(Search, { className: "mui-33228ff7d583 mui-747355bdc2a2 mui-866c339ea145 mui-4e45f4841abb mui-5dde0fd996f0 mui-100c22d5776b mui-0b5a4d1257ab", strokeWidth: 1.5, "aria-hidden": "true" }), _jsx(Label, { htmlFor: id, className: "mui-32fb090591d9", children: label }), _jsx(Input, { ref: inputRef, id: id, type: "search", className: "mui-75b27e813dcc mui-4f05a238500e", placeholder: searchPlaceholder ?? label, value: query, onChange: (event) => setQuery(event.target.value), onKeyDown: handleSearchKey })] })), filtered.length ? (_jsx("div", { role: "menu", "aria-label": label, className: "mui-1dee6e3ec67d", children: children(filtered) })) : (_jsx("p", { role: "status", className: "mui-094f5333853b mui-c74ab393b96d mui-35f35c41d134", children: emptyMessage }))] }));
33
+ }, children: [searchable && (_jsx(FilterOptionSearch, { ref: inputRef, "aria-label": label, placeholder: searchPlaceholder ?? label, value: query, onChange: (event) => setQuery(event.target.value), onKeyDown: handleSearchKey })), filtered.length ? (_jsx("div", { role: "menu", "aria-label": label, className: "mui-1dee6e3ec67d", children: children(filtered) })) : (_jsx("p", { role: "status", className: "mui-094f5333853b mui-c74ab393b96d mui-35f35c41d134", children: emptyMessage }))] }));
35
34
  }
36
35
  /** Single selection applies immediately and closes the dropdown. */
37
36
  export function FilterSelectEditor({ value, onValueChange, ...props }) {
@@ -2,10 +2,14 @@ import type { ComponentProps, ReactNode } from "react";
2
2
  import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuTrigger } from "../primitives/dropdown-menu.js";
3
3
  export type FilterEditorProps = ComponentProps<typeof DropdownMenu>;
4
4
  export declare function FilterEditor(props: FilterEditorProps): import("react/jsx-runtime").JSX.Element;
5
+ /** Preserve the original list stagger; newly inserted chips animate immediately. */
6
+ export declare function FilterChipList({ children }: {
7
+ children: ReactNode;
8
+ }): import("react/jsx-runtime").JSX.Element;
5
9
  export type FilterChipProps = ComponentProps<"div"> & {
6
10
  entranceDelay?: number;
7
11
  };
8
- export declare function FilterChip({ className, ref, entranceDelay, ...props }: FilterChipProps): import("react/jsx-runtime").JSX.Element;
12
+ export declare function FilterChip({ className, entranceDelay, ...props }: FilterChipProps): import("react/jsx-runtime").JSX.Element;
9
13
  export type FilterEditorTriggerProps = ComponentProps<typeof DropdownMenuTrigger>;
10
14
  export declare function FilterEditorTrigger({ className, asChild, ...props }: FilterEditorTriggerProps): import("react/jsx-runtime").JSX.Element;
11
15
  export type FilterEditorContentProps = ComponentProps<typeof DropdownMenuContent>;
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useEffect, useLayoutEffect, useImperativeHandle, useRef, useState } from "react";
4
- import { useAnimate, useReducedMotion } from "motion/react";
3
+ import { createContext, useContext, useEffect, useRef, useState } from "react";
4
+ import { m, LazyMotion, domAnimation, useReducedMotion } from "motion/react";
5
5
  import { XIcon } from "lucide-react";
6
6
  import { Button } from "../customization.js";
7
7
  import { cn } from "../utils.js";
@@ -9,28 +9,33 @@ import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMe
9
9
  export function FilterEditor(props) {
10
10
  return _jsx(DropdownMenu, { modal: false, ...props });
11
11
  }
12
- export function FilterChip({ className, ref, entranceDelay = 0, ...props }) {
13
- const [scope, animate] = useAnimate();
12
+ const ChipListContext = createContext(false);
13
+ const listVariant = {
14
+ hidden: { y: 10, opacity: 0 },
15
+ show: {
16
+ y: 0,
17
+ opacity: 1,
18
+ transition: { duration: 0.05, staggerChildren: 0.06 },
19
+ },
20
+ };
21
+ const itemVariant = {
22
+ hidden: { y: 10, opacity: 0 },
23
+ show: { y: 0, opacity: 1 },
24
+ };
25
+ const reducedVariant = {
26
+ hidden: { y: 0, opacity: 1 },
27
+ show: { y: 0, opacity: 1, transition: { duration: 0 } },
28
+ };
29
+ /** Preserve the original list stagger; newly inserted chips animate immediately. */
30
+ export function FilterChipList({ children }) {
14
31
  const reducedMotion = useReducedMotion();
15
- const initialDelay = useRef(entranceDelay);
16
- useImperativeHandle(ref, () => scope.current);
17
- useLayoutEffect(() => {
18
- if (reducedMotion) {
19
- scope.current.style.transform = "none";
20
- scope.current.style.opacity = "1";
21
- return;
22
- }
23
- const animation = animate(scope.current, { y: [10, 0], opacity: [0, 1] }, {
24
- type: "spring",
25
- stiffness: 100,
26
- damping: 10,
27
- mass: 1,
28
- delay: initialDelay.current,
29
- opacity: { duration: 0.2 },
30
- });
31
- return () => animation.stop();
32
- }, [animate, scope, reducedMotion]);
33
- return (_jsx("div", { "data-mendy-ui": "", ref: scope, "data-slot": "filter-chip", className: cn("mui-123306850fe1 mui-539ae144f076 mui-81b198a2db84 mui-d5111d0e9f48 mui-3fa8c572949b mui-71556df3b421 mui-d191cb569aac mui-c74ab393b96d mui-35f35c41d134", className), ...props }));
32
+ return (_jsx(LazyMotion, { features: domAnimation, children: _jsx(ChipListContext.Provider, { value: true, children: _jsx(m.div, { variants: reducedMotion ? reducedVariant : listVariant, initial: "hidden", animate: "show", className: "mui-d1b2a59fbea7", children: children }) }) }));
33
+ }
34
+ export function FilterChip({ className, entranceDelay, ...props }) {
35
+ const inList = useContext(ChipListContext);
36
+ const reducedMotion = useReducedMotion();
37
+ const content = (_jsx(m.div, { "data-mendy-ui": "", "data-slot": "filter-chip-entrance", variants: reducedMotion ? reducedVariant : itemVariant, initial: inList ? undefined : "hidden", animate: inList ? undefined : "show", transition: entranceDelay === undefined || reducedMotion ? undefined : { delay: entranceDelay }, className: "mui-184ddc11e5f9 mui-81b198a2db84", children: _jsx("div", { "data-mendy-ui": "", "data-slot": "filter-chip", className: cn("mui-123306850fe1 mui-539ae144f076 mui-81b198a2db84 mui-d5111d0e9f48 mui-3fa8c572949b mui-71556df3b421 mui-d191cb569aac mui-c74ab393b96d mui-35f35c41d134", className), ...props }) }));
38
+ return inList ? content : _jsx(LazyMotion, { features: domAnimation, children: content });
34
39
  }
35
40
  export function FilterEditorTrigger({ className, asChild, ...props }) {
36
41
  return (_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { asChild: asChild, variant: "ghost", "data-mendy-ui": "", "data-slot": "filter-editor-trigger", "aria-haspopup": "dialog", className: cn("mui-222f930b8752 mui-57c930dc1c31 mui-66b490dd6005 mui-52417259a4f5 mui-52101fc7d8bb mui-184ddc11e5f9 mui-71556df3b421 mui-70007b876865 mui-e7e01cc7f4df mui-e9347b78185f mui-37ad15a95595 mui-4d6720d47806 mui-2e357972fc10 mui-355efe22aedb mui-50aafa8694bb mui-db549d38ff19 mui-8d3c1014b967 mui-4600b77303d6 mui-4027d9c589b6 mui-6f73a280432e", className), ...props }) }));
@@ -64,6 +64,10 @@ export function selectedIds(value) {
64
64
  ? [value]
65
65
  : [];
66
66
  }
67
+ // External queries belong to the consumer; opting out only disables our local search.
68
+ function optionSearchQuery(field, localQuery) {
69
+ return field.source?.query ?? (field.searchable === false ? "" : localQuery);
70
+ }
67
71
  export function useFilterOptions(id, field, value, enabled) {
68
72
  const sharedCache = useContext(FilterOptionCache);
69
73
  const privateCache = useRef(new Map());
@@ -75,7 +79,7 @@ export function useFilterOptions(id, field, value, enabled) {
75
79
  }, [source]);
76
80
  const scopeKey = JSON.stringify([id, source?.kind, source?.scope, source?.params]);
77
81
  const [localQuery, setLocalQuery] = useValueDraft(scopeKey, () => "", `${id}:query`);
78
- const query = source?.query ?? localQuery;
82
+ const query = optionSearchQuery(field, localQuery);
79
83
  const [retryKey, retry] = useState(0);
80
84
  const requestKey = JSON.stringify([scopeKey, query, retryKey]);
81
85
  const identity = JSON.stringify([id, source?.kind, source?.scope]);
@@ -1,8 +1,9 @@
1
- import type { RefObject } from "react";
1
+ import type { CSSProperties, RefObject } from "react";
2
2
  /** Position the menu against the search field and the available viewport. */
3
3
  export declare function useMenuPlacement(anchor: RefObject<HTMLDivElement | null> | undefined, trigger: RefObject<HTMLButtonElement | null>, desktop: boolean): {
4
4
  alignOffset: number;
5
5
  side: "top" | "bottom";
6
+ anchorStyle: CSSProperties | undefined;
6
7
  };
7
8
  /** Follow the selected row while keeping the editor inside the viewport. */
8
9
  export declare function useEditorOffset({ detached, editorPanel, content, rows, selectedId, }: {
@@ -1,8 +1,9 @@
1
1
  "use client";
2
- import { useLayoutEffect, useState } from "react";
2
+ import { useLayoutEffect, useRef, useState } from "react";
3
3
  /** Position the menu against the search field and the available viewport. */
4
4
  export function useMenuPlacement(anchor, trigger, desktop) {
5
5
  const [alignOffset, setAlignOffset] = useState(0);
6
+ const [anchorWidth, setAnchorWidth] = useState();
6
7
  const [side, setSide] = useState("bottom");
7
8
  useLayoutEffect(() => {
8
9
  const button = trigger.current;
@@ -11,6 +12,7 @@ export function useMenuPlacement(anchor, trigger, desktop) {
11
12
  const update = () => {
12
13
  const bounds = button.getBoundingClientRect();
13
14
  const target = anchor?.current?.getBoundingClientRect();
15
+ setAnchorWidth(target?.width);
14
16
  const rtl = getComputedStyle(button).direction === "rtl";
15
17
  const viewport = window.visualViewport;
16
18
  const viewportTop = viewport?.offsetTop ?? 0;
@@ -21,12 +23,14 @@ export function useMenuPlacement(anchor, trigger, desktop) {
21
23
  // A short list can fit below the trigger while its editor cannot. Choose room
22
24
  // for the editor before Radix constrains its height to the current side.
23
25
  setSide(below < preferredHeight && above > below ? "top" : "bottom");
24
- // Desktop starts at the search field's edge; mobile stays close to the icon.
26
+ // Follow the search edge in both layouts, including inset mobile triggers.
25
27
  setAlignOffset(desktop
26
28
  ? rtl
27
29
  ? bounds.right - (target?.right ?? bounds.right)
28
30
  : (target?.left ?? bounds.left) - bounds.left
29
- : 0);
31
+ : rtl
32
+ ? (target?.left ?? bounds.left) - bounds.left
33
+ : bounds.right - (target?.right ?? bounds.right));
30
34
  };
31
35
  update();
32
36
  const observer = new ResizeObserver(update);
@@ -43,11 +47,15 @@ export function useMenuPlacement(anchor, trigger, desktop) {
43
47
  window.visualViewport?.removeEventListener("scroll", update);
44
48
  };
45
49
  }, [anchor, desktop, trigger]);
46
- return { alignOffset, side };
50
+ const anchorStyle = anchorWidth
51
+ ? { "--mendy-filter-anchor-width": `${anchorWidth}px` }
52
+ : undefined;
53
+ return { alignOffset, side, anchorStyle };
47
54
  }
48
55
  /** Follow the selected row while keeping the editor inside the viewport. */
49
56
  export function useEditorOffset({ detached, editorPanel, content, rows, selectedId, }) {
50
57
  const [editorOffset, setEditorOffset] = useState(0);
58
+ const measured = useRef({ id: selectedId, height: 0 });
51
59
  useLayoutEffect(() => {
52
60
  if (!detached)
53
61
  return;
@@ -57,16 +65,35 @@ export function useEditorOffset({ detached, editorPanel, content, rows, selected
57
65
  return;
58
66
  const update = () => {
59
67
  const row = rows.current.get(selectedId ?? "");
60
- if (!row)
68
+ if (!row) {
69
+ setEditorOffset(0);
61
70
  return;
62
- const available = parseFloat(getComputedStyle(root).getPropertyValue("--radix-dropdown-menu-content-available-height")) || window.innerHeight - 32;
63
- const offset = row.getBoundingClientRect().top - root.getBoundingClientRect().top;
64
- setEditorOffset(Math.max(0, Math.min(offset - 5, available - panel.getBoundingClientRect().height - 2)));
71
+ }
72
+ const rootTop = root.getBoundingClientRect().top;
73
+ const list = root.querySelector('[data-slot="filter-menu-list"]');
74
+ const listBottom = list?.getBoundingClientRect().bottom ?? rootTop;
75
+ const currentHeight = panel.getBoundingClientRect().height;
76
+ if (measured.current.id !== selectedId)
77
+ measured.current = { id: selectedId, height: 0 };
78
+ // Result filtering may shrink the editor. Keep its input in place instead
79
+ // of moving it down under the pointer on every query change.
80
+ measured.current.height = Math.max(measured.current.height, currentHeight);
81
+ const height = measured.current.height;
82
+ const viewport = window.visualViewport;
83
+ const viewportBottom = (viewport?.offsetTop ?? 0) + (viewport?.height ?? window.innerHeight);
84
+ // Keep short editors inside the list's vertical span. Lower rows therefore
85
+ // open upward even on a tall viewport, instead of dangling below the list.
86
+ const latestTop = Math.max(rootTop, Math.min(listBottom, viewportBottom - 16) - height);
87
+ const preferredTop = row.getBoundingClientRect().top - 5;
88
+ setEditorOffset(Math.max(0, Math.min(preferredTop, latestTop) - rootTop));
65
89
  };
66
90
  update();
67
91
  const observer = new ResizeObserver(update);
68
92
  observer.observe(panel);
69
93
  observer.observe(root);
94
+ const list = root.querySelector('[data-slot="filter-menu-list"]');
95
+ if (list)
96
+ observer.observe(list);
70
97
  root.addEventListener("scroll", update, true);
71
98
  return () => {
72
99
  observer.disconnect();
@@ -3,7 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
4
  import { useMendyUI } from "../customization.js";
5
5
  import { cn } from "../utils.js";
6
- import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
6
+ import { CheckIcon, ChevronRightIcon } from "lucide-react";
7
7
  import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
8
8
  function DropdownMenu({ ...props }) {
9
9
  return _jsx(DropdownMenuPrimitive.Root, { "data-mendy-ui": "", "data-slot": "dropdown-menu", ...props });
@@ -31,7 +31,7 @@ function DropdownMenuRadioGroup({ ...props }) {
31
31
  return (_jsx(DropdownMenuPrimitive.RadioGroup, { "data-mendy-ui": "", "data-slot": "dropdown-menu-radio-group", ...props }));
32
32
  }
33
33
  function DropdownMenuRadioItem({ className, children, ...props }) {
34
- return (_jsxs(DropdownMenuPrimitive.RadioItem, { "data-mendy-ui": "", "data-slot": "dropdown-menu-radio-item", className: cn("mui-d2d9e1f13413 mui-222f930b8752 mui-d343f41ba73e mui-71556df3b421 mui-074569488cca mui-02e603944040 mui-a8c1dfb1d4ef mui-05d4103bd67f mui-078d945937da mui-c74ab393b96d mui-59edd3d33673 mui-78905c9e865c mui-a8c1861c5d03 mui-a85c4c5d7465 mui-397f5ba426a0 mui-9beb654fcb0d mui-bcae9d37090c mui-040e748a3fa0 mui-eb5ef2dbc2d4", className), ...props, children: [_jsx("span", { className: "mui-33228ff7d583 mui-747355bdc2a2 mui-207bd0b3f259 mui-222f930b8752 mui-61c000c8a98a mui-71556df3b421 mui-a503dd374cca", children: _jsx(DropdownMenuPrimitive.ItemIndicator, { children: _jsx(CircleIcon, { className: "mui-9e7600197f38 mui-717b342c2d01" }) }) }), children] }));
34
+ return (_jsxs(DropdownMenuPrimitive.RadioItem, { "data-mendy-ui": "", "data-slot": "dropdown-menu-radio-item", className: cn("mui-d2d9e1f13413 mui-222f930b8752 mui-d343f41ba73e mui-71556df3b421 mui-074569488cca mui-02e603944040 mui-a8c1dfb1d4ef mui-05d4103bd67f mui-078d945937da mui-c74ab393b96d mui-59edd3d33673 mui-78905c9e865c mui-a8c1861c5d03 mui-a85c4c5d7465 mui-397f5ba426a0 mui-9beb654fcb0d mui-bcae9d37090c mui-040e748a3fa0 mui-eb5ef2dbc2d4", className), ...props, children: [_jsx("span", { className: "mui-33228ff7d583 mui-747355bdc2a2 mui-207bd0b3f259 mui-222f930b8752 mui-61c000c8a98a mui-71556df3b421 mui-a503dd374cca", children: _jsx(DropdownMenuPrimitive.ItemIndicator, { children: _jsx(CheckIcon, { className: "mui-100c22d5776b" }) }) }), children] }));
35
35
  }
36
36
  function DropdownMenuLabel({ className, inset, ...props }) {
37
37
  return (_jsx(DropdownMenuPrimitive.Label, { "data-mendy-ui": "", "data-slot": "dropdown-menu-label", "data-inset": inset, className: cn("mui-e7e01cc7f4df mui-a8c1dfb1d4ef mui-c74ab393b96d mui-daaac3fbf55e mui-6fa6a8ade7c4", className), ...props }));
package/dist/styles.css CHANGED
@@ -13,6 +13,7 @@
13
13
  --font-weight-medium: 500;
14
14
  --font-weight-semibold: 600;
15
15
  --tracking-widest: 0.1em;
16
+ --drop-shadow-md: 0 3px 3px rgb(0 0 0 / 0.12);
16
17
  --animate-pulse: mendy-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
17
18
  --default-transition-duration: 150ms;
18
19
  --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
@@ -60,9 +61,6 @@
60
61
  .mui-cea70f23972e:where([data-mendy-ui], [data-mendy-ui] *) {
61
62
  inset-inline-start: calc(var(--spacing) * 3);
62
63
  }
63
- .mui-96a350bd3168:where([data-mendy-ui], [data-mendy-ui] *) {
64
- inset-inline-start: calc(var(--spacing) * 4);
65
- }
66
64
  .mui-361e48d0308f:where([data-mendy-ui], [data-mendy-ui] *) {
67
65
  inset-inline-end: var(--spacing);
68
66
  }
@@ -78,9 +76,6 @@
78
76
  .mui-4e45f4841abb:where([data-mendy-ui], [data-mendy-ui] *) {
79
77
  top: calc(1 / 2 * 100%);
80
78
  }
81
- .mui-866c339ea145:where([data-mendy-ui], [data-mendy-ui] *) {
82
- left: calc(var(--spacing) * 4);
83
- }
84
79
  .mui-3eef1ce97dba:where([data-mendy-ui], [data-mendy-ui] *) {
85
80
  z-index: 50;
86
81
  }
@@ -117,6 +112,9 @@
117
112
  .mui-958e2cfcf5b6:where([data-mendy-ui], [data-mendy-ui] *) {
118
113
  margin-inline-start: calc(var(--spacing) * -2);
119
114
  }
115
+ .mui-291952c2525a:where([data-mendy-ui], [data-mendy-ui] *) {
116
+ margin-inline-start: -1px;
117
+ }
120
118
  .mui-8cc46fa87f41:where([data-mendy-ui], [data-mendy-ui] *) {
121
119
  margin-inline-end: calc(var(--spacing) * -1.5);
122
120
  }
@@ -129,6 +127,9 @@
129
127
  .mui-496aca80e4d8:where([data-mendy-ui], [data-mendy-ui] *) {
130
128
  display: block;
131
129
  }
130
+ .mui-d1b2a59fbea7:where([data-mendy-ui], [data-mendy-ui] *) {
131
+ display: contents;
132
+ }
132
133
  .mui-222f930b8752:where([data-mendy-ui], [data-mendy-ui] *) {
133
134
  display: flex;
134
135
  }
@@ -158,10 +159,6 @@
158
159
  width: calc(var(--spacing) * 1.5);
159
160
  height: calc(var(--spacing) * 1.5);
160
161
  }
161
- .mui-9e7600197f38:where([data-mendy-ui], [data-mendy-ui] *) {
162
- width: calc(var(--spacing) * 2);
163
- height: calc(var(--spacing) * 2);
164
- }
165
162
  .mui-61c000c8a98a:where([data-mendy-ui], [data-mendy-ui] *) {
166
163
  width: calc(var(--spacing) * 3.5);
167
164
  height: calc(var(--spacing) * 3.5);
@@ -209,6 +206,9 @@
209
206
  .mui-fdd2f85cad6b:where([data-mendy-ui], [data-mendy-ui] *) {
210
207
  height: calc(var(--spacing) * 10);
211
208
  }
209
+ .mui-2bf5d58a824b:where([data-mendy-ui], [data-mendy-ui] *) {
210
+ height: calc(var(--spacing) * 12);
211
+ }
212
212
  .mui-a66e9985b093:where([data-mendy-ui], [data-mendy-ui] *) {
213
213
  height: auto;
214
214
  }
@@ -260,11 +260,11 @@
260
260
  .mui-37535002f0f7:where([data-mendy-ui], [data-mendy-ui] *) {
261
261
  width: calc(var(--spacing) * 72);
262
262
  }
263
- .mui-919182384559:where([data-mendy-ui], [data-mendy-ui] *) {
264
- width: 18.75rem;
263
+ .mui-0b9c84552e40:where([data-mendy-ui], [data-mendy-ui] *) {
264
+ width: var(--mendy-filter-list-width,var(--mendy-filter-anchor-width,18.75rem));
265
265
  }
266
- .mui-8dd3eece40db:where([data-mendy-ui], [data-mendy-ui] *) {
267
- width: var(--mendy-filter-menu-width,32rem);
266
+ .mui-bd8a502f98ae:where([data-mendy-ui], [data-mendy-ui] *) {
267
+ width: var(--mendy-filter-menu-width,calc(var(--filter-list-width) + 19rem));
268
268
  }
269
269
  .mui-8cfb5a42ef9f:where([data-mendy-ui], [data-mendy-ui] *) {
270
270
  width: fit-content;
@@ -327,8 +327,8 @@
327
327
  .mui-ae112c903ef8:where([data-mendy-ui], [data-mendy-ui] *) {
328
328
  resize: vertical;
329
329
  }
330
- .mui-da607d0a2538:where([data-mendy-ui], [data-mendy-ui] *) {
331
- grid-template-columns: min(var(--mendy-filter-list-width,13rem), 50%) minmax(0,1fr);
330
+ .mui-a3c6c8c31aed:where([data-mendy-ui], [data-mendy-ui] *) {
331
+ grid-template-columns: min(var(--filter-list-width), calc(100% - min(19rem, 50%))) minmax(0,1fr);
332
332
  }
333
333
  .mui-b5985369ee35:where([data-mendy-ui], [data-mendy-ui] *) {
334
334
  grid-template-rows: minmax(0,1fr);
@@ -418,6 +418,10 @@
418
418
  .mui-02e603944040:where([data-mendy-ui], [data-mendy-ui] *) {
419
419
  border-radius: max(0px, calc(var(--radius, 0.5rem) - 4px));
420
420
  }
421
+ .mui-b31810dbd8a9:where([data-mendy-ui], [data-mendy-ui] *) {
422
+ border-start-start-radius: 0;
423
+ border-end-start-radius: 0;
424
+ }
421
425
  .mui-a22ea0ba562a:where([data-mendy-ui], [data-mendy-ui] *) {
422
426
  border-top-left-radius: 0;
423
427
  border-top-right-radius: 0;
@@ -500,9 +504,6 @@
500
504
  .mui-8fca9236d191:where([data-mendy-ui], [data-mendy-ui] *) {
501
505
  background-color: transparent;
502
506
  }
503
- .mui-717b342c2d01:where([data-mendy-ui], [data-mendy-ui] *) {
504
- fill: currentcolor;
505
- }
506
507
  .mui-04760bcd507f:where([data-mendy-ui], [data-mendy-ui] *) {
507
508
  padding: calc(var(--spacing) * 0);
508
509
  }
@@ -551,6 +552,9 @@
551
552
  .mui-05d4103bd67f:where([data-mendy-ui], [data-mendy-ui] *) {
552
553
  padding-inline-end: calc(var(--spacing) * 2);
553
554
  }
555
+ .mui-a202804a1738:where([data-mendy-ui], [data-mendy-ui] *) {
556
+ padding-inline-end: calc(var(--spacing) * 3);
557
+ }
554
558
  .mui-0e14c365f9e8:where([data-mendy-ui], [data-mendy-ui] *) {
555
559
  padding-inline-end: calc(var(--spacing) * 9);
556
560
  }
@@ -569,9 +573,6 @@
569
573
  .mui-f5d8e661d857:where([data-mendy-ui], [data-mendy-ui] *) {
570
574
  padding-left: calc(var(--spacing) * 2);
571
575
  }
572
- .mui-75b27e813dcc:where([data-mendy-ui], [data-mendy-ui] *) {
573
- padding-left: calc(var(--spacing) * 8);
574
- }
575
576
  .mui-05ab12448317:where([data-mendy-ui], [data-mendy-ui] *) {
576
577
  text-align: center;
577
578
  }
@@ -694,9 +695,19 @@
694
695
  outline-style: var(--mendy-tw-outline-style);
695
696
  outline-width: 1px;
696
697
  }
698
+ .mui-e0122edc668b:where([data-mendy-ui], [data-mendy-ui] *) {
699
+ --mendy-tw-drop-shadow-size: drop-shadow(0 3px 3px var(--mendy-tw-drop-shadow-color, rgb(0 0 0 / 0.12)));
700
+ --mendy-tw-drop-shadow: drop-shadow(var(--drop-shadow-md));
701
+ filter: var(--mendy-tw-blur,) var(--mendy-tw-brightness,) var(--mendy-tw-contrast,) var(--mendy-tw-grayscale,) var(--mendy-tw-hue-rotate,) var(--mendy-tw-invert,) var(--mendy-tw-saturate,) var(--mendy-tw-sepia,) var(--mendy-tw-drop-shadow,);
702
+ }
697
703
  .mui-dfc3376b8266:where([data-mendy-ui], [data-mendy-ui] *) {
698
704
  filter: var(--mendy-tw-blur,) var(--mendy-tw-brightness,) var(--mendy-tw-contrast,) var(--mendy-tw-grayscale,) var(--mendy-tw-hue-rotate,) var(--mendy-tw-invert,) var(--mendy-tw-saturate,) var(--mendy-tw-sepia,) var(--mendy-tw-drop-shadow,);
699
705
  }
706
+ .mui-70dd37c11434:where([data-mendy-ui], [data-mendy-ui] *) {
707
+ transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --mendy-tw-gradient-from, --mendy-tw-gradient-via, --mendy-tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;
708
+ transition-timing-function: var(--mendy-tw-ease, var(--default-transition-timing-function));
709
+ transition-duration: var(--mendy-tw-duration, var(--default-transition-duration));
710
+ }
700
711
  .mui-eae178841c68:where([data-mendy-ui], [data-mendy-ui] *) {
701
712
  transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --mendy-tw-gradient-from, --mendy-tw-gradient-via, --mendy-tw-gradient-to;
702
713
  transition-timing-function: var(--mendy-tw-ease, var(--default-transition-timing-function));
@@ -729,6 +740,9 @@
729
740
  .mui-82c2977beb8e:where([data-mendy-ui], [data-mendy-ui] *) {
730
741
  --cell-size: min(2rem, calc((100vw - 3.5rem) / 7));
731
742
  }
743
+ .mui-d7d803c609c5:where([data-mendy-ui], [data-mendy-ui] *) {
744
+ --filter-list-width: var(--mendy-filter-list-width,var(--mendy-filter-anchor-width,13rem));
745
+ }
732
746
  .mui-971625533e56:where([data-mendy-ui], [data-mendy-ui] *) {
733
747
  --filter-menu-height: min(var(--mendy-filter-menu-max-height,44rem), var(--radix-dropdown-menu-content-available-height,44rem));
734
748
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mendylanda/ui",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Mendy Landa’s reusable React components. Typed filters with dynamic options, URL persistence, and customizable UI.",
5
5
  "homepage": "https://ui.mendylanda.com",
6
6
  "license": "MIT",
@@ -62,6 +62,11 @@
62
62
  "publishConfig": {
63
63
  "access": "public"
64
64
  },
65
+ "scripts": {
66
+ "build": "tsc -p tsconfig.build.json && node scripts/build-css.mjs",
67
+ "typecheck": "tsc -p tsconfig.build.json --noEmit",
68
+ "prepack": "pnpm build"
69
+ },
65
70
  "dependencies": {
66
71
  "@tanstack/react-virtual": "^3.14.11",
67
72
  "class-variance-authority": "^0.7.1",
@@ -92,9 +97,5 @@
92
97
  "nuqs": {
93
98
  "optional": true
94
99
  }
95
- },
96
- "scripts": {
97
- "build": "tsc -p tsconfig.build.json && node scripts/build-css.mjs",
98
- "typecheck": "tsc -p tsconfig.build.json --noEmit"
99
100
  }
100
- }
101
+ }